diff options
Diffstat (limited to 'src/net')
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 |