summaryrefslogtreecommitdiff
path: root/src/client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.cpp')
-rw-r--r--src/client.cpp239
1 files changed, 148 insertions, 91 deletions
diff --git a/src/client.cpp b/src/client.cpp
index abe3500c..437e1f06 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 */
@@ -166,29 +166,22 @@ int get_elapsed_time(int start_time)
* 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 +195,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 +210,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 == "")
+ 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 +348,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 +375,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)
{
@@ -405,25 +404,25 @@ Client::Client(const Options &options):
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 +434,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 +454,7 @@ Client::~Client()
// Unload XML databases
ColorDB::unload();
EmoteDB::unload();
- ItemDB::unload();
+ delete itemDb;
MonsterDB::unload();
NPCDB::unload();
StatusEffect::unload();
@@ -488,8 +495,6 @@ int Client::exec()
while (mState != STATE_EXIT)
{
- bool handledEvents = false;
-
if (game)
{
// Let the game handle the events while it is active
@@ -500,8 +505,6 @@ int Client::exec()
// Handle SDL events
while (SDL_PollEvent(&event))
{
- handledEvents = true;
-
switch (event.type)
{
case SDL_QUIT:
@@ -525,6 +528,8 @@ int Client::exec()
if (game)
game->logic();
+ sound.logic();
+
++lastTickTime;
}
@@ -577,10 +582,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);
}
@@ -592,9 +595,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)
{
@@ -751,17 +757,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;
@@ -787,7 +822,7 @@ int Client::exec()
mOptions.character, CharSelectDialog::Choose))
{
((CharSelectDialog*) mCurrentDialog)->selectByName(
- config.getValue("lastCharacter", ""),
+ config.getStringValue("lastCharacter"),
mOptions.chooseDefault ?
CharSelectDialog::Choose :
CharSelectDialog::Focus);
@@ -839,16 +874,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:
@@ -882,10 +913,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;
@@ -902,10 +932,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:
@@ -923,12 +952,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:
@@ -981,9 +1008,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;
@@ -997,12 +1022,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)
@@ -1018,6 +1063,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()
@@ -1086,6 +1135,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())
@@ -1110,6 +1162,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())
@@ -1204,6 +1260,7 @@ void Client::initConfiguration()
{
fclose(configFile);
config.init(configPath);
+ config.setDefaultValues(getConfigDefaults());
}
}
@@ -1218,7 +1275,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
@@ -1226,7 +1283,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
@@ -1234,7 +1291,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();
@@ -1305,7 +1362,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",