From 8150191686759b13a239c25970924c3c186140ff Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Wed, 27 Mar 2013 19:05:24 +0300
Subject: improve charserverhandler class.

---
 src/CMakeLists.txt                    |   4 +-
 src/Makefile.am                       |   4 +-
 src/being.cpp                         |  10 +--
 src/client.cpp                        |   2 +-
 src/gui/charcreatedialog.cpp          |   6 +-
 src/gui/charselectdialog.cpp          |  18 ++---
 src/gui/charselectdialog.h            |   8 +--
 src/gui/logindialog.cpp               |   4 +-
 src/gui/quitdialog.cpp                |   4 +-
 src/net/charhandler.cpp               |  43 ------------
 src/net/charhandler.h                 | 120 ----------------------------------
 src/net/ea/charserverhandler.cpp      |  73 +++++++++++++++++++--
 src/net/ea/charserverhandler.h        |  41 +++++++-----
 src/net/eathena/charserverhandler.cpp |  78 +++++-----------------
 src/net/eathena/charserverhandler.h   |  25 +++----
 src/net/eathena/generalhandler.cpp    |   8 +--
 src/net/eathena/generalhandler.h      |   2 +-
 src/net/net.cpp                       |   8 +--
 src/net/net.h                         |   4 +-
 src/net/tmwa/charserverhandler.cpp    |  82 ++++++-----------------
 src/net/tmwa/charserverhandler.h      |  25 +++----
 src/net/tmwa/generalhandler.cpp       |   8 +--
 src/net/tmwa/generalhandler.h         |   2 +-
 23 files changed, 200 insertions(+), 379 deletions(-)
 delete mode 100644 src/net/charhandler.cpp
 delete mode 100644 src/net/charhandler.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 32ad5c08a..9e1f1be3e 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -380,8 +380,8 @@ SET(SRCS
     gui/worldselectdialog.cpp
     gui/worldselectdialog.h
     net/adminhandler.h
-    net/charhandler.cpp
-    net/charhandler.h
+    net/charserverhandler.cpp
+    net/charserverhandler.h
     net/chathandler.h
     net/download.cpp
     net/download.h
diff --git a/src/Makefile.am b/src/Makefile.am
index c926a8e2e..ee43ad9a4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -381,8 +381,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \
 	      net/adminhandler.h \
 	      net/beinghandler.h \
 	      net/buysellhandler.h \
-	      net/charhandler.cpp \
-	      net/charhandler.h \
+	      net/charserverhandler.cpp \
+	      net/charserverhandler.h \
 	      net/chathandler.h \
 	      net/download.cpp \
 	      net/download.h \
diff --git a/src/being.cpp b/src/being.cpp
index a30693d19..c57532fbf 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -45,7 +45,7 @@
 #include "gui/sdlfont.h"
 #include "gui/skilldialog.h"
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 #include "net/gamehandler.h"
 #include "net/inventoryhandler.h"
 #include "net/net.h"
@@ -340,8 +340,8 @@ void Being::setSubtype(const uint16_t subtype)
             setRaceName(info.getName());
         }
 
-        if (Net::getCharHandler())
-            setSprite(Net::getCharHandler()->baseSprite(), id);
+        if (Net::getCharServerHandler())
+            setSprite(Net::getCharServerHandler()->baseSprite(), id);
     }
 }
 
