summaryrefslogtreecommitdiff
path: root/src/net
diff options
context:
space:
mode:
authorHello=) <hello@themanaworld.org>2024-03-28 03:58:45 +0300
committerHello=) <hello@themanaworld.org>2024-03-28 03:58:45 +0300
commitdb0b1da0060f5eb4b2af040c22ea9373d36970af (patch)
treedc2bdc0478c341bf4368fee4993c20e52f2d41c1 /src/net
downloadguildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.tar.gz
guildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.tar.bz2
guildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.tar.xz
guildbot-db0b1da0060f5eb4b2af040c22ea9373d36970af.zip
Initial commit of Guild Bot, as seen in:
$ sha256sum guildsrc.zip ef61469ab59ce3f5dd3289505e89bd5b84e3a82b89cda90d25ae3c41f7464beb guildsrc.zip Verification shown its source 100% match to currently running version on TMWA. The following changes were made VS version found in guildsrc.zip: 1) src/build and src/dist content completely removed. Rationale: build-time artifacts; binaries contained login/password. 2) Executable flag (+x) removed from src/automation.cpp and src/main.cpp. Rationale: executable CPP sources are weird thing. No change to file content. 3) src/main.cpp changes: 3 lines: std::string main_username = "test"; std::string main_pw = "test"; std::string main_host = "127.0.0.1"; Rationale: avoid leaking real production credentials and ensure experimenters dont hammer real TMW prod server by experiments. Effort been made to preserve original file timestamps, etc. However toplevel src/ dir date adjusted to date of mentioned changes.
Diffstat (limited to 'src/net')
-rw-r--r--src/net/charserverhandler.cpp166
-rw-r--r--src/net/charserverhandler.cpp~167
-rw-r--r--src/net/charserverhandler.h52
-rw-r--r--src/net/chathandler.cpp146
-rw-r--r--src/net/chathandler.cpp~147
-rw-r--r--src/net/chathandler.h38
-rw-r--r--src/net/loginhandler.cpp126
-rw-r--r--src/net/loginhandler.cpp~119
-rw-r--r--src/net/loginhandler.h45
-rw-r--r--src/net/maploginhandler.cpp62
-rw-r--r--src/net/maploginhandler.cpp~62
-rw-r--r--src/net/maploginhandler.h37
-rw-r--r--src/net/messagehandler.cpp45
-rw-r--r--src/net/messagehandler.h48
-rw-r--r--src/net/messagein.cpp198
-rw-r--r--src/net/messagein.h97
-rw-r--r--src/net/messageout.cpp116
-rw-r--r--src/net/messageout.h65
-rw-r--r--src/net/nethandler.cpp182
-rw-r--r--src/net/nethandler.cpp~183
-rw-r--r--src/net/nethandler.h33
-rw-r--r--src/net/network.cpp442
-rw-r--r--src/net/network.cpp~443
-rw-r--r--src/net/network.h103
-rw-r--r--src/net/packet.cpp40
-rw-r--r--src/net/packet.h47
-rw-r--r--src/net/protocol.cpp79
-rw-r--r--src/net/protocol.h118
28 files changed, 3406 insertions, 0 deletions
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
new file mode 100644
index 0000000..d500c0d
--- /dev/null
+++ b/src/net/charserverhandler.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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: charserverhandler.cpp 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#include "charserverhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../game.h"
+#include "../logindata.h"
+#include "../main.h"
+
+CharServerHandler::CharServerHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x006b,
+ 0x006c,
+ 0x006d,
+ 0x0071,
+ 0x0081,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void CharServerHandler::handleMessage(MessageIn *msg)
+{
+ int slot;
+
+ /* logger->log("CharServerHandler: Packet ID: %x, Length: %d",
+ msg->getId(), msg->getLength());*/
+ switch (msg->getId())
+ {
+ case 0x006b:
+ {
+ int tmpCharID[3];
+ // 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;
+
+ for (int i = 0; i < n_character; i++)
+ {
+
+ tmpCharID[i] = msg->readInt32();
+ msg->readInt32(); //xp
+ msg->readInt32(); //gp
+ msg->readInt32(); //jobxp
+ msg->readInt32(); //joblvl
+ msg->skip(8); // unknown
+ msg->readInt32(); // option
+ msg->readInt32(); // karma
+ msg->readInt32(); // manner
+ msg->skip(2); // unknown
+ msg->readInt16(); //hp
+ msg->readInt16(); //maxhp
+ msg->readInt16(); //mp
+ msg->readInt16(); //maxmp
+ msg->readInt16(); // speed
+ msg->readInt16(); // class
+ msg->readInt16(); //hair
+ msg->readInt16(); //weapon
+ msg->readInt16(); //lvl
+ msg->readInt16(); // skill point
+ msg->readInt16(); // head bottom
+ msg->readInt16(); // shield
+ msg->readInt16(); // head option top
+ msg->readInt16(); // head option mid
+ msg->readInt16(); // hair color
+ msg->readInt16(); // unknown
+ std::string charname = msg->readString(24);
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ int slot = msg->readInt8(); // character slot
+ charID[slot] = tmpCharID[i]; /* Get the Character Id's, needed for map server.*/
+ msg->readInt8(); // unknown
+
+ if (slot == main_charno)
+ char_name = charname;
+
+ /* logger->log("CharServer: Player: %s (%d)",
+ charname.c_str(), slot);*/
+ }
+
+ 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;
+ }
+ break;
+
+ case 0x006d:
+ state = CONNECTING_STATE;
+ break;
+
+ case 0x0071:
+ {
+ msg->skip(4); // CharID, the same as the one we've already recieved.
+ map_path = msg->readString(16);
+ mLoginData->hostname = iptostring(msg->readInt32());
+ mLoginData->port = msg->readInt16();
+ /*logger->log("Map: Server: %s (%s:%d)",
+ map_path.c_str(),
+ mLoginData->hostname.c_str(),
+ mLoginData->port);*/
+
+ state = CONNECTING_STATE;
+ break;
+ }
+
+ 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;
+ };
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/charserverhandler.cpp~ b/src/net/charserverhandler.cpp~
new file mode 100644
index 0000000..ea08c00
--- /dev/null
+++ b/src/net/charserverhandler.cpp~
@@ -0,0 +1,167 @@
+/*
+ * 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: charserverhandler.cpp 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#include "charserverhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../game.h"
+#include "../log.h"
+#include "../logindata.h"
+#include "../main.h"
+
+CharServerHandler::CharServerHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x006b,
+ 0x006c,
+ 0x006d,
+ 0x0071,
+ 0x0081,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void CharServerHandler::handleMessage(MessageIn *msg)
+{
+ int slot;
+
+ /* logger->log("CharServerHandler: Packet ID: %x, Length: %d",
+ msg->getId(), msg->getLength());*/
+ switch (msg->getId())
+ {
+ case 0x006b:
+ {
+ int tmpCharID[3];
+ // 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;
+
+ for (int i = 0; i < n_character; i++)
+ {
+
+ tmpCharID[i] = msg->readInt32();
+ msg->readInt32(); //xp
+ msg->readInt32(); //gp
+ msg->readInt32(); //jobxp
+ msg->readInt32(); //joblvl
+ msg->skip(8); // unknown
+ msg->readInt32(); // option
+ msg->readInt32(); // karma
+ msg->readInt32(); // manner
+ msg->skip(2); // unknown
+ msg->readInt16(); //hp
+ msg->readInt16(); //maxhp
+ msg->readInt16(); //mp
+ msg->readInt16(); //maxmp
+ msg->readInt16(); // speed
+ msg->readInt16(); // class
+ msg->readInt16(); //hair
+ msg->readInt16(); //weapon
+ msg->readInt16(); //lvl
+ msg->readInt16(); // skill point
+ msg->readInt16(); // head bottom
+ msg->readInt16(); // shield
+ msg->readInt16(); // head option top
+ msg->readInt16(); // head option mid
+ msg->readInt16(); // hair color
+ msg->readInt16(); // unknown
+ std::string charname = msg->readString(24);
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ msg->readInt8(); //ATTR
+ int slot = msg->readInt8(); // character slot
+ charID[slot] = tmpCharID[i]; /* Get the Character Id's, needed for map server.*/
+ msg->readInt8(); // unknown
+
+ if (slot == main_charno)
+ char_name = charname;
+
+ /* logger->log("CharServer: Player: %s (%d)",
+ charname.c_str(), slot);*/
+ }
+
+ 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;
+ }
+ break;
+
+ case 0x006d:
+ state = CONNECTING_STATE;
+ break;
+
+ case 0x0071:
+ {
+ msg->skip(4); // CharID, the same as the one we've already recieved.
+ map_path = msg->readString(16);
+ mLoginData->hostname = iptostring(msg->readInt32());
+ mLoginData->port = msg->readInt16();
+ /*logger->log("Map: Server: %s (%s:%d)",
+ map_path.c_str(),
+ mLoginData->hostname.c_str(),
+ mLoginData->port);*/
+
+ state = CONNECTING_STATE;
+ break;
+ }
+
+ 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;
+ };
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/charserverhandler.h b/src/net/charserverhandler.h
new file mode 100644
index 0000000..c6303a5
--- /dev/null
+++ b/src/net/charserverhandler.h
@@ -0,0 +1,52 @@
+/*
+ * 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: charserverhandler.h 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#ifndef _TMW_NET_CHARSERVERHANDLER_H
+#define _TMW_NET_CHARSERVERHANDLER_H
+
+#include "messagehandler.h"
+
+//#include "../lockedarray.h"
+
+class LocalPlayer;
+class LoginData;
+
+class CharServerHandler : public MessageHandler
+{
+ public:
+ CharServerHandler();
+
+ void handleMessage(MessageIn *msg);
+
+ //void setCharInfo(LockedArray<LocalPlayer*> *charInfo) { mCharInfo = charInfo; };
+
+ void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+
+ protected:
+ LoginData *mLoginData;
+ //LockedArray<LocalPlayer*> *mCharInfo;
+
+ //LocalPlayer* readPlayerData(MessageIn *msg, int &slot);
+};
+
+#endif
diff --git a/src/net/chathandler.cpp b/src/net/chathandler.cpp
new file mode 100644
index 0000000..19abc24
--- /dev/null
+++ b/src/net/chathandler.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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: chathandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "chathandler.h"
+
+#include <SDL_types.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+
+#include "messagein.h"
+#include "protocol.h"
+#include "messageout.h"
+#include "../automation.h"
+#include "../game.h"
+#include "../utils/stringutils.h"
+#include "nethandler.h"
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_CHAT,
+ SMSG_PLAYER_CHAT,
+ SMSG_WHISPER,
+ SMSG_WHISPER_RESPONSE,
+ SMSG_GM_CHAT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ChatHandler::handleMessage(MessageIn *msg)
+{
+ //Being *being;
+ std::string chatMsg;
+ std::stringstream ss;
+ Sint16 chatMsgLength;
+
+ switch (msg->getId())
+ {
+ // Received speech from being
+ case SMSG_BEING_CHAT:
+ {
+
+ chatMsgLength = msg->readInt16() - 8;
+ msg->readInt32();
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ std::string sender_name = ((pos == std::string::npos)
+ ? ""
+ : chatMsg.substr(0, pos));
+
+ std::string mess = chatMsg.substr(pos+3);
+ // do something with chat
+ break;
+ }
+ case SMSG_WHISPER:
+ {
+ chatMsgLength = msg->readInt16() - 28;
+ std::string nick = msg->readString(24);
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+ Automation::getAutomationHandler()->commandHandler(chatMsg, nick);
+
+ break;
+ }
+ case SMSG_WHISPER_RESPONSE:
+ {
+ int type = msg->readInt8();
+ switch (type)
+ {
+ case 0x00:
+ break;
+ case 0x01:
+ //logger->log("Whisper could not be sent, user is offline.");
+ break;
+ case 0x02:
+ //logger->log("Whisper could not be sent, ignored by user.");
+ break;
+ default:
+ /*if (logger)
+ logger->log("Unkown Whisper Response.");*/
+ break;
+ }
+ break;
+ }
+ case SMSG_PLAYER_CHAT:
+ case SMSG_GM_CHAT:
+ {
+ chatMsgLength = msg->readInt16() - 4;
+
+ if (chatMsgLength <= 0)
+ {
+ break;
+ }
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ if (msg->getId() == SMSG_PLAYER_CHAT)
+ {
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ if (pos != std::string::npos)
+ {
+ chatMsg.erase(0, pos + 3);
+ }
+ //player_node->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ //chatWindow->chatLog(chatMsg, BY_GM);
+ }
+ break;
+ }
+
+
+ }
+}
diff --git a/src/net/chathandler.cpp~ b/src/net/chathandler.cpp~
new file mode 100644
index 0000000..cb4c32c
--- /dev/null
+++ b/src/net/chathandler.cpp~
@@ -0,0 +1,147 @@
+/*
+ * 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: chathandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "chathandler.h"
+
+#include <SDL_types.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+
+#include "messagein.h"
+#include "protocol.h"
+#include "messageout.h"
+#include "../automation.h"
+#include "../game.h"
+#include "../utils/stringutils.h"
+#include "../log.h"
+#include "nethandler.h"
+
+ChatHandler::ChatHandler()
+{
+ static const Uint16 _messages[] = {
+ SMSG_BEING_CHAT,
+ SMSG_PLAYER_CHAT,
+ SMSG_WHISPER,
+ SMSG_WHISPER_RESPONSE,
+ SMSG_GM_CHAT,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void ChatHandler::handleMessage(MessageIn *msg)
+{
+ //Being *being;
+ std::string chatMsg;
+ std::stringstream ss;
+ Sint16 chatMsgLength;
+
+ switch (msg->getId())
+ {
+ // Received speech from being
+ case SMSG_BEING_CHAT:
+ {
+
+ chatMsgLength = msg->readInt16() - 8;
+ msg->readInt32();
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ std::string sender_name = ((pos == std::string::npos)
+ ? ""
+ : chatMsg.substr(0, pos));
+
+ std::string mess = chatMsg.substr(pos+3);
+ // do something with chat
+ break;
+ }
+ case SMSG_WHISPER:
+ {
+ chatMsgLength = msg->readInt16() - 28;
+ std::string nick = msg->readString(24);
+
+ if (chatMsgLength <= 0)
+ break;
+
+ chatMsg = msg->readString(chatMsgLength);
+ Automation::getAutomationHandler()->commandHandler(chatMsg, nick);
+
+ break;
+ }
+ case SMSG_WHISPER_RESPONSE:
+ {
+ int type = msg->readInt8();
+ switch (type)
+ {
+ case 0x00:
+ break;
+ case 0x01:
+ //logger->log("Whisper could not be sent, user is offline.");
+ break;
+ case 0x02:
+ //logger->log("Whisper could not be sent, ignored by user.");
+ break;
+ default:
+ /*if (logger)
+ logger->log("Unkown Whisper Response.");*/
+ break;
+ }
+ break;
+ }
+ case SMSG_PLAYER_CHAT:
+ case SMSG_GM_CHAT:
+ {
+ chatMsgLength = msg->readInt16() - 4;
+
+ if (chatMsgLength <= 0)
+ {
+ break;
+ }
+
+ chatMsg = msg->readString(chatMsgLength);
+
+ if (msg->getId() == SMSG_PLAYER_CHAT)
+ {
+
+ std::string::size_type pos = chatMsg.find(" : ", 0);
+ if (pos != std::string::npos)
+ {
+ chatMsg.erase(0, pos + 3);
+ }
+ //player_node->setSpeech(chatMsg, SPEECH_TIME);
+ }
+ else
+ {
+ //chatWindow->chatLog(chatMsg, BY_GM);
+ }
+ break;
+ }
+
+
+ }
+} \ No newline at end of file
diff --git a/src/net/chathandler.h b/src/net/chathandler.h
new file mode 100644
index 0000000..25874f0
--- /dev/null
+++ b/src/net/chathandler.h
@@ -0,0 +1,38 @@
+/*
+ * 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: chathandler.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_NET_CHATHANDLER_H
+#define _TMW_NET_CHATHANDLER_H
+
+#include "messagehandler.h"
+#include <string>
+
+class ChatHandler : public MessageHandler
+{
+ public:
+ ChatHandler();
+
+ void handleMessage(MessageIn *msg);
+};
+
+#endif
diff --git a/src/net/loginhandler.cpp b/src/net/loginhandler.cpp
new file mode 100644
index 0000000..b6f5b98
--- /dev/null
+++ b/src/net/loginhandler.cpp
@@ -0,0 +1,126 @@
+/*
+ * 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: loginhandler.cpp 2184 2006-02-23 16:02:00Z der_doener $
+ */
+
+#include <stdio.h>
+
+#include "loginhandler.h"
+
+#include "messagein.h"
+#include "network.h"
+#include "protocol.h"
+
+#include "../logindata.h"
+#include "../main.h"
+#include "../serverinfo.h"
+
+extern SERVER_INFO **server_info;
+
+LoginHandler::LoginHandler()
+{
+ static const Uint16 _messages[] = {
+ 0x0063,
+ 0x0069,
+ 0x006a,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LoginHandler::handleMessage(MessageIn *msg)
+{
+ switch (msg->getId())
+ {
+ case 0x0063:
+ // This is the update host. The bot doesn't need it.
+ msg->skip(2);
+ msg->skip(msg->getLength() - 4);
+ break;
+
+ 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++)
+ {
+ 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);
+
+ if (server_info[i]->name == "The Mana World")
+ world = i;
+
+ server_info[i]->online_users = msg->readInt16();
+ msg->skip(4); // unknown
+
+ /*logger->log("Network: Server: %s (%s:%d)",
+ server_info[i]->name.c_str(),
+ iptostring(server_info[i]->address),
+ server_info[i]->port);*/
+ }
+ state = CHAR_SERVER_STATE;
+ 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;
+ }
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/loginhandler.cpp~ b/src/net/loginhandler.cpp~
new file mode 100644
index 0000000..070127e
--- /dev/null
+++ b/src/net/loginhandler.cpp~
@@ -0,0 +1,119 @@
+/*
+ * 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: loginhandler.cpp 2184 2006-02-23 16:02:00Z der_doener $
+ */
+
+#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,
+ 0
+ };
+ handledMessages = _messages;
+}
+
+void LoginHandler::handleMessage(MessageIn *msg)
+{
+ 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++)
+ {
+ 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);
+
+ if (server_info[i]->name == "The Mana World")
+ world = i;
+
+ 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 = CHAR_SERVER_STATE;
+ 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;
+ }
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/loginhandler.h b/src/net/loginhandler.h
new file mode 100644
index 0000000..7a8feef
--- /dev/null
+++ b/src/net/loginhandler.h
@@ -0,0 +1,45 @@
+/*
+ * 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: loginhandler.h 2137 2006-02-04 16:54:35Z der_doener $
+ */
+
+#ifndef _TMW_NET_LOGINHANDLER_H
+#define _TMW_NET_LOGINHANDLER_H
+
+#include "messagehandler.h"
+#include "../serverinfo.h"
+
+struct LoginData;
+
+class LoginHandler : public MessageHandler
+{
+ public:
+ LoginHandler();
+
+ void handleMessage(MessageIn *msg);
+
+ void setLoginData(LoginData *loginData) { mLoginData = loginData; };
+
+ protected:
+ LoginData *mLoginData;
+};
+
+#endif
diff --git a/src/net/maploginhandler.cpp b/src/net/maploginhandler.cpp
new file mode 100644
index 0000000..1b0c4e7
--- /dev/null
+++ b/src/net/maploginhandler.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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: maploginhandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "maploginhandler.h"
+
+#include "messagein.h"
+#include "protocol.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
+ unsigned short startX, startY;
+ msg->readCoordinates(startX, startY, direction);
+ msg->skip(2); // unknown
+ /*logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
+ startX, startX, direction);*/
+ state = GAME_STATE;
+ break;
+
+ case 0x0081:
+ /*logger->log("Warning: Map server D/C");*/
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/maploginhandler.cpp~ b/src/net/maploginhandler.cpp~
new file mode 100644
index 0000000..1b0c4e7
--- /dev/null
+++ b/src/net/maploginhandler.cpp~
@@ -0,0 +1,62 @@
+/*
+ * 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: maploginhandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "maploginhandler.h"
+
+#include "messagein.h"
+#include "protocol.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
+ unsigned short startX, startY;
+ msg->readCoordinates(startX, startY, direction);
+ msg->skip(2); // unknown
+ /*logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
+ startX, startX, direction);*/
+ state = GAME_STATE;
+ break;
+
+ case 0x0081:
+ /*logger->log("Warning: Map server D/C");*/
+ state = ERROR_STATE;
+ break;
+ }
+}
diff --git a/src/net/maploginhandler.h b/src/net/maploginhandler.h
new file mode 100644
index 0000000..6ff6bc0
--- /dev/null
+++ b/src/net/maploginhandler.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: maploginhandler.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_NET_MAPLOGINHANDLER_H
+#define _TMW_NET_MAPLOGINHANDLER_H
+
+#include "messagehandler.h"
+
+class MapLoginHandler : public MessageHandler
+{
+ public:
+ MapLoginHandler();
+
+ void handleMessage(MessageIn *msg);
+};
+
+#endif
diff --git a/src/net/messagehandler.cpp b/src/net/messagehandler.cpp
new file mode 100644
index 0000000..370a01a
--- /dev/null
+++ b/src/net/messagehandler.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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: messagehandler.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "messagehandler.h"
+
+#include <cassert>
+
+#include "network.h"
+
+MessageHandler::MessageHandler():
+ mNetwork(0)
+{
+}
+
+MessageHandler::~MessageHandler()
+{
+ if (mNetwork)
+ mNetwork->unregisterHandler(this);
+}
+
+void MessageHandler::setNetwork(Network *network)
+{
+ assert(!(network && mNetwork));
+ mNetwork = network;
+}
diff --git a/src/net/messagehandler.h b/src/net/messagehandler.h
new file mode 100644
index 0000000..90ffa48
--- /dev/null
+++ b/src/net/messagehandler.h
@@ -0,0 +1,48 @@
+/*
+ * 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: messagehandler.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_NET_MESSAGEHANDLER_H
+#define _TMW_NET_MESSAGEHANDLER_H
+
+#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;
+};
+
+#endif
diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp
new file mode 100644
index 0000000..192e857
--- /dev/null
+++ b/src/net/messagein.cpp
@@ -0,0 +1,198 @@
+/*
+ * 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: messagein.cpp 2158 2006-02-07 10:37:54Z der_doener $
+ */
+
+#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))
+
+
+MessageIn::MessageIn(const char *data, unsigned int length):
+ mData(data),
+ mLength(length),
+ mPos(0)
+{
+ // Read the message ID
+ mId = readInt16();
+}
+
+Sint8
+MessageIn::readInt8()
+{
+ 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()
+{
+ 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
+}
+
+void
+MessageIn::readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction)
+{
+ 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)
+ {
+ 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;
+ }
+
+ mPos += 3;
+}
+
+void
+MessageIn::readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY)
+{
+ 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;
+}
+
+void
+MessageIn::skip(unsigned int length)
+{
+ assert(mPos + length <= mLength);
+ mPos += length;
+}
+
+std::string
+MessageIn::readString(int length)
+{
+ int stringLength = 0;
+
+ // Get string length
+ if (length < 0) {
+ stringLength = readInt16();
+ } else {
+ stringLength = length;
+ }
+
+ // Make sure there is enough data available
+ assert(mPos + length <= mLength);
+
+ // Read the string
+ char *tmpString = new char[stringLength + 1];
+ memcpy(tmpString, (void*)&mData[mPos], stringLength);
+ tmpString[stringLength] = 0;
+ mPos += stringLength;
+
+ std::string read = tmpString;
+ delete[] tmpString;
+
+ return read;
+}
+
+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
new file mode 100644
index 0000000..0a6b8b8
--- /dev/null
+++ b/src/net/messagein.h
@@ -0,0 +1,97 @@
+/*
+ * 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: messagein.h 1879 2005-10-16 21:18:11Z der_doener $
+ */
+
+#ifndef _TMW_MESSAGEIN_
+#define _TMW_MESSAGEIN_
+
+#include <string>
+#include <SDL_types.h>
+
+/**
+ * Used for parsing an incoming message.
+ */
+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.
+ */
+ MessageIn(const char *data, unsigned int length);
+
+ /**
+ * Returns the message ID.
+ */
+ short
+ getId() { return mId; }
+
+ /**
+ * Returns the message length.
+ */
+ unsigned int
+ getLength() { return mLength; }
+
+ Sint8 readInt8(); /**< Reads a byte. */
+ Sint16 readInt16(); /**< Reads a short. */
+ Sint32 readInt32(); /**< Reads a long. */
+
+ /**
+ * Reads a special 3 byte block used by eAthena, containing x and y
+ * coordinates and direction.
+ */
+ void
+ readCoordinates(Uint16 &x, Uint16 &y, Uint8 &direction);
+
+ /**
+ * Reads a special 5 byte block used by eAthena, containing a source
+ * and destination coordinate pair.
+ */
+ void
+ readCoordinatePair(Uint16 &srcX, Uint16 &srcY,
+ Uint16 &dstX, Uint16 &dstY);
+
+ /**
+ * Skips a given number of bytes.
+ */
+ void
+ skip(unsigned int length);
+
+ /**
+ * 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.
+ */
+ std::string
+ readString(int length = -1);
+
+ 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. */
+};
+
+#endif
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
new file mode 100644
index 0000000..b6a826c
--- /dev/null
+++ b/src/net/messageout.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: messageout.cpp 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#include "messageout.h"
+
+#include <string>
+#include <SDL.h>
+#include <SDL_endian.h>
+
+#include "network.h"
+#include "packet.h"
+
+MessageOut::MessageOut(Network *network):
+ mNetwork(network),
+ mData(0),
+ mDataSize(0),
+ mPos(0)
+{
+ mData = mNetwork->mOutBuffer + mNetwork->mOutSize;
+}
+
+void MessageOut::writeInt8(Sint8 value)
+{
+ mData[mPos] = value;
+ mPos += sizeof(Sint8);
+ mNetwork->mOutSize+= sizeof(Sint8);
+}
+
+void MessageOut::writeInt16(Sint16 value)
+{
+#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);
+}
+
+void MessageOut::writeInt32(Sint32 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);
+}
+
+void MessageOut::writeString(const std::string &string, int length)
+{
+ std::string toWrite = string;
+
+ if (length < 0)
+ {
+ // Write the length at the start if not fixed
+ writeInt16(string.length());
+ }
+ else
+ {
+ // Make sure the length of the string is no longer than specified
+ toWrite = string.substr(0, length);
+ }
+
+ // Write the actual string
+ memcpy(&mData[mPos], (void*)toWrite.c_str(), toWrite.length());
+ mPos += toWrite.length();
+ mNetwork->mOutSize += toWrite.length();
+
+ // Pad remaining space with zeros
+ if (length > (int)toWrite.length())
+ {
+ memset(&mData[mPos], '\0', length - toWrite.length());
+ mPos += length - toWrite.length();
+ mNetwork->mOutSize += length - toWrite.length();
+ }
+}
+
+MessageOut& operator<<(MessageOut &msg, const Sint8 &rhs)
+{
+ msg.writeInt8(rhs);
+ return msg;
+}
+
+MessageOut& operator<<(MessageOut &msg, const Sint16 &rhs)
+{
+ msg.writeInt16(rhs);
+ return msg;
+}
+
+MessageOut& operator<<(MessageOut &msg, const Sint32 &rhs)
+{
+ msg.writeInt32(rhs);
+ return msg;
+}
diff --git a/src/net/messageout.h b/src/net/messageout.h
new file mode 100644
index 0000000..33deb1b
--- /dev/null
+++ b/src/net/messageout.h
@@ -0,0 +1,65 @@
+/*
+ * 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: messageout.h 2112 2006-01-22 13:31:13Z der_doener $
+ */
+
+#ifndef _TMW_MESSAGEOUT_
+#define _TMW_MESSAGEOUT_
+
+#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);
+
+ void writeInt8(Sint8 value); /**< Writes a byte. */
+ void writeInt16(Sint16 value); /**< Writes a short. */
+ void writeInt32(Sint32 value); /**< Writes a long. */
+
+ /**
+ * Writes a string. If a fixed length is not given (-1), it is stored
+ * as a short at the start of the string.
+ */
+ void writeString(const std::string &string, int length = -1);
+
+ private:
+ Network *mNetwork;
+
+ char *mData; /**< Data building up. */
+ unsigned int mDataSize; /**< Size of data. */
+ unsigned int mPos; /**< Position in the data. */
+};
+
+#endif
diff --git a/src/net/nethandler.cpp b/src/net/nethandler.cpp
new file mode 100644
index 0000000..8021e55
--- /dev/null
+++ b/src/net/nethandler.cpp
@@ -0,0 +1,182 @@
+#include "nethandler.h"
+#include "network.h"
+#include "protocol.h"
+#include "messageout.h"
+
+#include "loginhandler.h"
+#include "chathandler.h"
+#include "charserverhandler.h"
+#include "maploginhandler.h"
+
+#include "../main.h"
+#include "../game.h"
+
+static NetHandler *NetInstance = NULL;
+static Network *mNetwork = NULL;
+MessageHandler *mChatHandler = NULL;
+
+LoginHandler loginHandler;
+CharServerHandler charServerHandler;
+MapLoginHandler mapLoginHandler;
+
+NetHandler::NetHandler()
+{
+ NetInstance = this;
+}
+
+NetHandler::~NetHandler()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL)
+ delete mChatHandler;
+
+ delete NetInstance;
+}
+
+void NetHandler::clean_up()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL) // fix a crash caused by map server D/C
+ delete mChatHandler;
+
+ mNetwork = new Network();
+}
+
+NetHandler *NetHandler::getNetInstance()
+{
+ return NetInstance;
+}
+
+Network *NetHandler::getNetwork()
+{
+ if (mNetwork == NULL)
+ mNetwork = new Network();
+
+ return mNetwork;
+}
+
+void NetHandler::loadHandlers()
+{
+ mChatHandler = new ChatHandler();
+ mNetwork->registerHandler(mChatHandler);
+}
+
+// All code related to login, from main.cpp
+
+void NetHandler::accountLogin(LoginData *loginData)
+{
+ /*
+ logger->log("Trying to connect to account server...");
+ logger->log("Username is %s", loginData->username.c_str());*/
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&loginHandler);
+ loginHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0064);
+ outMsg.writeInt32(9); // client version
+ outMsg.writeString(loginData->username, 24);
+ outMsg.writeString(loginData->password, 24);
+ outMsg.writeInt8(1 | 2); // flags
+}
+
+void NetHandler::charLogin(LoginData *loginData)
+{
+ /*logger->log("Trying to connect to char server...");
+
+ logger->log("Server: %s (%s:%d)",
+ server_info[0]->name.c_str(),
+ loginData->hostname.c_str(),
+ loginData->port);*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&charServerHandler);
+ charServerHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0065);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt16(1); // this should match MIN_CLIENT_VERSION in tmwa/src/char/char.hpp
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+void NetHandler::mapLogin(LoginData *loginData)
+{
+ MessageOut outMsg(mNetwork);
+
+ /*logger->log("Trying to connect to map server...");
+ logger->log("Map: %s", map_path.c_str());*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&mapLoginHandler);
+
+ // Send login infos
+ outMsg.writeInt16(0x0072);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(charID[main_charno]);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+// add a few of the packets that need to be sent.
+void NetHandler::attemptCharSelect()
+{
+ /*logger->log("CharServer: Character Select: %s",
+ char_name.c_str());*/
+ // Request character selection
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0066);
+ outMsg.writeInt8(main_charno);
+}
+
+void NetHandler::mapLoaded()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_MAP_LOADED);
+}
+
+void NetHandler::privateMessage(std::string name, std::string msg)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_WHISPER);
+ outMsg.writeInt16(static_cast<short>(msg.length() + 28));
+ outMsg.writeString(name, 24);
+ outMsg.writeString(msg, static_cast<int>(msg.length()));
+}
+
+void NetHandler::publicMessage(std::string msg)
+{
+ std::string mes = std::string("guild") + " : " + msg;
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_MESSAGE);
+ outMsg.writeInt16(static_cast<short>(mes.length() + 4 + 1));
+ outMsg.writeString(mes, static_cast<int>(mes.length() + 1));
+}
+
+void NetHandler::sit()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_CHANGE_ACT);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(2);
+}
+
+void NetHandler::ping(int tick)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CLIENT_PING);
+ outMsg.writeInt32(tick);
+}
diff --git a/src/net/nethandler.cpp~ b/src/net/nethandler.cpp~
new file mode 100644
index 0000000..d6f031e
--- /dev/null
+++ b/src/net/nethandler.cpp~
@@ -0,0 +1,183 @@
+#include "nethandler.h"
+#include "network.h"
+#include "protocol.h"
+#include "messageout.h"
+
+#include "loginhandler.h"
+#include "chathandler.h"
+#include "charserverhandler.h"
+#include "maploginhandler.h"
+
+#include "../log.h"
+#include "../main.h"
+#include "../game.h"
+
+static NetHandler *NetInstance = NULL;
+static Network *mNetwork = NULL;
+MessageHandler *mChatHandler = NULL;
+
+LoginHandler loginHandler;
+CharServerHandler charServerHandler;
+MapLoginHandler mapLoginHandler;
+
+NetHandler::NetHandler()
+{
+ NetInstance = this;
+}
+
+NetHandler::~NetHandler()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL)
+ delete mChatHandler;
+
+ delete NetInstance;
+}
+
+void NetHandler::clean_up()
+{
+ delete mNetwork;
+
+ if (mChatHandler != NULL) // fix a crash caused by map server D/C
+ delete mChatHandler;
+
+ mNetwork = new Network();
+}
+
+NetHandler *NetHandler::getNetInstance()
+{
+ return NetInstance;
+}
+
+Network *NetHandler::getNetwork()
+{
+ if (mNetwork == NULL)
+ mNetwork = new Network();
+
+ return mNetwork;
+}
+
+void NetHandler::loadHandlers()
+{
+ mChatHandler = new ChatHandler();
+ mNetwork->registerHandler(mChatHandler);
+}
+
+// All code related to login, from main.cpp
+
+void NetHandler::accountLogin(LoginData *loginData)
+{
+ /*
+ logger->log("Trying to connect to account server...");
+ logger->log("Username is %s", loginData->username.c_str());*/
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&loginHandler);
+ loginHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0064);
+ outMsg.writeInt32(0); // client version
+ outMsg.writeString(loginData->username, 24);
+ outMsg.writeString(loginData->password, 24);
+ outMsg.writeInt8(0); // unknown
+}
+
+void NetHandler::charLogin(LoginData *loginData)
+{
+ /*logger->log("Trying to connect to char server...");
+
+ logger->log("Server: %s (%s:%d)",
+ server_info[0]->name.c_str(),
+ loginData->hostname.c_str(),
+ loginData->port);*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&charServerHandler);
+ charServerHandler.setLoginData(loginData);
+
+ // Send login infos
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0065);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt16(0); // unknown
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+void NetHandler::mapLogin(LoginData *loginData)
+{
+ MessageOut outMsg(mNetwork);
+
+ /*logger->log("Trying to connect to map server...");
+ logger->log("Map: %s", map_path.c_str());*/
+
+ mNetwork->connect(loginData->hostname, loginData->port);
+ mNetwork->registerHandler(&mapLoginHandler);
+
+ // Send login infos
+ outMsg.writeInt16(0x0072);
+ outMsg.writeInt32(loginData->account_ID);
+ outMsg.writeInt32(charID[main_charno]);
+ outMsg.writeInt32(loginData->session_ID1);
+ outMsg.writeInt32(loginData->session_ID2);
+ outMsg.writeInt8(loginData->sex);
+
+ // We get 4 useless bytes before the real answer comes in
+ mNetwork->skip(4);
+}
+
+// add a few of the packets that need to be sent.
+void NetHandler::attemptCharSelect()
+{
+ /*logger->log("CharServer: Character Select: %s",
+ char_name.c_str());*/
+ // Request character selection
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(0x0066);
+ outMsg.writeInt8(main_charno);
+}
+
+void NetHandler::mapLoaded()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_MAP_LOADED);
+}
+
+void NetHandler::privateMessage(std::string name, std::string msg)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_WHISPER);
+ outMsg.writeInt16(static_cast<short>(msg.length() + 28));
+ outMsg.writeString(name, 24);
+ outMsg.writeString(msg, static_cast<int>(msg.length()));
+}
+
+void NetHandler::publicMessage(std::string msg)
+{
+ std::string mes = std::string("guild") + " : " + msg;
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CHAT_MESSAGE);
+ outMsg.writeInt16(static_cast<short>(mes.length() + 4 + 1));
+ outMsg.writeString(mes, static_cast<int>(mes.length() + 1));
+}
+
+void NetHandler::sit()
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_PLAYER_CHANGE_ACT);
+ outMsg.writeInt32(0);
+ outMsg.writeInt8(2);
+}
+
+void NetHandler::ping(int tick)
+{
+ MessageOut outMsg(mNetwork);
+ outMsg.writeInt16(CMSG_CLIENT_PING);
+ outMsg.writeInt32(tick);
+} \ No newline at end of file
diff --git a/src/net/nethandler.h b/src/net/nethandler.h
new file mode 100644
index 0000000..41f523c
--- /dev/null
+++ b/src/net/nethandler.h
@@ -0,0 +1,33 @@
+#include "network.h"
+
+#include "loginhandler.h"
+#include "../logindata.h"
+
+class NetHandler
+{
+
+
+public:
+
+ NetHandler();
+ ~NetHandler();
+
+ static NetHandler *getNetInstance();
+
+ void loadHandlers();
+ Network *getNetwork();
+ void clean_up(); // for restart
+
+ void accountLogin(LoginData *loginData);
+ void charLogin(LoginData *loginData);
+ void mapLogin(LoginData *loginData);
+ void attemptCharSelect();
+
+ void mapLoaded();
+ void privateMessage(std::string name, std::string msg);
+ void publicMessage(std::string msg);
+ void ping(int tick);
+ void sit();
+private:
+
+};
diff --git a/src/net/network.cpp b/src/net/network.cpp
new file mode 100644
index 0000000..e4c6e65
--- /dev/null
+++ b/src/net/network.cpp
@@ -0,0 +1,442 @@
+/*
+ * 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: network.cpp 2187 2006-02-24 20:15:19Z der_doener $
+ */
+
+#include "network.h"
+
+#include "messagehandler.h"
+#include "messagein.h"
+
+#include "../main.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, -1, 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, 4, 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;
+}
+
+Network::Network():
+ 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();
+}
+
+Network::~Network()
+{
+ clearHandlers();
+
+ if (mState != IDLE && mState != ERROR_BROKE)
+ disconnect();
+
+ SDL_DestroyMutex(mMutex);
+
+ delete mInBuffer;
+ delete mOutBuffer;
+}
+
+bool Network::connect(const std::string &address, short port)
+{
+ if (mState != IDLE && mState != ERROR_BROKE)
+ {
+ //logger->log("Tried to connect an already connected socket!");
+ return false;
+ }
+
+ if (address.empty())
+ {
+ //logger->log("Empty address given to Network::connect()!");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ //logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+
+ mAddress = address;
+ mPort = port;
+
+ // Reset to sane values
+ mOutSize = 0;
+ mInSize = 0;
+ mToSkip = 0;
+
+ mState = CONNECTING;
+ mWorkerThread = SDL_CreateThread(networkThread, this);
+ if (!mWorkerThread)
+ {
+ //logger->log("Unable to create network worker thread");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ return true;
+}
+
+void Network::disconnect()
+{
+ if (mState != CONNECTED && mState != CONNECTING)
+ return;
+
+ mState = IDLE;
+
+ if (mWorkerThread)
+ {
+ SDL_WaitThread(mWorkerThread, NULL);
+ mWorkerThread = NULL;
+ }
+ SDLNet_TCP_Close(mSocket);
+}
+
+void Network::registerHandler(MessageHandler *handler)
+{
+ const Uint16 *i = handler->handledMessages;
+
+ while(*i)
+ {
+ mMessageHandlers[*i] = handler;
+ i++;
+ }
+
+ handler->setNetwork(this);
+}
+
+void Network::unregisterHandler(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_BROKE;
+ }
+ mOutSize = 0;
+ SDL_mutexV(mMutex);
+}
+
+void Network::skip(int len)
+{
+ SDL_mutexP(mMutex);
+ mToSkip += len;
+ if (!mInSize)
+ {
+ SDL_mutexV(mMutex);
+ return;
+ }
+
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ SDL_mutexV(mMutex);
+}
+
+bool Network::messageReady()
+{
+ 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;
+}
+
+MessageIn Network::getNextMessage()
+{
+ while (!messageReady())
+ {
+ if (mState == ERROR_BROKE)
+ 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()
+{
+ IPaddress ipAddress;
+
+ if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
+ {
+ //logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ mState = CONNECTING;
+
+ mSocket = SDLNet_TCP_Open(&ipAddress);
+ if (!mSocket)
+ {
+ //logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ /*logger->log("Network::Started session with %s:%i",
+ iptostring(ipAddress.host), ipAddress.port);*/
+
+ mState = CONNECTED;
+
+ return true;
+}
+
+void Network::receive()
+{
+ SDLNet_SocketSet set;
+
+ if (!(set = SDLNet_AllocSocketSet(1)))
+ {
+ //logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return;
+ }
+
+ if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
+ {
+ //logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+
+ 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)
+ {
+ case -1:
+ // logger->log("Error: SDLNet_CheckSockets");
+ // FALLTHROUGH
+ case 0:
+ break;
+
+ case 1:
+ // Receive data from the socket
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+
+ if (!ret)
+ {
+ // We got disconnected
+ mState = ERROR_BROKE; //IDLE - changed to error to force a restart.
+ //logger->log("Disconnected.");
+ //state = LOGIN_STATE;
+ }
+ else if (ret < 0)
+ {
+ //logger->log("Error in SDLNet_TCP_Recv(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+ 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);
+ 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_BROKE;
+ 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.cpp~ b/src/net/network.cpp~
new file mode 100644
index 0000000..fb531de
--- /dev/null
+++ b/src/net/network.cpp~
@@ -0,0 +1,443 @@
+/*
+ * 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: network.cpp 2187 2006-02-24 20:15:19Z der_doener $
+ */
+
+#include "network.h"
+
+#include "messagehandler.h"
+#include "messagein.h"
+
+#include "../main.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;
+}
+
+Network::Network():
+ 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();
+}
+
+Network::~Network()
+{
+ clearHandlers();
+
+ if (mState != IDLE && mState != ERROR_BROKE)
+ disconnect();
+
+ SDL_DestroyMutex(mMutex);
+
+ delete mInBuffer;
+ delete mOutBuffer;
+}
+
+bool Network::connect(const std::string &address, short port)
+{
+ if (mState != IDLE && mState != ERROR_BROKE)
+ {
+ //logger->log("Tried to connect an already connected socket!");
+ return false;
+ }
+
+ if (address.empty())
+ {
+ //logger->log("Empty address given to Network::connect()!");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ //logger->log("Network::Connecting to %s:%i", address.c_str(), port);
+
+ mAddress = address;
+ mPort = port;
+
+ // Reset to sane values
+ mOutSize = 0;
+ mInSize = 0;
+ mToSkip = 0;
+
+ mState = CONNECTING;
+ mWorkerThread = SDL_CreateThread(networkThread, this);
+ if (!mWorkerThread)
+ {
+ //logger->log("Unable to create network worker thread");
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ return true;
+}
+
+void Network::disconnect()
+{
+ if (mState != CONNECTED && mState != CONNECTING)
+ return;
+
+ mState = IDLE;
+
+ if (mWorkerThread)
+ {
+ SDL_WaitThread(mWorkerThread, NULL);
+ mWorkerThread = NULL;
+ }
+ SDLNet_TCP_Close(mSocket);
+}
+
+void Network::registerHandler(MessageHandler *handler)
+{
+ const Uint16 *i = handler->handledMessages;
+
+ while(*i)
+ {
+ mMessageHandlers[*i] = handler;
+ i++;
+ }
+
+ handler->setNetwork(this);
+}
+
+void Network::unregisterHandler(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_BROKE;
+ }
+ mOutSize = 0;
+ SDL_mutexV(mMutex);
+}
+
+void Network::skip(int len)
+{
+ SDL_mutexP(mMutex);
+ mToSkip += len;
+ if (!mInSize)
+ {
+ SDL_mutexV(mMutex);
+ return;
+ }
+
+ if (mInSize >= mToSkip)
+ {
+ mInSize -= mToSkip;
+ memmove(mInBuffer, mInBuffer + mToSkip, mInSize);
+ mToSkip = 0;
+ }
+ else
+ {
+ mToSkip -= mInSize;
+ mInSize = 0;
+ }
+ SDL_mutexV(mMutex);
+}
+
+bool Network::messageReady()
+{
+ 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;
+}
+
+MessageIn Network::getNextMessage()
+{
+ while (!messageReady())
+ {
+ if (mState == ERROR_BROKE)
+ 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()
+{
+ IPaddress ipAddress;
+
+ if (SDLNet_ResolveHost(&ipAddress, mAddress.c_str(), mPort) == -1)
+ {
+ //logger->log("Error in SDLNet_ResolveHost(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ mState = CONNECTING;
+
+ mSocket = SDLNet_TCP_Open(&ipAddress);
+ if (!mSocket)
+ {
+ //logger->log("Error in SDLNet_TCP_Open(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return false;
+ }
+
+ /*logger->log("Network::Started session with %s:%i",
+ iptostring(ipAddress.host), ipAddress.port);*/
+
+ mState = CONNECTED;
+
+ return true;
+}
+
+void Network::receive()
+{
+ SDLNet_SocketSet set;
+
+ if (!(set = SDLNet_AllocSocketSet(1)))
+ {
+ //logger->log("Error in SDLNet_AllocSocketSet(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ return;
+ }
+
+ if (SDLNet_TCP_AddSocket(set, mSocket) == -1)
+ {
+ //logger->log("Error in SDLNet_AddSocket(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+
+ 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)
+ {
+ case -1:
+ // logger->log("Error: SDLNet_CheckSockets");
+ // FALLTHROUGH
+ case 0:
+ break;
+
+ case 1:
+ // Receive data from the socket
+ SDL_mutexP(mMutex);
+ ret = SDLNet_TCP_Recv(mSocket, mInBuffer + mInSize, BUFFER_SIZE - mInSize);
+
+ if (!ret)
+ {
+ // We got disconnected
+ mState = ERROR_BROKE; //IDLE - changed to error to force a restart.
+ //logger->log("Disconnected.");
+ //state = LOGIN_STATE;
+ }
+ else if (ret < 0)
+ {
+ //logger->log("Error in SDLNet_TCP_Recv(): %s", SDLNet_GetError());
+ mState = ERROR_BROKE;
+ }
+ 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);
+ 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_BROKE;
+ 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
new file mode 100644
index 0000000..45a9838
--- /dev/null
+++ b/src/net/network.h
@@ -0,0 +1,103 @@
+/*
+ * 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: network.h 2187 2006-02-24 20:15:19Z der_doener $
+ */
+
+#ifndef _TMW_NETWORK_
+#define _TMW_NETWORK_
+
+#include <map>
+#include <SDL_net.h>
+#include <SDL_thread.h>
+#include <string>
+
+class MessageHandler;
+class MessageIn;
+
+class Network;
+
+class Network
+{
+ 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_BROKE
+ };
+
+ 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);
+
+#endif
diff --git a/src/net/packet.cpp b/src/net/packet.cpp
new file mode 100644
index 0000000..53fb3ff
--- /dev/null
+++ b/src/net/packet.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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: packet.cpp 1846 2005-10-09 03:34:45Z b_lindeijer $
+ */
+
+#include "packet.h"
+
+#include <cstring>
+
+Packet::Packet(const char *data, int length):
+ mLength(length)
+{
+ // Create a copy of the data
+ mData = new char[mLength];
+ memcpy(mData, data, mLength);
+}
+
+Packet::~Packet()
+{
+ // Clean up the data
+ delete[] mData;
+}
diff --git a/src/net/packet.h b/src/net/packet.h
new file mode 100644
index 0000000..5f4e8a2
--- /dev/null
+++ b/src/net/packet.h
@@ -0,0 +1,47 @@
+/*
+ * 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: packet.h 1846 2005-10-09 03:34:45Z b_lindeijer $
+ */
+
+#ifndef _TMW_PACKET_
+#define _TMW_PACKET_
+
+/**
+ * A packet wraps a certain amount of bytes for sending and receiving.
+ */
+class Packet
+{
+ public:
+ /**
+ * Constructor.
+ */
+ Packet(const char *data, int length);
+
+ /**
+ * Destructor.
+ */
+ ~Packet();
+
+ char *mData; /**< Packet data */
+ unsigned int mLength; /**< Length of data in bytes */
+};
+
+#endif
diff --git a/src/net/protocol.cpp b/src/net/protocol.cpp
new file mode 100644
index 0000000..791b7fe
--- /dev/null
+++ b/src/net/protocol.cpp
@@ -0,0 +1,79 @@
+/*
+ * 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: protocol.cpp 2158 2006-02-07 10:37:54Z der_doener $
+ */
+
+#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
new file mode 100644
index 0000000..06b3df3
--- /dev/null
+++ b/src/net/protocol.h
@@ -0,0 +1,118 @@
+/*
+ * 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: protocol.h 2135 2006-02-03 13:53:50Z der_doener $
+ */
+
+#ifndef _TMW_PROTOCOL_
+#define _TMW_PROTOCOL_
+
+// Packets from server to client
+#define SMSG_SERVER_PING 0x007f /**< Contains server tick */
+#define SMSG_LOGIN_SUCCESS 0x0073 /**< Contains starting location */
+#define SMSG_QUEST_PLAYER_VARS 0x0215 /**< Quest Log info (ignored) */
+#define SMSG_PLAYER_UPDATE_1 0x01d8
+#define SMSG_PLAYER_UPDATE_2 0x01d9
+#define SMSG_PLAYER_MOVE 0x01da /**< A nearby player moves */
+#define SMSG_PLAYER_STAT_UPDATE_1 0x00b0
+#define SMSG_PLAYER_STAT_UPDATE_2 0x00b1
+#define SMSG_PLAYER_STAT_UPDATE_3 0x0141
+#define SMSG_PLAYER_STAT_UPDATE_4 0x00bc
+#define SMSG_PLAYER_STAT_UPDATE_5 0x00bd
+#define SMSG_PLAYER_STAT_UPDATE_6 0x00be
+#define SMSG_WHO_ANSWER 0x00c2
+#define SMSG_PLAYER_WARP 0x0091 /**< Warp player to map/location */
+#define SMSG_PLAYER_INVENTORY 0x01ee
+#define SMSG_PLAYER_INVENTORY_ADD 0x00a0
+#define SMSG_PLAYER_INVENTORY_REMOVE 0x00af
+#define SMSG_PLAYER_INVENTORY_USE 0x01c8
+#define SMSG_PLAYER_EQUIPMENT 0x00a4
+#define SMSG_PLAYER_EQUIP 0x00aa
+#define SMSG_PLAYER_UNEQUIP 0x00ac
+#define SMSG_PLAYER_ARROW_EQUIP 0x013c
+#define SMSG_PLAYER_ARROW_MESSAGE 0x013b
+#define SMSG_PLAYER_SKILLS 0x010f
+#define SMSG_SKILL_FAILED 0x0110
+#define SMSG_ITEM_USE_RESPONSE 0x00a8
+#define SMSG_ITEM_VISIBLE 0x009d /**< An item is on the floor */
+#define SMSG_ITEM_DROPPED 0x009e /**< An item is dropped */
+#define SMSG_ITEM_REMOVE 0x00a1 /**< An item disappers */
+#define SMSG_BEING_VISIBLE 0x0078
+#define SMSG_BEING_MOVE 0x007b /**< A nearby monster moves */
+#define SMSG_BEING_REMOVE 0x0080
+#define SMSG_BEING_CHANGE_LOOKS 0x00c3
+#define SMSG_BEING_LEVELUP 0x019b
+#define SMSG_BEING_EMOTION 0x00c0
+#define SMSG_BEING_ACTION 0x008a /**< Attack, sit, stand up, ... */
+#define SMSG_BEING_CHAT 0x008d /**< A being talks */
+#define SMSG_BEING_NAME_RESPONSE 0x0095 /**< Has to be requested */
+#define SMSG_NPC_MESSAGE 0x00b4
+#define SMSG_NPC_NEXT 0x00b5
+#define SMSG_NPC_CLOSE 0x00b6
+#define SMSG_NPC_CHOICE 0x00b7 /**< Display a choice */
+#define SMSG_NPC_BUY_SELL_CHOICE 0x00c4
+#define SMSG_NPC_BUY 0x00c6
+#define SMSG_NPC_SELL 0x00c7
+#define SMSG_NPC_BUY_RESPONSE 0x00ca
+#define SMSG_NPC_SELL_RESPONSE 0x00cb
+#define SMSG_PLAYER_CHAT 0x008e /**< Player talks */
+#define SMSG_WHISPER 0x0097 /**< Whisper Recieved */
+#define SMSG_WHISPER_RESPONSE 0x0098
+#define SMSG_GM_CHAT 0x009a /**< GM announce */
+#define SMSG_WALK_RESPONSE 0x0087
+#define SMSG_TRADE_REQUEST 0x00e5 /**< Receiving a request to trade */
+#define SMSG_TRADE_RESPONSE 0x00e7
+#define SMSG_TRADE_ITEM_ADD 0x00e9
+#define SMSG_TRADE_ITEM_ADD_RESPONSE 0x01b1 /**< Not standard eAthena! */
+#define SMSG_TRADE_OK 0x00ec
+#define SMSG_TRADE_CANCEL 0x00ee
+#define SMSG_TRADE_COMPLETE 0x00f0
+
+// Packets from client to server
+#define CMSG_CLIENT_PING 0x007e
+#define CMSG_TRADE_RESPONSE 0x00e6
+#define CMSG_ITEM_PICKUP 0x009f
+#define CMSG_MAP_LOADED 0x007d
+#define CMSG_NPC_BUY_REQUEST 0x00c8
+#define CMSG_NPC_BUY_SELL_REQUEST 0x00c5
+#define CMSG_CHAT_MESSAGE 0x008c
+#define CMSG_CHAT_WHISPER 0x0096
+#define CMSG_NPC_LIST_CHOICE 0x00b8
+#define CMSG_NPC_NEXT_REQUEST 0x00b9
+#define CMSG_NPC_SELL_REQUEST 0x00c9
+#define CMSG_SKILL_LEVELUP_REQUEST 0x0112
+#define CMSG_STAT_UPDATE_REQUEST 0x00bb
+#define CMSG_TRADE_ITEM_ADD_REQUEST 0x00e8
+#define CMSG_TRADE_CANCEL_REQUEST 0x00ed
+#define CMSG_TRADE_ADD_COMPLETE 0x00eb
+#define CMSG_TRADE_OK 0x00ef
+#define CMSG_NPC_TALK 0x0090
+#define CMSG_TRADE_REQUEST 0x00e4
+#define CMSG_PLAYER_INVENTORY_USE 0x00a7
+#define CMSG_PLAYER_INVENTORY_DROP 0x00a2
+#define CMSG_PLAYER_EQUIP 0x00a9
+#define CMSG_PLAYER_UNEQUIP 0x00ab
+#define CMSG_PLAYER_CHANGE_ACT 0x0089
+
+
+/** Encodes coords and direction in 3 bytes data */
+void set_coordinates(char *data, unsigned short x, unsigned short y, unsigned char direction);
+
+#endif