diff options
Diffstat (limited to 'src/client.cpp')
-rw-r--r-- | src/client.cpp | 250 |
1 files changed, 154 insertions, 96 deletions
diff --git a/src/client.cpp b/src/client.cpp index f63fc5f7..5736cec4 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -22,8 +22,10 @@ #include "client.h" #include "main.h" +#include "chatlog.h" #include "configuration.h" #include "emoteshortcut.h" +#include "event.h" #include "game.h" #include "itemshortcut.h" #include "keyboardconfig.h" @@ -47,10 +49,8 @@ #include "gui/sdlinput.h" #include "gui/serverdialog.h" #include "gui/setup.h" -#include "gui/theme.h" #include "gui/unregisterdialog.h" #include "gui/updatewindow.h" -#include "gui/userpalette.h" #include "gui/worldselectdialog.h" #include "gui/widgets/button.h" @@ -69,8 +69,11 @@ #include "resources/image.h" #include "resources/itemdb.h" #include "resources/monsterdb.h" +#include "resources/specialdb.h" #include "resources/npcdb.h" #include "resources/resourcemanager.h" +#include "resources/theme.h" +#include "resources/userpalette.h" #include "utils/gettext.h" #include "utils/mkdir.h" @@ -104,24 +107,21 @@ 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 */ Configuration paths; /**< XML default paths information reader */ Logger *logger; /**< Log object */ +ChatLogger *chatLogger; /**< Chat log object */ KeyboardConfig keyboard; UserPalette *userPalette; Graphics *graphics; -Sound sound; +ItemDB *itemDb; -void ErrorListener::action(const gcn::ActionEvent &) -{ - Client::setState(STATE_CHOOSE_SERVER); -} +Sound sound; volatile int tick_time; /**< Tick counter */ volatile int fps = 0; /**< Frames counted in the last second */ @@ -153,42 +153,31 @@ Uint32 nextSecond(Uint32 interval, void *param) return interval; } -/** - * @return the elapsed time in milliseconds - * between two tick values. - */ -int get_elapsed_time(int start_time) +int get_elapsed_time(int startTime) { - if (start_time <= tick_time) - return (tick_time - start_time) * MILLISECONDS_IN_A_TICK; + if (startTime <= tick_time) + return (tick_time - startTime) * MILLISECONDS_IN_A_TICK; else - return (tick_time + (MAX_TICK_VALUE - start_time)) + return (tick_time + (MAX_TICK_VALUE - startTime)) * MILLISECONDS_IN_A_TICK; } - -// This anonymous namespace hides whatever is inside from other modules. -namespace { - -class AccountListener : public gcn::ActionListener +bool isDoubleClick(int selected) { -public: - void action(const gcn::ActionEvent &) - { - Client::setState(STATE_CHAR_SELECT); - } -} accountListener; + const Uint32 maximumDelay = 500; + static Uint32 lastTime = 0; + static int lastSelected = -1; -class LoginListener : public gcn::ActionListener -{ -public: - void action(const gcn::ActionEvent &) + if (selected == lastSelected && lastTime + maximumDelay >= SDL_GetTicks()) { - Client::setState(STATE_LOGIN); + lastTime = 0; + return true; } -} loginListener; -} // anonymous namespace + lastTime = SDL_GetTicks(); + lastSelected = selected; + return false; +} Client *Client::mInstance = 0; @@ -202,6 +191,7 @@ Client::Client(const Options &options): mSetupButton(0), mState(STATE_CHOOSE_SERVER), mOldState(STATE_START), + mStateAfterOkDialog(mState), mIcon(0), mLogicCounterId(0), mSecondsCounterId(0), @@ -216,15 +206,22 @@ Client::Client(const Options &options): if (!options.brandingPath.empty()) { branding.init(options.brandingPath); + branding.setDefaultValues(getBrandingDefaults()); } initRootDir(); initHomeDir(); initConfiguration(); + chatLogger = new ChatLogger; + if (options.chatLogDir.empty()) + chatLogger->setLogDir(mLocalDataDir + std::string("/logs/")); + else + chatLogger->setLogDir(options.chatLogDir); + // Configure logger logger->setLogFile(mLocalDataDir + std::string("/mana.log")); - logger->setLogToStandardOut(config.getValue("logToStandardOut", 0)); + logger->setLogToStandardOut(config.getBoolValue("logToStandardOut")); // Log the mana version logger->log("Mana %s", FULL_VERSION); @@ -347,11 +344,11 @@ Client::Client(const Options &options): graphics = new Graphics; #endif - const int width = (int) config.getValue("screenwidth", defaultScreenWidth); - const int height = (int) config.getValue("screenheight", defaultScreenHeight); + const int width = config.getIntValue("screenwidth"); + const int height = config.getIntValue("screenheight"); const int bpp = 0; - const bool fullscreen = ((int) config.getValue("screen", 0) == 1); - const bool hwaccel = ((int) config.getValue("hwaccel", 0) == 1); + const bool fullscreen = config.getBoolValue("screen"); + const bool hwaccel = config.getBoolValue("hwaccel"); // Try to set the desired video mode if (!graphics->setVideoMode(width, height, bpp, fullscreen, hwaccel)) @@ -374,13 +371,11 @@ Client::Client(const Options &options): // Initialize sound engine try { - if (config.getValue("sound", 0) == 1) + if (config.getBoolValue("sound")) sound.init(); - sound.setSfxVolume((int) config.getValue("sfxVolume", - defaultSfxVolume)); - sound.setMusicVolume((int) config.getValue("musicVolume", - defaultMusicVolume)); + sound.setSfxVolume(config.getIntValue("sfxVolume")); + sound.setMusicVolume(config.getIntValue("musicVolume")); } catch (const char *err) { @@ -398,32 +393,33 @@ Client::Client(const Options &options): userPalette = new UserPalette; setupWindow = new Setup; - sound.playMusic(branding.getValue("loginMusic", "Magick - Real.ogg")); + sound.playMusic(branding.getValue("loginMusic", + "music/system/Magick - Real.ogg")); // Initialize default server mCurrentServer.hostname = options.serverName; mCurrentServer.port = options.serverPort; loginData.username = options.username; loginData.password = options.password; - loginData.remember = config.getValue("remember", 0); + loginData.remember = config.getBoolValue("remember"); loginData.registerLogin = false; if (mCurrentServer.hostname.empty()) - { - mCurrentServer.hostname = branding.getValue("defaultServer", - "").c_str(); - } + mCurrentServer.hostname = branding.getValue("defaultServer","").c_str(); if (mCurrentServer.port == 0) { mCurrentServer.port = (short) branding.getValue("defaultPort", - DEFAULT_PORT); + DEFAULT_PORT); mCurrentServer.type = ServerInfo::parseType( - branding.getValue("defaultServerType", "tmwathena")); + branding.getValue("defaultServerType", "tmwathena")); } + if (chatLogger) + chatLogger->setServerName(mCurrentServer.hostname); + if (loginData.username.empty() && loginData.remember) - loginData.username = config.getValue("username", ""); + loginData.username = config.getStringValue("username"); if (mState != STATE_ERROR) mState = STATE_CHOOSE_SERVER; @@ -435,8 +431,16 @@ Client::Client(const Options &options): // Initialize frame limiting SDL_initFramerate(&mFpsManager); - config.addListener("fpslimit", this); - optionChanged("fpslimit"); + + listen(Event::ConfigChannel); + + //TODO: fix having to fake a option changed event + Event fakeevent(Event::ConfigOptionChanged); + fakeevent.setString("option", "fpslimit"); + event(Event::ConfigChannel, fakeevent); + + // Initialize PlayerInfo + PlayerInfo::init(); } Client::~Client() @@ -447,7 +451,7 @@ Client::~Client() // Unload XML databases ColorDB::unload(); EmoteDB::unload(); - ItemDB::unload(); + delete itemDb; MonsterDB::unload(); NPCDB::unload(); StatusEffect::unload(); @@ -521,6 +525,8 @@ int Client::exec() if (game) game->logic(); + sound.logic(); + ++lastTickTime; } @@ -573,10 +579,8 @@ int Client::exec() - 3, 3); top->add(mSetupButton); - int screenWidth = (int) config.getValue("screenwidth", - defaultScreenWidth); - int screenHeight = (int) config.getValue("screenheight", - defaultScreenHeight); + int screenWidth = config.getIntValue("screenwidth"); + int screenHeight = config.getIntValue("screenheight"); mDesktop->setSize(screenWidth, screenHeight); } @@ -588,9 +592,12 @@ int Client::exec() if (mState != mOldState) { - Net::GeneralHandler *generalHandler = Net::getGeneralHandler(); - if (generalHandler) - generalHandler->stateChanged(mOldState, mState); + { + Event event(Event::StateChange); + event.setInt("oldState", mOldState); + event.setInt("newState", mState); + event.trigger(Event::ClientChannel); + } if (mOldState == STATE_GAME) { @@ -747,17 +754,46 @@ int Client::exec() // Read default paths file 'data/paths.xml' paths.init("paths.xml", true); + paths.setDefaultValues(getPathsDefaults()); + + Event::trigger(Event::ClientChannel, Event::LoadingDatabases); // Load XML databases ColorDB::load(); - ItemDB::load(); + switch (Net::getNetworkType()) + { + case ServerInfo::TMWATHENA: + itemDb = new TmwAthena::TaItemDB; + break; + case ServerInfo::MANASERV: + itemDb = new ManaServ::ManaServItemDB; + break; + default: + // Nothing + itemDb = 0; + break; + } + if (!itemDb || !itemDb->isLoaded()) + { + // Warn and return to login screen + errorMessage = + _("This server is missing needed world data. " + "Please contact the administrator(s)."); + showOkDialog(_("ItemDB: Error while loading " + ITEMS_DB_FILE "!"), errorMessage, + STATE_CHOOSE_SERVER); + break; + } Being::load(); // Hairstyles MonsterDB::load(); + SpecialDB::load(); NPCDB::load(); EmoteDB::load(); StatusEffect::load(); Units::loadUnits(); + ActorSprite::load(); + mDesktop->reloadWallpaper(); mState = STATE_GET_CHARACTERS; @@ -783,7 +819,7 @@ int Client::exec() mOptions.character, CharSelectDialog::Choose)) { ((CharSelectDialog*) mCurrentDialog)->selectByName( - config.getValue("lastCharacter", ""), + config.getStringValue("lastCharacter"), mOptions.chooseDefault ? CharSelectDialog::Choose : CharSelectDialog::Focus); @@ -835,16 +871,12 @@ int Client::exec() case STATE_LOGIN_ERROR: logger->log("State: LOGIN ERROR"); - mCurrentDialog = new OkDialog(_("Error"), errorMessage); - mCurrentDialog->addActionListener(&loginListener); - mCurrentDialog = NULL; // OkDialog deletes itself + showErrorDialog(errorMessage, STATE_LOGIN); break; case STATE_ACCOUNTCHANGE_ERROR: logger->log("State: ACCOUNT CHANGE ERROR"); - mCurrentDialog = new OkDialog(_("Error"), errorMessage); - mCurrentDialog->addActionListener(&accountListener); - mCurrentDialog = NULL; // OkDialog deletes itself + showErrorDialog(errorMessage, STATE_CHAR_SELECT); break; case STATE_REGISTER_PREP: @@ -878,10 +910,9 @@ int Client::exec() case STATE_CHANGEPASSWORD_SUCCESS: logger->log("State: CHANGE PASSWORD SUCCESS"); - mCurrentDialog = new OkDialog(_("Password Change"), - _("Password changed successfully!")); - mCurrentDialog->addActionListener(&accountListener); - mCurrentDialog = NULL; // OkDialog deletes itself + showOkDialog(_("Password Change"), + _("Password changed successfully!"), + STATE_CHAR_SELECT); loginData.password = loginData.newPassword; loginData.newPassword = ""; break; @@ -898,10 +929,9 @@ int Client::exec() case STATE_CHANGEEMAIL_SUCCESS: logger->log("State: CHANGE EMAIL SUCCESS"); - mCurrentDialog = new OkDialog(_("Email Change"), - _("Email changed successfully!")); - mCurrentDialog->addActionListener(&accountListener); - mCurrentDialog = NULL; // OkDialog deletes itself + showOkDialog(_("Email Change"), + _("Email changed successfully!"), + STATE_CHAR_SELECT); break; case STATE_UNREGISTER: @@ -919,12 +949,10 @@ int Client::exec() logger->log("State: UNREGISTER SUCCESS"); Net::getLoginHandler()->disconnect(); - mCurrentDialog = new OkDialog(_("Unregister Successful"), - _("Farewell, come back any time...")); + showOkDialog(_("Unregister Successful"), + _("Farewell, come back any time..."), + STATE_CHOOSE_SERVER); loginData.clear(); - //The errorlistener sets the state to STATE_CHOOSE_SERVER - mCurrentDialog->addActionListener(&errorListener); - mCurrentDialog = NULL; // OkDialog deletes itself break; case STATE_SWITCH_SERVER: @@ -977,9 +1005,7 @@ int Client::exec() case STATE_ERROR: logger->log("State: ERROR"); logger->log("Error: %s", errorMessage.c_str()); - mCurrentDialog = new OkDialog(_("Error"), errorMessage); - mCurrentDialog->addActionListener(&errorListener); - mCurrentDialog = NULL; // OkDialog deletes itself + showErrorDialog(errorMessage, STATE_CHOOSE_SERVER); Net::getGameHandler()->disconnect(); break; @@ -993,12 +1019,32 @@ int Client::exec() return 0; } -void Client::optionChanged(const std::string &name) +void Client::showOkDialog(const std::string &title, + const std::string &message, + State state) { - const int fpsLimit = (int) config.getValue("fpslimit", 60); - mLimitFps = fpsLimit > 0; - if (mLimitFps) - SDL_setFramerate(&mFpsManager, fpsLimit); + OkDialog *okDialog = new OkDialog(title, message); + okDialog->addActionListener(this); + mStateAfterOkDialog = state; +} + +void Client::showErrorDialog(const std::string &message, State state) +{ + showOkDialog(_("Error"), message, state); +} + +void Client::event(Event::Channel channel, const Event &event) +{ + if (channel == Event::ConfigChannel && + event.getType() == Event::ConfigOptionChanged && + event.getString("option") == "fpslimit") + { + const int fpsLimit = config.getIntValue("fpslimit"); + mLimitFps = fpsLimit > 0; + if (mLimitFps) + SDL_setFramerate(&mFpsManager, fpsLimit); + } + } void Client::action(const gcn::ActionEvent &event) @@ -1014,6 +1060,10 @@ void Client::action(const gcn::ActionEvent &event) if (window->isVisible()) window->requestMoveToTop(); } + + // If this came from the OkDialog used by showOkDialog + if (event.getId() == "ok") + mState = mStateAfterOkDialog; } void Client::initRootDir() @@ -1082,6 +1132,9 @@ void Client::initHomeDir() mLocalDataDir = std::string(PHYSFS_getUserDir()) + "/Library/Application Support/" + branding.getValue("appName", "Mana"); +#elif defined __HAIKU__ + mLocalDataDir = std::string(PHYSFS_getUserDir()) + + "/config/data/Mana"; #elif defined WIN32 mLocalDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA); if (mLocalDataDir.empty()) @@ -1106,6 +1159,10 @@ void Client::initHomeDir() const std::string app = branding.getValue("appShort", "manasource"); #ifdef __APPLE__ mConfigDir = mLocalDataDir + "/" + app; +#elif defined __HAIKU__ + mConfigDir = std::string(PHYSFS_getUserDir()) + + "/config/settings/Mana" + + branding.getValue("appName", "manasource"); #elif defined WIN32 mConfigDir = getSpecialFolderLocation(CSIDL_APPDATA); if (mConfigDir.empty()) @@ -1200,6 +1257,7 @@ void Client::initConfiguration() { fclose(configFile); config.init(configPath); + config.setDefaultValues(getConfigDefaults()); } } @@ -1214,7 +1272,7 @@ void Client::initUpdatesDir() // If updatesHost is currently empty, fill it from config file if (mUpdateHost.empty()) { - mUpdateHost = config.getValue("updatehost", ""); + mUpdateHost = config.getStringValue("updatehost"); } // Don't go out of range int he next check @@ -1222,7 +1280,7 @@ void Client::initUpdatesDir() return; // Remove any trailing slash at the end of the update host - if (mUpdateHost.at(mUpdateHost.size() - 1) == '/') + if (!mUpdateHost.empty() && mUpdateHost.at(mUpdateHost.size() - 1) == '/') mUpdateHost.resize(mUpdateHost.size() - 1); // Parse out any "http://" or "ftp://", and set the updates directory @@ -1230,7 +1288,7 @@ void Client::initUpdatesDir() pos = mUpdateHost.find("://"); if (pos != mUpdateHost.npos) { - if (pos + 3 < mUpdateHost.length()) + if (pos + 3 < mUpdateHost.length() && !mUpdateHost.empty()) { updates << "updates/" << mUpdateHost.substr(pos + 3); mUpdatesDir = updates.str(); @@ -1301,7 +1359,7 @@ void Client::initScreenshotDir() mScreenshotDir = std::string(PHYSFS_getUserDir()) + "Desktop"; #endif - if (config.getValue("useScreenshotDirectorySuffix", true)) + if (config.getBoolValue("useScreenshotDirectorySuffix")) { std::string configScreenshotSuffix = config.getValue("screenshotDirectorySuffix", |