summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
Diffstat (limited to 'src/net')
-rw-r--r--src/net/accountserver/account.cpp116
-rw-r--r--src/net/accountserver/account.h60
-rw-r--r--src/net/accountserver/accountserver.cpp68
-rw-r--r--src/net/accountserver/accountserver.h46
-rw-r--r--src/net/accountserver/internal.cpp34
-rw-r--r--src/net/accountserver/internal.h (renamed from src/net/maploginhandler.h)18
-rw-r--r--src/net/beinghandler.cpp352
-rw-r--r--src/net/beinghandler.h7
-rw-r--r--src/net/buysellhandler.cpp35
-rw-r--r--src/net/buysellhandler.h2
-rw-r--r--src/net/charserverhandler.cpp273
-rw-r--r--src/net/charserverhandler.h21
-rw-r--r--src/net/chathandler.cpp41
-rw-r--r--src/net/chathandler.h2
-rw-r--r--src/net/chatserver/chatserver.cpp116
-rw-r--r--src/net/chatserver/chatserver.h55
-rw-r--r--src/net/chatserver/internal.cpp34
-rw-r--r--src/net/chatserver/internal.h (renamed from src/net/packet.cpp)23
-rw-r--r--src/net/connection.cpp104
-rw-r--r--src/net/connection.h78
-rw-r--r--src/net/equipmenthandler.cpp47
-rw-r--r--src/net/equipmenthandler.h2
-rw-r--r--src/net/gameserver/gameserver.cpp42
-rw-r--r--src/net/gameserver/gameserver.h (renamed from src/net/packet.h)30
-rw-r--r--src/net/gameserver/internal.cpp34
-rw-r--r--src/net/gameserver/internal.h37
-rw-r--r--src/net/gameserver/player.cpp68
-rw-r--r--src/net/gameserver/player.h46
-rw-r--r--src/net/internal.cpp29
-rw-r--r--src/net/internal.h32
-rw-r--r--src/net/inventoryhandler.cpp61
-rw-r--r--src/net/inventoryhandler.h2
-rw-r--r--src/net/itemhandler.cpp17
-rw-r--r--src/net/itemhandler.h2
-rw-r--r--src/net/loginhandler.cpp131
-rw-r--r--src/net/loginhandler.h9
-rw-r--r--src/net/maploginhandler.cpp63
-rw-r--r--src/net/messagehandler.cpp14
-rw-r--r--src/net/messagehandler.h9
-rw-r--r--src/net/messagein.cpp174
-rw-r--r--src/net/messagein.h65
-rw-r--r--src/net/messageout.cpp103
-rw-r--r--src/net/messageout.h45
-rw-r--r--src/net/network.cpp447
-rw-r--r--src/net/network.h114
-rw-r--r--src/net/npchandler.cpp18
-rw-r--r--src/net/npchandler.h2
-rw-r--r--src/net/playerhandler.cpp197
-rw-r--r--src/net/playerhandler.h7
-rw-r--r--src/net/protocol.cpp79
-rw-r--r--src/net/protocol.h144
-rw-r--r--src/net/skillhandler.cpp34
-rw-r--r--src/net/skillhandler.h2
-rw-r--r--src/net/tradehandler.cpp29
-rw-r--r--src/net/tradehandler.h4
55 files changed, 2174 insertions, 1450 deletions
diff --git a/src/net/accountserver/account.cpp b/src/net/accountserver/account.cpp
new file mode 100644
index 00000000..385cd77a
--- /dev/null
+++ b/src/net/accountserver/account.cpp
@@ -0,0 +1,116 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "account.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+void Net::AccountServer::Account::createCharacter(
+ const std::string &name, char hairColor, char hairStyle, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short luck)
+{
+ MessageOut msg(PAMSG_CHAR_CREATE);
+
+ msg.writeString(name);
+ msg.writeByte(hairStyle);
+ msg.writeByte(hairColor);
+ msg.writeByte(gender);
+ msg.writeShort(strength);
+ msg.writeShort(agility);
+ msg.writeShort(vitality);
+ msg.writeShort(intelligence);
+ msg.writeShort(dexterity);
+ msg.writeShort(luck);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::deleteCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_DELETE);
+
+ msg.writeByte(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::selectCharacter(char slot)
+{
+ MessageOut msg(PAMSG_CHAR_SELECT);
+
+ msg.writeByte(slot);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::unregister()
+{
+ MessageOut msg(PAMSG_UNREGISTER);
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changeEmail(const std::string &email)
+{
+ MessageOut msg(PAMSG_EMAIL_CHANGE);
+
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::getEmail()
+{
+ MessageOut msg(PAMSG_EMAIL_GET);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::changePassword(
+ const std::string &oldPassword, const std::string &newPassword)
+{
+ MessageOut msg(PAMSG_PASSWORD_CHANGE);
+
+ msg.writeString(oldPassword);
+ msg.writeString(newPassword);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::enterWorld()
+{
+ MessageOut msg(PAMSG_ENTER_WORLD);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::Account::enterChat()
+{
+ MessageOut msg(PAMSG_ENTER_CHAT);
+
+ Net::AccountServer::connection->send(msg);
+}
diff --git a/src/net/accountserver/account.h b/src/net/accountserver/account.h
new file mode 100644
index 00000000..8e46eaa5
--- /dev/null
+++ b/src/net/accountserver/account.h
@@ -0,0 +1,60 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_ACCOUNTSERVER_CHARACTER_H
+#define _TMW_NET_ACCOUNTSERVER_CHARACTER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ namespace AccountServer
+ {
+ namespace Account
+ {
+ void createCharacter(const std::string &name,
+ char hairColor, char hairStyle, char gender,
+ short strength, short agility, short vitality,
+ short intelligence, short dexterity, short luck);
+
+ void deleteCharacter(char slot);
+
+ void selectCharacter(char slot);
+
+ void unregister();
+
+ void changeEmail(const std::string &email);
+
+ void getEmail();
+
+ void changePassword(const std::string &oldPassowrd,
+ const std::string &newPassword);
+
+ void enterWorld();
+
+ void enterChat();
+ }
+ }
+}
+
+#endif
diff --git a/src/net/accountserver/accountserver.cpp b/src/net/accountserver/accountserver.cpp
new file mode 100644
index 00000000..8fde6d5e
--- /dev/null
+++ b/src/net/accountserver/accountserver.cpp
@@ -0,0 +1,68 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "accountserver.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+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.writeLong(version);
+ msg.writeString(username);
+ msg.writeString(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.writeLong(version); // client version
+ msg.writeString(username);
+ msg.writeString(password);
+ msg.writeString(email);
+
+ Net::AccountServer::connection->send(msg);
+}
+
+void Net::AccountServer::logout()
+{
+ MessageOut msg(PAMSG_LOGOUT);
+ Net::AccountServer::connection->send(msg);
+
+ Net::AccountServer::connection = 0;
+}
diff --git a/src/net/accountserver/accountserver.h b/src/net/accountserver/accountserver.h
new file mode 100644
index 00000000..c05b5317
--- /dev/null
+++ b/src/net/accountserver/accountserver.h
@@ -0,0 +1,46 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_ACCOUNTSERVER_ACCOUNTSERVER_H
+#define _TMW_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();
+ }
+}
+
+#endif
diff --git a/src/net/accountserver/internal.cpp b/src/net/accountserver/internal.cpp
new file mode 100644
index 00000000..28a9695e
--- /dev/null
+++ b/src/net/accountserver/internal.cpp
@@ -0,0 +1,34 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace AccountServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/maploginhandler.h b/src/net/accountserver/internal.h
index fe597549..8af5ec04 100644
--- a/src/net/maploginhandler.h
+++ b/src/net/accountserver/internal.h
@@ -21,17 +21,17 @@
* $Id$
*/
-#ifndef _TMW_NET_MAPLOGINHANDLER_H
-#define _TMW_NET_MAPLOGINHANDLER_H
+#ifndef _TMW_NET_ACCOUNTSERVER_INTERNAL_H
+#define _TMW_NET_ACCOUNTSERVER_INTERNAL_H
-#include "messagehandler.h"
-
-class MapLoginHandler : public MessageHandler
+namespace Net
{
- public:
- MapLoginHandler();
+ class Connection;
- void handleMessage(MessageIn *msg);
-};
+ namespace AccountServer
+ {
+ extern Connection *connection;
+ }
+}
#endif
diff --git a/src/net/beinghandler.cpp b/src/net/beinghandler.cpp
index cd5653fc..2d68dd28 100644
--- a/src/net/beinghandler.cpp
+++ b/src/net/beinghandler.cpp
@@ -41,42 +41,60 @@ const int EMOTION_TIME = 150; /**< Duration of emotion icon */
BeingHandler::BeingHandler()
{
static const Uint16 _messages[] = {
- SMSG_BEING_VISIBLE,
- SMSG_BEING_MOVE,
- SMSG_BEING_REMOVE,
- SMSG_BEING_ACTION,
- SMSG_BEING_LEVELUP,
- SMSG_BEING_EMOTION,
- SMSG_BEING_CHANGE_LOOKS,
- SMSG_BEING_NAME_RESPONSE,
- SMSG_PLAYER_UPDATE_1,
- SMSG_PLAYER_UPDATE_2,
- SMSG_PLAYER_MOVE,
- 0x0119,
+ //SMSG_BEING_VISIBLE,
+ //SMSG_BEING_MOVE,
+ //SMSG_BEING_REMOVE,
+ //SMSG_BEING_ACTION,
+ //SMSG_BEING_LEVELUP,
+ //SMSG_BEING_EMOTION,
+ //SMSG_BEING_CHANGE_LOOKS,
+ //SMSG_BEING_NAME_RESPONSE,
+ //SMSG_PLAYER_UPDATE_1,
+ //SMSG_PLAYER_UPDATE_2,
+ //SMSG_PLAYER_MOVE,
+ //0x0119,
+ GPMSG_BEING_ENTER,
+ GPMSG_BEING_LEAVE,
+ GPMSG_BEINGS_MOVE,
0
};
handledMessages = _messages;
}
-void BeingHandler::handleMessage(MessageIn *msg)
+void BeingHandler::handleMessage(MessageIn &msg)
{
+ /*
Uint32 id;
Uint16 job, speed;
Sint16 param1;
Sint8 type;
Being *srcBeing, *dstBeing;
+ */
- switch (msg->getId())
+ 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 SMSG_BEING_VISIBLE:
case SMSG_BEING_MOVE:
// Information about a being in range
- id = msg->readInt32();
- speed = msg->readInt16();
- msg->readInt16(); // unknown
- msg->readInt16(); // unknown
- msg->readInt16(); // option
- job = msg->readInt16(); // class
+ id = msg.readLong();
+ speed = msg.readShort();
+ msg.readShort(); // unknown
+ msg.readShort(); // unknown
+ msg.readShort(); // option
+ job = msg.readShort(); // class
dstBeing = beingManager->findBeing(id);
@@ -91,7 +109,7 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing = beingManager->createBeing(id, job);
}
- else if (msg->getId() == 0x0078)
+ else if (msg.getId() == 0x0078)
{
dstBeing->clearPath();
dstBeing->mFrame = 0;
@@ -104,57 +122,56 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- dstBeing->setHairStyle(msg->readInt16());
- dstBeing->setWeapon(msg->readInt16());
- dstBeing->setVisibleEquipment(3, msg->readInt16()); // head bottom
+ dstBeing->setHairStyle(msg.readShort());
+ dstBeing->setWeapon(msg.readShort());
+ dstBeing->setVisibleEquipment(3, msg.readShort()); // head bottom
- if (msg->getId() == SMSG_BEING_MOVE)
+ if (msg.getId() == SMSG_BEING_MOVE)
{
- msg->readInt32(); // server tick
+ msg.readLong(); // server tick
}
- msg->readInt16(); // shield
- dstBeing->setVisibleEquipment(4, msg->readInt16()); // head top
- dstBeing->setVisibleEquipment(5, msg->readInt16()); // head mid
- dstBeing->setHairColor(msg->readInt16());
- msg->readInt16(); // unknown
- msg->readInt16(); // head dir
- msg->readInt16(); // guild
- msg->readInt16(); // unknown
- msg->readInt16(); // unknown
- msg->readInt16(); // manner
- msg->readInt16(); // karma
- msg->readInt8(); // unknown
- dstBeing->setSex(1 - msg->readInt8()); // sex
-
- if (msg->getId() == SMSG_BEING_MOVE)
+ msg.readShort(); // shield
+ dstBeing->setVisibleEquipment(4, msg.readShort()); // head top
+ dstBeing->setVisibleEquipment(5, msg.readShort()); // head mid
+ dstBeing->setHairColor(msg.readShort());
+ msg.readShort(); // unknown
+ msg.readShort(); // head dir
+ msg.readShort(); // guild
+ msg.readShort(); // unknown
+ msg.readShort(); // unknown
+ msg.readShort(); // manner
+ msg.readShort(); // karma
+ msg.readByte(); // unknown
+ dstBeing->setSex(1 - msg.readByte()); // sex
+
+ if (msg.getId() == SMSG_BEING_MOVE)
{
- Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->setAction(Being::STAND);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
- dstBeing->setDestination(dstX, dstY);
+ //Uint16 srcX, srcY, dstX, dstY;
+ //msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ //dstBeing->setAction(Being::STAND);
+ //dstBeing->mX = srcX;
+ //dstBeing->mY = srcY;
+ //dstBeing->setDestination(dstX, dstY);
}
else
{
- msg->readCoordinates(dstBeing->mX, dstBeing->mY,
- dstBeing->mDirection);
+ //msg.readCoordinates(dstBeing->mX, dstBeing->mY, dstBeing->mDirection);
}
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown / sit
+ msg.readByte(); // unknown
+ msg.readByte(); // unknown
+ msg.readByte(); // unknown / sit
break;
case SMSG_BEING_REMOVE:
// A being should be removed or has died
- dstBeing = beingManager->findBeing(msg->readInt32());
+ dstBeing = beingManager->findBeing(msg.readLong());
if (!dstBeing)
break;
- if (msg->readInt8() == 1)
+ if (msg.readByte() == 1)
{
// Death
switch (dstBeing->getType())
@@ -182,15 +199,15 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
case SMSG_BEING_ACTION:
- srcBeing = beingManager->findBeing(msg->readInt32());
- dstBeing = beingManager->findBeing(msg->readInt32());
- msg->readInt32(); // server tick
- msg->readInt32(); // src speed
- msg->readInt32(); // dst speed
- param1 = msg->readInt16();
- msg->readInt16(); // param 2
- type = msg->readInt8();
- msg->readInt16(); // param 3
+ srcBeing = beingManager->findBeing(msg.readLong());
+ dstBeing = beingManager->findBeing(msg.readLong());
+ msg.readLong(); // server tick
+ msg.readLong(); // src speed
+ msg.readLong(); // dst speed
+ param1 = msg.readShort();
+ msg.readShort(); // param 2
+ type = msg.readByte();
+ msg.readShort(); // param 3
switch (type)
{
@@ -231,63 +248,63 @@ void BeingHandler::handleMessage(MessageIn *msg)
break;
case SMSG_BEING_LEVELUP:
- if ((Uint32)msg->readInt32() == player_node->getId()) {
+ if ((Uint32) msg.readLong() == player_node->getId()) {
logger->log("Level up");
sound.playSfx("sfx/levelup.ogg");
} else {
logger->log("Someone else went level up");
}
- msg->readInt32(); // type
+ msg.readLong(); // type
break;
case SMSG_BEING_EMOTION:
- if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ if (!(dstBeing = beingManager->findBeing(msg.readLong())))
{
break;
}
- dstBeing->mEmotion = msg->readInt8();
+ dstBeing->mEmotion = msg.readByte();
dstBeing->mEmotionTime = EMOTION_TIME;
break;
case SMSG_BEING_CHANGE_LOOKS:
{
- if (!(dstBeing = beingManager->findBeing(msg->readInt32())))
+ if (!(dstBeing = beingManager->findBeing(msg.readLong())))
{
break;
}
-
- int type = msg->readInt8();
+
+ int type = msg.readByte();
switch (type) {
case 1:
- dstBeing->setHairStyle(msg->readInt8());
+ dstBeing->setHairStyle(msg.readByte());
break;
case 2:
- dstBeing->setWeapon(msg->readInt8());
+ dstBeing->setWeapon(msg.readByte());
break;
case 3:
case 4:
case 5:
// Equip/unequip head 3. Bottom 4. Top 5. Middle
- dstBeing->setVisibleEquipment(type, msg->readInt8());
+ dstBeing->setVisibleEquipment(type, msg.readByte());
// First 3 slots of mVisibleEquipments are reserved for
// later use, probably accessories.
break;
case 6:
- dstBeing->setHairColor(msg->readInt8());
+ dstBeing->setHairColor(msg.readByte());
break;
default:
- printf("c3: %i\n", msg->readInt8()); // unsupported
+ printf("c3: %i\n", msg.readByte()); // unsupported
break;
}
}
break;
case SMSG_BEING_NAME_RESPONSE:
- if ((dstBeing = beingManager->findBeing(msg->readInt32())))
+ if ((dstBeing = beingManager->findBeing(msg.readLong())))
{
- dstBeing->setName(msg->readString(24));
+ dstBeing->setName(msg.readString(24));
}
break;
@@ -295,12 +312,12 @@ void BeingHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_UPDATE_2:
case SMSG_PLAYER_MOVE:
// An update about a player, potentially including movement.
- id = msg->readInt32();
- speed = msg->readInt16();
- msg->readInt16(); // option 1
- msg->readInt16(); // option 2
- msg->readInt16(); // option
- job = msg->readInt16();
+ id = msg.readLong();
+ speed = msg.readShort();
+ msg.readShort(); // option 1
+ msg.readShort(); // option 2
+ msg.readShort(); // option
+ job = msg.readShort();
dstBeing = beingManager->findBeing(id);
@@ -311,58 +328,57 @@ void BeingHandler::handleMessage(MessageIn *msg)
dstBeing->setWalkSpeed(speed);
dstBeing->mJob = job;
- dstBeing->setHairStyle(msg->readInt16());
- dstBeing->setWeaponById(msg->readInt16()); // item id 1
- msg->readInt16(); // item id 2
- dstBeing->setVisibleEquipment(3, msg->readInt16()); // head bottom
+ dstBeing->setHairStyle(msg.readShort());
+ dstBeing->setWeaponById(msg.readShort()); // item id 1
+ msg.readShort(); // item id 2
+ dstBeing->setVisibleEquipment(3, msg.readShort()); // head bottom
- if (msg->getId() == SMSG_PLAYER_MOVE)
+ if (msg.getId() == SMSG_PLAYER_MOVE)
{
- msg->readInt32(); // server tick
+ msg.readLong(); // server tick
}
- dstBeing->setVisibleEquipment(4, msg->readInt16()); // head top
- dstBeing->setVisibleEquipment(5, msg->readInt16()); // head mid
- dstBeing->setHairColor(msg->readInt16());
- msg->readInt16(); // unknown
- msg->readInt16(); // head dir
- msg->readInt32(); // guild
- msg->readInt32(); // emblem
- msg->readInt16(); // manner
- msg->readInt8(); // karma
- dstBeing->setSex(1 - msg->readInt8()); // sex
-
- if (msg->getId() == SMSG_PLAYER_MOVE)
+ dstBeing->setVisibleEquipment(4, msg.readShort()); // head top
+ dstBeing->setVisibleEquipment(5, msg.readShort()); // head mid
+ dstBeing->setHairColor(msg.readShort());
+ msg.readShort(); // unknown
+ msg.readShort(); // head dir
+ msg.readLong(); // guild
+ msg.readLong(); // emblem
+ msg.readShort(); // manner
+ msg.readByte(); // karma
+ dstBeing->setSex(1 - msg.readByte()); // sex
+
+ if (msg.getId() == SMSG_PLAYER_MOVE)
{
- Uint16 srcX, srcY, dstX, dstY;
- msg->readCoordinatePair(srcX, srcY, dstX, dstY);
- dstBeing->mX = srcX;
- dstBeing->mY = srcY;
- dstBeing->setDestination(dstX, dstY);
+ //Uint16 srcX, srcY, dstX, dstY;
+ //msg.readCoordinatePair(srcX, srcY, dstX, dstY);
+ //dstBeing->mX = srcX;
+ //dstBeing->mY = srcY;
+ //dstBeing->setDestination(dstX, dstY);
}
else
{
- msg->readCoordinates(dstBeing->mX, dstBeing->mY,
- dstBeing->mDirection);
+ //msg.readCoordinates(dstBeing->mX, dstBeing->mY, dstBeing->mDirection);
}
- msg->readInt8(); // unknown
- msg->readInt8(); // unknown
+ msg.readByte(); // unknown
+ msg.readByte(); // unknown
- if (msg->getId() == SMSG_PLAYER_UPDATE_1)
+ if (msg.getId() == SMSG_PLAYER_UPDATE_1)
{
- if (msg->readInt8() == 2)
+ if (msg.readByte() == 2)
{
dstBeing->setAction(Being::SIT);
}
}
- else if (msg->getId() == SMSG_PLAYER_MOVE)
+ else if (msg.getId() == SMSG_PLAYER_MOVE)
{
- msg->readInt8(); // unknown
+ msg.readByte(); // unknown
}
- msg->readInt8(); // Lv
- msg->readInt8(); // unknown
+ msg.readByte(); // Lv
+ msg.readByte(); // unknown
dstBeing->mWalkTime = tick_time;
dstBeing->mFrame = 0;
@@ -370,9 +386,107 @@ void BeingHandler::handleMessage(MessageIn *msg)
case 0x0119:
// Change in players look
- printf("0x0119 %i %i %i %x %i\n", msg->readInt32(),
- msg->readInt16(), msg->readInt16(), msg->readInt16(),
- msg->readInt8());
+ printf("0x0119 %li %i %i %x %i\n", msg.readLong(),
+ msg.readShort(), msg.readShort(), msg.readShort(),
+ msg.readByte());
break;
+ */
+ }
+}
+
+void
+BeingHandler::handleBeingEnterMessage(MessageIn &msg)
+{
+ int type = msg.readByte(); // type
+ int id = msg.readShort();
+
+ switch (type) {
+ case OBJECT_PLAYER:
+ {
+ std::string name = msg.readString();
+ Being *being;
+ if (player_node->getName() == name)
+ {
+ being = player_node;
+ being->setId(id);
+ }
+ else
+ {
+ being = beingManager->createBeing(id, 0);
+ being->setName(name);
+ }
+ being->setHairStyle(msg.readByte());
+ being->setHairColor(msg.readByte());
+ being->setSex(msg.readByte());
+ } break;
+ case OBJECT_MONSTER:
+ {
+ int monsterId = msg.readShort();
+ Being *being;
+ being = beingManager->createBeing(id, 1002 + monsterId);
+ being->setWalkSpeed(150); // TODO
+ } break;
+ }
+}
+
+void BeingHandler::handleBeingLeaveMessage(MessageIn &msg)
+{
+ Being *being = beingManager->findBeing(msg.readShort());
+ if (!being) return;
+ if (being == player_node->getTarget())
+ {
+ player_node->stopAttack();
+ }
+ beingManager->destroyBeing(being);
+}
+
+void BeingHandler::handleBeingsMoveMessage(MessageIn &msg)
+{
+ while (msg.getUnreadLength())
+ {
+ Uint16 id = msg.readShort();
+ Uint8 flags = msg.readByte();
+ Being *being = beingManager->findBeing(id);
+ int sx = 0, sy = 0, dx = 0, dy = 0;
+ if (flags & MOVING_POSITION)
+ {
+ Uint16 sx2, sy2;
+ msg.readCoordinates(sx2, sy2);
+ sx = sx2 * 32 + 16;
+ sy = sy2 * 32 + 16;
+ }
+ if (flags & MOVING_DESTINATION)
+ {
+ dx = msg.readShort();
+ dy = msg.readShort();
+ if (!(flags & MOVING_POSITION))
+ {
+ sx = dx;
+ sy = dy;
+ }
+ }
+ if (!being || !(flags & (MOVING_POSITION | MOVING_DESTINATION)))
+ {
+ continue;
+ }
+ if (abs(being->mX - sx) + abs(being->mY - sy) > 4 * 32)
+ {
+ // Too large a desynchronization.
+ being->mX = sx;
+ being->mY = sy;
+ being->setDestination(dx, dy);
+ }
+ else if (!(flags & MOVING_POSITION))
+ {
+ being->setDestination(dx, dy);
+ }
+ else if (!(flags & MOVING_DESTINATION))
+ {
+ being->adjustCourse(sx, sy);
+ }
+ else
+ {
+ being->adjustCourse(sx, sy, dx, dy);
+ }
}
}
diff --git a/src/net/beinghandler.h b/src/net/beinghandler.h
index 03012f39..59539ffe 100644
--- a/src/net/beinghandler.h
+++ b/src/net/beinghandler.h
@@ -31,7 +31,12 @@ class BeingHandler : public MessageHandler
public:
BeingHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
+
+ private:
+ void handleBeingEnterMessage(MessageIn &msg);
+ void handleBeingLeaveMessage(MessageIn &msg);
+ void handleBeingsMoveMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/buysellhandler.cpp b/src/net/buysellhandler.cpp
index d7f063a7..173c59d2 100644
--- a/src/net/buysellhandler.cpp
+++ b/src/net/buysellhandler.cpp
@@ -54,10 +54,10 @@ BuySellHandler::BuySellHandler()
handledMessages = _messages;
}
-void BuySellHandler::handleMessage(MessageIn *msg)
+void BuySellHandler::handleMessage(MessageIn &msg)
{
int n_items;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_NPC_BUY_SELL_CHOICE:
buyDialog->setVisible(false);
@@ -65,39 +65,38 @@ void BuySellHandler::handleMessage(MessageIn *msg)
sellDialog->setVisible(false);
sellDialog->reset();
buySellDialog->setVisible(true);
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg->readInt32()));
+ current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg.readLong()));
break;
case SMSG_NPC_BUY:
- msg->readInt16(); // length
- n_items = (msg->getLength() - 4) / 11;
+ msg.readShort(); // length
+ n_items = (msg.getLength() - 4) / 11;
buyDialog->reset();
- buyDialog->setMoney(player_node->mGp);
+ buyDialog->setMoney(player_node->mMoney);
buyDialog->setVisible(true);
for (int k = 0; k < n_items; k++)
{
- Sint32 value = msg->readInt32();
- msg->readInt32(); // DCvalue
- msg->readInt8(); // type
- Sint16 itemId = msg->readInt16();
+ Sint32 value = msg.readLong();
+ msg.readLong(); // DCvalue
+ msg.readByte(); // type
+ Sint16 itemId = msg.readShort();
buyDialog->addItem(itemId, value);
}
break;
case SMSG_NPC_SELL:
- msg->readInt16(); // length
- n_items = (msg->getLength() - 4) / 10;
+ msg.readShort(); // length
+ n_items = (msg.getLength() - 4) / 10;
if (n_items > 0) {
- sellDialog->setMoney(player_node->mGp);
sellDialog->reset();
sellDialog->setVisible(true);
for (int k = 0; k < n_items; k++)
{
- Sint16 index = msg->readInt16();
- Sint32 value = msg->readInt32();
- msg->readInt32(); // OCvalue
+ Sint16 index = msg.readShort();
+ Sint32 value = msg.readLong();
+ msg.readLong(); // OCvalue
Item *item = player_node->getInvItem(index);
if (item && !(item->isEquipped())) {
@@ -112,7 +111,7 @@ void BuySellHandler::handleMessage(MessageIn *msg)
break;
case SMSG_NPC_BUY_RESPONSE:
- if (msg->readInt8() == 0) {
+ if (msg.readByte() == 0) {
chatWindow->chatLog("Thanks for buying", BY_SERVER);
} else {
chatWindow->chatLog("Unable to buy", BY_SERVER);
@@ -120,7 +119,7 @@ void BuySellHandler::handleMessage(MessageIn *msg)
break;
case SMSG_NPC_SELL_RESPONSE:
- if (msg->readInt8() == 0) {
+ if (msg.readByte() == 0) {
chatWindow->chatLog("Thanks for selling", BY_SERVER);
} else {
chatWindow->chatLog("Unable to sell", BY_SERVER);
diff --git a/src/net/buysellhandler.h b/src/net/buysellhandler.h
index 673aaac1..e242d373 100644
--- a/src/net/buysellhandler.h
+++ b/src/net/buysellhandler.h
@@ -31,7 +31,7 @@ class BuySellHandler : public MessageHandler
public:
BuySellHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index 06ec78c1..f715b434 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -23,9 +23,9 @@
#include "charserverhandler.h"
-#include "messagein.h"
-#include "network.h"
+#include "connection.h"
#include "protocol.h"
+#include "messagein.h"
#include "../game.h"
#include "../localplayer.h"
@@ -35,66 +35,67 @@
#include "../gui/ok_dialog.h"
+extern Net::Connection *gameServerConnection;
+extern Net::Connection *chatServerConnection;
+
CharServerHandler::CharServerHandler()
{
static const Uint16 _messages[] = {
- 0x006b,
- 0x006c,
- 0x006d,
- 0x006e,
- 0x006f,
- 0x0070,
- 0x0071,
- 0x0081,
+ APMSG_CHAR_CREATE_RESPONSE,
+ APMSG_CHAR_DELETE_RESPONSE,
+ APMSG_CHAR_INFO,
+ APMSG_CHAR_SELECT_RESPONSE,
0
};
handledMessages = _messages;
}
-void CharServerHandler::handleMessage(MessageIn *msg)
+void
+CharServerHandler::handleMessage(MessageIn &msg)
{
int slot;
LocalPlayer *tempPlayer;
- logger->log("CharServerHandler: Packet ID: %x, Length: %d",
- msg->getId(), msg->getLength());
- switch (msg->getId())
+ switch (msg.getId())
{
- case 0x006b:
- // Skip length word and an additional mysterious 20 bytes
- msg->skip(2 + 20);
-
- // Derive number of characters from message length
- n_character = (msg->getLength() - 24) / 106;
+ case APMSG_CHAR_CREATE_RESPONSE:
+ handleCharCreateResponse(msg);
+ break;
- for (int i = 0; i < n_character; i++)
+ case APMSG_CHAR_DELETE_RESPONSE:
+ {
+ int errMsg = msg.readByte();
+ // Character deletion successful
+ if (errMsg == ERRMSG_OK)
{
- tempPlayer = readPlayerData(msg, slot);
- mCharInfo->select(slot);
- mCharInfo->setEntry(tempPlayer);
- logger->log("CharServer: Player: %s (%d)",
- tempPlayer->getName().c_str(), slot);
+ delete mCharInfo->getEntry();
+ mCharInfo->setEntry(0);
+ mCharInfo->unlock();
+ n_character--;
+ new OkDialog("Info", "Player deleted");
}
-
- state = CHAR_SELECT_STATE;
- break;
-
- case 0x006c:
- switch (msg->readInt8()) {
- case 0:
- errorMessage = "Access denied";
- break;
- case 1:
- errorMessage = "Cannot use this ID";
- break;
- default:
- errorMessage = "Unknown failure to select character";
- break;
+ // Character deletion failed
+ else
+ {
+ std::string message = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ message = "Not logged in";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ message = "Selection out of range";
+ break;
+ default:
+ message = "Unknown error";
+ }
+ mCharInfo->unlock();
+ new OkDialog("Error", message);
}
- mCharInfo->unlock();
+ }
break;
- case 0x006d:
+ case APMSG_CHAR_INFO:
tempPlayer = readPlayerData(msg, slot);
mCharInfo->unlock();
mCharInfo->select(slot);
@@ -102,107 +103,111 @@ void CharServerHandler::handleMessage(MessageIn *msg)
n_character++;
break;
- case 0x006e:
- new OkDialog("Error", "Failed to create character");
- break;
-
- case 0x006f:
- delete mCharInfo->getEntry();
- mCharInfo->setEntry(0);
- mCharInfo->unlock();
- n_character--;
- new OkDialog("Info", "Player deleted");
+ case APMSG_CHAR_SELECT_RESPONSE:
+ handleCharSelectResponse(msg);
break;
+ }
+}
- case 0x0070:
- mCharInfo->unlock();
- new OkDialog("Error", "Failed to delete character.");
- break;
+void
+CharServerHandler::handleCharCreateResponse(MessageIn &msg)
+{
+ int errMsg = msg.readByte();
- case 0x0071:
- player_node = mCharInfo->getEntry();
- msg->skip(4); // CharID, must be the same as player_node->charID
- map_path = msg->readString(16);
- mLoginData->hostname = iptostring(msg->readInt32());
- mLoginData->port = msg->readInt16();
- mCharInfo->unlock();
- mCharInfo->select(0);
- // Clear unselected players infos
- do
- {
- LocalPlayer *tmp = mCharInfo->getEntry();
- if (tmp != player_node)
- delete tmp;
- mCharInfo->next();
- } while (mCharInfo->getPos());
+ // Character creation failed
+ if (errMsg != ERRMSG_OK)
+ {
+ std::string message = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ message = "Not logged in";
+ break;
+ case CREATE_TOO_MUCH_CHARACTERS:
+ message = "No empty slot";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ message = "Invalid name";
+ break;
+ case CREATE_EXISTS_NAME:
+ message = "Character's name already exists";
+ break;
+ case CREATE_INVALID_HAIRSTYLE:
+ message = "Invalid hairstyle";
+ break;
+ case CREATE_INVALID_HAIRCOLOR:
+ message = "Invalid hair color";
+ break;
+ case CREATE_INVALID_GENDER:
+ message = "Invalid gender";
+ break;
+ case CREATE_RAW_STATS_TOO_HIGH:
+ message = "Character's stats are too high";
+ break;
+ case CREATE_RAW_STATS_TOO_LOW:
+ message = "Character's stats are too low";
+ break;
+ case CREATE_RAW_STATS_INVALID_DIFF:
+ message = "Character's stats difference is too high";
+ break;
+ case CREATE_RAW_STATS_EQUAL_TO_ZERO:
+ message = "One stat is zero";
+ break;
+ default:
+ message = "Unknown error";
+ break;
+ }
+ new OkDialog("Error", message);
+ }
+}
- state = CONNECTING_STATE;
- break;
+void
+CharServerHandler::handleCharSelectResponse(MessageIn &msg)
+{
+ int errMsg = msg.readByte();
- case 0x0081:
- switch (msg->readInt8()) {
- case 1:
- errorMessage = "Map server offline";
- break;
- case 3:
- errorMessage = "Speed hack detected";
- break;
- case 8:
- errorMessage = "Duplicated login";
- break;
- default:
- errorMessage = "Unkown error with 0x0081";
- break;
- }
- mCharInfo->unlock();
- state = ERROR_STATE;
- break;
+ if (errMsg == ERRMSG_OK)
+ {
+ token = msg.readString(32);
+ std::string gameServer = msg.readString();
+ unsigned short gameServerPort = msg.readShort();
+ std::string chatServer = msg.readString();
+ unsigned short chatServerPort = msg.readShort();
+
+ logger->log("Game server: %s:%d", gameServer.c_str(), gameServerPort);
+ logger->log("Chat server: %s:%d", chatServer.c_str(), chatServerPort);
+
+ gameServerConnection->connect(gameServer, gameServerPort);
+ chatServerConnection->connect(chatServer, chatServerPort);
+
+ // Keep the selected character and delete the others
+ player_node = mCharInfo->getEntry();
+ mCharInfo->unlock();
+ mCharInfo->select(0);
+ do {
+ LocalPlayer *tmp = mCharInfo->getEntry();
+ if (tmp != player_node)
+ delete tmp;
+ mCharInfo->next();
+ } while (mCharInfo->getPos());
+
+ state = STATE_CONNECT_GAME;
}
}
-LocalPlayer* CharServerHandler::readPlayerData(MessageIn *msg, int &slot)
+LocalPlayer*
+CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
{
- LocalPlayer *tempPlayer = new LocalPlayer(mLoginData->account_ID, 0, NULL);
- tempPlayer->setSex(1 - mLoginData->sex);
-
- tempPlayer->mCharId = msg->readInt32();
- tempPlayer->mTotalWeight = 0;
- tempPlayer->mMaxWeight = 0;
- tempPlayer->mLastAttackTime = 0;
- tempPlayer->mXp = msg->readInt32();
- tempPlayer->mGp = msg->readInt32();
- tempPlayer->mJobXp = msg->readInt32();
- tempPlayer->mJobLevel = msg->readInt32();
- msg->skip(8); // unknown
- msg->readInt32(); // option
- msg->readInt32(); // karma
- msg->readInt32(); // manner
- msg->skip(2); // unknown
- tempPlayer->mHp = msg->readInt16();
- tempPlayer->mMaxHp = msg->readInt16();
- tempPlayer->mMp = msg->readInt16();
- tempPlayer->mMaxMp = msg->readInt16();
- msg->readInt16(); // speed
- msg->readInt16(); // class
- tempPlayer->setHairStyle(msg->readInt16());
- Uint16 weapon = msg->readInt16();
- if (weapon == 11)
- weapon = 2;
- tempPlayer->setWeapon(weapon);
- tempPlayer->mLevel = msg->readInt16();
- msg->readInt16(); // skill point
- tempPlayer->setVisibleEquipment(3, msg->readInt16()); // head bottom
- msg->readInt16(); // shield
- tempPlayer->setVisibleEquipment(4, msg->readInt16()); // head option top
- tempPlayer->setVisibleEquipment(5, msg->readInt16()); // head option mid
- tempPlayer->setHairColor(msg->readInt16());
- msg->readInt16(); // unknown
- tempPlayer->setName(msg->readString(24));
+ LocalPlayer *tempPlayer = new LocalPlayer;
+ slot = msg.readByte(); // character slot
+ tempPlayer->mName = msg.readString();
+ tempPlayer->setSex(msg.readByte());
+ tempPlayer->setHairStyle(msg.readByte());
+ tempPlayer->setHairColor(msg.readByte());
+ tempPlayer->mLevel = msg.readByte();
+ tempPlayer->mMoney = msg.readShort();
for (int i = 0; i < 6; i++) {
- tempPlayer->mAttr[i] = msg->readInt8();
+ tempPlayer->mAttr[i] = msg.readByte();
}
- slot = msg->readInt8(); // character slot
- msg->readInt8(); // unknown
-
return tempPlayer;
}
diff --git a/src/net/charserverhandler.h b/src/net/charserverhandler.h
index 16d2c361..342641d7 100644
--- a/src/net/charserverhandler.h
+++ b/src/net/charserverhandler.h
@@ -36,17 +36,26 @@ class CharServerHandler : public MessageHandler
public:
CharServerHandler();
- void handleMessage(MessageIn *msg);
+ void
+ handleMessage(MessageIn &msg);
- void setCharInfo(LockedArray<LocalPlayer*> *charInfo) { mCharInfo = charInfo; };
-
- void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+ void
+ setCharInfo(LockedArray<LocalPlayer*> *charInfo)
+ {
+ mCharInfo = charInfo;
+ }
protected:
- LoginData *mLoginData;
+ void
+ handleCharCreateResponse(MessageIn &msg);
+
+ void
+ handleCharSelectResponse(MessageIn &msg);
+
LockedArray<LocalPlayer*> *mCharInfo;
- LocalPlayer* readPlayerData(MessageIn *msg, int &slot);
+ LocalPlayer*
+ readPlayerData(MessageIn &msg, int &slot);
};
#endif
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
index 9095a4e1..f765f0f4 100644
--- a/src/net/chathandler.cpp
+++ b/src/net/chathandler.cpp
@@ -42,35 +42,53 @@ extern Being *player_node;
ChatHandler::ChatHandler()
{
static const Uint16 _messages[] = {
+ GPMSG_SAY,
+ /*
SMSG_BEING_CHAT,
SMSG_PLAYER_CHAT,
SMSG_GM_CHAT,
SMSG_WHO_ANSWER,
0x10c, // MVP
+ */
0
};
handledMessages = _messages;
}
-void ChatHandler::handleMessage(MessageIn *msg)
+void ChatHandler::handleMessage(MessageIn &msg)
{
Being *being;
std::string chatMsg;
- Sint16 chatMsgLength;
+ //Sint16 chatMsgLength;
- switch (msg->getId())
+ switch (msg.getId())
{
+ case GPMSG_SAY:
+ being = beingManager->findBeing(msg.readShort());
+ chatMsg = msg.readString();
+ if (being)
+ {
+ chatWindow->chatLog(being->getName() + " : " + chatMsg, being == player_node ? BY_PLAYER : BY_OTHER);
+ being->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ chatWindow->chatLog("John Doe : " + chatMsg, BY_OTHER);
+ }
+ break;
+
+ /*
// Received speech from being
case SMSG_BEING_CHAT:
- chatMsgLength = msg->readInt16() - 8;
- being = beingManager->findBeing(msg->readInt32());
+ chatMsgLength = msg.readShort() - 8;
+ being = beingManager->findBeing(msg.readLong());
if (!being || chatMsgLength <= 0)
{
break;
}
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
chatWindow->chatLog(chatMsg, BY_OTHER);
chatMsg.erase(0, chatMsg.find(" : ", 0) + 3);
being->setSpeech(chatMsg, SPEECH_TIME);
@@ -78,16 +96,16 @@ void ChatHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_CHAT:
case SMSG_GM_CHAT:
- chatMsgLength = msg->readInt16() - 4;
+ chatMsgLength = msg.readShort() - 4;
if (chatMsgLength <= 0)
{
break;
}
- chatMsg = msg->readString(chatMsgLength);
+ chatMsg = msg.readString(chatMsgLength);
- if (msg->getId() == SMSG_PLAYER_CHAT)
+ if (msg.getId() == SMSG_PLAYER_CHAT)
{
chatWindow->chatLog(chatMsg, BY_PLAYER);
@@ -105,14 +123,15 @@ void ChatHandler::handleMessage(MessageIn *msg)
break;
case SMSG_WHO_ANSWER:
- chatWindow->chatLog("Online users: " + toString(msg->readInt32()),
+ chatWindow->chatLog("Online users: " + toString(msg.readLong()),
BY_SERVER);
break;
case 0x010c:
// Display MVP player
- msg->readInt32(); // id
+ msg.readLong(); // id
chatWindow->chatLog("MVP player", BY_SERVER);
break;
+ */
}
}
diff --git a/src/net/chathandler.h b/src/net/chathandler.h
index eed19206..e9db3575 100644
--- a/src/net/chathandler.h
+++ b/src/net/chathandler.h
@@ -31,7 +31,7 @@ class ChatHandler : public MessageHandler
public:
ChatHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/chatserver/chatserver.cpp b/src/net/chatserver/chatserver.cpp
new file mode 100644
index 00000000..e6a3331d
--- /dev/null
+++ b/src/net/chatserver/chatserver.cpp
@@ -0,0 +1,116 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "chatserver.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.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::chat(short channel, const std::string &text)
+{
+ MessageOut msg(PCMSG_CHAT);
+
+ msg.writeString(text);
+ msg.writeShort(channel);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::announce(const std::string &text)
+{
+ MessageOut msg(PCMSG_ANNOUNCE);
+
+ msg.writeString(text);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::privMsg(const std::string &recipient,
+ const std::string &text)
+{
+ MessageOut msg(PCMSG_PRIVMSG);
+
+ msg.writeString(recipient);
+ msg.writeString(text);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::registerChannel(const std::string &name,
+ const std::string &annoucement, const std::string &password,
+ char isPrivate)
+{
+ MessageOut msg(PCMSG_REGISTER_CHANNEL);
+
+ msg.writeByte(isPrivate);
+ msg.writeString(name);
+ msg.writeString(annoucement);
+ msg.writeString(password);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::unregisterChannel(short channel)
+{
+ MessageOut msg(PCMSG_UNREGISTER_CHANNEL);
+
+ msg.writeShort(channel);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::enterChannel(short channel, const std::string &password)
+{
+ MessageOut msg(PCMSG_ENTER_CHANNEL);
+
+ msg.writeShort(channel);
+ msg.writeString(password);
+
+ connection->send(msg);
+}
+
+void Net::ChatServer::quitChannel(short channel)
+{
+ MessageOut msg(PCMSG_QUIT_CHANNEL);
+
+ msg.writeShort(channel);
+
+ connection->send(msg);
+}
diff --git a/src/net/chatserver/chatserver.h b/src/net/chatserver/chatserver.h
new file mode 100644
index 00000000..93fe17c4
--- /dev/null
+++ b/src/net/chatserver/chatserver.h
@@ -0,0 +1,55 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_CHATSERVER_CHATSERVER_H
+#define _TMW_NET_CHATSERVER_CHATSERVER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+
+ void chat(short channel, const std::string &text);
+
+ void announce(const std::string &text);
+
+ void privMsg(const std::string &recipient, const std::string &text);
+
+ void registerChannel(const std::string &name,
+ const std::string &announcement, const std::string &password,
+ char isPrivate);
+
+ void unregisterChannel(short channel);
+
+ void enterChannel(short channel, const std::string &password);
+
+ void quitChannel(short channel);
+ }
+}
+
+#endif
diff --git a/src/net/chatserver/internal.cpp b/src/net/chatserver/internal.cpp
new file mode 100644
index 00000000..c1f7a3f7
--- /dev/null
+++ b/src/net/chatserver/internal.cpp
@@ -0,0 +1,34 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace ChatServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/packet.cpp b/src/net/chatserver/internal.h
index e77ac117..7579972b 100644
--- a/src/net/packet.cpp
+++ b/src/net/chatserver/internal.h
@@ -21,20 +21,17 @@
* $Id$
*/
-#include "packet.h"
+#ifndef _TMW_NET_CHATSERVER_INTERNAL_H
+#define _TMW_NET_CHATSERVER_INTERNAL_H
-#include <cstring>
-
-Packet::Packet(const char *data, int length):
- mLength(length)
+namespace Net
{
- // Create a copy of the data
- mData = new char[mLength];
- memcpy(mData, data, mLength);
-}
+ class Connection;
-Packet::~Packet()
-{
- // Clean up the data
- delete[] mData;
+ namespace ChatServer
+ {
+ extern Connection *connection;
+ }
}
+
+#endif
diff --git a/src/net/connection.cpp b/src/net/connection.cpp
new file mode 100644
index 00000000..a17bc727
--- /dev/null
+++ b/src/net/connection.cpp
@@ -0,0 +1,104 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "connection.h"
+
+#include <string>
+
+#include "internal.h"
+#include "messageout.h"
+
+#include "../log.h"
+
+Net::Connection::Connection(ENetHost *client):
+ mConnection(0), mClient(client)
+{
+ 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 = 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 = ERROR;
+ return false;
+ }
+
+ 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;
+}
+
+void Net::Connection::send(const MessageOut &msg)
+{
+ if (!isConnected())
+ {
+ logger->log("Warning: cannot send message to not connected server!");
+ return;
+ }
+
+ logger->log("Sending message of size %d...", msg.getDataSize());
+
+ ENetPacket *packet = enet_packet_create(msg.getData(),
+ msg.getDataSize(),
+ ENET_PACKET_FLAG_RELIABLE);
+ enet_peer_send(mConnection, 0, packet);
+}
diff --git a/src/net/connection.h b/src/net/connection.h
new file mode 100644
index 00000000..179367c6
--- /dev/null
+++ b/src/net/connection.h
@@ -0,0 +1,78 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_CONNECTION_H
+#define _TMW_NET_CONNECTION_H
+
+#include <iosfwd>
+
+#include <enet/enet.h>
+
+class MessageOut;
+
+namespace Net
+{
+ class Connection
+ {
+ public:
+ enum State {
+ OK, 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);
+
+ ENetPeer *mConnection;
+ ENetHost *mClient;
+ State mState;
+ };
+}
+
+#endif
diff --git a/src/net/equipmenthandler.cpp b/src/net/equipmenthandler.cpp
index 01760eeb..1c0fd4ca 100644
--- a/src/net/equipmenthandler.cpp
+++ b/src/net/equipmenthandler.cpp
@@ -48,7 +48,7 @@ EquipmentHandler::EquipmentHandler()
handledMessages = _messages;
}
-void EquipmentHandler::handleMessage(MessageIn *msg)
+void EquipmentHandler::handleMessage(MessageIn &msg)
{
Sint32 itemCount;
Sint16 index, equipPoint, itemId;
@@ -57,23 +57,22 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
Being *being;
Item *item;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_EQUIPMENT:
- msg->readInt16(); // length
- itemCount = (msg->getLength() - 4) / 20;
+ msg.readShort(); // length
+ itemCount = (msg.getLength() - 4) / 20;
for (int loop = 0; loop < itemCount; loop++)
{
- index = msg->readInt16();
- itemId = msg->readInt16();
- msg->readInt8(); // type
- msg->readInt8(); // identify flag
- msg->readInt16(); // equip type
- equipPoint = msg->readInt16();
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card
+ index = msg.readShort();
+ itemId = msg.readShort();
+ msg.readByte(); // type
+ msg.readByte(); // identify flag
+ msg.readShort(); // equip type
+ equipPoint = msg.readShort();
+ msg.readByte(); // attribute
+ msg.readByte(); // refine
player_node->addInvItem(index, itemId, 1, true);
@@ -93,9 +92,9 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_EQUIP:
- index = msg->readInt16();
- equipPoint = msg->readInt16();
- type = msg->readInt8();
+ index = msg.readShort();
+ equipPoint = msg.readShort();
+ type = msg.readByte();
logger->log("Equipping: %i %i %i", index, equipPoint, type);
@@ -129,10 +128,10 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
case 0x01d7:
// Equipment related
- being = beingManager->findBeing(msg->readInt32());
- msg->readInt8(); // equip point
- itemId = msg->readInt16();
- msg->readInt16(); // item id 2
+ being = beingManager->findBeing(msg.readLong());
+ msg.readByte(); // equip point
+ itemId = msg.readShort();
+ msg.readShort(); // item id 2
if (!being)
break;
@@ -141,9 +140,9 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_UNEQUIP:
- index = msg->readInt16();
- equipPoint = msg->readInt16();
- type = msg->readInt8();
+ index = msg.readShort();
+ equipPoint = msg.readShort();
+ type = msg.readByte();
if (!type) {
chatWindow->chatLog("Unable to unequip.", BY_SERVER);
@@ -193,7 +192,7 @@ void EquipmentHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_ARROW_EQUIP:
- itemId = msg->readInt16();
+ itemId = msg.readShort();
if (itemId <= 1)
break;
diff --git a/src/net/equipmenthandler.h b/src/net/equipmenthandler.h
index 656f7a73..c9c65d67 100644
--- a/src/net/equipmenthandler.h
+++ b/src/net/equipmenthandler.h
@@ -31,7 +31,7 @@ class EquipmentHandler : public MessageHandler
public:
EquipmentHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/gameserver/gameserver.cpp b/src/net/gameserver/gameserver.cpp
new file mode 100644
index 00000000..04e5bb08
--- /dev/null
+++ b/src/net/gameserver/gameserver.cpp
@@ -0,0 +1,42 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "gameserver.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.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);
+}
diff --git a/src/net/packet.h b/src/net/gameserver/gameserver.h
index 84d16d5e..ee49d7e3 100644
--- a/src/net/packet.h
+++ b/src/net/gameserver/gameserver.h
@@ -21,27 +21,19 @@
* $Id$
*/
-#ifndef _TMW_PACKET_
-#define _TMW_PACKET_
+#ifndef _TMW_NET_GAMESERVER_GAMESERVER_H
+#define _TMW_NET_GAMESERVER_GAMESERVER_H
-/**
- * A packet wraps a certain amount of bytes for sending and receiving.
- */
-class Packet
-{
- public:
- /**
- * Constructor.
- */
- Packet(const char *data, int length);
+#include <iosfwd>
- /**
- * Destructor.
- */
- ~Packet();
+namespace Net
+{
+ class Connection;
- char *mData; /**< Packet data */
- unsigned int mLength; /**< Length of data in bytes */
-};
+ namespace GameServer
+ {
+ void connect(Net::Connection *connection, const std::string &token);
+ }
+}
#endif
diff --git a/src/net/gameserver/internal.cpp b/src/net/gameserver/internal.cpp
new file mode 100644
index 00000000..328b4863
--- /dev/null
+++ b/src/net/gameserver/internal.cpp
@@ -0,0 +1,34 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ Connection *connection = 0;
+ }
+}
diff --git a/src/net/gameserver/internal.h b/src/net/gameserver/internal.h
new file mode 100644
index 00000000..567e15d2
--- /dev/null
+++ b/src/net/gameserver/internal.h
@@ -0,0 +1,37 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_GAMESERVER_INTERNAL_H
+#define _TMW_NET_GAMESERVER_INTERNAL_H
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ extern Connection *connection;
+ }
+}
+
+#endif
diff --git a/src/net/gameserver/player.cpp b/src/net/gameserver/player.cpp
new file mode 100644
index 00000000..1f27276a
--- /dev/null
+++ b/src/net/gameserver/player.cpp
@@ -0,0 +1,68 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "player.h"
+
+#include "internal.h"
+
+#include "../connection.h"
+#include "../messageout.h"
+#include "../protocol.h"
+
+void Net::GameServer::Player::say(const std::string &text)
+{
+ MessageOut msg(PGMSG_SAY);
+
+ msg.writeString(text);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::walk(short x, short y)
+{
+ MessageOut msg(PGMSG_WALK);
+
+ msg.writeShort(x);
+ msg.writeShort(y);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::useItem(int itemId)
+{
+ MessageOut msg(PGMSG_USE_ITEM);
+
+ msg.writeLong(itemId);
+
+ Net::GameServer::connection->send(msg);
+}
+
+void Net::GameServer::Player::equip(int itemId, char slot)
+{
+ MessageOut msg(PGMSG_EQUIP);
+
+ msg.writeLong(itemId);
+ msg.writeByte(slot);
+
+ Net::GameServer::connection->send(msg);
+}
diff --git a/src/net/gameserver/player.h b/src/net/gameserver/player.h
new file mode 100644
index 00000000..34d5bb45
--- /dev/null
+++ b/src/net/gameserver/player.h
@@ -0,0 +1,46 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_GAMESERVER_PLAYER_H
+#define _TMW_NET_GAMESERVER_PLAYER_H
+
+#include <iosfwd>
+
+namespace Net
+{
+ class Connection;
+
+ namespace GameServer
+ {
+ namespace Player
+ {
+ void say(const std::string &text);
+ void walk(short x, short y);
+// void pickUp(...);
+ void useItem(int itemId);
+ void equip(int itemId, char slot);
+ }
+ }
+}
+
+#endif
diff --git a/src/net/internal.cpp b/src/net/internal.cpp
new file mode 100644
index 00000000..358aa143
--- /dev/null
+++ b/src/net/internal.cpp
@@ -0,0 +1,29 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#include "internal.h"
+
+namespace Net
+{
+ int connections = 0;
+}
diff --git a/src/net/internal.h b/src/net/internal.h
new file mode 100644
index 00000000..e1ef648a
--- /dev/null
+++ b/src/net/internal.h
@@ -0,0 +1,32 @@
+/*
+ * The Mana World
+ * Copyright 2004 The Mana World Development Team
+ *
+ * This file is part of The Mana World.
+ *
+ * The Mana World is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana World is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana World; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * $Id$
+ */
+
+#ifndef _TMW_NET_INTERNAL_H
+#define _TMW_NET_INTERNAL_H
+
+namespace Net
+{
+ extern int connections;
+}
+
+#endif
diff --git a/src/net/inventoryhandler.cpp b/src/net/inventoryhandler.cpp
index afe653eb..3f7e8709 100644
--- a/src/net/inventoryhandler.cpp
+++ b/src/net/inventoryhandler.cpp
@@ -47,29 +47,27 @@ InventoryHandler::InventoryHandler()
handledMessages = _messages;
}
-void InventoryHandler::handleMessage(MessageIn *msg)
+void InventoryHandler::handleMessage(MessageIn &msg)
{
Sint32 number;
Sint16 index, amount, itemId, equipType;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_INVENTORY:
// Only called on map load / warp. First reset all items
// to not load them twice on map change.
player_node->clearInventory();
- msg->readInt16(); // length
- number = (msg->getLength() - 4) / 18;
+ msg.readShort(); // length
+ number = (msg.getLength() - 4) / 18;
for (int loop = 0; loop < number; loop++)
{
- index = msg->readInt16();
- itemId = msg->readInt16();
- msg->readInt8(); // type
- msg->readInt8(); // identify flag
- amount = msg->readInt16();
- msg->skip(2); // unknown
- msg->skip(8); // card (4 shorts)
+ index = msg.readShort();
+ itemId = msg.readShort();
+ msg.readByte(); // type
+ msg.readByte(); // identify flag
+ amount = msg.readShort();
player_node->addInvItem(index, itemId, amount, false);
@@ -82,17 +80,16 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_ADD:
- index = msg->readInt16();
- amount = msg->readInt16();
- itemId = msg->readInt16();
- msg->readInt8(); // identify flag
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card
- equipType = msg->readInt16();
- msg->readInt8(); // type
-
- if (msg->readInt8()> 0) {
+ index = msg.readShort();
+ amount = msg.readShort();
+ itemId = msg.readShort();
+ msg.readByte(); // identify flag
+ msg.readByte(); // attribute
+ msg.readByte(); // refine
+ equipType = msg.readShort();
+ msg.readByte(); // type
+
+ if (msg.readByte()> 0) {
chatWindow->chatLog("Unable to pick up item", BY_SERVER);
} else {
const ItemInfo &itemInfo = itemDb->getItemInfo(itemId);
@@ -103,26 +100,26 @@ void InventoryHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_INVENTORY_REMOVE:
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readShort();
+ amount = msg.readShort();
player_node->getInvItem(index)->increaseQuantity(-amount);
break;
case SMSG_PLAYER_INVENTORY_USE:
- index = msg->readInt16();
- msg->readInt16(); // item id
- msg->readInt32(); // id
- amount = msg->readInt16();
- msg->readInt8(); // type
+ index = msg.readShort();
+ msg.readShort(); // item id
+ msg.readLong(); // id
+ amount = msg.readShort();
+ msg.readByte(); // type
player_node->getInvItem(index)->setQuantity(amount);
break;
case SMSG_ITEM_USE_RESPONSE:
- index = msg->readInt16();
- amount = msg->readInt16();
+ index = msg.readShort();
+ amount = msg.readShort();
- if (msg->readInt8() == 0) {
+ if (msg.readByte() == 0) {
chatWindow->chatLog("Failed to use item", BY_SERVER);
} else {
player_node->getInvItem(index)->setQuantity(amount);
diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h
index aedbc3a1..4190bf83 100644
--- a/src/net/inventoryhandler.h
+++ b/src/net/inventoryhandler.h
@@ -31,7 +31,7 @@ class InventoryHandler : public MessageHandler
public:
InventoryHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/itemhandler.cpp b/src/net/itemhandler.cpp
index 567a5382..2961f71b 100644
--- a/src/net/itemhandler.cpp
+++ b/src/net/itemhandler.cpp
@@ -40,29 +40,28 @@ ItemHandler::ItemHandler()
handledMessages = _messages;
}
-void ItemHandler::handleMessage(MessageIn *msg)
+void ItemHandler::handleMessage(MessageIn &msg)
{
Uint32 id;
Uint16 x, y;
Sint16 itemId;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_ITEM_VISIBLE:
case SMSG_ITEM_DROPPED:
- id = msg->readInt32();
- itemId = msg->readInt16();
- msg->readInt8(); // identify flag
- x = msg->readInt16();
- y = msg->readInt16();
- msg->skip(4); // amount,subX,subY / subX,subY,amount
+ id = msg.readLong();
+ itemId = msg.readShort();
+ msg.readByte(); // identify flag
+ x = msg.readShort();
+ y = msg.readShort();
floorItemManager->create(id, itemId, x, y, engine->getCurrentMap());
break;
case SMSG_ITEM_REMOVE:
FloorItem *item;
- item = floorItemManager->findById(msg->readInt32());
+ item = floorItemManager->findById(msg.readLong());
if (item)
floorItemManager->destroy(item);
break;
diff --git a/src/net/itemhandler.h b/src/net/itemhandler.h
index b2104722..5ffcb134 100644
--- a/src/net/itemhandler.h
+++ b/src/net/itemhandler.h
@@ -31,7 +31,7 @@ class ItemHandler : public MessageHandler
public:
ItemHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp
index 195e54e9..73be4b2f 100644
--- a/src/net/loginhandler.cpp
+++ b/src/net/loginhandler.cpp
@@ -24,92 +24,87 @@
#include "loginhandler.h"
#include "messagein.h"
-#include "network.h"
#include "protocol.h"
-#include "../log.h"
-#include "../logindata.h"
#include "../main.h"
-#include "../serverinfo.h"
-
-extern SERVER_INFO **server_info;
LoginHandler::LoginHandler()
{
static const Uint16 _messages[] = {
- 0x0069,
- 0x006a,
+ APMSG_LOGIN_RESPONSE,
+ APMSG_REGISTER_RESPONSE,
0
};
handledMessages = _messages;
}
-void LoginHandler::handleMessage(MessageIn *msg)
+void LoginHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
- case 0x0069:
- // Skip the length word
- msg->skip(2);
-
- n_server = (msg->getLength() - 47) / 32;
- server_info = (SERVER_INFO**)malloc(sizeof(SERVER_INFO*) * n_server);
-
- mLoginData->session_ID1 = msg->readInt32();
- mLoginData->account_ID = msg->readInt32();
- mLoginData->session_ID2 = msg->readInt32();
- msg->skip(30); // unknown
- mLoginData->sex = msg->readInt8();
-
- for (int i = 0; i < n_server; i++)
+ case APMSG_LOGIN_RESPONSE:
+ {
+ int errMsg = msg.readByte();
+ // Successful login
+ if (errMsg == ERRMSG_OK)
{
- server_info[i] = new SERVER_INFO;
-
- server_info[i]->address = msg->readInt32();
- server_info[i]->port = msg->readInt16();
- server_info[i]->name = msg->readString(20);
- server_info[i]->online_users = msg->readInt32();
- msg->skip(2); // unknown
-
- logger->log("Network: Server: %s (%s:%d)",
- server_info[i]->name.c_str(),
- iptostring(server_info[i]->address),
- server_info[i]->port);
+ state = STATE_CHAR_SELECT;
}
- state = CHAR_SERVER_STATE;
+ // Login failed
+ else
+ {
+ switch (errMsg) {
+ case LOGIN_INVALID_VERSION:
+ errorMessage = "Client has an insufficient version number to login.";
+ 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;
+ default:
+ errorMessage = "Unknown error";
+ break;
+ }
+ state = STATE_ERROR;
+ }
+ }
break;
-
- case 0x006a:
- int loginError = msg->readInt8();
- logger->log("Login::error code: %i", loginError);
-
- switch (loginError) {
- case 0:
- errorMessage = "Unregistered ID";
- break;
- case 1:
- errorMessage = "Wrong password";
- break;
- case 2:
- errorMessage = "Account expired";
- break;
- case 3:
- errorMessage = "Rejected from server";
- break;
- case 4:
- errorMessage = "You have been blocked by the GM Team";
- break;
- case 6:
- errorMessage = "You have been banned for 5 minutes";
- break;
- case 9:
- errorMessage = "This account is already logged in";
- break;
- default:
- errorMessage = "Unknown error";
- break;
+ case APMSG_REGISTER_RESPONSE:
+ {
+ int errMsg = msg.readByte();
+ // Successful registration
+ if (errMsg == ERRMSG_OK)
+ {
+ state = STATE_CHAR_SELECT;
+ }
+ // Registration failed
+ else
+ {
+ switch (errMsg) {
+ case REGISTER_INVALID_VERSION:
+ errorMessage = "Client has an insufficient version number to login.";
+ 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_ERROR;
}
- state = ERROR_STATE;
+ }
break;
}
}
diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h
index 52014559..5bac079c 100644
--- a/src/net/loginhandler.h
+++ b/src/net/loginhandler.h
@@ -26,19 +26,12 @@
#include "messagehandler.h"
-struct LoginData;
-
class LoginHandler : public MessageHandler
{
public:
LoginHandler();
- void handleMessage(MessageIn *msg);
-
- void setLoginData(LoginData *loginData) { mLoginData = loginData; };
-
- protected:
- LoginData *mLoginData;
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp
deleted file mode 100644
index 0afc8357..00000000
--- a/src/net/maploginhandler.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * The Mana World
- * Copyright 2004 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * The Mana World is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * The Mana World is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with The Mana World; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id$
- */
-
-#include "maploginhandler.h"
-
-#include "messagein.h"
-#include "protocol.h"
-
-#include "../localplayer.h"
-#include "../log.h"
-#include "../main.h"
-
-MapLoginHandler::MapLoginHandler()
-{
- static const Uint16 _messages[] = {
- SMSG_LOGIN_SUCCESS,
- 0x0081,
- 0
- };
- handledMessages = _messages;
-}
-
-void MapLoginHandler::handleMessage(MessageIn *msg)
-{
- unsigned char direction;
-
- switch (msg->getId())
- {
- case SMSG_LOGIN_SUCCESS:
- msg->readInt32(); // server tick
- msg->readCoordinates(player_node->mX, player_node->mY, direction);
- msg->skip(2); // unknown
- logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
- player_node->mX, player_node->mY, direction);
- state = GAME_STATE;
- break;
-
- case 0x0081:
- logger->log("Warning: Map server D/C");
- state = ERROR_STATE;
- break;
- }
-}
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
index 849b6716..b6074690 100644
--- a/src/net/messagehandler.cpp
+++ b/src/net/messagehandler.cpp
@@ -27,19 +27,7 @@
#include "network.h"
-MessageHandler::MessageHandler():
- mNetwork(0)
-{
-}
-
MessageHandler::~MessageHandler()
{
- if (mNetwork)
- mNetwork->unregisterHandler(this);
-}
-
-void MessageHandler::setNetwork(Network *network)
-{
- assert(!(network && mNetwork));
- mNetwork = network;
+ Net::unregisterHandler(this);
}
diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h
index c09037f6..b21abd72 100644
--- a/src/net/messagehandler.h
+++ b/src/net/messagehandler.h
@@ -27,22 +27,15 @@
#include <SDL_types.h>
class MessageIn;
-class Network;
class MessageHandler
{
public:
const Uint16 *handledMessages;
- MessageHandler();
virtual ~MessageHandler();
- virtual void handleMessage(MessageIn *msg) =0;
-
- void setNetwork(Network *network);
-
- protected:
- Network *mNetwork;
+ virtual void handleMessage(MessageIn &msg) = 0;
};
#endif
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
index bbc0a44c..a1707e06 100644
--- a/src/net/messagein.cpp
+++ b/src/net/messagein.cpp
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -23,14 +23,9 @@
#include "messagein.h"
-#include <cassert>
-#include <SDL.h>
-#include <SDL_endian.h>
-
-#define MAKEWORD(low,high) \
- ((unsigned short)(((unsigned char)(low)) | \
- ((unsigned short)((unsigned char)(high))) << 8))
+#include <string>
+#include <enet/enet.h>
MessageIn::MessageIn(const char *data, unsigned int length):
mData(data),
@@ -38,157 +33,78 @@ MessageIn::MessageIn(const char *data, unsigned int length):
mPos(0)
{
// Read the message ID
- mId = readInt16();
+ mId = readShort();
}
-Sint8
-MessageIn::readInt8()
+MessageIn::~MessageIn()
{
- assert(mPos < mLength);
- return mData[mPos++];
-}
-
-Sint16
-MessageIn::readInt16()
-{
- assert(mPos + 2 <= mLength);
- mPos += 2;
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- return SDL_Swap16(*(Sint16*)(mData + (mPos - 2)));
-#else
- return (*(Sint16*)(mData + (mPos - 2)));
-#endif
}
-Sint32
-MessageIn::readInt32()
+char MessageIn::readByte()
{
- assert(mPos + 4 <= mLength);
- mPos += 4;
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- return SDL_Swap32(*(Sint32*)(mData + (mPos - 4)));
-#else
- return (*(Sint32*)(mData + (mPos - 4)));
-#endif
+ char value = -1;
+ if (mPos < mLength)
+ {
+ value = mData[mPos];
+ }
+ mPos += 1;
+ return value;
}
-void
-MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
+short MessageIn::readShort()
{
- assert(mPos + 3 <= mLength);
-
- const char *data = mData + mPos;
- Sint16 temp;
-
- temp = MAKEWORD(data[1] & 0x00c0, data[0] & 0x00ff);
- x = temp >> 6;
- temp = MAKEWORD(data[2] & 0x00f0, data[1] & 0x003f);
- y = temp >> 4;
-
- direction = data[2] & 0x000f;
-
- // Translate from eAthena format
- switch (direction)
+ short value = -1;
+ if (mPos + 2 <= mLength)
{
- case 0:
- direction = 1;
- break;
- case 1:
- direction = 3;
- break;
- case 2:
- direction = 2;
- break;
- case 3:
- direction = 6;
- break;
- case 4:
- direction = 4;
- break;
- case 5:
- direction = 12;
- break;
- case 6:
- direction = 8;
- break;
- case 7:
- direction = 9;
- break;
- default:
- // OOPSIE! Impossible or unknown
- direction = 0;
+ uint16_t t;
+ memcpy(&t, mData + mPos, 2);
+ value = ENET_NET_TO_HOST_16(t);
}
-
- mPos += 3;
+ mPos += 2;
+ return value;
}
-void
-MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
- Uint16 &dstX, Uint16 &dstY)
+long MessageIn::readLong()
{
- assert(mPos + 5 <= mLength);
-
- const char *data = mData + mPos;
- Sint16 temp;
-
- temp = MAKEWORD(data[3], data[2] & 0x000f);
- dstX = temp >> 2;
-
- dstY = MAKEWORD(data[4], data[3] & 0x0003);
-
- temp = MAKEWORD(data[1], data[0]);
- srcX = temp >> 6;
-
- temp = MAKEWORD(data[2], data[1] & 0x003f);
- srcY = temp >> 4;
-
- mPos += 5;
+ long value = -1;
+ if (mPos + 4 <= mLength)
+ {
+ uint32_t t;
+ memcpy(&t, mData + mPos, 4);
+ value = ENET_NET_TO_HOST_32(t);
+ }
+ mPos += 4;
+ return value;
}
-void
-MessageIn::skip(unsigned int length)
+void MessageIn::readCoordinates(Uint16 &x, Uint16 &y)
{
- assert(mPos + length <= mLength);
- mPos += length;
+ if (mPos + 3 <= mLength)
+ {
+ unsigned char const *p = reinterpret_cast< unsigned char const * >(mData + mPos);
+ x = p[0] | ((p[1] & 0x07) << 8);
+ y = (p[1] >> 3) | ((p[2] & 0x3F) << 5);
+ }
+ mPos += 3;
}
-std::string
-MessageIn::readString(int length)
+std::string MessageIn::readString(int length)
{
// Get string length
if (length < 0) {
- length = readInt16();
+ length = readShort();
}
- // Make sure the string isn't erroneous
+ // Make sure the string isn't erroneus
if (length < 0 || mPos + length > mLength) {
mPos = mLength + 1;
return "";
}
// Read the string
- char const *stringBeg = mData + mPos;
- char const *stringEnd = (char const *)memchr(stringBeg, '\0', length);
- std::string readString(stringBeg,
- stringEnd ? stringEnd - stringBeg : length);
+ char const *stringBeg = mData + mPos,
+ *stringEnd = (char const *)memchr(stringBeg, '\0', length);
+ std::string readString(stringBeg, stringEnd ? stringEnd - stringBeg : length);
mPos += length;
return readString;
}
-
-Sint8& operator<<(Sint8 &lhs, MessageIn &msg)
-{
- lhs = msg.readInt8();
- return lhs;
-}
-
-Sint16& operator<<(Sint16 &lhs, MessageIn &msg)
-{
- lhs = msg.readInt16();
- return lhs;
-}
-
-Sint32& operator<<(Sint32 &lhs, MessageIn &msg)
-{
- lhs = msg.readInt32();
- return lhs;
-}
diff --git a/src/net/messagein.h b/src/net/messagein.h
index d97cd8b6..68bbb933 100644
--- a/src/net/messagein.h
+++ b/src/net/messagein.h
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -21,10 +21,11 @@
* $Id$
*/
-#ifndef _TMW_MESSAGEIN_
-#define _TMW_MESSAGEIN_
+#ifndef _TMWSERV_MESSAGEIN_H_
+#define _TMWSERV_MESSAGEIN_H_
#include <string>
+
#include <SDL_types.h>
/**
@@ -32,10 +33,6 @@
*/
class MessageIn
{
- friend Sint8& operator<<(Sint8 &lhs, MessageIn &msg);
- friend Sint16& operator<<(Sint16 &lhs, MessageIn &msg);
- friend Sint32& operator<<(Sint32 &lhs, MessageIn &msg);
-
public:
/**
* Constructor.
@@ -43,55 +40,51 @@ class MessageIn
MessageIn(const char *data, unsigned int length);
/**
- * Returns the message ID.
+ * Destructor.
*/
- short
- getId() { return mId; }
+ ~MessageIn();
- /**
- * Returns the message length.
- */
- unsigned int
- getLength() { return mLength; }
+ short getId() { return mId; } /**< Returns the message ID. */
- Sint8 readInt8(); /**< Reads a byte. */
- Sint16 readInt16(); /**< Reads a short. */
- Sint32 readInt32(); /**< Reads a long. */
+ char readByte(); /**< Reads a byte. */
+ short readShort(); /**< Reads a short. */
+ long readLong(); /**< Reads a long. */
/**
- * Reads a special 3 byte block used by eAthena, containing x and y
- * coordinates and direction.
+ * Reads a 3-byte block containing tile-based coordinates.
*/
- void
- readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
+ void readCoordinates(Uint16 &x, Uint16 &y);
/**
- * Reads a special 5 byte block used by eAthena, containing a source
- * and destination coordinate pair.
+ * Reads a string. If a length is not given (-1), it is assumed
+ * that the length of the string is stored in a short at the
+ * start of the string.
*/
- void
- readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
- Uint16 &dstX, Uint16 &dstY);
+ std::string readString(int length = -1);
/**
- * Skips a given number of bytes.
+ * Returns the message length.
*/
- void
- skip(unsigned int length);
+ unsigned int
+ getLength() { return mLength; }
/**
- * Reads a string. If a length is not given (-1), it is assumed
- * that the length of the string is stored in a short at the
- * start of the string.
+ * Returns the length of unread data.
*/
- std::string
- readString(int length = -1);
+ unsigned int
+ getUnreadLength() { return mLength - mPos; }
private:
const char* mData; /**< The message data. */
unsigned int mLength; /**< The length of the data. */
- unsigned int mPos; /**< The position in the data. */
short mId; /**< The message ID. */
+
+ /**
+ * Actual position in the packet. From 0 to packet->length.
+ * A value bigger than packet->length means EOP was reached when
+ * reading it.
+ */
+ unsigned int mPos;
};
#endif
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
index f6ed5de6..4d68c14f 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -24,93 +24,92 @@
#include "messageout.h"
#include <string>
-#include <SDL.h>
-#include <SDL_endian.h>
-#include "network.h"
-#include "packet.h"
+#include <enet/enet.h>
-MessageOut::MessageOut(Network *network):
- mNetwork(network),
+MessageOut::MessageOut(short id):
mData(0),
mDataSize(0),
mPos(0)
{
- mData = mNetwork->mOutBuffer + mNetwork->mOutSize;
+ writeShort(id);
}
-void MessageOut::writeInt8(Sint8 value)
+MessageOut::~MessageOut()
{
- mData[mPos] = value;
- mPos += sizeof(Sint8);
- mNetwork->mOutSize+= sizeof(Sint8);
+ if (mData) {
+ free(mData);
+ }
}
-void MessageOut::writeInt16(Sint16 value)
+void
+MessageOut::expand(size_t bytes)
{
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- (*(Sint16 *)(mData + mPos)) = SDL_Swap16(value);
-#else
- (*(Sint16 *)(mData + mPos)) = value;
-#endif
- mPos += sizeof(Sint16);
- mNetwork->mOutSize += sizeof(Sint16);
+ mData = (char*)realloc(mData, bytes);
+ mDataSize = bytes;
}
-void MessageOut::writeInt32(Sint32 value)
+void
+MessageOut::writeByte(char value)
{
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- (*(Sint32 *)(mData + mPos)) = SDL_Swap32(value);
-#else
- (*(Sint32 *)(mData + mPos)) = value;
-#endif
- mPos += sizeof(Sint32);
- mNetwork->mOutSize += sizeof(Sint32);
+ expand(mPos + 1);
+ mData[mPos] = value;
+ mPos += 1;
}
-void MessageOut::writeString(const std::string &string, int length)
+void MessageOut::writeShort(short value)
{
- std::string toWrite = string;
+ expand(mPos + 2);
+ uint16_t t = ENET_HOST_TO_NET_16(value);
+ memcpy(mData + mPos, &t, 2);
+ mPos += 2;
+}
+void
+MessageOut::writeLong(long value)
+{
+ expand(mPos + 4);
+ uint32_t t = ENET_HOST_TO_NET_32(value);
+ memcpy(mData + mPos, &t, 4);
+ mPos += 4;
+}
+
+void
+MessageOut::writeString(const std::string &string, int length)
+{
+ int stringLength = string.length();
if (length < 0)
{
// Write the length at the start if not fixed
- writeInt16(string.length());
+ writeShort(stringLength);
+ length = stringLength;
}
- else
+ else if (length < stringLength)
{
// Make sure the length of the string is no longer than specified
- toWrite = string.substr(0, length);
+ stringLength = length;
}
+ expand(mPos + length);
// Write the actual string
- memcpy(&mData[mPos], (void*)toWrite.c_str(), toWrite.length());
- mPos += toWrite.length();
- mNetwork->mOutSize += toWrite.length();
+ memcpy(mData + mPos, string.c_str(), stringLength);
// Pad remaining space with zeros
- if (length > (int)toWrite.length())
+ if (length > stringLength)
{
- memset(&mData[mPos], '\0', length - toWrite.length());
- mPos += length - toWrite.length();
- mNetwork->mOutSize += length - toWrite.length();
+ memset(mData + mPos + stringLength, '\0', length - stringLength);
}
+ mPos += length;
}
-MessageOut& operator<<(MessageOut &msg, const Sint8 &rhs)
-{
- msg.writeInt8(rhs);
- return msg;
-}
-
-MessageOut& operator<<(MessageOut &msg, const Sint16 &rhs)
+char*
+MessageOut::getData() const
{
- msg.writeInt16(rhs);
- return msg;
+ return mData;
}
-MessageOut& operator<<(MessageOut &msg, const Sint32 &rhs)
+unsigned int
+MessageOut::getDataSize() const
{
- msg.writeInt32(rhs);
- return msg;
+ return mDataSize;
}
diff --git a/src/net/messageout.h b/src/net/messageout.h
index f6468adb..af25e4b4 100644
--- a/src/net/messageout.h
+++ b/src/net/messageout.h
@@ -1,5 +1,5 @@
/*
- * The Mana World
+ * The Mana World Server
* Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
@@ -21,32 +21,30 @@
* $Id$
*/
-#ifndef _TMW_MESSAGEOUT_
-#define _TMW_MESSAGEOUT_
+#ifndef _TMWSERV_MESSAGEOUT_H_
+#define _TMWSERV_MESSAGEOUT_H_
#include <iosfwd>
-#include <SDL_types.h>
-
-class Network;
/**
* Used for building an outgoing message.
*/
class MessageOut
{
- friend MessageOut& operator<<(MessageOut &msg, const Sint8 &rhs);
- friend MessageOut& operator<<(MessageOut &msg, const Sint16 &rhs);
- friend MessageOut& operator<<(MessageOut &msg, const Sint32 &rhs);
-
public:
/**
* Constructor.
*/
- MessageOut(Network *network);
+ MessageOut(short id);
- void writeInt8(Sint8 value); /**< Writes a byte. */
- void writeInt16(Sint16 value); /**< Writes a short. */
- void writeInt32(Sint32 value); /**< Writes a long. */
+ /**
+ * Destructor.
+ */
+ ~MessageOut();
+
+ void writeByte(char value); /**< Writes a byte. */
+ void writeShort(short value); /**< Writes a short. */
+ void writeLong(long value); /**< Writes a long. */
/**
* Writes a string. If a fixed length is not given (-1), it is stored
@@ -54,8 +52,25 @@ class MessageOut
*/
void writeString(const std::string &string, int length = -1);
+ /**
+ * Returns the content of the message.
+ */
+ char *getData() const;
+
+ /**
+ * Returns the length of the data.
+ */
+ unsigned int getDataSize() const;
+
private:
- Network *mNetwork;
+ /**
+ * Expand the packet data to be able to hold more data.
+ *
+ * NOTE: For performance enhancements this method could allocate extra
+ * memory in advance instead of expanding size every time more data is
+ * added.
+ */
+ void expand(size_t size);
char *mData; /**< Data building up. */
unsigned int mDataSize; /**< Size of data. */
diff --git a/src/net/network.cpp b/src/net/network.cpp
index 757a533e..b94c9eb8 100644
--- a/src/net/network.cpp
+++ b/src/net/network.cpp
@@ -23,422 +23,153 @@
#include "network.h"
+#include <enet/enet.h>
+
+#include <map>
+
+#include "connection.h"
+#include "internal.h"
#include "messagehandler.h"
#include "messagein.h"
#include "../log.h"
-/** Warning: buffers and other variables are shared,
- so there can be only one connection active at a time */
-
-short packet_lengths[] = {
- 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-// #0x0040
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,108, 3, 2,
- 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6,
-// #0x0080
- 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 23, -1, -1, -1, 0,
- 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6,
- 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6,
- 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3,
-// #0x00C0
- 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 6, 2, 27,
- 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1,
- 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2,
- 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10,
-// #0x0100
- 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1,
- 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16,
- 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1,
- 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26,
-// #0x0140
- 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6,
- 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42,
- -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182,
- 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1,
-// #0x0180
- 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6,
- 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, 4, 6, 2, 6,
- 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4,
- 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3,
-// #0x01C0
- 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 0, 9, 9, 29, 6, 28,
- 8, 14, 10, 35, 6, 8, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6,
- 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1,
- -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10,
-// #0x200
- 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-const unsigned int BUFFER_SIZE = 65536;
-
-int networkThread(void *data)
-{
- Network *network = static_cast<Network*>(data);
-
- if (!network->realConnect())
- return -1;
-
- network->receive();
-
- return 0;
+/**
+ * The local host which is shared for all outgoing connections.
+ */
+namespace {
+ ENetHost *client;
}
-Network::Network():
- mSocket(0),
- mAddress(), mPort(0),
- mInBuffer(new char[BUFFER_SIZE]),
- mOutBuffer(new char[BUFFER_SIZE]),
- mInSize(0), mOutSize(0),
- mToSkip(0),
- mState(IDLE),
- mWorkerThread(0)
-{
- mMutex = SDL_CreateMutex();
-}
+typedef std::map<unsigned short, MessageHandler*> MessageHandlers;
+typedef MessageHandlers::iterator MessageHandlerIterator;
+static MessageHandlers mMessageHandlers;
-Network::~Network()
+void Net::initialize()
{
- clearHandlers();
-
- if (mState != IDLE && mState != ERROR)
- disconnect();
-
- SDL_DestroyMutex(mMutex);
-
- delete[] mInBuffer;
- delete[] mOutBuffer;
-}
-
-bool Network::connect(const std::string &address, short port)
-{
- if (mState != IDLE && mState != ERROR)
- {
- logger->log("Tried to connect an already connected socket!");
- return false;
- }
-
- if (address.empty())
+ if (enet_initialize())
{
- logger->log("Empty address given to Network::connect()!");
- mState = ERROR;
- return false;
+ logger->error("Failed to initialize ENet.");
}
- logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+ client = enet_host_create(NULL, 3, 0, 0);
- mAddress = address;
- mPort = port;
-
- // Reset to sane values
- mOutSize = 0;
- mInSize = 0;
- mToSkip = 0;
-
- mState = CONNECTING;
- mWorkerThread = SDL_CreateThread(networkThread, this);
- if (!mWorkerThread)
+ if (!client)
{
- logger->log("Unable to create network worker thread");
- mState = ERROR;
- return false;
+ logger->error("Failed to create the local host.");
}
-
- return true;
}
-void Network::disconnect()
+void Net::finalize()
{
- mState = IDLE;
+ if (!client)
+ return; // Wasn't initialized at all
- if (mWorkerThread)
- {
- SDL_WaitThread(mWorkerThread, NULL);
- mWorkerThread = NULL;
+ if (Net::connections) {
+ logger->error("Tried to shutdown the network subsystem while there "
+ "are network connections left!");
}
- if (mSocket)
- {
- SDLNet_TCP_Close(mSocket);
- mSocket = 0;
- }
+ clearHandlers();
+ enet_deinitialize();
}
-void Network::registerHandler(MessageHandler *handler)
+Net::Connection *Net::getConnection()
{
- const Uint16 *i = handler->handledMessages;
-
- while(*i)
+ if (!client)
{
- mMessageHandlers[*i] = handler;
- i++;
+ logger->error("Tried to instantiate a network object before "
+ "initializing the network subsystem!");
}
- handler->setNetwork(this);
+ return new Net::Connection(client);
}
-void Network::unregisterHandler(MessageHandler *handler)
+void
+Net::registerHandler(MessageHandler *handler)
{
for (const Uint16 *i = handler->handledMessages; *i; i++)
{
- mMessageHandlers.erase(*i);
- }
-
- handler->setNetwork(0);
-}
-
-void Network::clearHandlers()
-{
- MessageHandlerIterator i;
- for (i = mMessageHandlers.begin(); i != mMessageHandlers.end(); i++)
- {
- i->second->setNetwork(0);
- }
- mMessageHandlers.clear();
-}
-
-void Network::dispatchMessages()
-{
- while (messageReady())
- {
- MessageIn msg = getNextMessage();
-
- MessageHandlerIterator iter = mMessageHandlers.find(msg.getId());
-
- if (iter != mMessageHandlers.end())
- iter->second->handleMessage(&msg);
- else
- logger->log("Unhandled packet: %x", msg.getId());
-
- skip(msg.getLength());
- }
-}
-
-void Network::flush()
-{
- if (!mOutSize || mState != CONNECTED)
- return;
-
- int ret;
-
-
- SDL_mutexP(mMutex);
- ret = SDLNet_TCP_Send(mSocket, mOutBuffer, mOutSize);
- if (ret < (int)mOutSize)
- {
- logger->log("Error in SDLNet_TCP_Send(): %s", SDLNet_GetError());
- mState = ERROR;
+ mMessageHandlers[*i] = handler;
}
- mOutSize = 0;
- SDL_mutexV(mMutex);
}
-void Network::skip(int len)
+void
+Net::unregisterHandler(MessageHandler *handler)
{
- SDL_mutexP(mMutex);
- mToSkip += len;
- if (!mInSize)
- {
- SDL_mutexV(mMutex);
- return;
- }
-
- if (mInSize >= mToSkip)
- {
- mInSize -= mToSkip;
- memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
- mToSkip = 0;
- }
- else
+ for (const Uint16 *i = handler->handledMessages; *i; i++)
{
- mToSkip -= mInSize;
- mInSize = 0;
+ mMessageHandlers.erase(*i);
}
- SDL_mutexV(mMutex);
}
-bool Network::messageReady()
+void
+Net::clearHandlers()
{
- int len = -1;
-
- SDL_mutexP(mMutex);
- if (mInSize >= 2)
- {
- len = packet_lengths[readWord(0)];
-
- if (len == -1 && mInSize > 4)
- len = readWord(2);
-
- }
-
- bool ret = (mInSize >= static_cast<unsigned int>(len));
- SDL_mutexV(mMutex);
-
- return ret;
+ mMessageHandlers.clear();
}
-MessageIn Network::getNextMessage()
-{
- while (!messageReady())
- {
- if (mState == ERROR)
- break;
- }
-
- SDL_mutexP(mMutex);
- int msgId = readWord(0);
- int len = packet_lengths[msgId];
-
- if (len == -1)
- len = readWord(2);
-
-#ifdef DEBUG
- printf("Received packet 0x%x of length %d\n", msgId, length);
-#endif
-
- MessageIn msg(mInBuffer, len);
- SDL_mutexV(mMutex);
-
- return msg;
-}
-bool Network::realConnect()
+/**
+ * Dispatches a message to the appropriate message handler and
+ * destroys it afterwards.
+ */
+namespace
{
- IPaddress ipAddress;
-
- if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
- {
- logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError());
- mState = ERROR;
- return false;
- }
-
- mState = CONNECTING;
-
- mSocket = SDLNet_TCP_Open(&ipAddress);
- if (!mSocket)
- {
- logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
- mState = ERROR;
- return false;
- }
-
- logger->log("Network::Started session with %s:%i",
- iptostring(ipAddress.host), ipAddress.port);
-
- mState = CONNECTED;
-
- return true;
+ 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 Network::receive()
+void Net::flush()
{
- SDLNet_SocketSet set;
+ ENetEvent event;
- if (!(set = SDLNet_AllocSocketSet(1)))
+ // Wait up to 10 milliseconds for an event.
+ while (enet_host_service(client, &event, 10) > 0)
{
- logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError());
- mState = ERROR;
- return;
- }
-
- if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
- {
- logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError());
- mState = ERROR;
- }
-
- while (mState == CONNECTED)
- {
- // TODO Try to get this to block all the time while still being able
- // to escape the loop
- int numReady = SDLNet_CheckSockets(set, ((Uint32)500));
- int ret;
- switch (numReady)
+ switch (event.type)
{
- case -1:
- logger->log("Error: SDLNet_CheckSockets");
- // FALLTHROUGH
- case 0:
+ case ENET_EVENT_TYPE_CONNECT:
+ logger->log("Connected.");
+ // Store any relevant server information here.
+ event.peer->data = 0;
+ break;
+
+ case ENET_EVENT_TYPE_RECEIVE:
+ dispatchMessage(event.packet);
break;
- case 1:
- // Receive data from the socket
- SDL_mutexP(mMutex);
- ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+ case ENET_EVENT_TYPE_DISCONNECT:
+ logger->log("Disconnected.");
+ // Reset the server information.
+ event.peer->data = 0;
+ break;
- if (!ret)
- {
- // We got disconnected
- mState = IDLE;
- logger->log("Disconnected.");
- }
- else if (ret < 0)
- {
- logger->log("Error in SDLNet_TCP_Recv(): %s", SDLNet_GetError());
- mState = ERROR;
- }
- else {
- mInSize += ret;
- if (mToSkip)
- {
- if (mInSize >= mToSkip)
- {
- mInSize -= mToSkip;
- memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
- mToSkip = 0;
- }
- else
- {
- mToSkip -= mInSize;
- mInSize = 0;
- }
- }
- }
- SDL_mutexV(mMutex);
+ case ENET_EVENT_TYPE_NONE:
+ logger->log("No event during 10 milliseconds.");
break;
default:
- // more than one socket is ready..
- // this should not happen since we only listen once socket.
- logger->log("Error in SDLNet_TCP_Recv(), %d sockets are ready : %s", numReady, SDLNet_GetError());
- mState = ERROR;
+ logger->log("Unhandled enet event.");
break;
}
}
-
- if (SDLNet_TCP_DelSocket(set, mSocket) == -1)
- {
- logger->log("Error in SDLNet_DelSocket(): %s", SDLNet_GetError());
- }
-
- SDLNet_FreeSocketSet(set);
-}
-
-char *iptostring(int address)
-{
- static char asciiIP[16];
-
- sprintf(asciiIP, "%i.%i.%i.%i",
- (unsigned char)(address),
- (unsigned char)(address >> 8),
- (unsigned char)(address >> 16),
- (unsigned char)(address >> 24));
-
- return asciiIP;
-}
-
-Uint16 Network::readWord(int pos)
-{
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- return SDL_Swap16((*(Uint16*)(mInBuffer+(pos))));
-#else
- return (*(Uint16*)(mInBuffer+(pos)));
-#endif
}
diff --git a/src/net/network.h b/src/net/network.h
index f4637f73..9ffcbb6d 100644
--- a/src/net/network.h
+++ b/src/net/network.h
@@ -21,83 +21,51 @@
* $Id$
*/
-#ifndef _TMW_NETWORK_
-#define _TMW_NETWORK_
+#ifndef _TMW_NET_NETWORK_H
+#define _TMW_NET_NETWORK_H
-#include <map>
-#include <SDL_net.h>
-#include <SDL_thread.h>
-#include <string>
+#include <iosfwd>
class MessageHandler;
-class MessageIn;
+class MessageOut;
-class Network;
-
-class Network
+namespace Net
{
- public:
- friend int networkThread(void *data);
- friend class MessageOut;
-
- Network();
- ~Network();
-
- bool connect(const std::string &address, short port);
- void disconnect();
-
- void registerHandler(MessageHandler *handler);
- void unregisterHandler(MessageHandler *handler);
- void clearHandlers();
-
- int getState() const { return mState; }
- bool isConnected() const { return mState == CONNECTED; }
-
- int getInSize() const { return mInSize; }
-
- void skip(int len);
-
- bool messageReady();
- MessageIn getNextMessage();
-
- void dispatchMessages();
- void flush();
-
- enum {
- IDLE,
- CONNECTED,
- CONNECTING,
- DATA,
- ERROR
- };
-
- protected:
- Uint16 readWord(int pos);
-
- TCPsocket mSocket;
-
- std::string mAddress;
- short mPort;
-
- char *mInBuffer, *mOutBuffer;
- unsigned int mInSize, mOutSize;
-
- unsigned int mToSkip;
-
- int mState;
-
- SDL_Thread *mWorkerThread;
- SDL_mutex *mMutex;
-
- typedef std::map<Uint16, MessageHandler*> MessageHandlers;
- typedef MessageHandlers::iterator MessageHandlerIterator;
- MessageHandlers mMessageHandlers;
-
- bool realConnect();
- void receive();
-};
-
-/** Convert an address from int format to string */
-char *iptostring(int address);
+ class Connection;
+
+ /**
+ * Initializes the network subsystem.
+ */
+ void initialize();
+
+ /**
+ * Finalizes the network subsystem.
+ */
+ void finalize();
+
+ 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/npchandler.cpp b/src/net/npchandler.cpp
index a803710e..9c89e71f 100644
--- a/src/net/npchandler.cpp
+++ b/src/net/npchandler.cpp
@@ -47,21 +47,23 @@ NPCHandler::NPCHandler()
handledMessages = _messages;
}
-void NPCHandler::handleMessage(MessageIn *msg)
+void NPCHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_NPC_CHOICE:
- msg->readInt16(); // length
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg->readInt32()));
- npcListDialog->parseItems(msg->readString(msg->getLength() - 8));
+ msg.readShort(); // length
+ current_npc = dynamic_cast<NPC*>(
+ beingManager->findBeing(msg.readLong()));
+ npcListDialog->parseItems(msg.readString(msg.getLength() - 8));
npcListDialog->setVisible(true);
break;
case SMSG_NPC_MESSAGE:
- msg->readInt16(); // length
- current_npc = dynamic_cast<NPC*>(beingManager->findBeing(msg->readInt32()));
- npcTextDialog->addText(msg->readString(msg->getLength() - 8));
+ msg.readShort(); // length
+ current_npc = dynamic_cast<NPC*>(
+ beingManager->findBeing(msg.readLong()));
+ npcTextDialog->addText(msg.readString(msg.getLength() - 8));
npcListDialog->setVisible(false);
npcTextDialog->setVisible(true);
break;
diff --git a/src/net/npchandler.h b/src/net/npchandler.h
index 903ecd10..0cb40f64 100644
--- a/src/net/npchandler.h
+++ b/src/net/npchandler.h
@@ -31,7 +31,7 @@ class NPCHandler : public MessageHandler
public:
NPCHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/playerhandler.cpp b/src/net/playerhandler.cpp
index 3786cd0b..6eb80d59 100644
--- a/src/net/playerhandler.cpp
+++ b/src/net/playerhandler.cpp
@@ -46,7 +46,9 @@ OkDialog *deathNotice = NULL;
namespace {
struct WeightListener : public gcn::ActionListener
{
- void action(const std::string& eventId, gcn::Widget* widget) { weightNotice = NULL; }
+ void action(const std::string &eventId, gcn::Widget *widget) {
+ weightNotice = NULL;
+ }
} weightListener;
}
@@ -56,7 +58,7 @@ namespace {
// TODO Move somewhere else
namespace {
struct DeathListener : public gcn::ActionListener {
- void action(const std::string& eventId, gcn::Widget* widget) {
+ void action(const std::string &eventId, gcn::Widget *widget) {
player_node->revive();
deathNotice = NULL;
}
@@ -66,61 +68,36 @@ namespace {
PlayerHandler::PlayerHandler()
{
static const Uint16 _messages[] = {
- SMSG_WALK_RESPONSE,
- SMSG_PLAYER_WARP,
- SMSG_PLAYER_STAT_UPDATE_1,
- SMSG_PLAYER_STAT_UPDATE_2,
- SMSG_PLAYER_STAT_UPDATE_3,
- SMSG_PLAYER_STAT_UPDATE_4,
- SMSG_PLAYER_STAT_UPDATE_5,
- SMSG_PLAYER_STAT_UPDATE_6,
- SMSG_PLAYER_ARROW_MESSAGE,
+ //SMSG_PLAYER_STAT_UPDATE_1,
+ //SMSG_PLAYER_STAT_UPDATE_2,
+ //SMSG_PLAYER_STAT_UPDATE_3,
+ //SMSG_PLAYER_STAT_UPDATE_4,
+ //SMSG_PLAYER_STAT_UPDATE_5,
+ //SMSG_PLAYER_STAT_UPDATE_6,
+ //SMSG_PLAYER_ARROW_MESSAGE,
+ GPMSG_PLAYER_MAP_CHANGE,
0
};
handledMessages = _messages;
}
-void PlayerHandler::handleMessage(MessageIn *msg)
+void PlayerHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
- case SMSG_WALK_RESPONSE:
- // It is assumed by the client any request to walk actually
- // succeeds on the server. The plan is to have a correction
- // message when the server senses the client has the wrong
- // idea.
- break;
-
- case SMSG_PLAYER_WARP:
- {
- std::string mapPath = msg->readString(16);
- Uint16 x = msg->readInt16();
- Uint16 y = msg->readInt16();
-
- logger->log("Warping to %s (%d, %d)", mapPath.c_str(), x, y);
-
- // Switch the actual map, deleting the previous one
- engine->changeMap(mapPath);
-
- current_npc = 0;
-
- player_node->setAction(Being::STAND);
- player_node->stopAttack();
- player_node->mFrame = 0;
- player_node->mX = x;
- player_node->mY = y;
- }
+ case GPMSG_PLAYER_MAP_CHANGE:
+ handleMapChangeMessage(msg);
break;
case SMSG_PLAYER_STAT_UPDATE_1:
{
- Sint16 type = msg->readInt16();
- Uint32 value = msg->readInt32();
+ Sint16 type = msg.readShort();
+ Uint32 value = msg.readLong();
switch (type)
{
//case 0x0000:
- // player_node->setWalkSpeed(msg->readInt32());
+ // player_node->setWalkSpeed(msg.readLong());
// break;
case 0x0005: player_node->mHp = value; break;
case 0x0006: player_node->mMaxHp = value; break;
@@ -169,30 +146,30 @@ void PlayerHandler::handleMessage(MessageIn *msg)
break;
case SMSG_PLAYER_STAT_UPDATE_2:
- switch (msg->readInt16()) {
+ switch (msg.readShort()) {
case 0x0001:
- player_node->mXp = msg->readInt32();
+ player_node->mXp = msg.readLong();
break;
case 0x0002:
- player_node->mJobXp = msg->readInt32();
+ player_node->mJobXp = msg.readLong();
break;
case 0x0014:
- player_node->mGp = msg->readInt32();
+ player_node->mMoney = msg.readLong();
break;
case 0x0016:
- player_node->mXpForNextLevel = msg->readInt32();
+ player_node->mXpForNextLevel = msg.readLong();
break;
case 0x0017:
- player_node->mJobXpForNextLevel = msg->readInt32();
+ player_node->mJobXpForNextLevel = msg.readLong();
break;
}
break;
case SMSG_PLAYER_STAT_UPDATE_3:
{
- Sint32 type = msg->readInt32();
- Sint32 base = msg->readInt32();
- Sint32 bonus = msg->readInt32();
+ Sint32 type = msg.readLong();
+ Sint32 base = msg.readLong();
+ Sint32 bonus = msg.readLong();
Sint32 total = base + bonus;
switch (type) {
@@ -214,9 +191,9 @@ void PlayerHandler::handleMessage(MessageIn *msg)
case SMSG_PLAYER_STAT_UPDATE_4:
{
- Sint16 type = msg->readInt16();
- Sint8 fail = msg->readInt8();
- Sint8 value = msg->readInt8();
+ Sint16 type = msg.readShort();
+ Sint8 fail = msg.readByte();
+ Sint8 value = msg.readByte();
if (fail != 1)
break;
@@ -240,60 +217,60 @@ void PlayerHandler::handleMessage(MessageIn *msg)
// Updates stats and status points
case SMSG_PLAYER_STAT_UPDATE_5:
- player_node->mStatsPointsToAttribute = msg->readInt16();
- player_node->mAttr[LocalPlayer::STR] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::STR] = msg->readInt8();
- player_node->mAttr[LocalPlayer::AGI] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::AGI] = msg->readInt8();
- player_node->mAttr[LocalPlayer::VIT] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::VIT] = msg->readInt8();
- player_node->mAttr[LocalPlayer::INT] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::INT] = msg->readInt8();
- player_node->mAttr[LocalPlayer::DEX] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::DEX] = msg->readInt8();
- player_node->mAttr[LocalPlayer::LUK] = msg->readInt8();
- player_node->mAttrUp[LocalPlayer::LUK] = msg->readInt8();
- player_node->ATK = msg->readInt16(); // ATK
- player_node->ATK_BONUS = msg->readInt16(); // ATK bonus
- player_node->MATK = msg->readInt16(); // MATK max
- player_node->MATK_BONUS = msg->readInt16(); // MATK min
- player_node->DEF = msg->readInt16(); // DEF
- player_node->DEF_BONUS = msg->readInt16(); // DEF bonus
- player_node->MDEF = msg->readInt16(); // MDEF
- player_node->MDEF_BONUS = msg->readInt16(); // MDEF bonus
- player_node->HIT = msg->readInt16(); // HIT
- player_node->FLEE = msg->readInt16(); // FLEE
- player_node->FLEE_BONUS = msg->readInt16(); // FLEE bonus
- msg->readInt16(); // critical
- msg->readInt16(); // unknown
+ player_node->mStatsPointsToAttribute = msg.readShort();
+ player_node->mAttr[LocalPlayer::STR] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readByte();
+ player_node->mAttr[LocalPlayer::AGI] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readByte();
+ player_node->mAttr[LocalPlayer::VIT] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readByte();
+ player_node->mAttr[LocalPlayer::INT] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readByte();
+ player_node->mAttr[LocalPlayer::DEX] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readByte();
+ player_node->mAttr[LocalPlayer::LUK] = msg.readByte();
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readByte();
+ player_node->ATK = msg.readShort(); // ATK
+ player_node->ATK_BONUS = msg.readShort(); // ATK bonus
+ player_node->MATK = msg.readShort(); // MATK max
+ player_node->MATK_BONUS = msg.readShort(); // MATK min
+ player_node->DEF = msg.readShort(); // DEF
+ player_node->DEF_BONUS = msg.readShort(); // DEF bonus
+ player_node->MDEF = msg.readShort(); // MDEF
+ player_node->MDEF_BONUS = msg.readShort(); // MDEF bonus
+ player_node->HIT = msg.readShort(); // HIT
+ player_node->FLEE = msg.readShort(); // FLEE
+ player_node->FLEE_BONUS = msg.readShort(); // FLEE bonus
+ msg.readShort(); // critical
+ msg.readShort(); // unknown
break;
case SMSG_PLAYER_STAT_UPDATE_6:
- switch (msg->readInt16()) {
+ switch (msg.readShort()) {
case 0x0020:
- player_node->mAttrUp[LocalPlayer::STR] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::STR] = msg.readByte();
break;
case 0x0021:
- player_node->mAttrUp[LocalPlayer::AGI] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::AGI] = msg.readByte();
break;
case 0x0022:
- player_node->mAttrUp[LocalPlayer::VIT] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::VIT] = msg.readByte();
break;
case 0x0023:
- player_node->mAttrUp[LocalPlayer::INT] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::INT] = msg.readByte();
break;
case 0x0024:
- player_node->mAttrUp[LocalPlayer::DEX] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::DEX] = msg.readByte();
break;
case 0x0025:
- player_node->mAttrUp[LocalPlayer::LUK] = msg->readInt8();
+ player_node->mAttrUp[LocalPlayer::LUK] = msg.readByte();
break;
}
break;
case SMSG_PLAYER_ARROW_MESSAGE:
{
- Sint16 type = msg->readInt16();
+ Sint16 type = msg.readShort();
switch (type) {
case 0:
@@ -306,18 +283,38 @@ void PlayerHandler::handleMessage(MessageIn *msg)
}
}
break;
+ }
+}
+
+void
+PlayerHandler::handleMapChangeMessage(MessageIn &msg)
+{
+ // { "mapname", x, y, B new server [, token, "gameserver", W port] }
+
+ std::string mapName = msg.readString();
+ unsigned short x = msg.readShort();
+ unsigned short y = msg.readShort();
+ unsigned char newServer = msg.readByte();
+
+ logger->log("Changing map to %s (%d, %d) on %s server",
+ mapName.c_str(), x, y, (newServer) ? "another" : "same");
- //Stop walking
- //case 0x0088: // Disabled because giving some problems
- //if (being = beingManager->findBeing(readInt32(2))) {
- // if (being->getId() != player_node->getId()) {
- // being->action = STAND;
- // being->mFrame = 0;
- // set_coordinates(being->coordinates,
- // readWord(6), readWord(8),
- // get_direction(being->coordinates));
- // }
- //}
- //break;
+ // Switch the actual map, deleting the previous one
+ engine->changeMap(mapName);
+
+ current_npc = 0;
+
+ player_node->setAction(Being::STAND);
+ player_node->stopAttack();
+
+ player_node->mX = x;
+ player_node->mY = y;
+
+ if (newServer)
+ {
+ // TODO: Implement reconnecting to another game server
+ //std::string token = msg.readString(32);
+ //std::string gameServer = msg.readString();
+ //unsigned short gameServerPort = msg.readShort();
}
}
diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h
index b28a23f5..9b6c9e01 100644
--- a/src/net/playerhandler.h
+++ b/src/net/playerhandler.h
@@ -31,7 +31,12 @@ class PlayerHandler : public MessageHandler
public:
PlayerHandler();
- void handleMessage(MessageIn *msg);
+ void
+ handleMessage(MessageIn &msg);
+
+ private:
+ void
+ handleMapChangeMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp
deleted file mode 100644
index d3db50bf..00000000
--- a/src/net/protocol.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * The Mana World
- * Copyright 2004 The Mana World Development Team
- *
- * This file is part of The Mana World.
- *
- * The Mana World is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * The Mana World is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with The Mana World; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id$
- */
-
-#include "protocol.h"
-
-#define LOBYTE(w) ((unsigned char)(w))
-#define HIBYTE(w) ((unsigned char)(((unsigned short)(w)) >> 8))
-
-void set_coordinates(char *data,
- unsigned short x,
- unsigned short y,
- unsigned char direction)
-{
- short temp;
- temp = x;
- temp <<= 6;
- data[0] = 0;
- data[1] = 1;
- data[2] = 2;
- data[0] = HIBYTE(temp);
- data[1] = (unsigned char)(temp);
- temp = y;
- temp <<= 4;
- data[1] |= HIBYTE(temp);
- data[2] = LOBYTE(temp);
-
- // Translate direction to eAthena format
- switch (direction)
- {
- case 1:
- direction = 0;
- break;
- case 3:
- direction = 1;
- break;
- case 2:
- direction = 2;
- break;
- case 6:
- direction = 3;
- break;
- case 4:
- direction = 4;
- break;
- case 12:
- direction = 5;
- break;
- case 8:
- direction = 6;
- break;
- case 9:
- direction = 7;
- break;
- default:
- // OOPSIE! Impossible or unknown
- direction = (unsigned char)-1;
- }
- data[2] |= direction;
-}
diff --git a/src/net/protocol.h b/src/net/protocol.h
index 72b459ed..07b5c926 100644
--- a/src/net/protocol.h
+++ b/src/net/protocol.h
@@ -104,7 +104,147 @@
#define CMSG_PLAYER_EQUIP 0x00a9
#define CMSG_PLAYER_UNEQUIP 0x00ab
-/** Encodes coords and direction in 3 bytes data */
-void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction);
+/**
+ * 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)
+ */
+enum {
+ // Login/Register
+ PAMSG_REGISTER = 0x0000, // L version, S username, S password, S email
+ APMSG_REGISTER_RESPONSE = 0x0002, // B error
+ PAMSG_UNREGISTER = 0x0003, // -
+ APMSG_UNREGISTER_RESPONSE = 0x0004, // B error
+ PAMSG_LOGIN = 0x0010, // L version, S username, S password
+ APMSG_LOGIN_RESPONSE = 0x0012, // B error
+ 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, B level, W money, W*6 stats, S mapname, W*2 position
+ APMSG_CHAR_LIST_RESPONSE = 0x0025, // B number, { B index, S name, B gender, B hair style, B hair color, B level, W money, W*6 stats, S mapname, W*2 position }*
+ PAMSG_CHAR_SELECT = 0x0026, // B index
+ APMSG_CHAR_SELECT_RESPONSE = 0x0027, // B error, S mapname, W*2 position
+ PAMSG_EMAIL_CHANGE = 0x0030, // S email
+ APMSG_EMAIL_CHANGE_RESPONSE = 0x0031, // B error
+ PAMSG_EMAIL_GET = 0x0032, // -
+ APMSG_EMAIL_GET_RESPONSE = 0x0033, // B error, S email
+ PAMSG_PASSWORD_CHANGE = 0x0034, // S old password, S new password
+ APMSG_PASSWORD_CHANGE_RESPONSE = 0x0035, // B error
+ PAMSG_ENTER_WORLD = 0x0040, // -
+ APMSG_ENTER_WORLD_RESPONSE = 0x0041, // B error, S address, W port, B*32 token
+ PAMSG_ENTER_CHAT = 0x0042, // -
+ APMSG_ENTER_CHAT_RESPONSE = 0x0043, // B error, S address, W port, B*32 token
+ PGMSG_CONNECT = 0x0050, // B*32 token
+ GPMSG_CONNECT_RESPONSE = 0x0051, // B error
+ PCMSG_CONNECT = 0x0053, // B*32 token
+ CPMSG_CONNECT_RESPONSE = 0x0054, // B error
+
+ // Game
+ GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y, B newserv
+ // [, S32 token, S server, W port]
+ PGMSG_PICKUP = 0x0110,
+ GPMSG_PICKUP_RESPONSE = 0x0111,
+ GPMSG_BEING_ENTER = 0x0200, // B type, W being id
+ // player: S name, B hair style, B hair color, B gender
+ // monster: W type id
+ GPMSG_BEING_LEAVE = 0x0201, // W being id
+ PGMSG_WALK = 0x0260, // W*2 destination
+ GPMSG_BEINGS_MOVE = 0x0280, // { W being id, B flags [, C position] [, W*2 destination] }*
+ PGMSG_SAY = 0x02A0, // S text
+ GPMSG_SAY = 0x02A1, // W being id, S text
+ PGMSG_USE_ITEM = 0x0300, // L item id
+ GPMSG_USE_RESPONSE = 0x0301, // B error
+ PGMSG_EQUIP = 0x0302, // L item id, B slot
+ GPMSG_EQUIP_RESPONSE = 0x0303, // B error
+
+ // 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
+ // -- Channeling
+ PCMSG_REGISTER_CHANNEL = 0x0413, // B pub/priv, S name, S announcement, S password
+ CPMSG_REGISTER_CHANNEL_RESPONSE = 0x0414, // B error
+ PCMSG_UNREGISTER_CHANNEL = 0x0415, // W channel
+ CPMSG_UNREGISTER_CHANNEL_RESPONSE = 0x0416, // B error
+ CPMSG_CHANNEL_EVENT = 0x0418, // W channel, B event, S user
+ PCMSG_ENTER_CHANNEL = 0x0419, // W channel, S password
+ CPMSG_ENTER_CHANNEL_RESPONSE = 0x0420, // B error
+ PCMSG_QUIT_CHANNEL = 0x0421, // W channel
+ CPMSG_QUIT_CHANNEL_RESPONSE = 0x0422, // B error
+
+ 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
+};
+
+// Login specific return values
+enum {
+ LOGIN_INVALID_VERSION = 0x40, // the user is using an incompatible protocol
+ 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_INVALID_DIFF,
+ CREATE_RAW_STATS_EQUAL_TO_ZERO,
+ CREATE_EXISTS_NAME,
+ CREATE_TOO_MUCH_CHARACTERS
+};
+
+// 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
+};
#endif
diff --git a/src/net/skillhandler.cpp b/src/net/skillhandler.cpp
index e9dc9c19..d9bea775 100644
--- a/src/net/skillhandler.cpp
+++ b/src/net/skillhandler.cpp
@@ -39,27 +39,27 @@ SkillHandler::SkillHandler()
handledMessages = _messages;
}
-void SkillHandler::handleMessage(MessageIn *msg)
+void SkillHandler::handleMessage(MessageIn &msg)
{
int skillCount;
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_PLAYER_SKILLS:
- msg->readInt16(); // length
- skillCount = (msg->getLength() - 4) / 37;
+ msg.readShort(); // length
+ skillCount = (msg.getLength() - 4) / 37;
skillDialog->cleanList();
for (int k = 0; k < skillCount; k++)
{
- Sint16 skillId = msg->readInt16();
- msg->readInt16(); // target type
- msg->readInt16(); // unknown
- Sint16 level = msg->readInt16();
- Sint16 sp = msg->readInt16();
- msg->readInt16(); // range
- std::string skillName = msg->readString(24);
- Sint8 up = msg->readInt8();
+ Sint16 skillId = msg.readShort();
+ msg.readShort(); // target type
+ msg.readShort(); // unknown
+ Sint16 level = msg.readShort();
+ Sint16 sp = msg.readShort();
+ msg.readShort(); // range
+ std::string skillName = msg.readString(24);
+ Sint8 up = msg.readByte();
if (level != 0 || up != 0)
{
@@ -77,11 +77,11 @@ void SkillHandler::handleMessage(MessageIn *msg)
// Action failed (ex. sit because you have not reached the
// right level)
CHATSKILL action;
- action.skill = msg->readInt16();
- action.bskill = msg->readInt16();
- action.unused = msg->readInt16(); // unknown
- action.success = msg->readInt8();
- action.reason = msg->readInt8();
+ action.skill = msg.readShort();
+ action.bskill = msg.readShort();
+ action.unused = msg.readShort(); // unknown
+ action.success = msg.readByte();
+ action.reason = msg.readByte();
if (action.success != SKILL_FAILED &&
action.bskill == BSKILL_EMOTE)
{
diff --git a/src/net/skillhandler.h b/src/net/skillhandler.h
index 820a7b6a..8c0653d4 100644
--- a/src/net/skillhandler.h
+++ b/src/net/skillhandler.h
@@ -31,7 +31,7 @@ class SkillHandler : public MessageHandler
public:
SkillHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif
diff --git a/src/net/tradehandler.cpp b/src/net/tradehandler.cpp
index 8f9788a2..2ebc160f 100644
--- a/src/net/tradehandler.cpp
+++ b/src/net/tradehandler.cpp
@@ -41,7 +41,7 @@ std::string tradePartnerName;
namespace {
struct RequestTradeListener : public gcn::ActionListener
{
- void action(const std::string& eventId, gcn::Widget* widget)
+ void action(const std::string &eventId, gcn::Widget *widget)
{
player_node->tradeReply(eventId == "yes");
};
@@ -63,9 +63,9 @@ TradeHandler::TradeHandler()
handledMessages = _messages;
}
-void TradeHandler::handleMessage(MessageIn *msg)
+void TradeHandler::handleMessage(MessageIn &msg)
{
- switch (msg->getId())
+ switch (msg.getId())
{
case SMSG_TRADE_REQUEST:
// If a trade window or request window is already open, send a
@@ -81,7 +81,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
}
player_node->setTrading(true);
- tradePartnerName = msg->readString(24);
+ tradePartnerName = msg.readString(24);
ConfirmDialog *dlg;
dlg = new ConfirmDialog("Request for trade",
tradePartnerName +
@@ -90,7 +90,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
break;
case SMSG_TRADE_RESPONSE:
- switch (msg->readInt8())
+ switch (msg.readByte())
{
case 0: // Too far away
chatWindow->chatLog("Trading isn't possible. "
@@ -126,12 +126,11 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_ITEM_ADD:
{
- Sint32 amount = msg->readInt32();
- Sint16 type = msg->readInt16();
- msg->readInt8(); // identified flag
- msg->readInt8(); // attribute
- msg->readInt8(); // refine
- msg->skip(8); // card (4 shorts)
+ Sint32 amount = msg.readLong();
+ Sint16 type = msg.readShort();
+ msg.readByte(); // identified flag
+ msg.readByte(); // attribute
+ msg.readByte(); // refine
// TODO: handle also identified, etc
if (type == 0) {
@@ -145,10 +144,10 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_ITEM_ADD_RESPONSE:
// Trade: New Item add response (was 0x00ea, now 01b1)
{
- Item *item = player_node->getInvItem(msg->readInt16());
- Sint16 quantity = msg->readInt16();
+ Item *item = player_node->getInvItem(msg.readShort());
+ Sint16 quantity = msg.readShort();
- switch (msg->readInt8())
+ switch (msg.readByte())
{
case 0:
// Successfully added item
@@ -176,7 +175,7 @@ void TradeHandler::handleMessage(MessageIn *msg)
case SMSG_TRADE_OK:
// 0 means ok from myself, 1 means ok from other;
- tradeWindow->receivedOk(msg->readInt8() == 0);
+ tradeWindow->receivedOk(msg.readByte() == 0);
break;
case SMSG_TRADE_CANCEL:
diff --git a/src/net/tradehandler.h b/src/net/tradehandler.h
index a1971004..1ab3c2e4 100644
--- a/src/net/tradehandler.h
+++ b/src/net/tradehandler.h
@@ -26,14 +26,12 @@
#include "messagehandler.h"
-class Network;
-
class TradeHandler : public MessageHandler
{
public:
TradeHandler();
- void handleMessage(MessageIn *msg);
+ void handleMessage(MessageIn &msg);
};
#endif