summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mana.files2
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/being.cpp3
-rw-r--r--src/client.cpp1152
-rw-r--r--src/client.h212
-rw-r--r--src/game.cpp163
-rw-r--r--src/game.h36
-rw-r--r--src/gui/changeemaildialog.cpp6
-rw-r--r--src/gui/changepassworddialog.cpp6
-rw-r--r--src/gui/charselectdialog.cpp14
-rw-r--r--src/gui/charselectdialog.h1
-rw-r--r--src/gui/connectiondialog.cpp3
-rw-r--r--src/gui/connectiondialog.h2
-rw-r--r--src/gui/debugwindow.cpp1
-rw-r--r--src/gui/login.cpp13
-rw-r--r--src/gui/login.h2
-rw-r--r--src/gui/palette.cpp2
-rw-r--r--src/gui/quitdialog.cpp14
-rw-r--r--src/gui/recorder.cpp4
-rw-r--r--src/gui/register.cpp8
-rw-r--r--src/gui/serverdialog.cpp11
-rw-r--r--src/gui/unregisterdialog.cpp6
-rw-r--r--src/gui/updatewindow.cpp17
-rw-r--r--src/gui/viewport.cpp2
-rw-r--r--src/gui/widgets/avatarlistbox.cpp2
-rw-r--r--src/gui/worldselectdialog.cpp8
-rw-r--r--src/localplayer.cpp2
-rw-r--r--src/main.cpp1104
-rw-r--r--src/main.h67
-rw-r--r--src/map.cpp10
-rw-r--r--src/monster.cpp7
-rw-r--r--src/net/ea/beinghandler.cpp2
-rw-r--r--src/net/ea/charserverhandler.cpp6
-rw-r--r--src/net/ea/gamehandler.cpp7
-rw-r--r--src/net/ea/generalhandler.cpp8
-rw-r--r--src/net/ea/loginhandler.cpp15
-rw-r--r--src/net/logindata.h3
-rw-r--r--src/net/manaserv/beinghandler.cpp7
-rw-r--r--src/net/manaserv/charhandler.cpp9
-rw-r--r--src/net/manaserv/chathandler.cpp5
-rw-r--r--src/net/manaserv/gamehandler.cpp6
-rw-r--r--src/net/manaserv/generalhandler.cpp6
-rw-r--r--src/net/manaserv/loginhandler.cpp36
-rw-r--r--src/net/manaserv/playerhandler.cpp4
-rw-r--r--src/player.cpp5
-rw-r--r--src/statuseffect.cpp1
-rw-r--r--src/statuseffect.h1
48 files changed, 1553 insertions, 1452 deletions
diff --git a/mana.files b/mana.files
index 83ae2e10..ca34ff3c 100644
--- a/mana.files
+++ b/mana.files
@@ -282,6 +282,8 @@
./src/imageparticle.h
./src/inventory.cpp
./src/inventory.h
+./src/client.cpp
+./src/client.h
./src/item.cpp
./src/item.h
./src/itemshortcut.cpp
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1273fe40..4f90d0a2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -396,6 +396,8 @@ SET(SRCS
being.h
beingmanager.cpp
beingmanager.h
+ client.cpp
+ client.h
channel.cpp
channel.h
channelmanager.cpp
diff --git a/src/Makefile.am b/src/Makefile.am
index 8f7c7164..75b699b7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -301,6 +301,8 @@ mana_SOURCES = gui/widgets/avatarlistbox.cpp \
being.h \
beingmanager.cpp \
beingmanager.h \
+ client.cpp \
+ client.h \
channel.cpp \
channel.h \
channelmanager.cpp \
diff --git a/src/being.cpp b/src/being.cpp
index c49834f1..33194e0e 100644
--- a/src/being.cpp
+++ b/src/being.cpp
@@ -22,9 +22,9 @@
#include "being.h"
#include "animatedsprite.h"
+#include "client.h"
#include "configuration.h"
#include "effectmanager.h"
-#include "game.h"
#include "graphics.h"
#include "localplayer.h"
#include "log.h"
@@ -62,7 +62,6 @@
static const int DEFAULT_BEING_WIDTH = 32;
static const int DEFAULT_BEING_HEIGHT = 32;
-extern const int MILLISECONDS_IN_A_TICK;
int Being::mNumberOfHairstyles = 1;
diff --git a/src/client.cpp b/src/client.cpp
new file mode 100644
index 00000000..1f608fa6
--- /dev/null
+++ b/src/client.cpp
@@ -0,0 +1,1152 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana 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 "client.h"
+#include "main.h"
+
+#include "configuration.h"
+#include "emoteshortcut.h"
+#include "game.h"
+#include "itemshortcut.h"
+#include "keyboardconfig.h"
+#ifdef USE_OPENGL
+#include "openglgraphics.h"
+#endif
+#include "playerrelations.h"
+#include "sound.h"
+#include "statuseffect.h"
+#include "units.h"
+
+#include "gui/changeemaildialog.h"
+#include "gui/changepassworddialog.h"
+#include "gui/charselectdialog.h"
+#include "gui/connectiondialog.h"
+#include "gui/gui.h"
+#include "gui/skin.h"
+#include "gui/login.h"
+#include "gui/okdialog.h"
+#include "gui/palette.h"
+#include "gui/quitdialog.h"
+#include "gui/register.h"
+#include "gui/sdlinput.h"
+#include "gui/serverdialog.h"
+#include "gui/setup.h"
+#include "gui/unregisterdialog.h"
+#include "gui/updatewindow.h"
+#include "gui/worldselectdialog.h"
+
+#include "gui/widgets/button.h"
+#include "gui/widgets/desktop.h"
+
+#include "net/charhandler.h"
+#include "net/gamehandler.h"
+#include "net/generalhandler.h"
+#include "net/logindata.h"
+#include "net/loginhandler.h"
+#include "net/net.h"
+#include "net/worldinfo.h"
+
+#include "resources/colordb.h"
+#include "resources/emotedb.h"
+#include "resources/image.h"
+#include "resources/itemdb.h"
+#include "resources/monsterdb.h"
+#include "resources/npcdb.h"
+#include "resources/resourcemanager.h"
+
+#include "utils/gettext.h"
+#include "utils/stringutils.h"
+
+#ifdef __APPLE__
+#include <CoreFoundation/CFBundle.h>
+#endif
+
+#include <physfs.h>
+#include <SDL_image.h>
+
+#ifdef WIN32
+#include <SDL_syswm.h>
+#else
+#include <cerrno>
+#include <sys/stat.h>
+#endif
+
+#include <cassert>
+
+/**
+ * Tells the max tick value,
+ * setting it back to zero (and start again).
+ */
+static const int MAX_TICK_VALUE = 10000;
+
+static const int defaultSfxVolume = 100;
+static const int defaultMusicVolume = 60;
+
+// TODO: Get rid fo these globals
+std::string errorMessage;
+ErrorListener errorListener;
+LoginData loginData;
+
+Configuration config; /**< XML file configuration reader */
+Configuration branding; /**< XML branding information reader */
+Logger *logger; /**< Log object */
+KeyboardConfig keyboard;
+
+Palette *guiPalette;
+Graphics *graphics;
+
+Sound sound;
+
+void ErrorListener::action(const gcn::ActionEvent &)
+{
+ Client::setState(STATE_CHOOSE_SERVER);
+}
+
+volatile int tick_time; /**< Tick counter */
+volatile int fps = 0; /**< Frames counted in the last second */
+volatile int frame_count = 0; /**< Counts the frames during one second */
+
+/**
+ * Advances game logic counter.
+ * Called every 10 milliseconds by SDL_AddTimer()
+ * @see MILLISECONDS_IN_A_TICK value
+ */
+Uint32 nextTick(Uint32 interval, void *param)
+{
+ tick_time++;
+ if (tick_time == MAX_TICK_VALUE)
+ tick_time = 0;
+ return interval;
+}
+
+/**
+ * Updates fps.
+ * Called every seconds by SDL_AddTimer()
+ */
+Uint32 nextSecond(Uint32 interval, void *param)
+{
+ fps = frame_count;
+ frame_count = 0;
+
+ return interval;
+}
+
+/**
+ * @return the elapsed time in milliseconds
+ * between two tick values.
+ */
+int get_elapsed_time(int start_time)
+{
+ if (start_time <= tick_time)
+ return (tick_time - start_time) * MILLISECONDS_IN_A_TICK;
+ else
+ return (tick_time + (MAX_TICK_VALUE - start_time))
+ * MILLISECONDS_IN_A_TICK;
+}
+
+
+// This anonymous namespace hides whatever is inside from other modules.
+namespace {
+
+class AccountListener : public gcn::ActionListener
+{
+public:
+ void action(const gcn::ActionEvent &)
+ {
+ Client::setState(STATE_CHAR_SELECT);
+ }
+} accountListener;
+
+class LoginListener : public gcn::ActionListener
+{
+public:
+ void action(const gcn::ActionEvent &)
+ {
+ Client::setState(STATE_LOGIN);
+ }
+} loginListener;
+
+} // anonymous namespace
+
+
+Client *Client::mInstance = 0;
+
+Client::Client(const Options &options):
+ options(options),
+ currentDialog(0),
+ quitDialog(0),
+ desktop(0),
+ setupButton(0),
+ state(STATE_CHOOSE_SERVER),
+ oldstate(STATE_START),
+ mLogicCounterId(0),
+ mSecondsCounterId(0),
+ mLimitFps(false)
+{
+ assert(!mInstance);
+ mInstance = this;
+
+ // Load branding information
+ branding.init("data/branding.xml");
+
+ initHomeDir(options);
+ initScreenshotDir(options.screenshotDir);
+
+ // Configure logger
+ logger = new Logger;
+ logger->setLogFile(homeDir + std::string("/mana.log"));
+
+ // Log the mana version
+ logger->log("Mana %s", FULL_VERSION);
+
+ initConfiguration(options);
+ logger->setLogToStandardOut(config.getValue("logToStandardOut", 0));
+
+ // Initialize SDL
+ logger->log("Initializing SDL...");
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
+ {
+ logger->error(strprintf("Could not initialize SDL: %s",
+ SDL_GetError()));
+ }
+ atexit(SDL_Quit);
+
+ SDL_EnableUNICODE(1);
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+
+ SDL_WM_SetCaption(branding.getValue("appName", "Mana").c_str(), NULL);
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ if (!resman->setWriteDir(homeDir))
+ {
+ logger->error(strprintf("%s couldn't be set as home directory! "
+ "Exiting.", homeDir.c_str()));
+ }
+
+ // Add the user's homedir to PhysicsFS search path
+ resman->addToSearchPath(homeDir, false);
+
+ // Add the main data directories to our PhysicsFS search path
+ if (!options.dataPath.empty())
+ resman->addToSearchPath(options.dataPath, true);
+ resman->addToSearchPath("data", true);
+#if defined __APPLE__
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
+ char path[PATH_MAX];
+ if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path,
+ PATH_MAX))
+ {
+ fprintf(stderr, "Can't find Resources directory\n");
+ }
+ CFRelease(resourcesURL);
+ strncat(path, "/data", PATH_MAX - 1);
+ resman->addToSearchPath(path, true);
+#else
+ resman->addToSearchPath(PKG_DATADIR "data", true);
+#endif
+
+#ifdef WIN32
+ static SDL_SysWMinfo pInfo;
+ SDL_GetWMInfo(&pInfo);
+ HICON icon = LoadIcon(GetModuleHandle(NULL), "A");
+ if (icon)
+ {
+ SetClassLong(pInfo.window, GCL_HICON, (LONG) icon);
+ }
+#else
+ icon = IMG_Load(resman->getPath(
+ branding.getValue("appIcon", "data/icons/mana.png")).c_str());
+ if (icon)
+ {
+ SDL_SetAlpha(icon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
+ SDL_WM_SetIcon(icon, NULL);
+ }
+#endif
+
+#ifdef USE_OPENGL
+ bool useOpenGL = !options.noOpenGL && (config.getValue("opengl", 0) == 1);
+
+ // Setup image loading for the right image format
+ Image::setLoadAsOpenGL(useOpenGL);
+
+ // Create the graphics context
+ graphics = useOpenGL ? new OpenGLGraphics : new Graphics;
+#else
+ // Create the graphics context
+ graphics = new Graphics;
+#endif
+
+ const int width = (int) config.getValue("screenwidth", defaultScreenWidth);
+ const int height = (int) config.getValue("screenheight", defaultScreenHeight);
+ const int bpp = 0;
+ const bool fullscreen = ((int) config.getValue("screen", 0) == 1);
+ const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
+
+ // Try to set the desired video mode
+ if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
+ {
+ logger->error(strprintf("Couldn't set %dx%dx%d video mode: %s",
+ width, height, bpp, SDL_GetError()));
+ }
+
+ // Initialize for drawing
+ graphics->_beginDraw();
+
+ // Initialize the item shortcuts.
+ itemShortcut = new ItemShortcut;
+
+ // Initialize the emote shortcuts.
+ emoteShortcut = new EmoteShortcut;
+
+ gui = new Gui(graphics);
+
+ // Initialize sound engine
+ try
+ {
+ if (config.getValue("sound", 0) == 1)
+ sound.init();
+
+ sound.setSfxVolume((int) config.getValue("sfxVolume",
+ defaultSfxVolume));
+ sound.setMusicVolume((int) config.getValue("musicVolume",
+ defaultMusicVolume));
+ }
+ catch (const char *err)
+ {
+ state = STATE_ERROR;
+ errorMessage = err;
+ logger->log("Warning: %s", err);
+ }
+
+ // Initialize keyboard
+ keyboard.init();
+
+ // Initialise player relations
+ player_relations.init();
+
+ guiPalette = new Palette;
+ setupWindow = new Setup;
+
+ sound.playMusic(branding.getValue("loginMusic", "Magick - Real.ogg"));
+
+ // Initialize default server
+ currentServer.hostname = options.serverName;
+ currentServer.port = options.serverPort;
+ loginData.username = options.username;
+ loginData.password = options.password;
+ loginData.remember = config.getValue("remember", 0);
+ loginData.registerLogin = false;
+
+ if (currentServer.hostname.empty())
+ {
+ currentServer.hostname = branding.getValue("defaultServer",
+ "server.themanaworld.org").c_str();
+ }
+ if (options.serverPort == 0)
+ {
+ currentServer.port = (short) branding.getValue("defaultPort",
+ DEFAULT_PORT);
+ }
+ if (loginData.username.empty() && loginData.remember)
+ loginData.username = config.getValue("username", "");
+
+ if (state != STATE_ERROR)
+ state = STATE_CHOOSE_SERVER;
+
+ // Initialize logic and seconds counters
+ tick_time = 0;
+ mLogicCounterId = SDL_AddTimer(MILLISECONDS_IN_A_TICK, nextTick, NULL);
+ mSecondsCounterId = SDL_AddTimer(1000, nextSecond, NULL);
+
+ // Initialize frame limiting
+ SDL_initFramerate(&mFpsManager);
+ config.addListener("fpslimit", this);
+ optionChanged("fpslimit");
+}
+
+Client::~Client()
+{
+ SDL_RemoveTimer(mLogicCounterId);
+ SDL_RemoveTimer(mSecondsCounterId);
+
+ // Before config.write() since it writes the shortcuts to the config
+ delete itemShortcut;
+ delete emoteShortcut;
+
+ config.write();
+
+ delete gui;
+ delete graphics;
+
+ // Shutdown libxml
+ xmlCleanupParser();
+
+ // Shutdown sound
+ sound.close();
+
+ // Unload XML databases
+ ColorDB::unload();
+ EmoteDB::unload();
+ ItemDB::unload();
+ MonsterDB::unload();
+ NPCDB::unload();
+ StatusEffect::unload();
+
+ ResourceManager::deleteInstance();
+
+ SDL_FreeSurface(icon);
+
+ logger->log("Quitting");
+ delete guiPalette;
+ delete logger;
+
+ mInstance = 0;
+}
+
+int Client::exec()
+{
+ int lastTickTime = tick_time;
+
+ Game *game = 0;
+ SDL_Event event;
+
+ while (state != STATE_EXIT)
+ {
+ bool handledEvents = false;
+
+ if (game)
+ {
+ // Let the game handle the events while it is active
+ game->handleInput();
+ }
+ else
+ {
+ // Handle SDL events
+ while (SDL_PollEvent(&event))
+ {
+ handledEvents = true;
+
+ switch (event.type)
+ {
+ case SDL_QUIT:
+ state = STATE_EXIT;
+ break;
+
+ case SDL_KEYDOWN:
+ break;
+ }
+
+ guiInput->pushInput(event);
+ }
+ }
+
+ if (Net::getGeneralHandler())
+ Net::getGeneralHandler()->flushNetwork();
+
+ while (get_elapsed_time(lastTickTime) > 0)
+ {
+ gui->logic();
+ if (game)
+ game->logic();
+
+ ++lastTickTime;
+ }
+
+ // This is done because at some point tick_time will wrap.
+ lastTickTime = tick_time;
+
+ // Update the screen when application is active, delay otherwise.
+ if (SDL_GetAppState() & SDL_APPACTIVE)
+ {
+ frame_count++;
+ gui->draw();
+ graphics->updateScreen();
+ }
+ else
+ {
+ SDL_Delay(10);
+ }
+
+ if (mLimitFps)
+ SDL_framerateDelay(&mFpsManager);
+
+
+ // TODO: Add connect timeouts
+ if (state == STATE_CONNECT_GAME &&
+ Net::getGameHandler()->isConnected())
+ {
+ Net::getLoginHandler()->disconnect();
+ }
+ else if (state == STATE_CONNECT_SERVER && oldstate == STATE_CHOOSE_SERVER)
+ {
+ Net::connectToServer(currentServer);
+ }
+ else if (state == STATE_CONNECT_SERVER &&
+ oldstate != STATE_CHOOSE_SERVER &&
+ Net::getLoginHandler()->isConnected())
+ {
+ state = STATE_LOGIN;
+ }
+ else if (state == STATE_WORLD_SELECT && oldstate == STATE_UPDATE)
+ {
+ if (Net::getLoginHandler()->getWorlds().size() < 2)
+ {
+ state = STATE_LOGIN;
+ }
+ }
+ else if (oldstate == STATE_START ||
+ (oldstate == STATE_GAME && state != STATE_GAME))
+ {
+ gcn::Container *top = static_cast<gcn::Container*>(gui->getTop());
+
+ desktop = new Desktop;
+ top->add(desktop);
+ setupButton = new Button(_("Setup"), "Setup", this);
+ setupButton->setPosition(top->getWidth() - setupButton->getWidth()
+ - 3, 3);
+ top->add(setupButton);
+
+ int screenWidth = (int) config.getValue("screenwidth",
+ defaultScreenWidth);
+ int screenHeight = (int) config.getValue("screenheight",
+ defaultScreenHeight);
+
+ desktop->setSize(screenWidth, screenHeight);
+ }
+
+ if (state == STATE_SWITCH_LOGIN && oldstate == STATE_GAME)
+ {
+ Net::getGameHandler()->disconnect();
+ }
+
+ if (state != oldstate)
+ {
+ if (oldstate == STATE_GAME)
+ {
+ delete game;
+ game = 0;
+ }
+
+ oldstate = state;
+
+ // Get rid of the dialog of the previous state
+ if (currentDialog)
+ {
+ delete currentDialog;
+ currentDialog = NULL;
+ }
+ // State has changed, while the quitDialog was active, it might
+ // not be correct anymore
+ if (quitDialog)
+ quitDialog->scheduleDelete();
+
+ switch (state)
+ {
+ case STATE_CHOOSE_SERVER:
+ logger->log("State: CHOOSE SERVER");
+
+ // Allow changing this using a server choice dialog
+ // We show the dialog box only if the command-line
+ // options weren't set.
+ if (options.serverName.empty() && options.serverPort == 0)
+ {
+ // Don't allow an alpha opacity
+ // lower than the default value
+ SkinLoader::instance()->setMinimumOpacity(0.8f);
+
+ currentDialog = new ServerDialog(&currentServer,
+ homeDir);
+ }
+ else
+ {
+ state = STATE_CONNECT_SERVER;
+
+ // Reset options so that cancelling or connect
+ // timeout will show the server dialog.
+ options.serverName.clear();
+ options.serverPort = 0;
+ }
+ break;
+
+ case STATE_CONNECT_SERVER:
+ logger->log("State: CONNECT SERVER");
+ currentDialog = new ConnectionDialog(
+ _("Connecting to server"), STATE_SWITCH_SERVER);
+ break;
+
+ case STATE_LOGIN:
+ logger->log("State: LOGIN");
+ // Don't allow an alpha opacity
+ // lower than the default value
+ SkinLoader::instance()->setMinimumOpacity(0.8f);
+
+ if (options.username.empty()
+ || options.password.empty())
+ {
+ currentDialog = new LoginDialog(&loginData);
+ }
+ else
+ {
+ state = STATE_LOGIN_ATTEMPT;
+ // Clear the password so that when login fails, the
+ // dialog will show up next time.
+ options.password.clear();
+ }
+ break;
+
+ case STATE_LOGIN_ATTEMPT:
+ logger->log("State: LOGIN ATTEMPT");
+ accountLogin(&loginData);
+ currentDialog = new ConnectionDialog(
+ _("Logging in"), STATE_SWITCH_SERVER);
+ break;
+
+ case STATE_WORLD_SELECT:
+ logger->log("State: WORLD SELECT");
+ {
+ Worlds worlds = Net::getLoginHandler()->getWorlds();
+
+ if (worlds.size() == 0)
+ {
+ // Trust that the netcode knows what it's doing
+ state = STATE_UPDATE;
+ }
+ else if (worlds.size() == 1)
+ {
+ Net::getLoginHandler()->chooseServer(0);
+ state = STATE_UPDATE;
+ }
+ else
+ {
+ currentDialog = new WorldSelectDialog(worlds);
+ if (options.chooseDefault)
+ {
+ ((WorldSelectDialog*) currentDialog)->action(
+ gcn::ActionEvent(NULL, "ok"));
+ }
+ }
+ }
+ break;
+
+ case STATE_WORLD_SELECT_ATTEMPT:
+ logger->log("State: WORLD SELECT ATTEMPT");
+ currentDialog = new ConnectionDialog(
+ _("Entering game world"), STATE_WORLD_SELECT);
+ break;
+
+ case STATE_UPDATE:
+ // Determine which source to use for the update host
+ if (!options.updateHost.empty())
+ updateHost = options.updateHost;
+ else
+ updateHost = loginData.updateHost;
+ initUpdatesDir();
+
+ if (options.skipUpdate)
+ {
+ state = STATE_LOAD_DATA;
+ }
+ else
+ {
+ logger->log("State: UPDATE");
+ currentDialog = new UpdaterWindow(updateHost,
+ homeDir + "/" + updatesDir,options.dataPath.empty());
+ }
+ break;
+
+ case STATE_LOAD_DATA:
+ logger->log("State: LOAD DATA");
+
+ // If another data path has been set,
+ // we don't load any other files...
+ if (options.dataPath.empty())
+ {
+ // Add customdata directory
+ ResourceManager::getInstance()->searchAndAddArchives(
+ "customdata/",
+ "zip",
+ false);
+ }
+
+ // Load XML databases
+ ColorDB::load();
+ ItemDB::load();
+ Being::load(); // Hairstyles
+ MonsterDB::load();
+ NPCDB::load();
+ EmoteDB::load();
+ StatusEffect::load();
+ Units::loadUnits();
+
+ desktop->reloadWallpaper();
+
+ state = STATE_GET_CHARACTERS;
+ break;
+
+ case STATE_GET_CHARACTERS:
+ logger->log("State: GET CHARACTERS");
+ Net::getCharHandler()->requestCharacters();
+ currentDialog = new ConnectionDialog(
+ _("Requesting characters"),
+ STATE_SWITCH_SERVER);
+ break;
+
+ case STATE_CHAR_SELECT:
+ logger->log("State: CHAR SELECT");
+ // Don't allow an alpha opacity
+ // lower than the default value
+ SkinLoader::instance()->setMinimumOpacity(0.8f);
+
+ currentDialog = new CharSelectDialog(&loginData);
+
+ if (!((CharSelectDialog*) currentDialog)->selectByName(
+ options.character, CharSelectDialog::Choose))
+ {
+ ((CharSelectDialog*) currentDialog)->selectByName(
+ config.getValue("lastCharacter", ""),
+ options.chooseDefault ?
+ CharSelectDialog::Choose :
+ CharSelectDialog::Focus);
+ }
+
+ break;
+
+ case STATE_CONNECT_GAME:
+ logger->log("State: CONNECT GAME");
+
+ Net::getGameHandler()->connect();
+ currentDialog = new ConnectionDialog(
+ _("Connecting to the game server"),
+ STATE_SWITCH_CHARACTER);
+ break;
+
+ case STATE_GAME:
+ logger->log("Memorizing selected character %s",
+ player_node->getName().c_str());
+ config.setValue("lastCharacter", player_node->getName());
+
+ Net::getGameHandler()->inGame();
+
+ // Fade out logon-music here too to give the desired effect
+ // of "flowing" into the game.
+ sound.fadeOutMusic(1000);
+
+ // Allow any alpha opacity
+ SkinLoader::instance()->setMinimumOpacity(-1.0f);
+
+ delete setupButton;
+ delete desktop;
+ setupButton = NULL;
+ desktop = NULL;
+
+ currentDialog = NULL;
+
+ logger->log("State: GAME");
+ game = new Game;
+ break;
+
+ case STATE_LOGIN_ERROR:
+ logger->log("State: LOGIN ERROR");
+ currentDialog = new OkDialog(_("Error"), errorMessage);
+ currentDialog->addActionListener(&loginListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+ case STATE_ACCOUNTCHANGE_ERROR:
+ logger->log("State: ACCOUNT CHANGE ERROR");
+ currentDialog = new OkDialog(_("Error"), errorMessage);
+ currentDialog->addActionListener(&accountListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+ case STATE_REGISTER_PREP:
+ logger->log("State: REGISTER_PREP");
+ Net::getLoginHandler()->getRegistrationDetails();
+ currentDialog = new ConnectionDialog(
+ _("Requesting registration details"), STATE_LOGIN);
+ break;
+
+ case STATE_REGISTER:
+ logger->log("State: REGISTER");
+ currentDialog = new RegisterDialog(&loginData);
+ break;
+
+ case STATE_REGISTER_ATTEMPT:
+ logger->log("Username is %s", loginData.username.c_str());
+ Net::getLoginHandler()->registerAccount(&loginData);
+ break;
+
+ case STATE_CHANGEPASSWORD:
+ logger->log("State: CHANGE PASSWORD");
+ currentDialog = new ChangePasswordDialog(&loginData);
+ break;
+
+ case STATE_CHANGEPASSWORD_ATTEMPT:
+ logger->log("State: CHANGE PASSWORD ATTEMPT");
+ Net::getLoginHandler()->changePassword(loginData.username,
+ loginData.password,
+ loginData.newPassword);
+ break;
+
+ case STATE_CHANGEPASSWORD_SUCCESS:
+ logger->log("State: CHANGE PASSWORD SUCCESS");
+ currentDialog = new OkDialog(_("Password Change"),
+ _("Password changed successfully!"));
+ currentDialog->addActionListener(&accountListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ loginData.password = loginData.newPassword;
+ loginData.newPassword = "";
+ break;
+
+ case STATE_CHANGEEMAIL:
+ logger->log("State: CHANGE EMAIL");
+ currentDialog = new ChangeEmailDialog(&loginData);
+ break;
+
+ case STATE_CHANGEEMAIL_ATTEMPT:
+ logger->log("State: CHANGE EMAIL ATTEMPT");
+ Net::getLoginHandler()->changeEmail(loginData.email);
+ break;
+
+ case STATE_CHANGEEMAIL_SUCCESS:
+ logger->log("State: CHANGE EMAIL SUCCESS");
+ currentDialog = new OkDialog(_("Email Change"),
+ _("Email changed successfully!"));
+ currentDialog->addActionListener(&accountListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+ case STATE_UNREGISTER:
+ logger->log("State: UNREGISTER");
+ currentDialog = new UnRegisterDialog(&loginData);
+ break;
+
+ case STATE_UNREGISTER_ATTEMPT:
+ logger->log("State: UNREGISTER ATTEMPT");
+ Net::getLoginHandler()->unregisterAccount(
+ loginData.username, loginData.password);
+ break;
+
+ case STATE_UNREGISTER_SUCCESS:
+ logger->log("State: UNREGISTER SUCCESS");
+ Net::getLoginHandler()->disconnect();
+
+ currentDialog = new OkDialog(_("Unregister Successful"),
+ _("Farewell, come back any time..."));
+ loginData.clear();
+ //The errorlistener sets the state to STATE_CHOOSE_SERVER
+ currentDialog->addActionListener(&errorListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ break;
+
+ case STATE_SWITCH_SERVER:
+ logger->log("State: SWITCH SERVER");
+
+ Net::getLoginHandler()->disconnect();
+ Net::getGameHandler()->disconnect();
+
+ state = STATE_CHOOSE_SERVER;
+ break;
+
+ case STATE_SWITCH_LOGIN:
+ logger->log("State: SWITCH LOGIN");
+
+ Net::getLoginHandler()->logout();
+
+ state = STATE_LOGIN;
+ break;
+
+ case STATE_SWITCH_CHARACTER:
+ logger->log("State: SWITCH CHARACTER");
+
+ // Done with game
+ Net::getGameHandler()->disconnect();
+
+ Net::getCharHandler()->requestCharacters();
+ break;
+
+ case STATE_LOGOUT_ATTEMPT:
+ logger->log("State: LOGOUT ATTEMPT");
+ // TODO
+ break;
+
+ case STATE_WAIT:
+ logger->log("State: WAIT");
+ break;
+
+ case STATE_EXIT:
+ logger->log("State: EXIT");
+ Net::unload();
+ break;
+
+ case STATE_FORCE_QUIT:
+ logger->log("State: FORCE QUIT");
+ if (Net::getGeneralHandler())
+ Net::getGeneralHandler()->unload();
+ state = STATE_EXIT;
+ break;
+
+ case STATE_ERROR:
+ logger->log("State: ERROR");
+ currentDialog = new OkDialog(_("Error"), errorMessage);
+ currentDialog->addActionListener(&errorListener);
+ currentDialog = NULL; // OkDialog deletes itself
+ Net::getGameHandler()->disconnect();
+ break;
+
+ default:
+ state = STATE_FORCE_QUIT;
+ break;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void Client::optionChanged(const std::string &name)
+{
+ const int fpsLimit = (int) config.getValue("fpslimit", 60);
+ mLimitFps = fpsLimit > 0;
+ if (mLimitFps)
+ SDL_setFramerate(&mFpsManager, fpsLimit);
+}
+
+void Client::action(const gcn::ActionEvent &event)
+{
+ Window *window = 0;
+
+ if (event.getId() == "Setup")
+ window = setupWindow;
+
+ if (window)
+ {
+ window->setVisible(!window->isVisible());
+ if (window->isVisible())
+ window->requestMoveToTop();
+ }
+}
+
+/**
+ * Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On
+ * Windows and other systems we use the current working directory.
+ */
+void Client::initHomeDir(const Options &options)
+{
+ homeDir = options.homeDir;
+
+ if (homeDir.empty())
+ {
+#ifdef __APPLE__
+ // Use Application Directory instead of .mana
+ homeDir = std::string(PHYSFS_getUserDir()) +
+ "/Library/Application Support/" +
+ branding.getValue("appName", "Mana");
+#else
+ homeDir = std::string(PHYSFS_getUserDir()) +
+ "/." + branding.getValue("appShort", "mana");
+#endif
+ }
+#if defined WIN32
+ if (!CreateDirectory(homeDir.c_str(), 0) &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+#else
+ // Create home directory if it doesn't exist already
+ if ((mkdir(homeDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) &&
+ (errno != EEXIST))
+#endif
+ {
+ logger->error(strprintf(_("%s doesn't exist and can't be created! "
+ "Exiting."), homeDir.c_str()));
+ }
+}
+
+/**
+ * Initialize configuration.
+ */
+void Client::initConfiguration(const Options &options)
+{
+ // Fill configuration with defaults
+ logger->log("Initializing configuration...");
+ std::string defaultHost = branding.getValue("defaultServer",
+ "server.themanaworld.org");
+ int defaultPort = (int) branding.getValue("defaultPort", DEFAULT_PORT);
+ config.setValue("port", defaultPort);
+ config.setValue("hwaccel", false);
+#if (defined __APPLE__ || defined WIN32) && defined USE_OPENGL
+ config.setValue("opengl", true);
+#else
+ config.setValue("opengl", false);
+#endif
+ config.setValue("screen", false);
+ config.setValue("sound", true);
+ config.setValue("guialpha", 0.8f);
+ config.setValue("remember", true);
+ config.setValue("sfxVolume", 100);
+ config.setValue("musicVolume", 60);
+ config.setValue("fpslimit", 60);
+ std::string defaultUpdateHost = branding.getValue("defaultUpdateHost",
+ "http://updates.themanaworld.org");
+ config.setValue("updatehost", defaultUpdateHost);
+ config.setValue("customcursor", true);
+ config.setValue("ChatLogLength", 128);
+
+ // Checking if the configuration file exists... otherwise create it with
+ // default options.
+ FILE *configFile = 0;
+ std::string configPath = options.configPath;
+
+ if (configPath.empty())
+ configPath = homeDir + "/config.xml";
+
+ configFile = fopen(configPath.c_str(), "r");
+
+ // If we can't read it, it doesn't exist !
+ if (configFile == NULL)
+ {
+ // We reopen the file in write mode and we create it
+ configFile = fopen(configPath.c_str(), "wt");
+ }
+ if (configFile == NULL)
+ {
+ logger->log("Can't create %s. Using defaults.", configPath.c_str());
+ }
+ else
+ {
+ fclose(configFile);
+ config.init(configPath);
+ }
+}
+
+/**
+ * Parse the update host and determine the updates directory
+ * Then verify that the directory exists (creating if needed).
+ */
+void Client::initUpdatesDir()
+{
+ std::stringstream updates;
+
+ // If updatesHost is currently empty, fill it from config file
+ if (updateHost.empty())
+ {
+ updateHost =
+ config.getValue("updatehost", "http://updates.themanaworld.org/");
+ }
+
+ // Remove any trailing slash at the end of the update host
+ if (updateHost.at(updateHost.size() - 1) == '/')
+ updateHost.resize(updateHost.size() - 1);
+
+ // Parse out any "http://" or "ftp://", and set the updates directory
+ size_t pos;
+ pos = updateHost.find("://");
+ if (pos != updateHost.npos)
+ {
+ if (pos + 3 < updateHost.length())
+ {
+ updates << "updates/" << updateHost.substr(pos + 3);
+ updatesDir = updates.str();
+ }
+ else
+ {
+ logger->log("Error: Invalid update host: %s", updateHost.c_str());
+ errorMessage = strprintf(_("Invalid update host: %s"),
+ updateHost.c_str());
+ state = STATE_ERROR;
+ }
+ }
+ else
+ {
+ logger->log("Warning: no protocol was specified for the update host");
+ updates << "updates/" << updateHost;
+ updatesDir = updates.str();
+ }
+
+ ResourceManager *resman = ResourceManager::getInstance();
+
+ // Verify that the updates directory exists. Create if necessary.
+ if (!resman->isDirectory("/" + updatesDir))
+ {
+ if (!resman->mkdir("/" + updatesDir))
+ {
+#if defined WIN32
+ std::string newDir = homeDir + "\\" + updatesDir;
+ std::string::size_type loc = newDir.find("/", 0);
+
+ while (loc != std::string::npos)
+ {
+ newDir.replace(loc, 1, "\\");
+ loc = newDir.find("/", loc);
+ }
+
+ if (!CreateDirectory(newDir.c_str(), 0) &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+ {
+ logger->log("Error: %s can't be made, but doesn't exist!",
+ newDir.c_str());
+ errorMessage = _("Error creating updates directory!");
+ state = STATE_ERROR;
+ }
+#else
+ logger->log("Error: %s/%s can't be made, but doesn't exist!",
+ homeDir.c_str(), updatesDir.c_str());
+ errorMessage = _("Error creating updates directory!");
+ state = STATE_ERROR;
+#endif
+ }
+ }
+}
+
+void Client::initScreenshotDir(const std::string &dir)
+{
+ if (dir.empty())
+ {
+ screenshotDir = std::string(PHYSFS_getUserDir()) + "Desktop";
+ // If ~/Desktop does not exist, we save screenshots in the user's home.
+ struct stat statbuf;
+ if (stat(screenshotDir.c_str(), &statbuf))
+ screenshotDir = std::string(PHYSFS_getUserDir());
+ }
+ else
+ screenshotDir = dir;
+}
+
+void Client::accountLogin(LoginData *loginData)
+{
+ logger->log("Username is %s", loginData->username.c_str());
+
+ // Send login infos
+ if (loginData->registerLogin)
+ Net::getLoginHandler()->registerAccount(loginData);
+ else
+ Net::getLoginHandler()->loginAccount(loginData);
+
+ // Clear the password, avoids auto login when returning to login
+ loginData->password = "";
+
+ // TODO This is not the best place to save the config, but at least better
+ // than the login gui window
+ if (loginData->remember)
+ config.setValue("username", loginData->username);
+ config.setValue("remember", loginData->remember);
+}
diff --git a/src/client.h b/src/client.h
new file mode 100644
index 00000000..47328c4d
--- /dev/null
+++ b/src/client.h
@@ -0,0 +1,212 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2004-2009 The Mana World Development Team
+ * Copyright (C) 2009-2010 The Mana Developers
+ *
+ * This file is part of The Mana 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 CLIENT_H
+#define CLIENT_H
+
+#include "net/serverinfo.h"
+
+#include "configlistener.h"
+
+#include <guichan/actionlistener.hpp>
+
+#include <string>
+
+#include <SDL.h>
+#include <SDL_framerate.h>
+
+class Button;
+class Desktop;
+class LoginData;
+class Window;
+class QuitDialog;
+
+/**
+ * Set the milliseconds value of a tick time.
+ */
+static const int MILLISECONDS_IN_A_TICK = 10;
+
+//manaserv uses 9601
+//static const short DEFAULT_PORT = 9601;
+static const short DEFAULT_PORT = 6901;
+
+extern volatile int fps;
+extern volatile int tick_time;
+
+class ErrorListener : public gcn::ActionListener
+{
+ public:
+ void action(const gcn::ActionEvent &event);
+};
+
+extern std::string errorMessage;
+extern ErrorListener errorListener;
+extern LoginData loginData;
+
+/**
+ * Returns elapsed time. (Warning: supposes the delay is always < 100 seconds)
+ */
+int get_elapsed_time(int start_time);
+
+/**
+ * All client states.
+ */
+enum State {
+ STATE_ERROR = -1,
+ STATE_START = 0,
+ STATE_CHOOSE_SERVER,
+ STATE_CONNECT_SERVER,
+ STATE_LOGIN,
+ STATE_LOGIN_ATTEMPT,
+ STATE_WORLD_SELECT, // 5
+ STATE_WORLD_SELECT_ATTEMPT,
+ STATE_UPDATE,
+ STATE_LOAD_DATA,
+ STATE_GET_CHARACTERS,
+ STATE_CHAR_SELECT, // 10
+ STATE_CONNECT_GAME,
+ STATE_GAME,
+ STATE_CHANGE_MAP, // Switch map-server/gameserver
+ STATE_LOGIN_ERROR,
+ STATE_ACCOUNTCHANGE_ERROR, // 15
+ STATE_REGISTER_PREP,
+ STATE_REGISTER,
+ STATE_REGISTER_ATTEMPT,
+ STATE_CHANGEPASSWORD,
+ STATE_CHANGEPASSWORD_ATTEMPT, // 20
+ STATE_CHANGEPASSWORD_SUCCESS,
+ STATE_CHANGEEMAIL,
+ STATE_CHANGEEMAIL_ATTEMPT,
+ STATE_CHANGEEMAIL_SUCCESS,
+ STATE_UNREGISTER, // 25
+ STATE_UNREGISTER_ATTEMPT,
+ STATE_UNREGISTER_SUCCESS,
+ STATE_SWITCH_SERVER,
+ STATE_SWITCH_LOGIN,
+ STATE_SWITCH_CHARACTER, // 30
+ STATE_LOGOUT_ATTEMPT,
+ STATE_WAIT,
+ STATE_EXIT,
+ STATE_FORCE_QUIT
+};
+
+/**
+ * The core part of the client. This class initializes all subsystems, runs
+ * the event loop, and shuts everything down again.
+ */
+class Client : public ConfigListener, public gcn::ActionListener
+{
+public:
+ /**
+ * A structure holding the values of various options that can be passed
+ * from the command line.
+ */
+ struct Options
+ {
+ Options():
+ printHelp(false),
+ printVersion(false),
+ skipUpdate(false),
+ chooseDefault(false),
+ noOpenGL(false),
+ serverPort(0)
+ {}
+
+ bool printHelp;
+ bool printVersion;
+ bool skipUpdate;
+ bool chooseDefault;
+ bool noOpenGL;
+ std::string username;
+ std::string password;
+ std::string character;
+ std::string configPath;
+ std::string updateHost;
+ std::string dataPath;
+ std::string homeDir;
+ std::string screenshotDir;
+
+ std::string serverName;
+ short serverPort;
+ };
+
+ Client(const Options &options);
+ ~Client();
+
+ /**
+ * Provides access to the client instance.
+ */
+ static Client *instance() { return mInstance; }
+
+ int exec();
+
+ static void setState(State state)
+ { instance()->state = state; }
+
+ static State getState()
+ { return instance()->state; }
+
+ static const std::string &getHomeDirectory()
+ { return instance()->homeDir; }
+
+ static const std::string &getScreenshotDirectory()
+ { return instance()->screenshotDir; }
+
+ void optionChanged(const std::string &name);
+ void action(const gcn::ActionEvent &event);
+
+private:
+ void initHomeDir(const Options &options);
+ void initConfiguration(const Options &options);
+ void initUpdatesDir();
+ void initScreenshotDir(const std::string &dir);
+
+ void accountLogin(LoginData *loginData);
+
+ static Client *mInstance;
+
+ Options options;
+
+ std::string homeDir;
+ std::string updateHost;
+ std::string updatesDir;
+ std::string screenshotDir;
+
+ ServerInfo currentServer;
+
+ Window *currentDialog;
+ QuitDialog *quitDialog;
+ Desktop *desktop;
+ Button *setupButton;
+
+ State state;
+ State oldstate;
+
+ SDL_Surface *icon;
+
+ SDL_TimerID mLogicCounterId;
+ SDL_TimerID mSecondsCounterId;
+
+ bool mLimitFps;
+ FPSmanager mFpsManager;
+};
+
+#endif // CLIENT_H
diff --git a/src/game.cpp b/src/game.cpp
index 45e6b761..56978dca 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -23,6 +23,7 @@
#include "beingmanager.h"
#include "channelmanager.h"
+#include "client.h"
#include "commandhandler.h"
#include "configuration.h"
#include "effectmanager.h"
@@ -34,7 +35,6 @@
#include "keyboardconfig.h"
#include "localplayer.h"
#include "log.h"
-#include "main.h"
#include "map.h"
#include "npc.h"
#include "particle.h"
@@ -96,9 +96,6 @@
std::string map_path;
-volatile int tick_time;
-volatile int fps = 0, frame = 0;
-
Joystick *joystick = NULL;
OkDialog *weightNotice = NULL;
@@ -133,55 +130,6 @@ Viewport *viewport = NULL; /**< Viewport on the map. */
ChatTab *localChatTab = NULL;
-std::string screenshotDir = "";
-
-/**
- * Tells the max tick value,
- * setting it back to zero (and start again).
- */
-const int MAX_TICK_VALUE = 10000;
-/**
- * Set the milliseconds value of a tick time.
- */
-const int MILLISECONDS_IN_A_TICK = 10;
-
-/**
- * Advances game logic counter.
- * Called every 10 milliseconds by SDL_AddTimer()
- * @see MILLISECONDS_IN_A_TICK value
- */
-Uint32 nextTick(Uint32 interval, void *param)
-{
- tick_time++;
- if (tick_time == MAX_TICK_VALUE) tick_time = 0;
- return interval;
-}
-
-/**
- * Updates fps.
- * Called every seconds by SDL_AddTimer()
- */
-Uint32 nextSecond(Uint32 interval, void *param)
-{
- fps = frame;
- frame = 0;
-
- return interval;
-}
-
-/**
- * @return the elapsed time in milliseconds
- * between two tick values.
- */
-int get_elapsed_time(int start_time)
-{
- if (start_time <= tick_time)
- return (tick_time - start_time) * MILLISECONDS_IN_A_TICK;
- else
- return (tick_time + (MAX_TICK_VALUE - start_time))
- * MILLISECONDS_IN_A_TICK;
-}
-
/**
* Initialize every game sub-engines in the right order
*/
@@ -266,8 +214,6 @@ Game *Game::mInstance = 0;
Game::Game():
mLastTarget(Being::UNKNOWN),
- mLogicCounterId(0), mSecondsCounterId(0),
- mLimitFps(false),
mCurrentMap(0), mMapName("")
{
assert(!mInstance);
@@ -276,7 +222,7 @@ Game::Game():
disconnectedDialog = NULL;
// Create the viewport
- viewport = new Viewport();
+ viewport = new Viewport;
viewport->setDimension(gcn::Rectangle(0, 0, graphics->getWidth(),
graphics->getHeight()));
@@ -291,11 +237,6 @@ Game::Game():
initEngines();
- // Initialize logic and seconds counters
- tick_time = 0;
- mLogicCounterId = SDL_AddTimer(MILLISECONDS_IN_A_TICK, nextTick, NULL);
- mSecondsCounterId = SDL_AddTimer(1000, nextSecond, NULL);
-
// This part is eAthena specific
// For Manaserv, the map is obtained
// with the GPMSG_PLAYER_MAP_CHANGE flag.
@@ -317,11 +258,6 @@ Game::Game():
*/
Net::getGameHandler()->ping(tick_time);
- // Initialize frame limiting
- SDL_initFramerate(&mFpsManager);
- config.addListener("fpslimit", this);
- optionChanged("fpslimit");
-
Joystick::init();
// TODO: The user should be able to choose which one to use
// Open the first device
@@ -356,26 +292,9 @@ Game::~Game()
floorItemManager = NULL;
joystick = NULL;
- SDL_RemoveTimer(mLogicCounterId);
- SDL_RemoveTimer(mSecondsCounterId);
-
mInstance = 0;
}
-void setScreenshotDir(const std::string &dir)
-{
- if (dir.empty())
- {
- screenshotDir = std::string(PHYSFS_getUserDir()) + "Desktop";
- // If ~/Desktop does not exist, we save screenshots in the user's home.
- struct stat statbuf;
- if (stat(screenshotDir.c_str(), &statbuf))
- screenshotDir = std::string(PHYSFS_getUserDir());
- }
- else
- screenshotDir = dir;
-}
-
static bool saveScreenshot()
{
static unsigned int screenshotCount = 0;
@@ -392,7 +311,7 @@ static bool saveScreenshot()
screenshotCount++;
filenameSuffix.str("");
filename.str("");
- filename << screenshotDir << "/";
+ filename << Client::getScreenshotDirectory() << "/";
filenameSuffix << "Mana_Screenshot_" << screenshotCount << ".png";
filename << filenameSuffix.str();
testExists.open(filename.str().c_str(), std::ios::in);
@@ -420,74 +339,36 @@ static bool saveScreenshot()
return success;
}
-void Game::optionChanged(const std::string &name)
+void Game::logic()
{
- const int fpsLimit = (int) config.getValue("fpslimit", 60);
- mLimitFps = fpsLimit > 0;
- if (mLimitFps)
- SDL_setFramerate(&mFpsManager, fpsLimit);
-}
+ handleInput();
-void Game::exec()
-{
- int gameTime = tick_time;
+ // Handle all necessary game logic
+ beingManager->logic();
+ particleEngine->update();
+ if (mCurrentMap)
+ mCurrentMap->update();
- while (state == STATE_GAME)
+ // Handle network stuff
+ if (!Net::getGameHandler()->isConnected())
{
- if (mCurrentMap)
- mCurrentMap->update(get_elapsed_time(gameTime));
-
- handleInput();
-
- // Handle all necessary game logic
- while (get_elapsed_time(gameTime) > 0)
+ if (Client::getState() != STATE_ERROR)
{
- beingManager->logic();
- particleEngine->update();
- gui->logic();
-
- gameTime++;
+ errorMessage = _("The connection to the server was lost.");
}
- // This is done because at some point tick_time will wrap.
- gameTime = tick_time;
-
- // Update the screen when application is active, delay otherwise.
- if (SDL_GetAppState() & SDL_APPACTIVE)
+ if (!disconnectedDialog)
{
- frame++;
- gui->draw();
- graphics->updateScreen();
- }
- else
- {
- SDL_Delay(10);
- }
-
- if (mLimitFps)
- SDL_framerateDelay(&mFpsManager);
-
- // Handle network stuff
- Net::getGeneralHandler()->flushNetwork();
- if (!Net::getGameHandler()->isConnected())
- {
- if (state != STATE_ERROR)
- {
- errorMessage = _("The connection to the server was lost.");
- }
-
- if (!disconnectedDialog)
- {
- disconnectedDialog = new OkDialog(_("Network Error"), errorMessage);
- disconnectedDialog->addActionListener(&errorListener);
- disconnectedDialog->requestMoveToTop();
- }
+ disconnectedDialog = new OkDialog(_("Network Error"),
+ errorMessage);
+ disconnectedDialog->addActionListener(&errorListener);
+ disconnectedDialog->requestMoveToTop();
}
}
}
/**
- * The MONSTER input handling method.
+ * The huge input handling method.
*/
void Game::handleInput()
{
@@ -849,7 +730,7 @@ void Game::handleInput()
// Quit event
else if (event.type == SDL_QUIT)
{
- state = STATE_EXIT;
+ Client::setState(STATE_EXIT);
}
// Push input to GUI when not used
@@ -861,7 +742,7 @@ void Game::handleInput()
}
catch (gcn::Exception e)
{
- const char* err = e.getMessage().c_str();
+ const char *err = e.getMessage().c_str();
logger->log("Warning: guichan input exception: %s", err);
}
}
diff --git a/src/game.h b/src/game.h
index de601af6..cdd22e29 100644
--- a/src/game.h
+++ b/src/game.h
@@ -22,23 +22,18 @@
#ifndef GAME_H
#define GAME_H
-#include "configlistener.h"
+#include <string>
-#include <SDL.h>
-#include <SDL_framerate.h>
-
-extern std::string map_path;
-extern volatile int fps;
-extern volatile int tick_time;
-extern const int MILLISECONDS_IN_A_TICK;
+extern std::string map_path; // TODO: Get rid of this global
class Map;
class WindowMenu;
/**
- * The main class responsible for running the game.
+ * The main class responsible for running the game. The game starts after you
+ * have selected your character.
*/
-class Game : public ConfigListener
+class Game
{
public:
/**
@@ -58,14 +53,13 @@ class Game : public ConfigListener
static Game *instance() { return mInstance; }
/**
- * This method runs the game. It returns when the game stops.
+ * This method takes the game a small step further. It is called 100
+ * times per second.
*/
- void exec();
+ void logic();
void handleInput();
- void optionChanged(const std::string &name);
-
void changeMap(const std::string &mapName);
/**
@@ -76,13 +70,8 @@ class Game : public ConfigListener
const std::string &getCurrentMapName() { return mMapName; }
private:
- int mLastTarget;
- SDL_TimerID mLogicCounterId;
- SDL_TimerID mSecondsCounterId;
-
- bool mLimitFps;
- FPSmanager mFpsManager;
+ int mLastTarget;
WindowMenu *mWindowMenu;
@@ -92,11 +81,4 @@ class Game : public ConfigListener
static Game *mInstance;
};
-/**
- * Returns elapsed time. (Warning: supposes the delay is always < 100 seconds)
- */
-int get_elapsed_time(int start_time);
-
-void setScreenshotDir(const std::string &dir);
-
#endif
diff --git a/src/gui/changeemaildialog.cpp b/src/gui/changeemaildialog.cpp
index d31d569f..b8edb5f6 100644
--- a/src/gui/changeemaildialog.cpp
+++ b/src/gui/changeemaildialog.cpp
@@ -21,7 +21,7 @@
#include "gui/changeemaildialog.h"
-#include "main.h"
+#include "client.h"
#include "log.h"
#include "gui/register.h"
@@ -104,7 +104,7 @@ void ChangeEmailDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "cancel")
{
- state = STATE_CHAR_SELECT;
+ Client::setState(STATE_CHAR_SELECT);
}
else if (event.getId() == "change_email")
{
@@ -162,7 +162,7 @@ void ChangeEmailDialog::action(const gcn::ActionEvent &event)
mChangeEmailButton->setEnabled(false);
// Set the new email address
mLoginData->email = newFirstEmail;
- state = STATE_CHANGEEMAIL_ATTEMPT;
+ Client::setState(STATE_CHANGEEMAIL_ATTEMPT);
}
}
}
diff --git a/src/gui/changepassworddialog.cpp b/src/gui/changepassworddialog.cpp
index 7ad15db1..5f7c03f9 100644
--- a/src/gui/changepassworddialog.cpp
+++ b/src/gui/changepassworddialog.cpp
@@ -21,7 +21,7 @@
#include "changepassworddialog.h"
-#include "main.h"
+#include "client.h"
#include "log.h"
#include "gui/register.h"
@@ -85,7 +85,7 @@ void ChangePasswordDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "cancel")
{
- state = STATE_CHAR_SELECT;
+ Client::setState(STATE_CHAR_SELECT);
}
else if (event.getId() == "change_password")
{
@@ -156,7 +156,7 @@ void ChangePasswordDialog::action(const gcn::ActionEvent &event)
// Set the new password
mLoginData->password = oldPassword;
mLoginData->newPassword = newFirstPass;
- state = STATE_CHANGEPASSWORD_ATTEMPT;
+ Client::setState(STATE_CHANGEPASSWORD_ATTEMPT);
}
}
}
diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp
index ca525285..c2c63248 100644
--- a/src/gui/charselectdialog.cpp
+++ b/src/gui/charselectdialog.cpp
@@ -21,9 +21,9 @@
#include "gui/charselectdialog.h"
+#include "client.h"
#include "game.h"
#include "localplayer.h"
-#include "main.h"
#include "units.h"
#include "log.h"
@@ -179,7 +179,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
// Check if a button of a character was pressed
const gcn::Widget *sourceParent = event.getSource()->getParent();
int selected = -1;
- for (unsigned i = 0; i < MAX_CHARACTER_COUNT; ++i)
+ for (int i = 0; i < MAX_CHARACTER_COUNT; ++i)
if (mCharacterEntries[i] == sourceParent)
selected = i;
@@ -206,19 +206,19 @@ void CharSelectDialog::action(const gcn::ActionEvent &event)
}
else if (eventId == "switch")
{
- state = STATE_SWITCH_LOGIN;
+ Client::setState(STATE_SWITCH_LOGIN);
}
else if (eventId == "change_password")
{
- state = STATE_CHANGEPASSWORD;
+ Client::setState(STATE_CHANGEPASSWORD);
}
else if (eventId == "change_email")
{
- state = STATE_CHANGEEMAIL;
+ Client::setState(STATE_CHANGEEMAIL);
}
else if (eventId == "unregister")
{
- state = STATE_UNREGISTER;
+ Client::setState(STATE_UNREGISTER);
}
}
@@ -308,7 +308,7 @@ bool CharSelectDialog::selectByName(const std::string &name,
if (mLocked)
return false;
- for (unsigned i = 0; i < MAX_CHARACTER_COUNT; ++i) {
+ for (int i = 0; i < MAX_CHARACTER_COUNT; ++i) {
if (Net::Character *character = mCharacterEntries[i]->getCharacter()) {
if (character->dummy->getName() == name) {
mCharacterEntries[i]->requestFocus();
diff --git a/src/gui/charselectdialog.h b/src/gui/charselectdialog.h
index 5a21566f..b6e71715 100644
--- a/src/gui/charselectdialog.h
+++ b/src/gui/charselectdialog.h
@@ -100,6 +100,7 @@ class CharSelectDialog : public Window, public gcn::ActionListener,
gcn::Button *mUnregisterButton;
gcn::Button *mChangeEmailButton;
+ enum { MAX_CHARACTER_COUNT = 3 };
CharacterDisplay *mCharacterEntries[MAX_CHARACTER_COUNT];
LoginData *mLoginData;
diff --git a/src/gui/connectiondialog.cpp b/src/gui/connectiondialog.cpp
index 7d474247..0ef14d5a 100644
--- a/src/gui/connectiondialog.cpp
+++ b/src/gui/connectiondialog.cpp
@@ -21,7 +21,6 @@
#include "connectiondialog.h"
-#include "main.h"
#include "log.h"
#include "gui/widgets/button.h"
@@ -56,7 +55,7 @@ ConnectionDialog::ConnectionDialog(const std::string &text,
void ConnectionDialog::action(const gcn::ActionEvent &)
{
logger->log("Cancel pressed");
- state = mCancelState;
+ Client::setState(mCancelState);
}
void ConnectionDialog::draw(gcn::Graphics *graphics)
diff --git a/src/gui/connectiondialog.h b/src/gui/connectiondialog.h
index 0f826c9a..623a6645 100644
--- a/src/gui/connectiondialog.h
+++ b/src/gui/connectiondialog.h
@@ -22,7 +22,7 @@
#ifndef CONNECTION_H
#define CONNECTION_H
-#include "main.h"
+#include "client.h"
#include "gui/widgets/window.h"
diff --git a/src/gui/debugwindow.cpp b/src/gui/debugwindow.cpp
index 317ca93b..2ad0ba4a 100644
--- a/src/gui/debugwindow.cpp
+++ b/src/gui/debugwindow.cpp
@@ -21,6 +21,7 @@
#include "gui/debugwindow.h"
+#include "client.h"
#include "game.h"
#include "particle.h"
#include "main.h"
diff --git a/src/gui/login.cpp b/src/gui/login.cpp
index 20a48a44..9eb3f2c0 100644
--- a/src/gui/login.cpp
+++ b/src/gui/login.cpp
@@ -21,7 +21,7 @@
#include "gui/login.h"
-#include "main.h"
+#include "client.h"
#include "configuration.h"
#include "gui/okdialog.h"
@@ -107,18 +107,19 @@ void LoginDialog::action(const gcn::ActionEvent &event)
mRegisterButton->setEnabled(false);
mServerButton->setEnabled(false);
mLoginButton->setEnabled(false);
- state = STATE_LOGIN_ATTEMPT;
+
+ Client::setState(STATE_LOGIN_ATTEMPT);
}
else if (event.getId() == "server")
{
- state = STATE_SWITCH_SERVER;
+ Client::setState(STATE_SWITCH_SERVER);
}
else if (event.getId() == "register")
{
mLoginData->username = mUserField->getText();
mLoginData->password = mPassField->getText();
- state = STATE_REGISTER_PREP;
+ Client::setState(STATE_REGISTER_PREP);
}
}
@@ -140,9 +141,9 @@ void LoginDialog::keyPressed(gcn::KeyEvent &keyEvent)
}
}
-bool LoginDialog::canSubmit()
+bool LoginDialog::canSubmit() const
{
return !mUserField->getText().empty() &&
!mPassField->getText().empty() &&
- state == STATE_LOGIN;
+ Client::getState() == STATE_LOGIN;
}
diff --git a/src/gui/login.h b/src/gui/login.h
index b26ba776..93bae338 100644
--- a/src/gui/login.h
+++ b/src/gui/login.h
@@ -66,7 +66,7 @@ class LoginDialog : public Window, public gcn::ActionListener,
* Returns whether submit can be enabled. This is true in the login
* state, when all necessary fields have some text.
*/
- bool canSubmit();
+ bool canSubmit() const;
gcn::TextField *mUserField;
gcn::TextField *mPassField;
diff --git a/src/gui/palette.cpp b/src/gui/palette.cpp
index b853a8f5..e7c49c89 100644
--- a/src/gui/palette.cpp
+++ b/src/gui/palette.cpp
@@ -23,7 +23,7 @@
#include "palette.h"
#include "configuration.h"
-#include "game.h"
+#include "client.h"
#include "gui/gui.h"
diff --git a/src/gui/quitdialog.cpp b/src/gui/quitdialog.cpp
index 0645dd7f..6ecc62a6 100644
--- a/src/gui/quitdialog.cpp
+++ b/src/gui/quitdialog.cpp
@@ -21,7 +21,7 @@
#include "gui/quitdialog.h"
-#include "main.h"
+#include "client.h"
#include "gui/sdlinput.h"
@@ -50,7 +50,9 @@ QuitDialog::QuitDialog(QuitDialog** pointerToMe):
ContainerPlacer place = getPlacer(0, 0);
- //All states, when we're not logged in to someone.
+ const State state = Client::getState();
+
+ // All states, when we're not logged in to someone.
if (state == STATE_CHOOSE_SERVER ||
state == STATE_CONNECT_SERVER ||
state == STATE_LOGIN ||
@@ -106,19 +108,19 @@ void QuitDialog::action(const gcn::ActionEvent &event)
{
if (mForceQuit->isSelected())
{
- state = STATE_FORCE_QUIT;
+ Client::setState(STATE_FORCE_QUIT);
}
else if (mLogoutQuit->isSelected())
{
- state = STATE_EXIT;
+ Client::setState(STATE_EXIT);
}
else if (mSwitchAccountServer->isSelected())
{
- state = STATE_SWITCH_SERVER;
+ Client::setState(STATE_SWITCH_SERVER);
}
else if (mSwitchCharacter->isSelected())
{
- assert(state == STATE_GAME);
+ assert(Client::getState() == STATE_GAME);
Net::getCharHandler()->switchCharacter();
}
diff --git a/src/gui/recorder.cpp b/src/gui/recorder.cpp
index 5bb02844..7cb6e055 100644
--- a/src/gui/recorder.cpp
+++ b/src/gui/recorder.cpp
@@ -20,7 +20,7 @@
#include "gui/recorder.h"
-#include "main.h"
+#include "client.h"
#include "gui/chat.h"
@@ -102,7 +102,7 @@ void Recorder::setRecordingFile(const std::string &msg)
* recorded.
*/
localChatTab->chatLog(_("Starting to record..."), BY_SERVER);
- const std::string file = std::string(getHomeDirectory() + msgCopy);
+ const std::string file = Client::getHomeDirectory() + msgCopy;
mStream.open(file.c_str(), std::ios_base::trunc);
diff --git a/src/gui/register.cpp b/src/gui/register.cpp
index dd863483..9fbd8cc8 100644
--- a/src/gui/register.cpp
+++ b/src/gui/register.cpp
@@ -21,9 +21,9 @@
#include "gui/register.h"
+#include "client.h"
#include "configuration.h"
#include "log.h"
-#include "main.h"
#include "gui/login.h"
#include "gui/okdialog.h"
@@ -144,7 +144,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "cancel")
{
- state = STATE_LOGIN;
+ Client::setState(STATE_LOGIN);
}
else if (event.getId() == "register" && canSubmit())
{
@@ -232,7 +232,7 @@ void RegisterDialog::action(const gcn::ActionEvent &event)
mLoginData->email = mEmailField->getText();
mLoginData->registerLogin = true;
- state = STATE_REGISTER_ATTEMPT;
+ Client::setState(STATE_REGISTER_ATTEMPT);
}
}
}
@@ -247,5 +247,5 @@ bool RegisterDialog::canSubmit() const
return !mUserField->getText().empty() &&
!mPasswordField->getText().empty() &&
!mConfirmField->getText().empty() &&
- state == STATE_REGISTER;
+ Client::getState() == STATE_REGISTER;
}
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index 091197c5..f439420b 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -21,9 +21,9 @@
#include "gui/serverdialog.h"
+#include "client.h"
#include "configuration.h"
#include "log.h"
-#include "main.h"
#include "gui/okdialog.h"
#include "gui/sdlinput.h"
@@ -149,7 +149,8 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir):
currentServer.hostname = config.getValue(currentConfig, "");
currentConfig = "MostUsedServerPort" + toString(i);
- currentServer.port = (short) config.getValue(currentConfig, DEFAULT_PORT);
+ currentServer.port = (short) config.getValue(currentConfig,
+ DEFAULT_PORT);
currentConfig = "MostUsedServerType" + toString(i);
currentServer.type = stringToServerType(config
@@ -308,13 +309,13 @@ void ServerDialog::action(const gcn::ActionEvent &event)
mServerInfo->hostname = currentServer.hostname;
mServerInfo->port = currentServer.port;
mServerInfo->type = currentServer.type;
- state = STATE_CONNECT_SERVER;
+ Client::setState(STATE_CONNECT_SERVER);
}
}
else if (event.getId() == "quit")
{
mDownload->cancel();
- state = STATE_FORCE_QUIT;
+ Client::setState(STATE_FORCE_QUIT);
}
else if (event.getId() == "addEntry")
{
@@ -328,7 +329,7 @@ void ServerDialog::keyPressed(gcn::KeyEvent &keyEvent)
if (key.getValue() == Key::ESCAPE)
{
- state = STATE_EXIT;
+ Client::setState(STATE_EXIT);
}
else if (key.getValue() == Key::ENTER)
{
diff --git a/src/gui/unregisterdialog.cpp b/src/gui/unregisterdialog.cpp
index 97b3bf76..8601e76b 100644
--- a/src/gui/unregisterdialog.cpp
+++ b/src/gui/unregisterdialog.cpp
@@ -21,7 +21,7 @@
#include "gui/unregisterdialog.h"
-#include "main.h"
+#include "client.h"
#include "log.h"
#include "gui/okdialog.h"
@@ -95,7 +95,7 @@ void UnRegisterDialog::action(const gcn::ActionEvent &event)
{
if (event.getId() == "cancel")
{
- state = STATE_CHAR_SELECT;
+ Client::setState(STATE_CHAR_SELECT);
}
else if (event.getId() == "unregister")
{
@@ -138,7 +138,7 @@ void UnRegisterDialog::action(const gcn::ActionEvent &event)
// No errors detected, unregister the new user.
mUnRegisterButton->setEnabled(false);
mLoginData->password = password;
- state = STATE_UNREGISTER_ATTEMPT;
+ Client::setState(STATE_UNREGISTER_ATTEMPT);
}
}
}
diff --git a/src/gui/updatewindow.cpp b/src/gui/updatewindow.cpp
index 1d5f001a..743f3936 100644
--- a/src/gui/updatewindow.cpp
+++ b/src/gui/updatewindow.cpp
@@ -21,9 +21,9 @@
#include "gui/updatewindow.h"
+#include "client.h"
#include "configuration.h"
#include "log.h"
-#include "main.h"
#include "gui/sdlinput.h"
@@ -223,7 +223,7 @@ void UpdaterWindow::action(const gcn::ActionEvent &event)
}
else if (event.getId() == "play")
{
- state = STATE_LOAD_DATA;
+ Client::setState(STATE_LOAD_DATA);
}
}
@@ -234,7 +234,7 @@ void UpdaterWindow::keyPressed(gcn::KeyEvent &keyEvent)
if (key.getValue() == Key::ESCAPE)
{
action(gcn::ActionEvent(NULL, mCancelButton->getActionEventId()));
- state = STATE_WORLD_SELECT;
+ Client::setState(STATE_WORLD_SELECT);
}
else if (key.getValue() == Key::ENTER)
{
@@ -296,15 +296,18 @@ int UpdaterWindow::updateProgress(void *ptr, DownloadStatus status,
float progress = (float) dn / dt;
- if (progress != progress) progress = 0.0f; // check for NaN
- if (progress < 0.0f) progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway.
- if (progress > 1.0f) progress = 1.0f;
+ if (progress != progress)
+ progress = 0.0f; // check for NaN
+ if (progress < 0.0f)
+ progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway.
+ if (progress > 1.0f)
+ progress = 1.0f;
uw->setLabel(
uw->mCurrentFile + " (" + toString((int) (progress * 100)) + "%)");
uw->setProgress(progress);
- if (state != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR)
+ if (Client::getState() != STATE_UPDATE || uw->mDownloadStatus == UPDATE_ERROR)
{
// If the action was canceled return an error code to stop the mThread
return -1;
diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp
index 8320e7b1..b51d4878 100644
--- a/src/gui/viewport.cpp
+++ b/src/gui/viewport.cpp
@@ -21,10 +21,10 @@
#include "gui/viewport.h"
+#include "client.h"
#include "beingmanager.h"
#include "configuration.h"
#include "flooritemmanager.h"
-#include "game.h"
#include "graphics.h"
#include "keyboardconfig.h"
#include "localplayer.h"
diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp
index 9cbc7030..cf6dd6f5 100644
--- a/src/gui/widgets/avatarlistbox.cpp
+++ b/src/gui/widgets/avatarlistbox.cpp
@@ -29,6 +29,8 @@
#include "resources/image.h"
#include "resources/resourcemanager.h"
+#include "utils/stringutils.h"
+
#include <guichan/font.hpp>
int AvatarListBox::instances = 0;
diff --git a/src/gui/worldselectdialog.cpp b/src/gui/worldselectdialog.cpp
index ac229302..3219b83d 100644
--- a/src/gui/worldselectdialog.cpp
+++ b/src/gui/worldselectdialog.cpp
@@ -21,7 +21,7 @@
#include "gui/worldselectdialog.h"
-#include "main.h"
+#include "client.h"
#include "gui/sdlinput.h"
@@ -115,12 +115,12 @@ void WorldSelectDialog::action(const gcn::ActionEvent &event)
Net::getLoginHandler()->chooseServer(mWorldList->getSelected());
// Check in case netcode moves us forward
- if (state == STATE_WORLD_SELECT)
- state = STATE_WORLD_SELECT_ATTEMPT;
+ if (Client::getState() == STATE_WORLD_SELECT)
+ Client::setState(STATE_WORLD_SELECT_ATTEMPT);
}
else if (event.getId() == "login")
{
- state = STATE_LOGIN;
+ Client::setState(STATE_LOGIN);
}
}
diff --git a/src/localplayer.cpp b/src/localplayer.cpp
index bb6373eb..8133bf4a 100644
--- a/src/localplayer.cpp
+++ b/src/localplayer.cpp
@@ -21,11 +21,11 @@
#include "localplayer.h"
+#include "client.h"
#include "configuration.h"
#include "effectmanager.h"
#include "equipment.h"
#include "flooritem.h"
-#include "game.h"
#include "graphics.h"
#include "guild.h"
#include "inventory.h"
diff --git a/src/main.cpp b/src/main.cpp
index 8d5cbf84..5ed1c4ec 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,496 +21,15 @@
#include "main.h"
-#include "configuration.h"
-#include "emoteshortcut.h"
-#include "game.h"
-#include "graphics.h"
-#include "itemshortcut.h"
-#include "keyboardconfig.h"
-#include "localplayer.h"
-#include "log.h"
-#ifdef USE_OPENGL
-#include "openglgraphics.h"
-#endif
-#include "playerrelations.h"
-#include "sound.h"
-#include "statuseffect.h"
-#include "units.h"
-
-#include "gui/changeemaildialog.h"
-#include "gui/changepassworddialog.h"
-#include "gui/charselectdialog.h"
-#include "gui/connectiondialog.h"
-#include "gui/gui.h"
-#include "gui/skin.h"
-#include "gui/login.h"
-#include "gui/okdialog.h"
-#include "gui/palette.h"
-#include "gui/quitdialog.h"
-#include "gui/register.h"
-#include "gui/sdlinput.h"
-#include "gui/serverdialog.h"
-#include "gui/setup.h"
-#include "gui/unregisterdialog.h"
-#include "gui/updatewindow.h"
-#include "gui/worldselectdialog.h"
-
-#include "gui/widgets/button.h"
-#include "gui/widgets/desktop.h"
-
-#include "net/charhandler.h"
-#include "net/gamehandler.h"
-#include "net/generalhandler.h"
-#include "net/logindata.h"
-#include "net/loginhandler.h"
-#include "net/net.h"
-#include "net/worldinfo.h"
-
-#include "resources/colordb.h"
-#include "resources/emotedb.h"
-#include "resources/image.h"
-#include "resources/itemdb.h"
-#include "resources/monsterdb.h"
-#include "resources/npcdb.h"
-#include "resources/resourcemanager.h"
-
#include "utils/gettext.h"
-#include "utils/stringutils.h"
-#include <SDL_image.h>
+#include "client.h"
#include <libxml/parser.h>
-#ifdef WIN32
-#include <SDL_syswm.h>
-#else
-#include <cerrno>
-#include <sys/stat.h>
-#endif
-
#include <getopt.h>
#include <iostream>
#include <physfs.h>
-#include <unistd.h>
-#include <vector>
-
-#ifdef __APPLE__
-#include <CoreFoundation/CFBundle.h>
-#endif
-
-#ifdef __MINGW32__
-#include <windows.h>
-#define usleep(usec) (Sleep ((usec) / 1000), 0)
-#endif
-
-namespace
-{
- class SetupListener : public gcn::ActionListener
- {
- public:
- /**
- * Called when receiving actions from widget.
- */
- void action(const gcn::ActionEvent &event);
- } listener;
-}
-
-static const int defaultSfxVolume = 100;
-static const int defaultMusicVolume = 60;
-
-Graphics *graphics;
-Game *game = 0;
-
-State state = STATE_START;
-std::string errorMessage;
-ErrorListener errorListener;
-
-Sound sound;
-Music *bgm;
-
-Configuration config; /**< XML file configuration reader */
-Configuration branding; /**< XML branding information reader */
-Logger *logger; /**< Log object */
-KeyboardConfig keyboard;
-
-LoginData loginData;
-
-Palette *guiPalette;
-
-// This anonymous namespace hides whatever is inside from other modules.
-namespace {
-
-std::string homeDir;
-std::string updateHost;
-std::string updatesDir;
-
-SDL_Surface *icon;
-
-/**
- * A structure holding the values of various options that can be passed from
- * the command line.
- */
-struct Options
-{
- /**
- * Constructor.
- */
- Options():
- printHelp(false),
- printVersion(false),
- skipUpdate(false),
- chooseDefault(false),
- noOpenGL(false),
- serverPort(0)
- {}
-
- bool printHelp;
- bool printVersion;
- bool skipUpdate;
- bool chooseDefault;
- bool noOpenGL;
- std::string username;
- std::string password;
- std::string character;
- std::string configPath;
- std::string updateHost;
- std::string dataPath;
- std::string homeDir;
- std::string screenshotDir;
-
- std::string serverName;
- short serverPort;
-
-};
-
-/**
- * Parse the update host and determine the updates directory
- * Then verify that the directory exists (creating if needed).
- */
-static void setUpdatesDir()
-{
- std::stringstream updates;
-
- // If updatesHost is currently empty, fill it from config file
- if (updateHost.empty())
- {
- updateHost =
- config.getValue("updatehost", "http://updates.themanaworld.org/");
- }
-
- // Remove any trailing slash at the end of the update host
- if (updateHost.at(updateHost.size() - 1) == '/')
- updateHost.resize(updateHost.size() - 1);
-
- // Parse out any "http://" or "ftp://", and set the updates directory
- size_t pos;
- pos = updateHost.find("://");
- if (pos != updateHost.npos)
- {
- if (pos + 3 < updateHost.length())
- {
- updates << "updates/" << updateHost.substr(pos + 3);
- updatesDir = updates.str();
- }
- else
- {
- logger->log("Error: Invalid update host: %s", updateHost.c_str());
- errorMessage = strprintf(_("Invalid update host: %s"), updateHost.c_str());
- state = STATE_ERROR;
- }
- }
- else
- {
- logger->log("Warning: no protocol was specified for the update host");
- updates << "updates/" << updateHost;
- updatesDir = updates.str();
- }
-
- ResourceManager *resman = ResourceManager::getInstance();
-
- // Verify that the updates directory exists. Create if necessary.
- if (!resman->isDirectory("/" + updatesDir))
- {
- if (!resman->mkdir("/" + updatesDir))
- {
-#if defined WIN32
- std::string newDir = homeDir + "\\" + updatesDir;
- std::string::size_type loc = newDir.find("/", 0);
-
- while (loc != std::string::npos)
- {
- newDir.replace(loc, 1, "\\");
- loc = newDir.find("/", loc);
- }
-
- if (!CreateDirectory(newDir.c_str(), 0) &&
- GetLastError() != ERROR_ALREADY_EXISTS)
- {
- logger->log("Error: %s can't be made, but doesn't exist!",
- newDir.c_str());
- errorMessage = _("Error creating updates directory!");
- state = STATE_ERROR;
- }
-#else
- logger->log("Error: %s/%s can't be made, but doesn't exist!",
- homeDir.c_str(), updatesDir.c_str());
- errorMessage = _("Error creating updates directory!");
- state = STATE_ERROR;
-#endif
- }
- }
-}
-
-/**
- * Initializes the home directory. On UNIX and FreeBSD, ~/.mana is used. On
- * Windows and other systems we use the current working directory.
- */
-static void initHomeDir(const Options &options)
-{
- homeDir = options.homeDir;
-
- if (homeDir.empty())
- {
-#ifdef __APPLE__
- // Use Application Directory instead of .mana
- homeDir = std::string(PHYSFS_getUserDir()) +
- "/Library/Application Support/" +
- branding.getValue("appName", "Mana");
-#else
- homeDir = std::string(PHYSFS_getUserDir()) +
- "/." + branding.getValue("appShort", "mana");
-#endif
- }
-#if defined WIN32
- if (!CreateDirectory(homeDir.c_str(), 0) &&
- GetLastError() != ERROR_ALREADY_EXISTS)
-#else
- // Create home directory if it doesn't exist already
- if ((mkdir(homeDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) &&
- (errno != EEXIST))
-#endif
- {
- logger->error(strprintf(_("%s doesn't exist and can't be created! "
- "Exiting."), homeDir.c_str()));
- }
-}
-
-/**
- * Initialize configuration.
- */
-static void initConfiguration(const Options &options)
-{
- // Fill configuration with defaults
- logger->log("Initializing configuration...");
- std::string defaultHost = branding.getValue("defaultServer",
- "server.themanaworld.org");
- int defaultPort = (int)branding.getValue("defaultPort", DEFAULT_PORT);
- config.setValue("port", defaultPort);
- config.setValue("hwaccel", false);
-#if (defined __APPLE__ || defined WIN32) && defined USE_OPENGL
- config.setValue("opengl", true);
-#else
- config.setValue("opengl", false);
-#endif
- config.setValue("screen", false);
- config.setValue("sound", true);
- config.setValue("guialpha", 0.8f);
- config.setValue("remember", true);
- config.setValue("sfxVolume", 100);
- config.setValue("musicVolume", 60);
- config.setValue("fpslimit", 60);
- std::string defaultUpdateHost = branding.getValue("defaultUpdateHost",
- "http://updates.themanaworld.org");
- config.setValue("updatehost", defaultUpdateHost);
- config.setValue("customcursor", true);
- config.setValue("ChatLogLength", 128);
-
- // Checking if the configuration file exists... otherwise create it with
- // default options.
- FILE *configFile = 0;
- std::string configPath = options.configPath;
-
- if (configPath.empty())
- configPath = homeDir + "/config.xml";
-
- configFile = fopen(configPath.c_str(), "r");
-
- // If we can't read it, it doesn't exist !
- if (configFile == NULL)
- {
- // We reopen the file in write mode and we create it
- configFile = fopen(configPath.c_str(), "wt");
- }
- if (configFile == NULL)
- {
- logger->log("Can't create %s. Using defaults.", configPath.c_str());
- }
- else
- {
- fclose(configFile);
- config.init(configPath);
- }
-}
-
-/**
- * Do all initialization stuff.
- */
-static void initEngine(const Options &options)
-{
- // Initialize SDL
- logger->log("Initializing SDL...");
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
- {
- logger->error(strprintf("Could not initialize SDL: %s",
- SDL_GetError()));
- }
- atexit(SDL_Quit);
-
- SDL_EnableUNICODE(1);
- SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-
- SDL_WM_SetCaption(branding.getValue("appName", "Mana").c_str(), NULL);
-
- ResourceManager *resman = ResourceManager::getInstance();
-
- if (!resman->setWriteDir(homeDir))
- {
- logger->error(strprintf("%s couldn't be set as home directory! "
- "Exiting.", homeDir.c_str()));
- }
-
- // Add the user's homedir to PhysicsFS search path
- resman->addToSearchPath(homeDir, false);
-
- // Add the main data directories to our PhysicsFS search path
- if (!options.dataPath.empty())
- resman->addToSearchPath(options.dataPath, true);
- resman->addToSearchPath("data", true);
-#if defined __APPLE__
- CFBundleRef mainBundle = CFBundleGetMainBundle();
- CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
- char path[PATH_MAX];
- if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path,
- PATH_MAX))
- {
- fprintf(stderr, "Can't find Resources directory\n");
- }
- CFRelease(resourcesURL);
- strncat(path, "/data", PATH_MAX - 1);
- resman->addToSearchPath(path, true);
-#else
- resman->addToSearchPath(PKG_DATADIR "data", true);
-#endif
-
-#ifdef WIN32
- static SDL_SysWMinfo pInfo;
- SDL_GetWMInfo(&pInfo);
- HICON icon = LoadIcon(GetModuleHandle(NULL), "A");
- if (icon)
- {
- SetClassLong(pInfo.window, GCL_HICON, (LONG) icon);
- }
-#else
- icon = IMG_Load(resman->getPath(branding.getValue("appIcon", "data/icons/mana.png")).c_str());
- if (icon)
- {
- SDL_SetAlpha(icon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE);
- SDL_WM_SetIcon(icon, NULL);
- }
-#endif
-
-#ifdef USE_OPENGL
- bool useOpenGL = !options.noOpenGL && (config.getValue("opengl", 0) == 1);
-
- // Setup image loading for the right image format
- Image::setLoadAsOpenGL(useOpenGL);
-
- // Create the graphics context
- graphics = useOpenGL ? new OpenGLGraphics : new Graphics;
-#else
- // Create the graphics context
- graphics = new Graphics;
-#endif
-
- const int width = (int) config.getValue("screenwidth", defaultScreenWidth);
- const int height = (int) config.getValue("screenheight", defaultScreenHeight);
- const int bpp = 0;
- const bool fullscreen = ((int) config.getValue("screen", 0) == 1);
- const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1);
-
- // Try to set the desired video mode
- if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel))
- {
- logger->error(strprintf("Couldn't set %dx%dx%d video mode: %s",
- width, height, bpp, SDL_GetError()));
- }
-
- // Initialize for drawing
- graphics->_beginDraw();
-
- // Initialize the item shortcuts.
- itemShortcut = new ItemShortcut;
-
- // Initialize the emote shortcuts.
- emoteShortcut = new EmoteShortcut;
-
- gui = new Gui(graphics);
-
- // Initialize sound engine
- try
- {
- if (config.getValue("sound", 0) == 1)
- sound.init();
-
- sound.setSfxVolume((int) config.getValue("sfxVolume",
- defaultSfxVolume));
- sound.setMusicVolume((int) config.getValue("musicVolume",
- defaultMusicVolume));
- }
- catch (const char *err)
- {
- state = STATE_ERROR;
- errorMessage = err;
- logger->log("Warning: %s", err);
- }
-
- // Initialize keyboard
- keyboard.init();
-
- // Initialise player relations
- player_relations.init();
-}
-
-/** Clear the engine */
-static void exitEngine()
-{
- // Before config.write() since it writes the shortcuts to the config
- delete itemShortcut;
- delete emoteShortcut;
-
- config.write();
-
- delete gui;
- delete graphics;
-
- // Shutdown libxml
- xmlCleanupParser();
-
- // Shutdown sound
- sound.close();
-
- // Unload XML databases
- ColorDB::unload();
- EmoteDB::unload();
- ItemDB::unload();
- MonsterDB::unload();
- NPCDB::unload();
- StatusEffect::unload();
-
- ResourceManager::deleteInstance();
-
- SDL_FreeSurface(icon);
-}
static void printHelp()
{
@@ -544,7 +63,7 @@ static void printVersion()
std::cout << strprintf("Mana client %s", FULL_VERSION) << std::endl;
}
-static void parseOptions(int argc, char *argv[], Options &options)
+static void parseOptions(int argc, char *argv[], Client::Options &options)
{
const char *optstring = "hvud:U:P:Dc:s:p:C:H:S:Oi:";
@@ -626,58 +145,9 @@ static void parseOptions(int argc, char *argv[], Options &options)
}
}
-class AccountListener : public gcn::ActionListener
-{
-public:
- void action(const gcn::ActionEvent &)
- {
- state = STATE_CHAR_SELECT;
- }
-} accountListener;
-
-class LoginListener : public gcn::ActionListener
-{
-public:
- void action(const gcn::ActionEvent &)
- {
- state = STATE_LOGIN;
- }
-} loginListener;
-
-} // namespace
-
-void ErrorListener::action(const gcn::ActionEvent &)
-{
- state = STATE_CHOOSE_SERVER;
-}
-
-const std::string &getHomeDirectory()
-{
- return homeDir;
-}
-
-// TODO Find some nice place for these functions
-static void accountLogin(LoginData *loginData)
-{
- logger->log("Username is %s", loginData->username.c_str());
-
- // Send login infos
- if (loginData->registerLogin)
- Net::getLoginHandler()->registerAccount(loginData);
- else
- Net::getLoginHandler()->loginAccount(loginData);
-
- // Clear the password, avoids auto login when returning to login
- loginData->password = "";
-
- // TODO This is not the best place to save the config, but at least better
- // than the login gui window
- if (loginData->remember)
- config.setValue("username", loginData->username);
- config.setValue("remember", loginData->remember);
-}
-
+#ifdef WIN32
extern "C" char const *_nl_locale_name_default(void);
+#endif
static void initInternationalization()
{
@@ -711,16 +181,18 @@ static void initXML()
xmlSetGenericErrorFunc(NULL, xmlNullLogger);
}
-/** Main */
+
int main(int argc, char *argv[])
{
#if defined(DEBUG) && defined(WIN32)
- // load mingw crash handler. Won't fail if dll is not present.
+ // Load mingw crash handler. Won't fail if dll is not present.
LoadLibrary("exchndl.dll");
#endif
+
// Parse command line options
- Options options;
+ Client::Options options;
parseOptions(argc, argv, options);
+
if (options.printHelp)
{
printHelp();
@@ -735,557 +207,15 @@ int main(int argc, char *argv[])
initInternationalization();
// Initialize PhysicsFS
- PHYSFS_init(argv[0]);
-
- initXML();
-
- // Load branding information
- branding.init("data/branding.xml");
-
- initHomeDir(options);
-
- setScreenshotDir(options.screenshotDir);
-
- // Configure logger
- logger = new Logger;
- logger->setLogFile(homeDir + std::string("/mana.log"));
-
- // Log the mana version
- logger->log("Mana %s", FULL_VERSION);
-
- initConfiguration(options);
- logger->setLogToStandardOut(config.getValue("logToStandardOut", 0));
-
- initEngine(options);
-
- // Needs to be created in main, as the updater uses it
- guiPalette = new Palette;
-
- Window *currentDialog = 0;
- QuitDialog *quitDialog = 0;
- setupWindow = new Setup;
-
- gcn::Container *top = static_cast<gcn::Container*>(gui->getTop());
- Desktop *desktop = 0;
- Button *setupButton = 0;
-
- sound.playMusic(branding.getValue("loginMusic", "Magick - Real.ogg"));
-
- // Initialize default server
- ServerInfo currentServer;
- currentServer.hostname = options.serverName;
- currentServer.port = options.serverPort;
- loginData.username = options.username;
- loginData.password = options.password;
- loginData.remember = config.getValue("remember", 0);
- loginData.registerLogin = false;
-
- if (currentServer.hostname.empty())
- {
- currentServer.hostname = branding.getValue("defaultServer",
- "server.themanaworld.org").c_str();
- }
- if (options.serverPort == 0)
- {
- currentServer.port = (short) branding.getValue("defaultPort",
- DEFAULT_PORT);
- }
- if (loginData.username.empty() && loginData.remember)
- loginData.username = config.getValue("username", "");
-
- if (state != STATE_ERROR)
- state = STATE_CHOOSE_SERVER;
- State oldstate = STATE_START; // We start with a status change
-
- SDL_Event event;
-
- while (state != STATE_EXIT)
- {
- bool handledEvents = false;
-
- // Handle SDL events
- while (SDL_PollEvent(&event))
- {
- handledEvents = true;
-
- switch (event.type)
- {
- case SDL_QUIT:
- state = STATE_EXIT;
- break;
-
- case SDL_KEYDOWN:
- break;
- }
-
- guiInput->pushInput(event);
- }
-
- if (Net::getGeneralHandler())
- Net::getGeneralHandler()->flushNetwork();
-
- gui->logic();
- gui->draw();
- graphics->updateScreen();
-
- // TODO: Add connect timeouts
- if (state == STATE_CONNECT_GAME &&
- Net::getGameHandler()->isConnected())
- {
- Net::getLoginHandler()->disconnect();
- }
- else if (state == STATE_CONNECT_SERVER && oldstate == STATE_CHOOSE_SERVER)
- {
- Net::connectToServer(currentServer);
- }
- else if (state == STATE_CONNECT_SERVER &&
- oldstate != STATE_CHOOSE_SERVER &&
- Net::getLoginHandler()->isConnected())
- {
- state = STATE_LOGIN;
- }
- else if (state == STATE_WORLD_SELECT && oldstate == STATE_UPDATE)
- {
- if (Net::getLoginHandler()->getWorlds().size() < 2)
- {
- state = STATE_LOGIN;
- }
- }
- else if (oldstate == STATE_START || oldstate == STATE_GAME)
- {
- desktop = new Desktop;
- top->add(desktop);
- setupButton = new Button(_("Setup"), "Setup", &listener);
- setupButton->setPosition(top->getWidth() - setupButton->getWidth()
- - 3, 3);
- top->add(setupButton);
-
- int screenWidth = (int) config.getValue("screenwidth",
- defaultScreenWidth);
- int screenHeight = (int) config.getValue("screenheight",
- defaultScreenHeight);
-
- desktop->setSize(screenWidth, screenHeight);
- }
-
- if (state == STATE_SWITCH_LOGIN && oldstate == STATE_GAME)
- {
- Net::getGameHandler()->disconnect();
- }
-
- if (state != oldstate)
- {
- oldstate = state;
-
- // Get rid of the dialog of the previous state
- if (currentDialog)
- {
- delete currentDialog;
- currentDialog = NULL;
- }
- // State has changed, while the quitDialog was active, it might
- // not be correct anymore
- if (quitDialog)
- quitDialog->scheduleDelete();
-
- switch (state)
- {
- case STATE_CHOOSE_SERVER:
- logger->log("State: CHOOSE SERVER");
-
- // Allow changing this using a server choice dialog
- // We show the dialog box only if the command-line
- // options weren't set.
- if (options.serverName.empty() && options.serverPort == 0)
- {
- // Don't allow an alpha opacity
- // lower than the default value
- SkinLoader::instance()->setMinimumOpacity(0.8f);
-
- currentDialog = new ServerDialog(&currentServer,
- homeDir);
- }
- else
- {
- state = STATE_CONNECT_SERVER;
-
- // Reset options so that cancelling or connect
- // timeout will show the server dialog.
- options.serverName.clear();
- options.serverPort = 0;
- }
- break;
-
- case STATE_CONNECT_SERVER:
- logger->log("State: CONNECT SERVER");
- currentDialog = new ConnectionDialog(
- _("Connecting to server"), STATE_SWITCH_SERVER);
- break;
-
- case STATE_LOGIN:
- logger->log("State: LOGIN");
- // Don't allow an alpha opacity
- // lower than the default value
- SkinLoader::instance()->setMinimumOpacity(0.8f);
-
- if (options.username.empty()
- || options.password.empty())
- {
- currentDialog = new LoginDialog(&loginData);
- }
- else
- {
- state = STATE_LOGIN_ATTEMPT;
- // Clear the password so that when login fails, the
- // dialog will show up next time.
- options.password.clear();
- }
- break;
-
- case STATE_LOGIN_ATTEMPT:
- logger->log("State: LOGIN ATTEMPT");
- accountLogin(&loginData);
- currentDialog = new ConnectionDialog(
- _("Logging in"), STATE_SWITCH_SERVER);
- break;
-
- case STATE_WORLD_SELECT:
- logger->log("State: WORLD SELECT");
- {
- Worlds worlds = Net::getLoginHandler()->getWorlds();
-
- if (worlds.size() == 0)
- {
- // Trust that the netcode knows what it's doing
- state = STATE_UPDATE;
- }
- else if (worlds.size() == 1)
- {
- Net::getLoginHandler()->chooseServer(0);
- state = STATE_UPDATE;
- }
- else
- {
- currentDialog = new WorldSelectDialog(worlds);
- if (options.chooseDefault)
- {
- ((WorldSelectDialog*) currentDialog)->action(
- gcn::ActionEvent(NULL, "ok"));
- }
- }
- }
- break;
-
- case STATE_WORLD_SELECT_ATTEMPT:
- logger->log("State: WORLD SELECT ATTEMPT");
- currentDialog = new ConnectionDialog(
- _("Entering game world"), STATE_WORLD_SELECT);
- break;
-
- case STATE_UPDATE:
-
- // Determine which source to use for the update host
- if (!options.updateHost.empty())
- updateHost = options.updateHost;
- else
- updateHost = loginData.updateHost;
- setUpdatesDir();
-
- if (options.skipUpdate)
- {
- state = STATE_LOAD_DATA;
- }
- else
- {
- logger->log("State: UPDATE");
- currentDialog = new UpdaterWindow(updateHost,
- homeDir + "/" + updatesDir,options.dataPath.empty());
- }
- break;
-
- case STATE_LOAD_DATA:
- logger->log("State: LOAD DATA");
-
- // If another data path has been set,
- // we don't load any other files...
- if (options.dataPath.empty())
- {
- // Add customdata directory
- ResourceManager::getInstance()->searchAndAddArchives(
- "customdata/",
- "zip",
- false);
- }
-
- // Load XML databases
- ColorDB::load();
- ItemDB::load();
- Being::load(); // Hairstyles
- MonsterDB::load();
- NPCDB::load();
- EmoteDB::load();
- StatusEffect::load();
- Units::loadUnits();
-
- desktop->reloadWallpaper();
-
- state = STATE_GET_CHARACTERS;
- break;
-
- case STATE_GET_CHARACTERS:
- logger->log("State: GET CHARACTERS");
- Net::getCharHandler()->requestCharacters();
- currentDialog = new ConnectionDialog(
- _("Requesting characters"),
- STATE_SWITCH_SERVER);
- break;
-
- case STATE_CHAR_SELECT:
- logger->log("State: CHAR SELECT");
- // Don't allow an alpha opacity
- // lower than the default value
- SkinLoader::instance()->setMinimumOpacity(0.8f);
-
- currentDialog = new CharSelectDialog(&loginData);
-
- if (!((CharSelectDialog*) currentDialog)->selectByName(
- options.character, CharSelectDialog::Choose))
- {
- ((CharSelectDialog*) currentDialog)->selectByName(
- config.getValue("lastCharacter", ""),
- options.chooseDefault ?
- CharSelectDialog::Choose :
- CharSelectDialog::Focus);
- }
-
- break;
-
- case STATE_CONNECT_GAME:
- logger->log("State: CONNECT GAME");
-
- Net::getGameHandler()->connect();
- currentDialog = new ConnectionDialog(
- _("Connecting to the game server"),
- STATE_SWITCH_CHARACTER);
- break;
-
- case STATE_GAME:
- logger->log("Memorizing selected character %s",
- player_node->getName().c_str());
- config.setValue("lastCharacter", player_node->getName());
-
- Net::getGameHandler()->inGame();
-
- // Fade out logon-music here too to give the desired effect
- // of "flowing" into the game.
- sound.fadeOutMusic(1000);
-
- // Allow any alpha opacity
- SkinLoader::instance()->setMinimumOpacity(-1.0f);
-
- delete setupButton;
- delete desktop;
- setupButton = NULL;
- desktop = NULL;
-
- currentDialog = NULL;
-
- logger->log("State: GAME");
- game = new Game;
- game->exec();
- delete game;
- game = 0;
-
- if (state == STATE_GAME)
- state = STATE_EXIT;
-
- break;
-
- case STATE_LOGIN_ERROR:
- logger->log("State: LOGIN ERROR");
- currentDialog = new OkDialog(_("Error"), errorMessage);
- currentDialog->addActionListener(&loginListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
- case STATE_ACCOUNTCHANGE_ERROR:
- logger->log("State: ACCOUNT CHANGE ERROR");
- currentDialog = new OkDialog(_("Error"), errorMessage);
- currentDialog->addActionListener(&accountListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
- case STATE_REGISTER_PREP:
- logger->log("State: REGISTER_PREP");
- Net::getLoginHandler()->getRegistrationDetails();
- currentDialog = new ConnectionDialog(
- _("Requesting registration details"), STATE_LOGIN);
- break;
-
- case STATE_REGISTER:
- logger->log("State: REGISTER");
- currentDialog = new RegisterDialog(&loginData);
- break;
-
- case STATE_REGISTER_ATTEMPT:
- logger->log("Username is %s", loginData.username.c_str());
- Net::getLoginHandler()->registerAccount(&loginData);
- break;
-
- case STATE_CHANGEPASSWORD:
- logger->log("State: CHANGE PASSWORD");
- currentDialog = new ChangePasswordDialog(&loginData);
- break;
-
- case STATE_CHANGEPASSWORD_ATTEMPT:
- logger->log("State: CHANGE PASSWORD ATTEMPT");
- Net::getLoginHandler()->changePassword(loginData.username,
- loginData.password,
- loginData.newPassword);
- break;
-
- case STATE_CHANGEPASSWORD_SUCCESS:
- logger->log("State: CHANGE PASSWORD SUCCESS");
- currentDialog = new OkDialog(_("Password Change"),
- _("Password changed successfully!"));
- currentDialog->addActionListener(&accountListener);
- currentDialog = NULL; // OkDialog deletes itself
- loginData.password = loginData.newPassword;
- loginData.newPassword = "";
- break;
-
- case STATE_CHANGEEMAIL:
- logger->log("State: CHANGE EMAIL");
- currentDialog = new ChangeEmailDialog(&loginData);
- break;
-
- case STATE_CHANGEEMAIL_ATTEMPT:
- logger->log("State: CHANGE EMAIL ATTEMPT");
- Net::getLoginHandler()->changeEmail(loginData.email);
- break;
-
- case STATE_CHANGEEMAIL_SUCCESS:
- logger->log("State: CHANGE EMAIL SUCCESS");
- currentDialog = new OkDialog(_("Email Change"),
- _("Email changed successfully!"));
- currentDialog->addActionListener(&accountListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
- case STATE_UNREGISTER:
- logger->log("State: UNREGISTER");
- currentDialog = new UnRegisterDialog(&loginData);
- break;
-
- case STATE_UNREGISTER_ATTEMPT:
- logger->log("State: UNREGISTER ATTEMPT");
- Net::getLoginHandler()->unregisterAccount(
- loginData.username, loginData.password);
- break;
-
- case STATE_UNREGISTER_SUCCESS:
- logger->log("State: UNREGISTER SUCCESS");
- Net::getLoginHandler()->disconnect();
-
- currentDialog = new OkDialog(_("Unregister Successful"),
- _("Farewell, come back any time..."));
- loginData.clear();
- //The errorlistener sets the state to STATE_CHOOSE_SERVER
- currentDialog->addActionListener(&errorListener);
- currentDialog = NULL; // OkDialog deletes itself
- break;
-
- case STATE_SWITCH_SERVER:
- logger->log("State: SWITCH SERVER");
-
- Net::getLoginHandler()->disconnect();
- Net::getGameHandler()->disconnect();
-
- state = STATE_CHOOSE_SERVER;
- break;
-
- case STATE_SWITCH_LOGIN:
- logger->log("State: SWITCH LOGIN");
-
- Net::getLoginHandler()->logout();
-
- state = STATE_LOGIN;
- break;
-
- case STATE_SWITCH_CHARACTER:
- logger->log("State: SWITCH CHARACTER");
-
- // Done with game
- Net::getGameHandler()->disconnect();
-
- Net::getCharHandler()->requestCharacters();
- break;
-
- case STATE_LOGOUT_ATTEMPT:
- logger->log("State: LOGOUT ATTEMPT");
- // TODO
- break;
-
- case STATE_WAIT:
- logger->log("State: WAIT");
- break;
-
- case STATE_EXIT:
- logger->log("State: EXIT");
- Net::unload();
- break;
-
- case STATE_FORCE_QUIT:
- logger->log("State: FORCE QUIT");
- if (Net::getGeneralHandler())
- Net::getGeneralHandler()->unload();
- state = STATE_EXIT;
- break;
-
- case STATE_ERROR:
- logger->log("State: ERROR");
- currentDialog = new OkDialog(_("Error"), errorMessage);
- currentDialog->addActionListener(&errorListener);
- currentDialog = NULL; // OkDialog deletes itself
- Net::getGameHandler()->disconnect();
- break;
-
- default:
- state = STATE_FORCE_QUIT;
- break;
- }
- }
-
- /*
- * This loop can really stress the CPU, for no reason since it's
- * just constantly redrawing the wallpaper. Added the following
- * usleep to limit it to 40 FPS during the login sequence
- */
- if (!handledEvents)
- usleep(25000);
+ if (!PHYSFS_init(argv[0])) {
+ std::cout << "Error while initializing PhysFS: "
+ << PHYSFS_getLastError() << std::endl;
+ return 1;
}
+ atexit((void(*)()) PHYSFS_deinit);
- delete guiPalette;
-
- logger->log("Quitting");
- exitEngine();
- PHYSFS_deinit();
- delete logger;
-
- return 0;
-}
-
-void SetupListener::action(const gcn::ActionEvent &event)
-{
- Window *window = NULL;
-
- if (event.getId() == "Setup")
- window = setupWindow;
+ initXML();
- if (window)
- {
- window->setVisible(!window->isVisible());
- if (window->isVisible())
- window->requestMoveToTop();
- }
+ Client client(options);
+ return client.exec();
}
diff --git a/src/main.h b/src/main.h
index 4fe77ba5..9848d9b1 100644
--- a/src/main.h
+++ b/src/main.h
@@ -59,12 +59,6 @@
#define PACKAGE_VERSION "0.0.29.1"
#endif
-#include "net/logindata.h"
-
-#include <guichan/actionlistener.hpp>
-
-#include <string>
-
#ifdef PACKAGE_VERSION
#define FULL_VERSION "v" PACKAGE_VERSION
#else
@@ -75,65 +69,4 @@
#define PKG_DATADIR ""
#endif
-#define MAX_CHARACTER_COUNT 3
-
-//manaserv uses 9601
-//#define DEFAULT_PORT 9601
-#define DEFAULT_PORT 6901
-
-const std::string &getHomeDirectory();
-
-/*
- * Client different States
- */
-enum State {
- STATE_ERROR = -1,
- STATE_START = 0,
- STATE_CHOOSE_SERVER,
- STATE_CONNECT_SERVER,
- STATE_LOGIN,
- STATE_LOGIN_ATTEMPT,
- STATE_WORLD_SELECT, // 5
- STATE_WORLD_SELECT_ATTEMPT,
- STATE_UPDATE,
- STATE_LOAD_DATA,
- STATE_GET_CHARACTERS,
- STATE_CHAR_SELECT, // 10
- STATE_CONNECT_GAME,
- STATE_GAME,
- STATE_CHANGE_MAP, // Switch map-server/gameserver
- STATE_LOGIN_ERROR,
- STATE_ACCOUNTCHANGE_ERROR, // 15
- STATE_REGISTER_PREP,
- STATE_REGISTER,
- STATE_REGISTER_ATTEMPT,
- STATE_CHANGEPASSWORD,
- STATE_CHANGEPASSWORD_ATTEMPT, // 20
- STATE_CHANGEPASSWORD_SUCCESS,
- STATE_CHANGEEMAIL,
- STATE_CHANGEEMAIL_ATTEMPT,
- STATE_CHANGEEMAIL_SUCCESS,
- STATE_UNREGISTER, // 25
- STATE_UNREGISTER_ATTEMPT,
- STATE_UNREGISTER_SUCCESS,
- STATE_SWITCH_SERVER,
- STATE_SWITCH_LOGIN,
- STATE_SWITCH_CHARACTER, // 30
- STATE_LOGOUT_ATTEMPT,
- STATE_WAIT,
- STATE_EXIT,
- STATE_FORCE_QUIT
-};
-
-class ErrorListener : public gcn::ActionListener
-{
- public:
- void action(const gcn::ActionEvent &event);
-};
-
-extern State state;
-extern std::string errorMessage;
-extern ErrorListener errorListener;
-extern LoginData loginData;
-
#endif
diff --git a/src/map.cpp b/src/map.cpp
index 7c45050b..6d332d48 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -19,11 +19,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "map.h"
+
#include "beingmanager.h"
+#include "client.h"
#include "configuration.h"
-#include "game.h"
#include "graphics.h"
-#include "map.h"
#include "particle.h"
#include "simpleanimation.h"
#include "sprite.h"
@@ -38,8 +39,6 @@
#include <queue>
-extern volatile int tick_time;
-
/**
* A location on a tile map. Used for pathfinding, open list.
*/
@@ -291,14 +290,13 @@ bool spriteCompare(const Sprite *a, const Sprite *b)
void Map::update(int ticks)
{
- //update animated tiles
+ // Update animated tiles
for (std::map<int, TileAnimation*>::iterator iAni = mTileAnimations.begin();
iAni != mTileAnimations.end();
iAni++)
{
iAni->second->update(ticks);
}
-
}
void Map::draw(Graphics *graphics, int scrollX, int scrollY)
diff --git a/src/monster.cpp b/src/monster.cpp
index 044f80a2..dfe84e65 100644
--- a/src/monster.cpp
+++ b/src/monster.cpp
@@ -19,10 +19,11 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "monster.h"
+
#include "animatedsprite.h"
-#include "game.h"
+#include "client.h"
#include "localplayer.h"
-#include "monster.h"
#include "particle.h"
#include "sound.h"
#include "text.h"
@@ -38,7 +39,7 @@ Monster::Monster(int id, int job, Map *map):
Being(id, job, map),
mAttackType(1)
{
- const MonsterInfo& info = getInfo();
+ const MonsterInfo &info = getInfo();
// Setup Monster sprites
const std::list<std::string> &sprites = info.getSprites();
diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp
index 14ed40bc..fd08ecaf 100644
--- a/src/net/ea/beinghandler.cpp
+++ b/src/net/ea/beinghandler.cpp
@@ -23,8 +23,8 @@
#include "being.h"
#include "beingmanager.h"
+#include "client.h"
#include "effectmanager.h"
-#include "game.h"
#include "localplayer.h"
#include "log.h"
#include "npc.h"
diff --git a/src/net/ea/charserverhandler.cpp b/src/net/ea/charserverhandler.cpp
index 23d88356..f0a13f43 100644
--- a/src/net/ea/charserverhandler.cpp
+++ b/src/net/ea/charserverhandler.cpp
@@ -21,9 +21,9 @@
#include "net/ea/charserverhandler.h"
+#include "client.h"
#include "game.h"
#include "log.h"
-#include "main.h"
#include "gui/charcreatedialog.h"
#include "gui/okdialog.h"
@@ -92,7 +92,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
character->dummy->getName().c_str(), slot);
}
- state = STATE_CHAR_SELECT;
+ Client::setState(STATE_CHAR_SELECT);
}
break;
@@ -167,7 +167,7 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
updateCharSelectDialog();
mNetwork->disconnect();
- state = STATE_CONNECT_GAME;
+ Client::setState(STATE_CONNECT_GAME);
break;
}
}
diff --git a/src/net/ea/gamehandler.cpp b/src/net/ea/gamehandler.cpp
index b7b8389a..3625b9ab 100644
--- a/src/net/ea/gamehandler.cpp
+++ b/src/net/ea/gamehandler.cpp
@@ -21,10 +21,9 @@
#include "net/ea/gamehandler.h"
-#include "game.h"
+#include "client.h"
#include "localplayer.h"
#include "log.h"
-#include "main.h"
#include "gui/widgets/chattab.h"
@@ -74,7 +73,7 @@ void GameHandler::handleMessage(Net::MessageIn &msg)
logger->log("Protocol: Player start position: (%d, %d), Direction: %d",
x, y, direction);
// Switch now or we'll have problems
- state = STATE_GAME;
+ Client::setState(STATE_GAME);
player_node->setTileCoords(x, y);
} break;
@@ -91,7 +90,7 @@ void GameHandler::handleMessage(Net::MessageIn &msg)
case SMSG_CHAR_SWITCH_RESPONSE:
if (msg.readInt8())
{
- state = STATE_SWITCH_CHARACTER;
+ Client::setState(STATE_SWITCH_CHARACTER);
}
break;
diff --git a/src/net/ea/generalhandler.cpp b/src/net/ea/generalhandler.cpp
index 7fc5886a..f7d495a6 100644
--- a/src/net/ea/generalhandler.cpp
+++ b/src/net/ea/generalhandler.cpp
@@ -21,9 +21,9 @@
#include "net/ea/generalhandler.h"
+#include "client.h"
#include "configuration.h"
#include "log.h"
-#include "main.h"
#include "gui/charselectdialog.h"
#include "gui/inventorywindow.h"
@@ -129,7 +129,7 @@ void GeneralHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("No servers available.");
break;
case 2:
- if (state == STATE_GAME)
+ if (Client::getState() == STATE_GAME)
errorMessage = _("Someone else is trying to use this "
"account.");
else
@@ -145,7 +145,7 @@ void GeneralHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("Unknown connection error.");
break;
}
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
break;
}
}
@@ -199,7 +199,7 @@ void GeneralHandler::flushNetwork()
else
errorMessage = _("Got disconnected from server!");
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
}
}
diff --git a/src/net/ea/loginhandler.cpp b/src/net/ea/loginhandler.cpp
index 3f0fe0d0..bec97ed7 100644
--- a/src/net/ea/loginhandler.cpp
+++ b/src/net/ea/loginhandler.cpp
@@ -21,8 +21,8 @@
#include "net/ea/loginhandler.h"
+#include "client.h"
#include "log.h"
-#include "main.h"
#include "net/logindata.h"
#include "net/messagein.h"
@@ -68,7 +68,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
// Successful pass change
if (errMsg == 1)
{
- state = STATE_CHANGEPASSWORD_SUCCESS;
+ Client::setState(STATE_CHANGEPASSWORD_SUCCESS);
}
// pass change failed
else
@@ -88,7 +88,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_ACCOUNTCHANGE_ERROR;
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
}
}
break;
@@ -136,7 +136,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
mWorlds.push_back(world);
}
- state = STATE_WORLD_SELECT;
+ Client::setState(STATE_WORLD_SELECT);
break;
case SMSG_LOGIN_ERROR:
@@ -175,8 +175,9 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
break;
+
case SMSG_SERVER_VERSION_RESPONSE:
{
// TODO: verify these!
@@ -214,7 +215,7 @@ void LoginHandler::disconnect()
void LoginHandler::getRegistrationDetails()
{
// Not supported, so move on
- state = STATE_REGISTER;
+ Client::setState(STATE_REGISTER);
}
void LoginHandler::loginAccount(LoginData *loginData)
@@ -250,7 +251,7 @@ void LoginHandler::chooseServer(unsigned int server)
charServer.hostname = ipToString(mWorlds[server]->address);
charServer.port = mWorlds[server]->port;
- state = STATE_UPDATE;
+ Client::setState(STATE_UPDATE);
}
void LoginHandler::registerAccount(LoginData *loginData)
diff --git a/src/net/logindata.h b/src/net/logindata.h
index 5a96db20..9bbeed4f 100644
--- a/src/net/logindata.h
+++ b/src/net/logindata.h
@@ -28,8 +28,9 @@
#include <string>
-struct LoginData
+class LoginData
{
+public:
std::string username;
std::string password;
std::string newPassword;
diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp
index 86f86d3f..bab5471b 100644
--- a/src/net/manaserv/beinghandler.cpp
+++ b/src/net/manaserv/beinghandler.cpp
@@ -23,13 +23,12 @@
#include "being.h"
#include "beingmanager.h"
+#include "client.h"
#include "game.h"
#include "localplayer.h"
#include "log.h"
-#include "main.h"
#include "npc.h"
#include "particle.h"
-#include "sound.h"
#include "gui/okdialog.h"
@@ -103,10 +102,10 @@ Vector BeingHandler::giveSpeedInPixelsPerTicks(float speedInTilesPerSeconds)
{
speedInTicks.x = speedInTilesPerSeconds
* (float)map->getTileWidth()
- / 1000 * (float)MILLISECONDS_IN_A_TICK;
+ / 1000 * (float) MILLISECONDS_IN_A_TICK;
speedInTicks.y = speedInTilesPerSeconds
* (float)map->getTileHeight()
- / 1000 * (float)MILLISECONDS_IN_A_TICK;
+ / 1000 * (float) MILLISECONDS_IN_A_TICK;
}
}
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
index 14d2b11f..4b574821 100644
--- a/src/net/manaserv/charhandler.cpp
+++ b/src/net/manaserv/charhandler.cpp
@@ -21,10 +21,9 @@
#include "net/manaserv/charhandler.h"
-#include "game.h"
+#include "client.h"
#include "localplayer.h"
#include "log.h"
-#include "main.h"
#include "gui/charcreatedialog.h"
#include "gui/okdialog.h"
@@ -236,14 +235,14 @@ void CharHandler::handleCharacterSelectResponse(Net::MessageIn &msg)
mCachedCharacterInfos.clear();
updateCharacters();
- state = STATE_CONNECT_GAME;
+ Client::setState(STATE_CONNECT_GAME);
}
else if (errMsg == ERRMSG_FAILURE)
{
errorMessage = _("No gameservers are available.");
delete_all(mCharacters);
mCharacters.clear();
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
}
}
@@ -280,7 +279,7 @@ void CharHandler::requestCharacters()
else
{
// The characters are already there, continue to character selection
- state = STATE_CHAR_SELECT;
+ Client::setState(STATE_CHAR_SELECT);
}
}
diff --git a/src/net/manaserv/chathandler.cpp b/src/net/manaserv/chathandler.cpp
index d6da557d..a452281f 100644
--- a/src/net/manaserv/chathandler.cpp
+++ b/src/net/manaserv/chathandler.cpp
@@ -23,10 +23,9 @@
#include "being.h"
#include "beingmanager.h"
+#include "client.h"
#include "channel.h"
#include "channelmanager.h"
-#include "game.h"
-#include "main.h"
#include "gui/chat.h"
@@ -136,7 +135,7 @@ void ChatHandler::handleMessage(Net::MessageIn &msg)
errorMessage = "Chatserver: Unknown error";
break;
}
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
}
}
break;
diff --git a/src/net/manaserv/gamehandler.cpp b/src/net/manaserv/gamehandler.cpp
index a7d979a1..dd6120ae 100644
--- a/src/net/manaserv/gamehandler.cpp
+++ b/src/net/manaserv/gamehandler.cpp
@@ -21,8 +21,8 @@
#include "net/manaserv/gamehandler.h"
+#include "client.h"
#include "localplayer.h"
-#include "main.h"
#include "net/manaserv/chathandler.h"
#include "net/manaserv/connection.h"
@@ -63,7 +63,7 @@ void GameHandler::handleMessage(Net::MessageIn &msg)
\
if (!netToken.empty())
{
- state = STATE_SWITCH_CHARACTER;
+ Client::setState(STATE_SWITCH_CHARACTER);
}
else
{
@@ -82,7 +82,7 @@ void GameHandler::handleMessage(Net::MessageIn &msg)
errorMessage = "Gameserver: Unknown error";
break;
}
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
}
}
break;
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
index 9f14fd38..171ca214 100644
--- a/src/net/manaserv/generalhandler.cpp
+++ b/src/net/manaserv/generalhandler.cpp
@@ -21,7 +21,7 @@
#include "net/manaserv/generalhandler.h"
-#include "main.h"
+#include "client.h"
#include "gui/changeemaildialog.h"
#include "gui/charselectdialog.h"
@@ -147,11 +147,11 @@ void GeneralHandler::flushNetwork()
{
flush();
- if (state == STATE_SWITCH_CHARACTER &&
+ if (Client::getState() == STATE_SWITCH_CHARACTER &&
Net::getLoginHandler()->isConnected())
{
loginHandler->reconnect();
- state = STATE_GET_CHARACTERS;
+ Client::setState(STATE_GET_CHARACTERS);
}
}
diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp
index a8395204..cbc8e510 100644
--- a/src/net/manaserv/loginhandler.cpp
+++ b/src/net/manaserv/loginhandler.cpp
@@ -21,7 +21,7 @@
#include "net/manaserv/loginhandler.h"
-#include "main.h"
+#include "client.h"
#include "net/logindata.h"
@@ -75,7 +75,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
// Successful login
if (errMsg == ERRMSG_OK)
{
- state = STATE_CHAR_SELECT;
+ Client::setState(STATE_CHAR_SELECT);
}
// Login failed
else
@@ -95,7 +95,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
}
}
break;
@@ -106,7 +106,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
// Successful pass change
if (errMsg == ERRMSG_OK)
{
- state = STATE_CHANGEPASSWORD_SUCCESS;
+ Client::setState(STATE_CHANGEPASSWORD_SUCCESS);
}
// pass change failed
else
@@ -126,7 +126,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_ACCOUNTCHANGE_ERROR;
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
}
}
break;
@@ -137,7 +137,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
// Successful pass change
if (errMsg == ERRMSG_OK)
{
- state = STATE_CHANGEEMAIL_SUCCESS;
+ Client::setState(STATE_CHANGEEMAIL_SUCCESS);
}
// pass change failed
else
@@ -160,7 +160,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_ACCOUNTCHANGE_ERROR;
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
}
}
break;
@@ -185,7 +185,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = "Accountserver: Unknown error";
break;
}
- state = STATE_ERROR;
+ Client::setState(STATE_ERROR);
}
}
break;
@@ -195,7 +195,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
// Successful unregistration
if (errMsg == ERRMSG_OK)
{
- state = STATE_UNREGISTER;
+ Client::setState(STATE_UNREGISTER);
}
// Unregistration failed
else
@@ -210,7 +210,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
errorMessage = "Accountserver: Unknown error";
break;
}
- state = STATE_ACCOUNTCHANGE_ERROR;
+ Client::setState(STATE_ACCOUNTCHANGE_ERROR);
}
}
break;
@@ -228,7 +228,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
printf("%s: %s\n", captchaURL.c_str(), captchaInstructions.c_str());
- state = STATE_REGISTER;
+ Client::setState(STATE_REGISTER);
}
else
{
@@ -237,7 +237,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
if (errorMessage.empty())
errorMessage = _("Client registration is not allowed. "
"Please contact server administration.");
- state = STATE_LOGIN_ERROR;
+ Client::setState(STATE_LOGIN_ERROR);
}
}
break;
@@ -252,7 +252,7 @@ void LoginHandler::handleLoginResponse(Net::MessageIn &msg)
{
readUpdateHost(msg);
// No worlds atm, but future use :-D
- state = STATE_WORLD_SELECT;
+ Client::setState(STATE_WORLD_SELECT);
}
else
{
@@ -278,7 +278,7 @@ void LoginHandler::handleLoginResponse(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_LOGIN_ERROR;
+ Client::setState(STATE_LOGIN_ERROR);
}
}
@@ -289,7 +289,7 @@ void LoginHandler::handleRegisterResponse(Net::MessageIn &msg)
if (errMsg == ERRMSG_OK)
{
readUpdateHost(msg);
- state = STATE_WORLD_SELECT;
+ Client::setState(STATE_WORLD_SELECT);
}
else
{
@@ -315,7 +315,7 @@ void LoginHandler::handleRegisterResponse(Net::MessageIn &msg)
errorMessage = _("Unknown error.");
break;
}
- state = STATE_LOGIN_ERROR;
+ Client::setState(STATE_LOGIN_ERROR);
}
}
@@ -342,9 +342,9 @@ void LoginHandler::disconnect()
{
accountServerConnection->disconnect();
- if (state == STATE_CONNECT_GAME)
+ if (Client::getState() == STATE_CONNECT_GAME)
{
- state = STATE_GAME;
+ Client::setState(STATE_GAME);
}
}
diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp
index a78afa8a..3a5d68a2 100644
--- a/src/net/manaserv/playerhandler.cpp
+++ b/src/net/manaserv/playerhandler.cpp
@@ -22,6 +22,7 @@
#include "net/manaserv/playerhandler.h"
#include "net/manaserv/beinghandler.h"
+#include "client.h"
#include "effectmanager.h"
#include "game.h"
#include "localplayer.h"
@@ -41,9 +42,6 @@
#include "net/manaserv/messageout.h"
#include "net/manaserv/protocol.h"
-/** @see in game.cpp */
-extern const int MILLISECONDS_IN_A_TICK;
-
/**
* Max. distance we are willing to scroll after a teleport;
* everything beyond will reset the port hard.
diff --git a/src/player.cpp b/src/player.cpp
index 700301d5..18dc0818 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -19,14 +19,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "player.h"
+
#include "animatedsprite.h"
+#include "client.h"
#include "configuration.h"
-#include "game.h"
#include "guild.h"
#include "localplayer.h"
#include "particle.h"
#include "party.h"
-#include "player.h"
#include "text.h"
#include "gui/palette.h"
diff --git a/src/statuseffect.cpp b/src/statuseffect.cpp
index 1eed3e1c..66e8010d 100644
--- a/src/statuseffect.cpp
+++ b/src/statuseffect.cpp
@@ -22,6 +22,7 @@
#include "statuseffect.h"
#include "log.h"
+#include "sound.h"
#include "gui/widgets/chattab.h"
diff --git a/src/statuseffect.h b/src/statuseffect.h
index 320f4004..0fed5748 100644
--- a/src/statuseffect.h
+++ b/src/statuseffect.h
@@ -24,7 +24,6 @@
#include "particle.h"
#include "animatedsprite.h"
-#include "sound.h"
#include "resources/animation.h"