@@ -1777,7 +1777,7 @@ void Being::setSprite(const unsigned int slot, const int id,
                       std::string color, const unsigned char colorId,
                       const bool isWeapon, const bool isTempSprite)
 {
-    if (slot >= Net::getCharHandler()->maxSprite())
+    if (slot >= Net::getCharServerHandler()->maxSprite())
         return;
 
     if (slot >= size())
@@ -2305,7 +2305,7 @@ void Being::recalcSpritesOrder()
     if (mAction == DEAD)
         dir = 9;
 
-    const unsigned int hairSlot = Net::getCharHandler()->hairSprite();
+    const unsigned int hairSlot = Net::getCharServerHandler()->hairSprite();
 
     for (unsigned slot = 0; slot < sz; slot ++)
     {
diff --git a/src/client.cpp b/src/client.cpp
index 8f64b6b1e..57987e82b 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -1397,7 +1397,7 @@ int Client::gameExec()
                 case STATE_GET_CHARACTERS:
                     BLOCK_START("Client::gameExec STATE_GET_CHARACTERS")
                     logger->log1("State: GET CHARACTERS");
-                    Net::getCharHandler()->requestCharacters();
+                    Net::getCharServerHandler()->requestCharacters();
                     mCurrentDialog = new ConnectionDialog(
                             _("Requesting characters"),
                             STATE_SWITCH_SERVER);
diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp
index 7ed2f0703..9ff4b038e 100644
--- a/src/gui/charcreatedialog.cpp
+++ b/src/gui/charcreatedialog.cpp
@@ -252,7 +252,7 @@ CharCreateDialog::~CharCreateDialog()
     mPlayer = nullptr;
 
     // Make sure the char server handler knows that we're gone
-    Net::getCharHandler()->setCharCreateDialog(nullptr);
+    Net::getCharServerHandler()->setCharCreateDialog(nullptr);
 }
 
 void CharCreateDialog::action(const gcn::ActionEvent &event)
@@ -285,7 +285,7 @@ void CharCreateDialog::action(const gcn::ActionEvent &event)
             const int characterSlot = mSlot;
 #endif
 
-            Net::getCharHandler()->newCharacter(getName(), characterSlot,
+            Net::getCharServerHandler()->newCharacter(getName(), characterSlot,
                 mFemale->isSelected(), mHairStyle, mHairColor,
                 static_cast<unsigned char>(mRace), atts);
         }
@@ -524,7 +524,7 @@ void CharCreateDialog::updateHair()
     mHairColorNameLabel->setCaption(ColorDB::getHairColorName(mHairColor));
     mHairColorNameLabel->adjustSize();
 
-    mPlayer->setSprite(Net::getCharHandler()->hairSprite(),
+    mPlayer->setSprite(Net::getCharServerHandler()->hairSprite(),
         mHairStyle * -1, item.getDyeColorsString(mHairColor));
 }
 
diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp
index bc2c42dc7..712870ad8 100644
--- a/src/gui/charselectdialog.cpp
+++ b/src/gui/charselectdialog.cpp
@@ -244,7 +244,7 @@ CharSelectDialog::CharSelectDialog(LoginData *const data):
     mChangeEmailButton(nullptr),
     mCharacterScroller(nullptr),
     mCharacterEntries(0),
-    mCharHandler(Net::getCharHandler()),
+    mCharServerHandler(Net::getCharServerHandler()),
     mDeleteDialog(nullptr),
     mDeleteIndex(-1),
     mSmallScreen(mainGraphics->getWidth() < 485
@@ -313,7 +313,7 @@ CharSelectDialog::CharSelectDialog(LoginData *const data):
     center();
     setVisible(true);
 
-    Net::getCharHandler()->setCharSelectDialog(this);
+    Net::getCharServerHandler()->setCharSelectDialog(this);
     focusCharacter(0);
 }
 
@@ -350,7 +350,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
         if (eventId == "use" && mCharacterEntries[selected]->getCharacter())
         {
             attemptCharacterSelect(selected);
-//            Net::getCharHandler()->clear();
+//            Net::getCharServerHandler()->clear();
             return;
         }
         else if (eventId == "new" &&
@@ -359,7 +359,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
             // Start new character dialog
             CharCreateDialog *const charCreateDialog =
                 new CharCreateDialog(this, selected);
-            mCharHandler->setCharCreateDialog(charCreateDialog);
+            mCharServerHandler->setCharCreateDialog(charCreateDialog);
             return;
         }
         else if (eventId == "delete"
@@ -371,7 +371,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
     }
     if (eventId == "switch")
     {
-        Net::getCharHandler()->clear();
+        Net::getCharServerHandler()->clear();
         close();
     }
     else if (eventId == "change_password")
@@ -384,7 +384,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
     }
     else if (eventId == "unregister")
     {
-        Net::getCharHandler()->clear();
+        Net::getCharServerHandler()->clear();
         Client::setState(STATE_UNREGISTER);
     }
     else if (eventId == "try delete character")
@@ -558,7 +558,7 @@ void CharSelectDialog::attemptCharacterDelete(const int index)
     if (mLocked)
         return;
 
-    mCharHandler->deleteCharacter(mCharacterEntries[index]->getCharacter());
+    mCharServerHandler->deleteCharacter(mCharacterEntries[index]->getCharacter());
     lock();
 }
 
@@ -581,9 +581,9 @@ void CharSelectDialog::attemptCharacterSelect(const int index)
         return;
 
     setVisible(false);
