summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2010-02-21 20:40:07 +0100
committerChuck Miller <shadowmil@gmail.com>2010-02-21 17:05:40 -0500
commitc8b0d1e56f27c3141895d28b2fc768afffe7bb2d (patch)
tree0a03458836badee3e1b0da13a0721c9261e7fa86 /src/main.cpp
parent204a14c91bbe4436eb3b26bebf30cbe5669bdd1a (diff)
downloadmana-c8b0d1e56f27c3141895d28b2fc768afffe7bb2d.tar.gz
mana-c8b0d1e56f27c3141895d28b2fc768afffe7bb2d.tar.bz2
mana-c8b0d1e56f27c3141895d28b2fc768afffe7bb2d.tar.xz
mana-c8b0d1e56f27c3141895d28b2fc768afffe7bb2d.zip
Made tick counter and framerate limiter work during login sequence
Much code was moved from main() to the new Client::exec(). This new event loop now integrates with the Game class, so that the tick counter and framerate limiter apply universally. The Client class is also responsible for some things that used to be global variables. Mantis-issue: ...
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp1104
1 files changed, 17 insertions, 1087 deletions
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();
}