summaryrefslogtreecommitdiff
path: root/src/net/charserverhandler.cpp
diff options
context:
space:
mode:
authorBjørn Lindeijer <bjorn@lindeijer.nl>2009-03-22 19:45:03 +0100
committerBjørn Lindeijer <bjorn@lindeijer.nl>2009-03-22 19:45:56 +0100
commit0c43d04b438d41c277ae80402d4b4888db1a0b64 (patch)
tree3aaeb75ecd1bcbe85decedab5f1fa426fe0411e3 /src/net/charserverhandler.cpp
parenta7f5eaeb7f643658d356533a608f0f18d85b6d32 (diff)
parent401802c1d7a1b3d659bdc53a45d9a6292fc1121e (diff)
downloadmana-client-0c43d04b438d41c277ae80402d4b4888db1a0b64.tar.gz
mana-client-0c43d04b438d41c277ae80402d4b4888db1a0b64.tar.bz2
mana-client-0c43d04b438d41c277ae80402d4b4888db1a0b64.tar.xz
mana-client-0c43d04b438d41c277ae80402d4b4888db1a0b64.zip
Merged the tmwserv client with the eAthena client
This merge involved major changes on both sides, and as such took several weeks. Lots of things are expected to be broken now, however, we now have a single code base to improve and extend, which can be compiled to support either eAthena or tmwserv. In the coming months, the plan is to work towards a client that supports both eAthena and tmwserv, without needing to be recompiled. Conflicts: Everywhere!
Diffstat (limited to 'src/net/charserverhandler.cpp')
-rw-r--r--src/net/charserverhandler.cpp310
1 files changed, 151 insertions, 159 deletions
diff --git a/src/net/charserverhandler.cpp b/src/net/charserverhandler.cpp
index 8e743bf0..5905dba0 100644
--- a/src/net/charserverhandler.cpp
+++ b/src/net/charserverhandler.cpp
@@ -1,25 +1,27 @@
/*
* The Mana World
- * Copyright (C) 2004 The Mana World Development Team
+ * Copyright 2004 The Mana World Development Team
*
* This file is part of The Mana World.
*
- * This program is free software; you can redistribute it and/or modify
+ * 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.
*
- * This program is distributed in the hope that it will be useful,
+ * 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 this program; if not, write to the Free Software
+ * along with The Mana World; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "charserverhandler.h"
+
+#include "connection.h"
#include "messagein.h"
#include "protocol.h"
@@ -29,107 +31,73 @@
#include "../logindata.h"
#include "../main.h"
-#include "../gui/char_select.h"
#include "../gui/ok_dialog.h"
+#include "../gui/char_select.h"
-#include "../utils/gettext.h"
-#include "../utils/stringutils.h"
+extern Net::Connection *gameServerConnection;
+extern Net::Connection *chatServerConnection;
CharServerHandler::CharServerHandler():
mCharCreateDialog(0)
{
static const Uint16 _messages[] = {
- SMSG_CONNECTION_PROBLEM,
- 0x006b,
- 0x006c,
- 0x006d,
- 0x006e,
- 0x006f,
- 0x0070,
- 0x0071,
+ APMSG_CHAR_CREATE_RESPONSE,
+ APMSG_CHAR_DELETE_RESPONSE,
+ APMSG_CHAR_INFO,
+ APMSG_CHAR_SELECT_RESPONSE,
0
};
handledMessages = _messages;
}
-void CharServerHandler::handleMessage(MessageIn *msg)
+void CharServerHandler::handleMessage(MessageIn &msg)
{
- int slot, flags, code;
+ int slot;
LocalPlayer *tempPlayer;
- logger->log("CharServerHandler: Packet ID: %x, Length: %d",
- msg->getId(), msg->getLength());
- switch (msg->getId())
+ switch (msg.getId())
{
- case SMSG_CONNECTION_PROBLEM:
- code = msg->readInt8();
- logger->log("Connection problem: %i", code);
-
- switch (code) {
- case 0:
- errorMessage = _("Authentication failed");
- break;
- case 1:
- errorMessage = _("Map server(s) offline");
- break;
- case 2:
- errorMessage = _("This account is already logged in");
- break;
- case 3:
- errorMessage = _("Speed hack detected");
- break;
- case 8:
- errorMessage = _("Duplicated login");
- break;
- default:
- errorMessage = _("Unknown connection error");
- break;
- }
- state = ERROR_STATE;
+ case APMSG_CHAR_CREATE_RESPONSE:
+ handleCharCreateResponse(msg);
break;
- case 0x006b:
- msg->skip(2); // Length word
- flags = msg->readInt32(); // Aethyra extensions flags
- logger->log("Server flags are: %x", flags);
- msg->skip(16); // Unused
-
- // Derive number of characters from message length
- n_character = (msg->getLength() - 24) / 106;
-
- for (int i = 0; i < n_character; i++)
+ case APMSG_CHAR_DELETE_RESPONSE:
+ {
+ int errMsg = msg.readInt8();
+ // Character deletion successful
+ if (errMsg == ERRMSG_OK)
{
- tempPlayer = readPlayerData(*msg, slot);
- mCharInfo->select(slot);
- mCharInfo->setEntry(tempPlayer);
- logger->log("CharServer: Player: %s (%d)",
- tempPlayer->getName().c_str(), slot);
+ delete mCharInfo->getEntry();
+ mCharInfo->setEntry(0);
+ mCharInfo->unlock();
+ new OkDialog("Info", "Player deleted");
}
-
- state = CHAR_SELECT_STATE;
- break;
-
- case 0x006c:
- switch (msg->readInt8()) {
- case 0:
- errorMessage = _("Access denied");
- break;
- case 1:
- errorMessage = _("Cannot use this ID");
- break;
- default:
- errorMessage = _("Unknown failure to select character");
- break;
+ // Character deletion failed
+ else
+ {
+ std::string message = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ message = "Not logged in";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ message = "Selection out of range";
+ break;
+ default:
+ message = "Unknown error";
+ }
+ mCharInfo->unlock();
+ new OkDialog("Error", message);
}
- mCharInfo->unlock();
+ }
break;
- case 0x006d:
- tempPlayer = readPlayerData(*msg, slot);
+ case APMSG_CHAR_INFO:
+ tempPlayer = readPlayerData(msg, slot);
mCharInfo->unlock();
mCharInfo->select(slot);
mCharInfo->setEntry(tempPlayer);
- n_character++;
// Close the character create dialog
if (mCharCreateDialog)
@@ -139,97 +107,121 @@ void CharServerHandler::handleMessage(MessageIn *msg)
}
break;
- case 0x006e:
- new OkDialog(_("Error"), _("Failed to create character. Most likely"
- " the name is already taken."));
-
- if (mCharCreateDialog)
- mCharCreateDialog->unlock();
+ case APMSG_CHAR_SELECT_RESPONSE:
+ handleCharSelectResponse(msg);
break;
+ }
+}
- case 0x006f:
- delete mCharInfo->getEntry();
- mCharInfo->setEntry(0);
- mCharInfo->unlock();
- n_character--;
- new OkDialog(_("Info"), _("Player deleted"));
- break;
+void CharServerHandler::handleCharCreateResponse(MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
- case 0x0070:
- mCharInfo->unlock();
- new OkDialog(_("Error"), _("Failed to delete character."));
- break;
+ // Character creation failed
+ if (errMsg != ERRMSG_OK)
+ {
+ std::string message = "";
+ switch (errMsg)
+ {
+ case ERRMSG_NO_LOGIN:
+ message = "Not logged in";
+ break;
+ case CREATE_TOO_MUCH_CHARACTERS:
+ message = "No empty slot";
+ break;
+ case ERRMSG_INVALID_ARGUMENT:
+ message = "Invalid name";
+ break;
+ case CREATE_EXISTS_NAME:
+ message = "Character's name already exists";
+ break;
+ case CREATE_INVALID_HAIRSTYLE:
+ message = "Invalid hairstyle";
+ break;
+ case CREATE_INVALID_HAIRCOLOR:
+ message = "Invalid hair color";
+ break;
+ case CREATE_INVALID_GENDER:
+ message = "Invalid gender";
+ break;
+ case CREATE_RAW_STATS_TOO_HIGH:
+ message = "Character's stats are too high";
+ break;
+ case CREATE_RAW_STATS_TOO_LOW:
+ message = "Character's stats are too low";
+ break;
+ case CREATE_RAW_STATS_EQUAL_TO_ZERO:
+ message = "One stat is zero";
+ break;
+ default:
+ message = "Unknown error";
+ break;
+ }
+ new OkDialog("Error", message);
+ }
- case 0x0071:
- player_node = mCharInfo->getEntry();
- slot = mCharInfo->getPos();
- msg->skip(4); // CharID, must be the same as player_node->charID
- map_path = msg->readString(16);
- mLoginData->hostname = ipToString(msg->readInt32());
- mLoginData->port = msg->readInt16();
- mCharInfo->unlock();
- mCharInfo->select(0);
- // Clear unselected players infos
- do
+ if (mCharCreateDialog)
+ mCharCreateDialog->unlock();
+}
+
+void CharServerHandler::handleCharSelectResponse(MessageIn &msg)
+{
+ int errMsg = msg.readInt8();
+
+ if (errMsg == ERRMSG_OK)
+ {
+ token = msg.readString(32);
+ std::string gameServer = msg.readString();
+ unsigned short gameServerPort = msg.readInt16();
+ std::string chatServer = msg.readString();
+ unsigned short chatServerPort = msg.readInt16();
+
+ logger->log("Game server: %s:%d", gameServer.c_str(), gameServerPort);
+ logger->log("Chat server: %s:%d", chatServer.c_str(), chatServerPort);
+
+ gameServerConnection->connect(gameServer, gameServerPort);
+ chatServerConnection->connect(chatServer, chatServerPort);
+
+ // Keep the selected character and delete the others
+ player_node = mCharInfo->getEntry();
+ int slot = mCharInfo->getPos();
+ mCharInfo->unlock();
+ mCharInfo->select(0);
+
+ do {
+ LocalPlayer *tmp = mCharInfo->getEntry();
+ if (tmp != player_node)
{
- LocalPlayer *tmp = mCharInfo->getEntry();
- if (tmp != player_node)
- {
- delete tmp;
- mCharInfo->setEntry(0);
- }
- mCharInfo->next();
- } while (mCharInfo->getPos());
+ delete tmp;
+ mCharInfo->setEntry(0);
+ }
+ mCharInfo->next();
+ } while (mCharInfo->getPos());
+ mCharInfo->select(slot);
- mCharInfo->select(slot);
- state = CONNECTING_STATE;
- break;
+ mCharInfo->clear(); //player_node will be deleted by ~Game
+
+ state = STATE_CONNECT_GAME;
}
}
-LocalPlayer *CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
+LocalPlayer* CharServerHandler::readPlayerData(MessageIn &msg, int &slot)
{
- LocalPlayer *tempPlayer = new LocalPlayer(mLoginData->account_ID, 0, NULL);
- tempPlayer->setGender(
- (mLoginData->sex == 0) ? GENDER_FEMALE : GENDER_MALE);
-
- tempPlayer->mCharId = msg.readInt32();
- tempPlayer->setXp(msg.readInt32());
- tempPlayer->mGp = msg.readInt32();
- tempPlayer->mJobXp = msg.readInt32();
- tempPlayer->mJobLevel = msg.readInt32();
- tempPlayer->setSprite(Being::SHOE_SPRITE, msg.readInt16());
- tempPlayer->setSprite(Being::GLOVES_SPRITE, msg.readInt16());
- tempPlayer->setSprite(Being::CAPE_SPRITE, msg.readInt16());
- tempPlayer->setSprite(Being::MISC1_SPRITE, msg.readInt16());
- msg.readInt32(); // option
- msg.readInt32(); // karma
- msg.readInt32(); // manner
- msg.skip(2); // unknown
- tempPlayer->mHp = msg.readInt16();
- tempPlayer->mMaxHp = msg.readInt16();
- tempPlayer->mMp = msg.readInt16();
- tempPlayer->mMaxMp = msg.readInt16();
- msg.readInt16(); // speed
- msg.readInt16(); // class
- int hairStyle = msg.readInt16();
- Uint16 weapon = msg.readInt16();
- tempPlayer->setSprite(Being::WEAPON_SPRITE, weapon);
- tempPlayer->mLevel = msg.readInt16();
- msg.readInt16(); // skill point
- tempPlayer->setSprite(Being::BOTTOMCLOTHES_SPRITE, msg.readInt16()); // head bottom
- tempPlayer->setSprite(Being::SHIELD_SPRITE, msg.readInt16());
- tempPlayer->setSprite(Being::HAT_SPRITE, msg.readInt16()); // head option top
- tempPlayer->setSprite(Being::TOPCLOTHES_SPRITE, msg.readInt16()); // head option mid
- int hairColor = msg.readInt16();
- tempPlayer->setHairStyle(hairStyle, hairColor);
- tempPlayer->setSprite(Being::MISC2_SPRITE, msg.readInt16());
- tempPlayer->setName(msg.readString(24));
- for (int i = 0; i < 6; i++) {
- tempPlayer->mAttr[i] = msg.readInt8();
- }
+ LocalPlayer *tempPlayer = new LocalPlayer;
slot = msg.readInt8(); // character slot
- msg.readInt8(); // unknown
+ tempPlayer->setName(msg.readString());
+ tempPlayer->setGender(msg.readInt8() == GENDER_MALE ? GENDER_MALE : GENDER_FEMALE);
+ int hs = msg.readInt8(), hc = msg.readInt8();
+ tempPlayer->setHairStyle(hs, hc);
+ tempPlayer->setLevel(msg.readInt16());
+ tempPlayer->setCharacterPoints(msg.readInt16());
+ tempPlayer->setCorrectionPoints(msg.readInt16());
+ tempPlayer->setMoney(msg.readInt32());
+
+ for (int i = 0; i < 7; i++)
+ {
+ tempPlayer->setAttributeBase(i, msg.readInt8());
+ }
return tempPlayer;
}