-    if (mCharHandler && mCharacterEntries[index])
+    if (mCharServerHandler && mCharacterEntries[index])
     {
-        mCharHandler->chooseCharacter(
+        mCharServerHandler->chooseCharacter(
             mCharacterEntries[index]->getCharacter());
     }
     lock();
diff --git a/src/gui/charselectdialog.h b/src/gui/charselectdialog.h
index f9030d561..8c1b92522 100644
--- a/src/gui/charselectdialog.h
+++ b/src/gui/charselectdialog.h
@@ -28,7 +28,7 @@
 
 #include "gui/widgets/window.h"
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 
 #include <guichan/actionlistener.hpp>
 #include <guichan/keylistener.hpp>
@@ -44,7 +44,7 @@ class TextDialog;
 
 namespace Net
 {
-    class CharHandler;
+    class CharServerHandler;
 }
 
 /**
@@ -58,7 +58,7 @@ class CharSelectDialog final : public Window,
 {
     public:
         friend class CharDeleteConfirm;
-        friend class Net::CharHandler;
+        friend class Net::CharServerHandler;
 
         /**
          * Constructor.
@@ -129,7 +129,7 @@ class CharSelectDialog final : public Window,
         /** The player boxes */
         std::vector<CharacterDisplay*> mCharacterEntries;
 
-        Net::CharHandler *mCharHandler;
+        Net::CharServerHandler *mCharServerHandler;
         TextDialog *mDeleteDialog;
         int mDeleteIndex;
         bool mSmallScreen;
diff --git a/src/gui/logindialog.cpp b/src/gui/logindialog.cpp
index 5767390c7..c69560c38 100644
--- a/src/gui/logindialog.cpp
+++ b/src/gui/logindialog.cpp
@@ -38,7 +38,7 @@
 #include "gui/widgets/layout.h"
 #include "gui/widgets/passwordfield.h"
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 #include "net/logindata.h"
 #include "net/loginhandler.h"
 #include "net/net.h"
@@ -155,7 +155,7 @@ LoginDialog::LoginDialog(LoginData *const data, std::string serverName,
 {
     setCloseButton(true);
 
-    Net::getCharHandler()->clear();
+    Net::getCharServerHandler()->clear();
 
     Label *const serverLabel1 = new Label(this, _("Server:"));
     Label *const serverLabel2 = new Label(this, serverName);
diff --git a/src/gui/quitdialog.cpp b/src/gui/quitdialog.cpp
index 4ded1450f..3bf63c9a1 100644
--- a/src/gui/quitdialog.cpp
+++ b/src/gui/quitdialog.cpp
@@ -39,7 +39,7 @@
 #include "gui/widgets/button.h"
 #include "gui/widgets/radiobutton.h"
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 #include "net/gamehandler.h"
 #include "net/npchandler.h"
 #include "net/net.h"
@@ -188,7 +188,7 @@ void QuitDialog::action(const gcn::ActionEvent &event)
         {
             if (Client::getState() == STATE_GAME)
             {
-                Net::getCharHandler()->switchCharacter();
+                Net::getCharServerHandler()->switchCharacter();
                 Game::closeDialogs();
             }
         }
diff --git a/src/net/charhandler.cpp b/src/net/charhandler.cpp
deleted file mode 100644
index 28a51751c..000000000
--- a/src/net/charhandler.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2010  The Mana Developers
- *  Copyright (C) 2011-2013  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "net/charhandler.h"
-
-#include "gui/charselectdialog.h"
-
-#include "debug.h"
-
-namespace Net
-{
-
-void CharHandler::updateCharSelectDialog()
-{
-    if (mCharSelectDialog)
-        mCharSelectDialog->setCharacters(mCharacters);
-}
-
-void CharHandler::unlockCharSelectDialog()
-{
-    if (mCharSelectDialog)
-        mCharSelectDialog->unlock();
-}
-
-}
diff --git a/src/net/charhandler.h b/src/net/charhandler.h
deleted file mode 100644
index 9b20be57c..000000000
--- a/src/net/charhandler.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- *  The ManaPlus Client
- *  Copyright (C) 2009  The Mana World Development Team
- *  Copyright (C) 2009-2010  The Mana Developers
- *  Copyright (C) 2011-2013  The ManaPlus Developers
- *
- *  This file is part of The ManaPlus Client.
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef CHARHANDLER_H
-#define CHARHANDLER_H
-
-#include "localplayer.h"
-#include "playerinfo.h"
-
-#include <iosfwd>
-#include <string>
-#include <vector>
-
-class CharCreateDialog;
-class CharSelectDialog;
-
-namespace Net
-{
-
-/**
- * A structure to hold information about a character.
- */
-struct Character
-{
-    Character() :
-        slot(0),
-        dummy(nullptr)
-    {
-    }
-
-    A_DELETE_COPY(Character)
-
-    ~Character()
-    {
-        delete dummy;
-        dummy = nullptr;
-    }
-
-    int slot;            /**< The index in the list of characters */
-    LocalPlayer *dummy;  /**< A dummy representing this character */
-    PlayerInfoBackend data;
-};
-
-typedef std::list<Character*> Characters;
-
-class CharHandler
-{
-    public:
-        A_DELETE_COPY(CharHandler)
-
-        virtual ~CharHandler()
-        { }
-
-        virtual void setCharSelectDialog(CharSelectDialog *window) = 0;
-
-        virtual void setCharCreateDialog(CharCreateDialog *window) = 0;
-
-        virtual void requestCharacters() = 0;
-
-        virtual void chooseCharacter(Net::Character *character) = 0;
-
-        virtual void newCharacter(const std::string &name, int slot,
-                                  bool gender, int hairstyle, int hairColor,
-                                  unsigned char race,
-                                  const std::vector<int> &stats) = 0;
-
-        virtual void deleteCharacter(Net::Character *character) = 0;
-
-        virtual void switchCharacter() = 0;
-
-        virtual unsigned int baseSprite() const A_WARN_UNUSED = 0;
-
-        virtual unsigned int hairSprite() const A_WARN_UNUSED = 0;
-
-        virtual unsigned int maxSprite() const A_WARN_UNUSED = 0;
-
-        virtual void clear() = 0;
-
-    protected:
-        CharHandler() :
-            mSelectedCharacter(nullptr),
-            mCharSelectDialog(nullptr),
-            mCharCreateDialog(nullptr)
-        {}
-
-        void updateCharSelectDialog();
-        void unlockCharSelectDialog();
-
-        /** The list of available characters. */
-        Net::Characters mCharacters;
-
-        /** The selected character. */
-        Net::Character *mSelectedCharacter;
-
-        CharSelectDialog *mCharSelectDialog;
-        CharCreateDialog *mCharCreateDialog;
-};
-
-} // namespace Net
-
-#endif // CHARHANDLER_H
diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp
index e6e7e022e..3d665af22 100644
--- a/src/net/ea/charserverhandler.cpp
+++ b/src/net/ea/charserverhandler.cpp
@@ -23,12 +23,15 @@
 #include "net/ea/charserverhandler.h"
 
 #include "client.h"
+#include "configuration.h"
 
 #include "gui/charcreatedialog.h"
 #include "gui/okdialog.h"
 
 #include "net/ea/loginhandler.h"
 #include "net/ea/eaprotocol.h"
+#include "net/ea/gamehandler.h"
+#include "net/ea/network.h"
 
 #include "utils/dtor.h"
 #include "utils/gettext.h"
@@ -37,23 +40,25 @@
 
 #include "debug.h"
 
-extern Net::CharHandler *charHandler;
+extern Net::CharServerHandler *charServerHandler;
 
 namespace Ea
 {
 
+extern ServerInfo mapServer;
+
 CharServerHandler::CharServerHandler() :
-    Net::CharHandler()
+    Net::CharServerHandler()
 {
 }
 
-void CharServerHandler::setCharSelectDialog(CharSelectDialog *window)
+void CharServerHandler::setCharSelectDialog(CharSelectDialog *const window)
 {
     mCharSelectDialog = window;
     updateCharSelectDialog();
 }
 
-void CharServerHandler::setCharCreateDialog(CharCreateDialog *window)
+void CharServerHandler::setCharCreateDialog(CharCreateDialog *const window)
 {
     mCharCreateDialog = window;
 
@@ -105,7 +110,7 @@ unsigned int CharServerHandler::maxSprite() const
     return EA_SPRITE_VECTOREND;
 }
 
-void CharServerHandler::processCharLoginError(Net::MessageIn &msg)
+void CharServerHandler::processCharLoginError(Net::MessageIn &msg) const
 {
     switch (msg.readInt8())
     {
@@ -123,7 +128,8 @@ void CharServerHandler::processCharLoginError(Net::MessageIn &msg)
     Client::setState(STATE_ERROR);
 }
 
-void CharServerHandler::processCharCreate(Net::MessageIn &msg, bool withColors)
+void CharServerHandler::processCharCreate(Net::MessageIn &msg,
+                                          const bool withColors)
 {
     Net::Character *const character = new Net::Character;
     readPlayerData(msg, character, withColors);
@@ -192,4 +198,59 @@ void CharServerHandler::clear()
     mCharacters.clear();
 }
 
+void CharServerHandler::processCharMapInfo(Net::MessageIn &msg,
+                                           Network *const network,
+                                           ServerInfo &server)
+{
+//    msg.skip(4); // CharID, must be the same as player_node->charID
+    PlayerInfo::setCharId(msg.readInt32());
+    GameHandler *const gh = static_cast<GameHandler*>(Net::getGameHandler());
+    gh->setMap(msg.readString(16));
+    if (config.getBoolValue("usePersistentIP"))
+    {
+        msg.readInt32();
+        server.hostname = Client::getServerName();
+    }
+    else
+    {
+        server.hostname = ipToString(msg.readInt32());
+    }
+    server.port = msg.readInt16();
+
+    // Prevent the selected local player from being deleted
+    player_node = mSelectedCharacter->dummy;
+    PlayerInfo::setBackend(mSelectedCharacter->data);
+
+    mSelectedCharacter->dummy = nullptr;
+
+    Net::getCharServerHandler()->clear();
+    updateCharSelectDialog();
+
+    if (network)
+        network->disconnect();
+    Client::setState(STATE_CONNECT_GAME);
+}
+
+void CharServerHandler::processChangeMapServer(Net::MessageIn &msg,
+                                               Network *const network,
+                                               ServerInfo &server) const
+{
+    GameHandler *const gh = static_cast<GameHandler*>(Net::getGameHandler());
+    if (!gh || !network)
+        return;
+    gh->setMap(msg.readString(16));
+    const int x = msg.readInt16();
+    const int y = msg.readInt16();
+    server.hostname = ipToString(msg.readInt32());
+    server.port = msg.readInt16();
+
+    network->disconnect();
+    Client::setState(STATE_CHANGE_MAP);
+    if (player_node)
+    {
+        player_node->setTileCoords(x, y);
+        player_node->setMap(nullptr);
+    }
+}
+
 } // namespace Ea
diff --git a/src/net/ea/charserverhandler.h b/src/net/ea/charserverhandler.h
index 0b9908fee..6622371b3 100644
--- a/src/net/ea/charserverhandler.h
+++ b/src/net/ea/charserverhandler.h
@@ -23,7 +23,7 @@
 #ifndef NET_EA_CHARSERVERHANDLER_H
 #define NET_EA_CHARSERVERHANDLER_H
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 #include "net/messagein.h"
 #include "net/net.h"
 
@@ -32,40 +32,43 @@ class LoginData;
 namespace Ea
 {
 
+class Network;
+
 /**
  * Deals with incoming messages from the character server.
  */
-class CharServerHandler : public Net::CharHandler
+class CharServerHandler : public Net::CharServerHandler
 {
     public:
         CharServerHandler();
 
         A_DELETE_COPY(CharServerHandler)
 
-        virtual void setCharSelectDialog(CharSelectDialog *window);
+        virtual void setCharSelectDialog(CharSelectDialog *const window)
+                                         override;
 
         /**
          * Sets the character create dialog. The handler will clean up this
          * dialog when a new character is succesfully created, and will unlock
          * the dialog when a new character failed to be created.
          */
-        virtual void setCharCreateDialog(CharCreateDialog *window);
+        virtual void setCharCreateDialog(CharCreateDialog *const window)
+                                         override;
 
-        virtual void requestCharacters();
+        virtual void requestCharacters() override;
 
-        virtual unsigned int baseSprite() const A_WARN_UNUSED;
+        virtual unsigned int baseSprite() const override A_WARN_UNUSED;
 
-        virtual unsigned int hairSprite() const A_WARN_UNUSED;
+        virtual unsigned int hairSprite() const override A_WARN_UNUSED;
 
-        virtual unsigned int maxSprite() const A_WARN_UNUSED;
+        virtual unsigned int maxSprite() const override A_WARN_UNUSED;
 
         virtual void connect() = 0;
 
-        virtual void processCharLogin(Net::MessageIn &msg) = 0;
-
-        virtual void processCharLoginError(Net::MessageIn &msg);
+        virtual void processCharLoginError(Net::MessageIn &msg) const;
 
-        virtual void processCharCreate(Net::MessageIn &msg, bool withColors);
+        virtual void processCharCreate(Net::MessageIn &msg,
+                                       const bool withColors);
 
         virtual void processCharCreateFailed(Net::MessageIn &msg);
 
@@ -73,12 +76,20 @@ class CharServerHandler : public Net::CharHandler
 
         virtual void processCharDeleteFailed(Net::MessageIn &msg);
 
-        virtual void clear();
+        virtual void processCharMapInfo(Net::MessageIn &msg,
+                                        Network *const network,
+                                        ServerInfo &mapServer);
+
+        virtual void processChangeMapServer(Net::MessageIn &msg,
+                                            Network *const network,
+                                            ServerInfo &mapServer) const;
+
+        virtual void clear() override;
 
     protected:
         virtual void readPlayerData(Net::MessageIn &msg,
-                                    Net::Character *character,
-                                    bool withColors) = 0;
+                                    Net::Character *const character,
+                                    const bool withColors) const = 0;
 };
 
 } // namespace Ea
diff --git a/src/net/eathena/charserverhandler.cpp b/src/net/eathena/charserverhandler.cpp
index 474874483..2fee39a03 100644
--- a/src/net/eathena/charserverhandler.cpp
+++ b/src/net/eathena/charserverhandler.cpp
@@ -42,7 +42,7 @@
 
 #include "debug.h"
 
-extern Net::CharHandler *charHandler;
+extern Net::CharServerHandler *charServerHandler;
 
 namespace EAthena
 {
@@ -68,7 +68,7 @@ CharServerHandler::CharServerHandler() :
         0
     };
     handledMessages = _messages;
-    charHandler = this;
+    charServerHandler = this;
 }
 
 void CharServerHandler::handleMessage(Net::MessageIn &msg)
@@ -104,59 +104,12 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
             break;
 
         case SMSG_CHAR_MAP_INFO:
-        {
-//            msg.skip(4); // CharID, must be the same as player_node->charID
-            PlayerInfo::setCharId(msg.readInt32());
-            GameHandler *const gh = static_cast<GameHandler*>(
-                Net::getGameHandler());
-            gh->setMap(msg.readString(16));
-            if (config.getBoolValue("usePersistentIP"))
-            {
-                msg.readInt32();
-                mapServer.hostname = Client::getServerName();
-            }
-            else
-            {
-                mapServer.hostname = ipToString(msg.readInt32());
-            }
-            mapServer.port = msg.readInt16();
-
-            // Prevent the selected local player from being deleted
-            player_node = mSelectedCharacter->dummy;
-            PlayerInfo::setBackend(mSelectedCharacter->data);
-
-            mSelectedCharacter->dummy = nullptr;
-
-            Net::getCharHandler()->clear();
-            updateCharSelectDialog();
-
-            if (mNetwork)
-                mNetwork->disconnect();
-            Client::setState(STATE_CONNECT_GAME);
-        }
-        break;
+            processCharMapInfo(msg, mNetwork, mapServer);
+            break;
 
         case SMSG_CHANGE_MAP_SERVER:
-        {
-            GameHandler *const gh = static_cast<GameHandler*>(
-                Net::getGameHandler());
-            if (!gh || !mNetwork)
-                return;
-            gh->setMap(msg.readString(16));
-            const int x = msg.readInt16();
-            const int y = msg.readInt16();
-            mapServer.hostname = ipToString(msg.readInt32());
-            mapServer.port = msg.readInt16();
-
-            mNetwork->disconnect();
-            Client::setState(STATE_CHANGE_MAP);
-            if (player_node)
-            {
-                player_node->setTileCoords(x, y);
-                player_node->setMap(nullptr);
-            }
-        }
-        break;
+            processChangeMapServer(msg, mNetwork, mapServer);
+            break;
 
         default:
             break;
@@ -164,7 +117,8 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
 }
 
 void CharServerHandler::readPlayerData(Net::MessageIn &msg,
-                                       Net::Character *character, bool)
+                                       Net::Character *const character,
+                                       const bool) const
 {
     if (!character)
         return;
@@ -244,7 +198,7 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg,
     msg.readInt8();                        // unknown
 }
 
-void CharServerHandler::chooseCharacter(Net::Character *character)
+void CharServerHandler::chooseCharacter(Net::Character *const character)
 {
     if (!character)
         return;
@@ -256,11 +210,11 @@ void CharServerHandler::chooseCharacter(Net::Character *character)
     outMsg.writeInt8(static_cast<unsigned char>(mSelectedCharacter->slot));
 }
 
-void CharServerHandler::newCharacter(const std::string &name, int slot,
-                                     bool gender A_UNUSED, int hairstyle,
-                                     int hairColor,
-                                     unsigned char race A_UNUSED,
-                                     const std::vector<int> &stats)
+void CharServerHandler::newCharacter(const std::string &name, const int slot,
+                                     const bool gender A_UNUSED,
+                                     const int hairstyle, const int hairColor,
+                                     const unsigned char race A_UNUSED,
+                                     const std::vector<int> &stats) const
 {
     MessageOut outMsg(CMSG_CHAR_CREATE);
     outMsg.writeString(name, 24);
@@ -272,7 +226,7 @@ void CharServerHandler::newCharacter(const std::string &name, int slot,
     outMsg.writeInt16(static_cast<short>(hairstyle));
 }
 
-void CharServerHandler::deleteCharacter(Net::Character *character)
+void CharServerHandler::deleteCharacter(Net::Character *const character)
 {
     if (!character)
         return;
@@ -284,7 +238,7 @@ void CharServerHandler::deleteCharacter(Net::Character *character)
     outMsg.writeString("a@a.com", 40);
 }
 
-void CharServerHandler::switchCharacter()
+void CharServerHandler::switchCharacter() const
 {
     // This is really a map-server packet
     MessageOut outMsg(CMSG_PLAYER_RESTART);
diff --git a/src/net/eathena/charserverhandler.h b/src/net/eathena/charserverhandler.h
index 4c4d3f511..3a49dbb9a 100644
--- a/src/net/eathena/charserverhandler.h
+++ b/src/net/eathena/charserverhandler.h
@@ -23,7 +23,7 @@
 #ifndef NET_EATHENA_CHARSERVERHANDLER_H
 #define NET_EATHENA_CHARSERVERHANDLER_H
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 
 #include "net/ea/charserverhandler.h"
 
@@ -47,26 +47,27 @@ class CharServerHandler final : public MessageHandler,
 
         A_DELETE_COPY(CharServerHandler)
 
-        virtual void handleMessage(Net::MessageIn &msg);
+        virtual void handleMessage(Net::MessageIn &msg) override;
 
-        void chooseCharacter(Net::Character *character);
+        void chooseCharacter(Net::Character *const character) override;
 
-        void newCharacter(const std::string &name, int slot,
-                          bool gender, int hairstyle, int hairColor,
-                          unsigned char race,
-                          const std::vector<int> &stats);
+        void newCharacter(const std::string &name, const int slot,
+                          const bool gender, const int hairstyle,
+                          const int hairColor, const unsigned char race,
+                          const std::vector<int> &stats) const override;
 
-        void deleteCharacter(Net::Character *character);
+        void deleteCharacter(Net::Character *const character) override;
 
-        void switchCharacter();
+        void switchCharacter() const override;
 
-        void connect();
+        void connect() override;
 
         void processCharLogin(Net::MessageIn &msg);
 
     protected:
-        void readPlayerData(Net::MessageIn &msg, Net::Character *character,
-                            bool);
+        void readPlayerData(Net::MessageIn &msg,
+                            Net::Character *const character,
+                            const bool) const override;
 };
 
 } // namespace EAthena
diff --git a/src/net/eathena/generalhandler.cpp b/src/net/eathena/generalhandler.cpp
index c656b944d..d34edff7c 100644
--- a/src/net/eathena/generalhandler.cpp
+++ b/src/net/eathena/generalhandler.cpp
@@ -77,7 +77,7 @@ GeneralHandler::GeneralHandler() :
     mAdminHandler(new AdminHandler),
     mBeingHandler(new BeingHandler(config.getBoolValue("EnableSync"))),
     mBuySellHandler(new BuySellHandler),
-    mCharHandler(new CharServerHandler),
+    mCharServerHandler(new CharServerHandler),
     mChatHandler(new ChatHandler),
     mGameHandler(new GameHandler),
     mGuildHandler(new GuildHandler),
@@ -175,7 +175,7 @@ void GeneralHandler::load()
     mNetwork->registerHandler(mBeingHandler.get());
     mNetwork->registerHandler(mBuySellHandler.get());
     mNetwork->registerHandler(mChatHandler.get());
-    mNetwork->registerHandler(mCharHandler.get());
+    mNetwork->registerHandler(mCharServerHandler.get());
     mNetwork->registerHandler(mGameHandler.get());
     mNetwork->registerHandler(mGuildHandler.get());
     mNetwork->registerHandler(mInventoryHandler.get());
@@ -195,9 +195,9 @@ void GeneralHandler::reload()
 
     static_cast<LoginHandler*>(mLoginHandler.get())->clearWorlds();
     static_cast<CharServerHandler*>(
-        mCharHandler.get())->setCharCreateDialog(nullptr);
+        mCharServerHandler.get())->setCharCreateDialog(nullptr);
     static_cast<CharServerHandler*>(
-        mCharHandler.get())->setCharSelectDialog(nullptr);
+        mCharServerHandler.get())->setCharSelectDialog(nullptr);
 
     static_cast<PartyHandler*>(mPartyHandler.get())->reload();
 }
diff --git a/src/net/eathena/generalhandler.h b/src/net/eathena/generalhandler.h
index 58c0d1e2e..184f30bdc 100644
--- a/src/net/eathena/generalhandler.h
+++ b/src/net/eathena/generalhandler.h
@@ -67,7 +67,7 @@ class GeneralHandler final : public MessageHandler,
         MessageHandlerPtr mAdminHandler;
         MessageHandlerPtr mBeingHandler;
         MessageHandlerPtr mBuySellHandler;
-        MessageHandlerPtr mCharHandler;
+        MessageHandlerPtr mCharServerHandler;
         MessageHandlerPtr mChatHandler;
         MessageHandlerPtr mGameHandler;
         MessageHandlerPtr mGuildHandler;
diff --git a/src/net/net.cpp b/src/net/net.cpp
index e614f9dc6..8e997b35b 100644
--- a/src/net/net.cpp
+++ b/src/net/net.cpp
@@ -27,7 +27,7 @@
 #include "net/adminhandler.h"
 #include "net/beinghandler.h"
 #include "net/buysellhandler.h"
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 #include "net/chathandler.h"
 #include "net/generalhandler.h"
 #include "net/guildhandler.h"
@@ -53,7 +53,7 @@
 #include "debug.h"
 
 Net::AdminHandler *adminHandler = nullptr;
-Net::CharHandler *charHandler = nullptr;
+Net::CharServerHandler *charServerHandler = nullptr;
 Net::ChatHandler *chatHandler = nullptr;
 Net::GeneralHandler *generalHandler = nullptr;
 Net::InventoryHandler *inventoryHandler = nullptr;
@@ -73,9 +73,9 @@ Net::AdminHandler *Net::getAdminHandler()
     return adminHandler;
 }
 
-Net::CharHandler *Net::getCharHandler()
+Net::CharServerHandler *Net::getCharServerHandler()
 {
-    return charHandler;
+    return charServerHandler;
 }
 
 Net::ChatHandler *Net::getChatHandler()
diff --git a/src/net/net.h b/src/net/net.h
index 0be63a3de..c2d19ac72 100644
--- a/src/net/net.h
+++ b/src/net/net.h
@@ -38,7 +38,7 @@ namespace Net
 
 class AdminHandler;
 class BeingHandler;
-class CharHandler;
+class CharServerHandler;
 class ChatHandler;
 class GameHandler;
 class GeneralHandler;
@@ -54,7 +54,7 @@ class BuySellHandler;
 
 AdminHandler *getAdminHandler() A_WARN_UNUSED;
 BeingHandler *getBeingHandler() A_WARN_UNUSED;
-CharHandler *getCharHandler() A_WARN_UNUSED;
+CharServerHandler *getCharServerHandler() A_WARN_UNUSED;
 ChatHandler *getChatHandler() A_WARN_UNUSED;
 GameHandler *getGameHandler() A_WARN_UNUSED;
 GeneralHandler *getGeneralHandler() A_WARN_UNUSED;
diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp
index d922f0852..0b449bff8 100644
--- a/src/net/tmwa/charserverhandler.cpp
+++ b/src/net/tmwa/charserverhandler.cpp
@@ -42,14 +42,15 @@
 
 #include "debug.h"
 
-extern Net::CharHandler *charHandler;
+extern Net::CharServerHandler *charServerHandler;
 
 namespace TmwAthena
 {
 
-extern ServerInfo charServer;
 extern ServerInfo mapServer;
 
+extern ServerInfo charServer;
+
 CharServerHandler::CharServerHandler() :
     MessageHandler(),
     Ea::CharServerHandler()
@@ -68,7 +69,7 @@ CharServerHandler::CharServerHandler() :
         0
     };
     handledMessages = _messages;
-    charHandler = this;
+    charServerHandler = this;
 }
 
 void CharServerHandler::handleMessage(Net::MessageIn &msg)
@@ -105,59 +106,12 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
             break;
 
         case SMSG_CHAR_MAP_INFO:
-        {
-//            msg.skip(4); // CharID, must be the same as player_node->charID
-            PlayerInfo::setCharId(msg.readInt32());
-            GameHandler *const gh = static_cast<GameHandler*>(
-                Net::getGameHandler());
-            gh->setMap(msg.readString(16));
-            if (config.getBoolValue("usePersistentIP"))
-            {
-                msg.readInt32();
-                mapServer.hostname = Client::getServerName();
-            }
-            else
-            {
-                mapServer.hostname = ipToString(msg.readInt32());
-            }
-            mapServer.port = msg.readInt16();
-
-            // Prevent the selected local player from being deleted
-            player_node = mSelectedCharacter->dummy;
-            PlayerInfo::setBackend(mSelectedCharacter->data);
-
-            mSelectedCharacter->dummy = nullptr;
-
-            Net::getCharHandler()->clear();
-            updateCharSelectDialog();
-
-            if (mNetwork)
-                mNetwork->disconnect();
-            Client::setState(STATE_CONNECT_GAME);
-        }
-        break;
+            processCharMapInfo(msg, mNetwork, mapServer);
+            break;
 
         case SMSG_CHANGE_MAP_SERVER:
-        {
-            GameHandler *const gh = static_cast<GameHandler*>(
-                Net::getGameHandler());
-            if (!gh || !mNetwork)
-                return;
-            gh->setMap(msg.readString(16));
-            const int x = msg.readInt16();
-            const int y = msg.readInt16();
-            mapServer.hostname = ipToString(msg.readInt32());
-            mapServer.port = msg.readInt16();
-
-            mNetwork->disconnect();
-            Client::setState(STATE_CHANGE_MAP);
-            if (player_node)
-            {
-                player_node->setTileCoords(x, y);
-                player_node->setMap(nullptr);
-            }
-        }
-        break;
+            processChangeMapServer(msg, mNetwork, mapServer);
+            break;
 
         default:
             break;
@@ -166,8 +120,8 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
 }
 
 void CharServerHandler::readPlayerData(Net::MessageIn &msg,
-                                       Net::Character *character,
-                                       bool withColors)
+                                       Net::Character *const character,
+                                       const bool withColors) const
 {
     if (!character)
         return;
@@ -275,7 +229,7 @@ void CharServerHandler::readPlayerData(Net::MessageIn &msg,
     msg.readInt8();                        // unknown
 }
 
-void CharServerHandler::chooseCharacter(Net::Character *character)
+void CharServerHandler::chooseCharacter(Net::Character *const character)
 {
     if (!character)
         return;
@@ -287,10 +241,12 @@ void CharServerHandler::chooseCharacter(Net::Character *character)
     outMsg.writeInt8(static_cast<unsigned char>(mSelectedCharacter->slot));
 }
 
-void CharServerHandler::newCharacter(const std::string &name, int slot,
-                                     bool gender A_UNUSED, int hairstyle,
-                                     int hairColor, unsigned char race,
-                                     const std::vector<int> &stats)
+void CharServerHandler::newCharacter(const std::string &name, const int slot,
+                                     const bool gender A_UNUSED,
+                                     const int hairstyle,
+                                     const int hairColor,
+                                     const unsigned char race,
+                                     const std::vector<int> &stats) const
 {
     MessageOut outMsg(CMSG_CHAR_CREATE);
     outMsg.writeString(name, 24);
@@ -304,7 +260,7 @@ void CharServerHandler::newCharacter(const std::string &name, int slot,
         outMsg.writeInt8(race);
 }
 
-void CharServerHandler::deleteCharacter(Net::Character *character)
+void CharServerHandler::deleteCharacter(Net::Character *const character)
 {
     if (!character)
         return;
@@ -316,7 +272,7 @@ void CharServerHandler::deleteCharacter(Net::Character *character)
     outMsg.writeString("a@a.com", 40);
 }
 
-void CharServerHandler::switchCharacter()
+void CharServerHandler::switchCharacter() const
 {
     // This is really a map-server packet
     MessageOut outMsg(CMSG_PLAYER_RESTART);
diff --git a/src/net/tmwa/charserverhandler.h b/src/net/tmwa/charserverhandler.h
index b83d7acaf..9d4006a4a 100644
--- a/src/net/tmwa/charserverhandler.h
+++ b/src/net/tmwa/charserverhandler.h
@@ -23,7 +23,7 @@
 #ifndef NET_TA_CHARSERVERHANDLER_H
 #define NET_TA_CHARSERVERHANDLER_H
 
-#include "net/charhandler.h"
+#include "net/charserverhandler.h"
 
 #include "net/ea/charserverhandler.h"
 
@@ -47,26 +47,27 @@ class CharServerHandler final : public MessageHandler,
 
         A_DELETE_COPY(CharServerHandler)
 
-        virtual void handleMessage(Net::MessageIn &msg);
+        virtual void handleMessage(Net::MessageIn &msg) override;
 
-        void chooseCharacter(Net::Character *character);
+        void chooseCharacter(Net::Character *const character) override;
 
-        void newCharacter(const std::string &name, int slot,
-                          bool gender, int hairstyle, int hairColor,
-                          unsigned char race,
-                          const std::vector<int> &stats);
+        void newCharacter(const std::string &name, const int slot,
+                          const bool gender, const int hairstyle,
+                          const int hairColor, const unsigned char race,
+                          const std::vector<int> &stats) const override;
 
-        void deleteCharacter(Net::Character *character);
+        void deleteCharacter(Net::Character *const character) override;
 
-        void switchCharacter();
+        void switchCharacter() const override;
 
-        void connect();
+        void connect() override;
 
         void processCharLogin(Net::MessageIn &msg);
 
     protected:
-        void readPlayerData(Net::MessageIn &msg, Net::Character *character,
-                            bool withColors);
+        void readPlayerData(Net::MessageIn &msg,
+                            Net::Character *const character,
+                            const bool withColors) const override;
 };
 
 } // namespace TmwAthena
diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp
index c366efc9d..f6a78372e 100644
--- a/src/net/tmwa/generalhandler.cpp
+++ b/src/net/tmwa/generalhandler.cpp
@@ -78,7 +78,7 @@ GeneralHandler::GeneralHandler() :
     mAdminHandler(new AdminHandler),
     mBeingHandler(new BeingHandler(config.getBoolValue("EnableSync"))),
     mBuySellHandler(new BuySellHandler),
-    mCharHandler(new CharServerHandler),
+    mCharServerHandler(new CharServerHandler),
     mChatHandler(new ChatHandler),
     mGameHandler(new GameHandler),
     mGuildHandler(new GuildHandler),
@@ -179,7 +179,7 @@ void GeneralHandler::load()
     mNetwork->registerHandler(mBeingHandler.get());
     mNetwork->registerHandler(mBuySellHandler.get());
     mNetwork->registerHandler(mChatHandler.get());
-    mNetwork->registerHandler(mCharHandler.get());
+    mNetwork->registerHandler(mCharServerHandler.get());
     mNetwork->registerHandler(mGameHandler.get());
     mNetwork->registerHandler(mGuildHandler.get());
     mNetwork->registerHandler(mInventoryHandler.get());
@@ -200,9 +200,9 @@ void GeneralHandler::reload()
 
     static_cast<LoginHandler*>(mLoginHandler.get())->clearWorlds();
     static_cast<CharServerHandler*>(
-        mCharHandler.get())->setCharCreateDialog(nullptr);
+        mCharServerHandler.get())->setCharCreateDialog(nullptr);
     static_cast<CharServerHandler*>(
-        mCharHandler.get())->setCharSelectDialog(nullptr);
+        mCharServerHandler.get())->setCharSelectDialog(nullptr);
 
     static_cast<PartyHandler*>(mPartyHandler.get())->reload();
 }
diff --git a/src/net/tmwa/generalhandler.h b/src/net/tmwa/generalhandler.h
index 2fcc625d1..e1254e18f 100644
--- a/src/net/tmwa/generalhandler.h
+++ b/src/net/tmwa/generalhandler.h
@@ -64,7 +64,7 @@ class GeneralHandler final : public MessageHandler, public Net::GeneralHandler,
         MessageHandlerPtr mAdminHandler;
         MessageHandlerPtr mBeingHandler;
         MessageHandlerPtr mBuySellHandler;
-        MessageHandlerPtr mCharHandler;
+        MessageHandlerPtr mCharServerHandler;
         MessageHandlerPtr mChatHandler;
         MessageHandlerPtr mGameHandler;
         MessageHandlerPtr mGuildHandler;
-- 
cgit v1.2.3-70-g09d2