diff options
110 files changed, 917 insertions, 660 deletions
diff --git a/data/graphics/gui/CMakeLists.txt b/data/graphics/gui/CMakeLists.txt index 01b8674f..fc825139 100644 --- a/data/graphics/gui/CMakeLists.txt +++ b/data/graphics/gui/CMakeLists.txt @@ -9,7 +9,6 @@ SET (FILES circle-green.png close_button.png deepbox.png - gui.xml hscroll_left_default.png hscroll_left_highlight.png hscroll_left_pressed.png @@ -48,6 +47,7 @@ SET (FILES vscroll_up_highlight.png vscroll_up_pressed.png window.png + window.xml ) INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/gui) diff --git a/data/graphics/gui/Makefile.am b/data/graphics/gui/Makefile.am index ed48c012..68d11bf7 100644 --- a/data/graphics/gui/Makefile.am +++ b/data/graphics/gui/Makefile.am @@ -12,7 +12,6 @@ gui_DATA = \ circle-green.png \ close_button.png \ deepbox.png \ - gui.xml \ hscroll_left_default.png \ hscroll_left_highlight.png \ hscroll_left_pressed.png \ @@ -50,7 +49,8 @@ gui_DATA = \ vscroll_up_default.png \ vscroll_up_highlight.png \ vscroll_up_pressed.png \ - window.png + window.png \ + window.xml EXTRA_DIST = \ $(gui_DATA) diff --git a/data/graphics/gui/button.png b/data/graphics/gui/button.png Binary files differindex 4f6a5a81..9ebbea63 100644 --- a/data/graphics/gui/button.png +++ b/data/graphics/gui/button.png diff --git a/data/graphics/gui/button_disabled.png b/data/graphics/gui/button_disabled.png Binary files differindex 2a8fdf43..0ce3aa6f 100644 --- a/data/graphics/gui/button_disabled.png +++ b/data/graphics/gui/button_disabled.png diff --git a/data/graphics/gui/buttonhi.png b/data/graphics/gui/buttonhi.png Binary files differindex 24c09718..c4772634 100644 --- a/data/graphics/gui/buttonhi.png +++ b/data/graphics/gui/buttonhi.png diff --git a/data/graphics/gui/buttonpress.png b/data/graphics/gui/buttonpress.png Binary files differindex d192534a..e9cd1765 100644 --- a/data/graphics/gui/buttonpress.png +++ b/data/graphics/gui/buttonpress.png diff --git a/data/graphics/gui/checkbox.png b/data/graphics/gui/checkbox.png Binary files differindex b68893fc..29b64100 100644 --- a/data/graphics/gui/checkbox.png +++ b/data/graphics/gui/checkbox.png diff --git a/data/graphics/gui/close_button.png b/data/graphics/gui/close_button.png Binary files differindex a4f802e0..f87cc2a9 100644 --- a/data/graphics/gui/close_button.png +++ b/data/graphics/gui/close_button.png diff --git a/data/graphics/gui/deepbox.png b/data/graphics/gui/deepbox.png Binary files differindex 6b63168a..084b5f61 100644 --- a/data/graphics/gui/deepbox.png +++ b/data/graphics/gui/deepbox.png diff --git a/data/graphics/gui/gui.xml b/data/graphics/gui/gui.xml deleted file mode 100644 index 015c6ce3..00000000 --- a/data/graphics/gui/gui.xml +++ /dev/null @@ -1,19 +0,0 @@ -<skinset name="Default" image="window.png"> - <widget type="Window"> - <!-- <option name="padding" value="5" /> --> - <!-- Top Row --> - <part type="top-left-corner" xpos="0" ypos="0" width="10" height="10" /> - <part type="top-edge" xpos="11" ypos="0" width="127" height="10" /> - <part type="top-right-corner" xpos="139" ypos="0" width="12" height="10" /> - - <!-- Middle Row --> - <part type="left-edge" xpos="0" ypos="11" width="10" height="81" /> - <part type="bg-quad" xpos="11" ypos="11" width="127" height="81" /> - <part type="right-edge" xpos="139" ypos="11" width="12" height="81" /> - - <!-- Bottom Row --> - <part type="bottom-left-corner" xpos="0" ypos="93" width="10" height="12" /> - <part type="bottom-edge" xpos="11" ypos="93" width="127" height="12" /> - <part type="bottom-right-corner" xpos="139" ypos="93" width="12" height="12" /> - </widget> -</skinset> diff --git a/data/graphics/gui/hscroll_left_default.png b/data/graphics/gui/hscroll_left_default.png Binary files differindex 07e5e078..2f763d30 100644 --- a/data/graphics/gui/hscroll_left_default.png +++ b/data/graphics/gui/hscroll_left_default.png diff --git a/data/graphics/gui/hscroll_left_highlight.png b/data/graphics/gui/hscroll_left_highlight.png Binary files differindex c77427f8..6be5ae25 100644 --- a/data/graphics/gui/hscroll_left_highlight.png +++ b/data/graphics/gui/hscroll_left_highlight.png diff --git a/data/graphics/gui/hscroll_left_pressed.png b/data/graphics/gui/hscroll_left_pressed.png Binary files differindex 081eaa3a..b8ebcb46 100644 --- a/data/graphics/gui/hscroll_left_pressed.png +++ b/data/graphics/gui/hscroll_left_pressed.png diff --git a/data/graphics/gui/hscroll_right_default.png b/data/graphics/gui/hscroll_right_default.png Binary files differindex ee74c071..33fdddd0 100644 --- a/data/graphics/gui/hscroll_right_default.png +++ b/data/graphics/gui/hscroll_right_default.png diff --git a/data/graphics/gui/hscroll_right_highlight.png b/data/graphics/gui/hscroll_right_highlight.png Binary files differindex 9f8911e4..e9e633ea 100644 --- a/data/graphics/gui/hscroll_right_highlight.png +++ b/data/graphics/gui/hscroll_right_highlight.png diff --git a/data/graphics/gui/hscroll_right_pressed.png b/data/graphics/gui/hscroll_right_pressed.png Binary files differindex 6ef987a5..53972f2b 100644 --- a/data/graphics/gui/hscroll_right_pressed.png +++ b/data/graphics/gui/hscroll_right_pressed.png diff --git a/data/graphics/gui/item_shortcut_bgr.png b/data/graphics/gui/item_shortcut_bgr.png Binary files differindex 5b3c5e7c..0543e38a 100644 --- a/data/graphics/gui/item_shortcut_bgr.png +++ b/data/graphics/gui/item_shortcut_bgr.png diff --git a/data/graphics/gui/mouse.png b/data/graphics/gui/mouse.png Binary files differindex 84dc2ad1..df460e49 100644 --- a/data/graphics/gui/mouse.png +++ b/data/graphics/gui/mouse.png diff --git a/data/graphics/gui/radioin.png b/data/graphics/gui/radioin.png Binary files differindex 8d0e5f74..12e027fe 100644 --- a/data/graphics/gui/radioin.png +++ b/data/graphics/gui/radioin.png diff --git a/data/graphics/gui/radioin_highlight.png b/data/graphics/gui/radioin_highlight.png Binary files differindex c020f0ba..b193d3e3 100644 --- a/data/graphics/gui/radioin_highlight.png +++ b/data/graphics/gui/radioin_highlight.png diff --git a/data/graphics/gui/radioout.png b/data/graphics/gui/radioout.png Binary files differindex 70a25256..5eb67bd8 100644 --- a/data/graphics/gui/radioout.png +++ b/data/graphics/gui/radioout.png diff --git a/data/graphics/gui/radioout_highlight.png b/data/graphics/gui/radioout_highlight.png Binary files differindex 957a1fa6..dd31e6e3 100644 --- a/data/graphics/gui/radioout_highlight.png +++ b/data/graphics/gui/radioout_highlight.png diff --git a/data/graphics/gui/resize.png b/data/graphics/gui/resize.png Binary files differindex dfe79ebf..6b31ac64 100644 --- a/data/graphics/gui/resize.png +++ b/data/graphics/gui/resize.png diff --git a/data/graphics/gui/selection.png b/data/graphics/gui/selection.png Binary files differindex a117a78a..78827daf 100644 --- a/data/graphics/gui/selection.png +++ b/data/graphics/gui/selection.png diff --git a/data/graphics/gui/slider.png b/data/graphics/gui/slider.png Binary files differindex df9abe56..465ad0e8 100644 --- a/data/graphics/gui/slider.png +++ b/data/graphics/gui/slider.png diff --git a/data/graphics/gui/slider_hilight.png b/data/graphics/gui/slider_hilight.png Binary files differindex 8b7d2be6..37c780cd 100644 --- a/data/graphics/gui/slider_hilight.png +++ b/data/graphics/gui/slider_hilight.png diff --git a/data/graphics/gui/speech_bubble.png b/data/graphics/gui/speech_bubble.png Binary files differdeleted file mode 100644 index 3e678099..00000000 --- a/data/graphics/gui/speech_bubble.png +++ /dev/null diff --git a/data/graphics/gui/sticky_button.png b/data/graphics/gui/sticky_button.png Binary files differindex 2708dd99..8c570573 100644 --- a/data/graphics/gui/sticky_button.png +++ b/data/graphics/gui/sticky_button.png diff --git a/data/graphics/gui/tab.png b/data/graphics/gui/tab.png Binary files differindex 689981a9..91eadf08 100644 --- a/data/graphics/gui/tab.png +++ b/data/graphics/gui/tab.png diff --git a/data/graphics/gui/tab_hilight.png b/data/graphics/gui/tab_hilight.png Binary files differindex d0585e8f..f6b39942 100644 --- a/data/graphics/gui/tab_hilight.png +++ b/data/graphics/gui/tab_hilight.png diff --git a/data/graphics/gui/tabselected.png b/data/graphics/gui/tabselected.png Binary files differindex 72a48973..e2983060 100644 --- a/data/graphics/gui/tabselected.png +++ b/data/graphics/gui/tabselected.png diff --git a/data/graphics/gui/vscroll_down_default.png b/data/graphics/gui/vscroll_down_default.png Binary files differindex 0ec2a3ee..c4292489 100644 --- a/data/graphics/gui/vscroll_down_default.png +++ b/data/graphics/gui/vscroll_down_default.png diff --git a/data/graphics/gui/vscroll_down_highlight.png b/data/graphics/gui/vscroll_down_highlight.png Binary files differindex d2934daa..ac88f7c7 100644 --- a/data/graphics/gui/vscroll_down_highlight.png +++ b/data/graphics/gui/vscroll_down_highlight.png diff --git a/data/graphics/gui/vscroll_down_pressed.png b/data/graphics/gui/vscroll_down_pressed.png Binary files differindex 6aa44ba6..9dcc89f6 100644 --- a/data/graphics/gui/vscroll_down_pressed.png +++ b/data/graphics/gui/vscroll_down_pressed.png diff --git a/data/graphics/gui/vscroll_grey.png b/data/graphics/gui/vscroll_grey.png Binary files differindex 3f65a883..f99da467 100644 --- a/data/graphics/gui/vscroll_grey.png +++ b/data/graphics/gui/vscroll_grey.png diff --git a/data/graphics/gui/vscroll_highlight.png b/data/graphics/gui/vscroll_highlight.png Binary files differindex 9802044c..2e0fcbfc 100644 --- a/data/graphics/gui/vscroll_highlight.png +++ b/data/graphics/gui/vscroll_highlight.png diff --git a/data/graphics/gui/vscroll_up_default.png b/data/graphics/gui/vscroll_up_default.png Binary files differindex 73a4266f..1cecc351 100644 --- a/data/graphics/gui/vscroll_up_default.png +++ b/data/graphics/gui/vscroll_up_default.png diff --git a/data/graphics/gui/vscroll_up_highlight.png b/data/graphics/gui/vscroll_up_highlight.png Binary files differindex 6fc3884d..7b5009f3 100644 --- a/data/graphics/gui/vscroll_up_highlight.png +++ b/data/graphics/gui/vscroll_up_highlight.png diff --git a/data/graphics/gui/vscroll_up_pressed.png b/data/graphics/gui/vscroll_up_pressed.png Binary files differindex bfa8e175..2320ec42 100644 --- a/data/graphics/gui/vscroll_up_pressed.png +++ b/data/graphics/gui/vscroll_up_pressed.png diff --git a/data/graphics/gui/window.png b/data/graphics/gui/window.png Binary files differindex 671b7740..f0ef1af4 100644 --- a/data/graphics/gui/window.png +++ b/data/graphics/gui/window.png diff --git a/data/graphics/gui/window.xml b/data/graphics/gui/window.xml new file mode 100644 index 00000000..f27dbc7f --- /dev/null +++ b/data/graphics/gui/window.xml @@ -0,0 +1,18 @@ +<skinset name="Default" image="window.png"> + <widget type="Window"> + <!-- Top Row --> + <part type="top-left-corner" xpos="0" ypos="0" width="4" height="4" /> + <part type="top-edge" xpos="4" ypos="0" width="32" height="4" /> + <part type="top-right-corner" xpos="36" ypos="0" width="4" height="4" /> + + <!-- Middle Row --> + <part type="left-edge" xpos="0" ypos="4" width="4" height="216" /> + <part type="bg-quad" xpos="4" ypos="4" width="32" height="216" /> + <part type="right-edge" xpos="36" ypos="4" width="4" height="216" /> + + <!-- Bottom Row --> + <part type="bottom-left-corner" xpos="0" ypos="220" width="4" height="4" /> + <part type="bottom-edge" xpos="4" ypos="220" width="32" height="4" /> + <part type="bottom-right-corner" xpos="36" ypos="220" width="4" height="4" /> + </widget> +</skinset> diff --git a/docs/example.mana b/docs/example.mana index 795d8d40..9802c280 100644 --- a/docs/example.mana +++ b/docs/example.mana @@ -13,9 +13,11 @@ filename / path as a command line parameter <option name="appShort" value="mana"/> <option name="appIcon" value="icons/mana.png"/> <option name="loginMusic" value="Magick - Real.ogg"/> + <option name="onlineServerList" value="http://manasource.org/serverlist.xml"/> <option name="defaultServer" value="testing.manasource.org"/> <option name="defaultPort" value="9601"/> <option name="defaultUpdateHost" value="http://updates.themanaworld.org"/> <option name="font" value="fonts/dejavusans.ttf" /> <option name="boldFont" value="fonts/dejavusans-bold.ttf" /> + <option name="theme" value="wood" /> </configuration> @@ -1,6 +1,5 @@ ./CMakeLists.txt ./config.h -./data/branding.xml ./data/CMakeLists.txt ./data/fonts/CMakeLists.txt ./data/fonts/Makefile.am @@ -27,6 +26,7 @@ ./data/icons/Makefile.am ./data/Makefile.am ./docs/clientupdates.txt +./docs/example.mana ./docs/FAQ.txt ./docs/HACKING.txt ./docs/items.txt @@ -51,6 +51,8 @@ ./src/channel.h ./src/channelmanager.cpp ./src/channelmanager.h +./src/client.cpp +./src/client.h ./src/CMakeLists.txt ./src/commandhandler.cpp ./src/commandhandler.h @@ -101,8 +103,6 @@ ./src/gui/focushandler.h ./src/gui/gui.cpp ./src/gui/gui.h -./src/gui/guildwindow.cpp -./src/gui/guildwindow.h ./src/gui/help.cpp ./src/gui/help.h ./src/gui/inventorywindow.cpp @@ -207,8 +207,6 @@ ./src/gui/widgets/emoteshortcutcontainer.h ./src/gui/widgets/flowcontainer.cpp ./src/gui/widgets/flowcontainer.h -./src/gui/widgets/guildlistbox.cpp -./src/gui/widgets/guildlistbox.h ./src/gui/widgets/icon.cpp ./src/gui/widgets/icon.h ./src/gui/widgets/inttextfield.cpp @@ -284,8 +282,6 @@ ./src/imageparticle.h ./src/inventory.cpp ./src/inventory.h -./src/client.cpp -./src/client.h ./src/item.cpp ./src/item.h ./src/itemshortcut.cpp @@ -325,10 +321,10 @@ ./src/net/ea/gamehandler.h ./src/net/ea/generalhandler.cpp ./src/net/ea/generalhandler.h -./src/net/ea/guildhandler.cpp -./src/net/ea/guildhandler.h ./src/net/ea/gui/guildtab.cpp ./src/net/ea/gui/guildtab.h +./src/net/ea/guildhandler.cpp +./src/net/ea/guildhandler.h ./src/net/ea/gui/partytab.cpp ./src/net/ea/gui/partytab.h ./src/net/ea/inventoryhandler.cpp @@ -524,6 +520,8 @@ ./src/utils/mutex.h ./src/utils/sha256.cpp ./src/utils/sha256.h +./src/utils/specialfolder.cpp +./src/utils/specialfolder.h ./src/utils/stringutils.cpp ./src/utils/stringutils.h ./src/utils/xml.cpp diff --git a/src/being.h b/src/being.h index ff21825c..f1d98ba4 100644 --- a/src/being.h +++ b/src/being.h @@ -234,7 +234,7 @@ class Being : public Sprite, public ConfigListener */ virtual void setName(const std::string &name); - const bool getShowName() const + bool getShowName() const { return mShowName; } virtual void setShowName(bool doShowName); diff --git a/src/client.cpp b/src/client.cpp index cd40615b..dfa42034 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -192,13 +192,14 @@ public: 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), + mOptions(options), + mCurrentDialog(0), + mQuitDialog(0), + mDesktop(0), + mSetupButton(0), + mState(STATE_CHOOSE_SERVER), + mOldState(STATE_START), + mIcon(0), mLogicCounterId(0), mSecondsCounterId(0), mLimitFps(false) @@ -214,18 +215,17 @@ Client::Client(const Options &options): branding.init(options.brandingPath); } - initHomeDir(options); + initHomeDir(); + initConfiguration(); // Configure logger - logger->setLogFile(localDataDir + std::string("/mana.log")); + logger->setLogFile(mLocalDataDir + std::string("/mana.log")); + logger->setLogToStandardOut(config.getValue("logToStandardOut", 0)); // Log the mana version logger->log("Mana %s", FULL_VERSION); - initConfiguration(options); - initScreenshotDir(options.screenshotDir); - - logger->setLogToStandardOut(config.getValue("logToStandardOut", 0)); + initScreenshotDir(); // Initialize SDL logger->log("Initializing SDL..."); @@ -243,19 +243,12 @@ Client::Client(const Options &options): ResourceManager *resman = ResourceManager::getInstance(); - if (!resman->setWriteDir(localDataDir)) + if (!resman->setWriteDir(mLocalDataDir)) { logger->error(strprintf("%s couldn't be set as home directory! " - "Exiting.", localDataDir.c_str())); + "Exiting.", mLocalDataDir.c_str())); } - // Add the local data directory to PhysicsFS search path - resman->addToSearchPath(localDataDir, 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); @@ -267,10 +260,38 @@ Client::Client(const Options &options): } CFRelease(resourcesURL); strncat(path, "/data", PATH_MAX - 1); - resman->addToSearchPath(path, true); + resman->addToSearchPath(path, false); + mPackageDir = path; +#else + resman->addToSearchPath(PKG_DATADIR "data", false); + mPackageDir = PKG_DATADIR "data"; +#endif + + resman->addToSearchPath("data", false); + + // Add branding/data to PhysFS search path + if (!options.brandingPath.empty()) + { + std::string path = options.brandingPath; + + // Strip blah.mana from the path +#ifdef WIN32 + int loc1 = path.find_last_of('/'); + int loc2 = path.find_last_of('\\'); + int loc = std::max(loc1, loc2); #else - resman->addToSearchPath(PKG_DATADIR "data", true); + int loc = path.find_last_of('/'); #endif + if (loc > 0) + resman->addToSearchPath(path.substr(0, loc + 1) + "data", false); + } + + // Add the main data directories to our PhysicsFS search path + if (!options.dataPath.empty()) + resman->addToSearchPath(options.dataPath, false); + + // Add the local data directory to PhysicsFS search path + resman->addToSearchPath(mLocalDataDir, false); #ifdef WIN32 static SDL_SysWMinfo pInfo; @@ -281,17 +302,17 @@ Client::Client(const Options &options): SetClassLong(pInfo.window, GCL_HICON, (LONG) icon); } #else - icon = IMG_Load(resman->getPath( + mIcon = IMG_Load(resman->getPath( branding.getValue("appIcon", "data/icons/mana.png")).c_str()); - if (icon) + if (mIcon) { - SDL_SetAlpha(icon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); - SDL_WM_SetIcon(icon, NULL); + SDL_SetAlpha(mIcon, SDL_SRCALPHA, SDL_ALPHA_OPAQUE); + SDL_WM_SetIcon(mIcon, NULL); } #endif #ifdef USE_OPENGL - bool useOpenGL = !options.noOpenGL && (config.getValue("opengl", 0) == 1); + bool useOpenGL = !mOptions.noOpenGL && (config.getValue("opengl", 0) == 1); // Setup image loading for the right image format Image::setLoadAsOpenGL(useOpenGL); @@ -319,10 +340,10 @@ Client::Client(const Options &options): // Initialize for drawing graphics->_beginDraw(); - // Initialize the item shortcuts. - itemShortcut = new ItemShortcut; + SkinLoader::prepareThemePath(); - // Initialize the emote shortcuts. + // Initialize the item and emote shortcuts. + itemShortcut = new ItemShortcut; emoteShortcut = new EmoteShortcut; gui = new Gui(graphics); @@ -340,7 +361,7 @@ Client::Client(const Options &options): } catch (const char *err) { - state = STATE_ERROR; + mState = STATE_ERROR; errorMessage = err; logger->log("Warning: %s", err); } @@ -357,28 +378,28 @@ Client::Client(const Options &options): sound.playMusic(branding.getValue("loginMusic", "Magick - Real.ogg")); // Initialize default server - currentServer.hostname = options.serverName; - currentServer.port = options.serverPort; + mCurrentServer.hostname = options.serverName; + mCurrentServer.port = options.serverPort; loginData.username = options.username; loginData.password = options.password; loginData.remember = config.getValue("remember", 0); loginData.registerLogin = false; - if (currentServer.hostname.empty()) + if (mCurrentServer.hostname.empty()) { - currentServer.hostname = branding.getValue("defaultServer", + mCurrentServer.hostname = branding.getValue("defaultServer", "server.themanaworld.org").c_str(); } if (options.serverPort == 0) { - currentServer.port = (short) branding.getValue("defaultPort", + mCurrentServer.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; + if (mState != STATE_ERROR) + mState = STATE_CHOOSE_SERVER; // Initialize logic and seconds counters tick_time = 0; @@ -400,8 +421,6 @@ Client::~Client() delete itemShortcut; delete emoteShortcut; - config.write(); - delete gui; delete graphics; @@ -421,10 +440,13 @@ Client::~Client() ResourceManager::deleteInstance(); - SDL_FreeSurface(icon); + SDL_FreeSurface(mIcon); logger->log("Quitting"); delete guiPalette; + + config.write(); + delete logger; mInstance = 0; @@ -437,7 +459,7 @@ int Client::exec() Game *game = 0; SDL_Event event; - while (state != STATE_EXIT) + while (mState != STATE_EXIT) { bool handledEvents = false; @@ -456,7 +478,7 @@ int Client::exec() switch (event.type) { case SDL_QUIT: - state = STATE_EXIT; + mState = STATE_EXIT; break; case SDL_KEYDOWN: @@ -499,75 +521,75 @@ int Client::exec() // TODO: Add connect timeouts - if (state == STATE_CONNECT_GAME && + if (mState == STATE_CONNECT_GAME && Net::getGameHandler()->isConnected()) { Net::getLoginHandler()->disconnect(); } - else if (state == STATE_CONNECT_SERVER && oldstate == STATE_CHOOSE_SERVER) + else if (mState == STATE_CONNECT_SERVER && mOldState == STATE_CHOOSE_SERVER) { - Net::connectToServer(currentServer); + Net::connectToServer(mCurrentServer); } - else if (state == STATE_CONNECT_SERVER && - oldstate != STATE_CHOOSE_SERVER && + else if (mState == STATE_CONNECT_SERVER && + mOldState != STATE_CHOOSE_SERVER && Net::getLoginHandler()->isConnected()) { - state = STATE_LOGIN; + mState = STATE_LOGIN; } - else if (state == STATE_WORLD_SELECT && oldstate == STATE_UPDATE) + else if (mState == STATE_WORLD_SELECT && mOldState == STATE_UPDATE) { if (Net::getLoginHandler()->getWorlds().size() < 2) { - state = STATE_LOGIN; + mState = STATE_LOGIN; } } - else if (oldstate == STATE_START || - (oldstate == STATE_GAME && state != STATE_GAME)) + else if (mOldState == STATE_START || + (mOldState == STATE_GAME && mState != 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() + mDesktop = new Desktop; + top->add(mDesktop); + mSetupButton = new Button(_("Setup"), "Setup", this); + mSetupButton->setPosition(top->getWidth() - mSetupButton->getWidth() - 3, 3); - top->add(setupButton); + top->add(mSetupButton); int screenWidth = (int) config.getValue("screenwidth", defaultScreenWidth); int screenHeight = (int) config.getValue("screenheight", defaultScreenHeight); - desktop->setSize(screenWidth, screenHeight); + mDesktop->setSize(screenWidth, screenHeight); } - if (state == STATE_SWITCH_LOGIN && oldstate == STATE_GAME) + if (mState == STATE_SWITCH_LOGIN && mOldState == STATE_GAME) { Net::getGameHandler()->disconnect(); } - if (state != oldstate) + if (mState != mOldState) { - if (oldstate == STATE_GAME) + if (mOldState == STATE_GAME) { delete game; game = 0; } - oldstate = state; + mOldState = mState; // Get rid of the dialog of the previous state - if (currentDialog) + if (mCurrentDialog) { - delete currentDialog; - currentDialog = NULL; + delete mCurrentDialog; + mCurrentDialog = NULL; } // State has changed, while the quitDialog was active, it might // not be correct anymore - if (quitDialog) - quitDialog->scheduleDelete(); + if (mQuitDialog) + mQuitDialog->scheduleDelete(); - switch (state) + switch (mState) { case STATE_CHOOSE_SERVER: logger->log("State: CHOOSE SERVER"); @@ -575,29 +597,29 @@ int Client::exec() // 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) + if (mOptions.serverName.empty() && mOptions.serverPort == 0) { // Don't allow an alpha opacity // lower than the default value SkinLoader::instance()->setMinimumOpacity(0.8f); - currentDialog = new ServerDialog(¤tServer, - configDir); + mCurrentDialog = new ServerDialog(&mCurrentServer, + mConfigDir); } else { - state = STATE_CONNECT_SERVER; + mState = STATE_CONNECT_SERVER; // Reset options so that cancelling or connect // timeout will show the server dialog. - options.serverName.clear(); - options.serverPort = 0; + mOptions.serverName.clear(); + mOptions.serverPort = 0; } break; case STATE_CONNECT_SERVER: logger->log("State: CONNECT SERVER"); - currentDialog = new ConnectionDialog( + mCurrentDialog = new ConnectionDialog( _("Connecting to server"), STATE_SWITCH_SERVER); break; @@ -607,24 +629,24 @@ int Client::exec() // lower than the default value SkinLoader::instance()->setMinimumOpacity(0.8f); - if (options.username.empty() - || options.password.empty()) + if (mOptions.username.empty() + || mOptions.password.empty()) { - currentDialog = new LoginDialog(&loginData); + mCurrentDialog = new LoginDialog(&loginData); } else { - state = STATE_LOGIN_ATTEMPT; + mState = STATE_LOGIN_ATTEMPT; // Clear the password so that when login fails, the // dialog will show up next time. - options.password.clear(); + mOptions.password.clear(); } break; case STATE_LOGIN_ATTEMPT: logger->log("State: LOGIN ATTEMPT"); accountLogin(&loginData); - currentDialog = new ConnectionDialog( + mCurrentDialog = new ConnectionDialog( _("Logging in"), STATE_SWITCH_SERVER); break; @@ -636,19 +658,19 @@ int Client::exec() if (worlds.size() == 0) { // Trust that the netcode knows what it's doing - state = STATE_UPDATE; + mState = STATE_UPDATE; } else if (worlds.size() == 1) { Net::getLoginHandler()->chooseServer(0); - state = STATE_UPDATE; + mState = STATE_UPDATE; } else { - currentDialog = new WorldSelectDialog(worlds); - if (options.chooseDefault) + mCurrentDialog = new WorldSelectDialog(worlds); + if (mOptions.chooseDefault) { - ((WorldSelectDialog*) currentDialog)->action( + ((WorldSelectDialog*) mCurrentDialog)->action( gcn::ActionEvent(NULL, "ok")); } } @@ -657,27 +679,27 @@ int Client::exec() case STATE_WORLD_SELECT_ATTEMPT: logger->log("State: WORLD SELECT ATTEMPT"); - currentDialog = new ConnectionDialog( + mCurrentDialog = 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; + if (!mOptions.updateHost.empty()) + mUpdateHost = mOptions.updateHost; else - updateHost = loginData.updateHost; + mUpdateHost = loginData.updateHost; initUpdatesDir(); - if (options.skipUpdate) + if (mOptions.skipUpdate) { - state = STATE_LOAD_DATA; + mState = STATE_LOAD_DATA; } else { logger->log("State: UPDATE"); - currentDialog = new UpdaterWindow(updateHost, - localDataDir + "/" + updatesDir,options.dataPath.empty()); + mCurrentDialog = new UpdaterWindow(mUpdateHost, + mLocalDataDir + "/" + mUpdatesDir,mOptions.dataPath.empty()); } break; @@ -686,7 +708,7 @@ int Client::exec() // If another data path has been set, // we don't load any other files... - if (options.dataPath.empty()) + if (mOptions.dataPath.empty()) { // Add customdata directory ResourceManager::getInstance()->searchAndAddArchives( @@ -705,15 +727,15 @@ int Client::exec() StatusEffect::load(); Units::loadUnits(); - desktop->reloadWallpaper(); + mDesktop->reloadWallpaper(); - state = STATE_GET_CHARACTERS; + mState = STATE_GET_CHARACTERS; break; case STATE_GET_CHARACTERS: logger->log("State: GET CHARACTERS"); Net::getCharHandler()->requestCharacters(); - currentDialog = new ConnectionDialog( + mCurrentDialog = new ConnectionDialog( _("Requesting characters"), STATE_SWITCH_SERVER); break; @@ -724,14 +746,14 @@ int Client::exec() // lower than the default value SkinLoader::instance()->setMinimumOpacity(0.8f); - currentDialog = new CharSelectDialog(&loginData); + mCurrentDialog = new CharSelectDialog(&loginData); - if (!((CharSelectDialog*) currentDialog)->selectByName( - options.character, CharSelectDialog::Choose)) + if (!((CharSelectDialog*) mCurrentDialog)->selectByName( + mOptions.character, CharSelectDialog::Choose)) { - ((CharSelectDialog*) currentDialog)->selectByName( + ((CharSelectDialog*) mCurrentDialog)->selectByName( config.getValue("lastCharacter", ""), - options.chooseDefault ? + mOptions.chooseDefault ? CharSelectDialog::Choose : CharSelectDialog::Focus); } @@ -742,7 +764,7 @@ int Client::exec() logger->log("State: CONNECT GAME"); Net::getGameHandler()->connect(); - currentDialog = new ConnectionDialog( + mCurrentDialog = new ConnectionDialog( _("Connecting to the game server"), STATE_SWITCH_CHARACTER); break; @@ -761,12 +783,12 @@ int Client::exec() // Allow any alpha opacity SkinLoader::instance()->setMinimumOpacity(-1.0f); - delete setupButton; - delete desktop; - setupButton = NULL; - desktop = NULL; + delete mSetupButton; + delete mDesktop; + mSetupButton = NULL; + mDesktop = NULL; - currentDialog = NULL; + mCurrentDialog = NULL; logger->log("State: GAME"); game = new Game; @@ -774,28 +796,28 @@ int Client::exec() case STATE_LOGIN_ERROR: logger->log("State: LOGIN ERROR"); - currentDialog = new OkDialog(_("Error"), errorMessage); - currentDialog->addActionListener(&loginListener); - currentDialog = NULL; // OkDialog deletes itself + mCurrentDialog = new OkDialog(_("Error"), errorMessage); + mCurrentDialog->addActionListener(&loginListener); + mCurrentDialog = 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 + mCurrentDialog = new OkDialog(_("Error"), errorMessage); + mCurrentDialog->addActionListener(&accountListener); + mCurrentDialog = NULL; // OkDialog deletes itself break; case STATE_REGISTER_PREP: logger->log("State: REGISTER_PREP"); Net::getLoginHandler()->getRegistrationDetails(); - currentDialog = new ConnectionDialog( + mCurrentDialog = new ConnectionDialog( _("Requesting registration details"), STATE_LOGIN); break; case STATE_REGISTER: logger->log("State: REGISTER"); - currentDialog = new RegisterDialog(&loginData); + mCurrentDialog = new RegisterDialog(&loginData); break; case STATE_REGISTER_ATTEMPT: @@ -805,7 +827,7 @@ int Client::exec() case STATE_CHANGEPASSWORD: logger->log("State: CHANGE PASSWORD"); - currentDialog = new ChangePasswordDialog(&loginData); + mCurrentDialog = new ChangePasswordDialog(&loginData); break; case STATE_CHANGEPASSWORD_ATTEMPT: @@ -817,17 +839,17 @@ int Client::exec() case STATE_CHANGEPASSWORD_SUCCESS: logger->log("State: CHANGE PASSWORD SUCCESS"); - currentDialog = new OkDialog(_("Password Change"), + mCurrentDialog = new OkDialog(_("Password Change"), _("Password changed successfully!")); - currentDialog->addActionListener(&accountListener); - currentDialog = NULL; // OkDialog deletes itself + mCurrentDialog->addActionListener(&accountListener); + mCurrentDialog = NULL; // OkDialog deletes itself loginData.password = loginData.newPassword; loginData.newPassword = ""; break; case STATE_CHANGEEMAIL: logger->log("State: CHANGE EMAIL"); - currentDialog = new ChangeEmailDialog(&loginData); + mCurrentDialog = new ChangeEmailDialog(&loginData); break; case STATE_CHANGEEMAIL_ATTEMPT: @@ -837,15 +859,15 @@ int Client::exec() case STATE_CHANGEEMAIL_SUCCESS: logger->log("State: CHANGE EMAIL SUCCESS"); - currentDialog = new OkDialog(_("Email Change"), + mCurrentDialog = new OkDialog(_("Email Change"), _("Email changed successfully!")); - currentDialog->addActionListener(&accountListener); - currentDialog = NULL; // OkDialog deletes itself + mCurrentDialog->addActionListener(&accountListener); + mCurrentDialog = NULL; // OkDialog deletes itself break; case STATE_UNREGISTER: logger->log("State: UNREGISTER"); - currentDialog = new UnRegisterDialog(&loginData); + mCurrentDialog = new UnRegisterDialog(&loginData); break; case STATE_UNREGISTER_ATTEMPT: @@ -858,12 +880,12 @@ int Client::exec() logger->log("State: UNREGISTER SUCCESS"); Net::getLoginHandler()->disconnect(); - currentDialog = new OkDialog(_("Unregister Successful"), + mCurrentDialog = 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 + mCurrentDialog->addActionListener(&errorListener); + mCurrentDialog = NULL; // OkDialog deletes itself break; case STATE_SWITCH_SERVER: @@ -872,7 +894,7 @@ int Client::exec() Net::getLoginHandler()->disconnect(); Net::getGameHandler()->disconnect(); - state = STATE_CHOOSE_SERVER; + mState = STATE_CHOOSE_SERVER; break; case STATE_SWITCH_LOGIN: @@ -880,7 +902,7 @@ int Client::exec() Net::getLoginHandler()->logout(); - state = STATE_LOGIN; + mState = STATE_LOGIN; break; case STATE_SWITCH_CHARACTER: @@ -910,19 +932,19 @@ int Client::exec() logger->log("State: FORCE QUIT"); if (Net::getGeneralHandler()) Net::getGeneralHandler()->unload(); - state = STATE_EXIT; + mState = STATE_EXIT; break; case STATE_ERROR: logger->log("State: ERROR"); - currentDialog = new OkDialog(_("Error"), errorMessage); - currentDialog->addActionListener(&errorListener); - currentDialog = NULL; // OkDialog deletes itself + mCurrentDialog = new OkDialog(_("Error"), errorMessage); + mCurrentDialog->addActionListener(&errorListener); + mCurrentDialog = NULL; // OkDialog deletes itself Net::getGameHandler()->disconnect(); break; default: - state = STATE_FORCE_QUIT; + mState = STATE_FORCE_QUIT; break; } } @@ -958,69 +980,64 @@ void Client::action(const gcn::ActionEvent &event) * 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) +void Client::initHomeDir() { - localDataDir = options.localDataDir; + mLocalDataDir = mOptions.localDataDir; - if (localDataDir.empty()) + if (mLocalDataDir.empty()) { #ifdef __APPLE__ // Use Application Directory instead of .mana - localDataDir = std::string(PHYSFS_getUserDir()) + + mLocalDataDir = std::string(PHYSFS_getUserDir()) + "/Library/Application Support/" + branding.getValue("appName", "Mana"); #elif defined WIN32 - localDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA); - if (localDataDir.empty()) - localDataDir = std::string(PHYSFS_getUserDir()); - localDataDir += "/Mana"; + mLocalDataDir = getSpecialFolderLocation(CSIDL_LOCAL_APPDATA); + if (mLocalDataDir.empty()) + mLocalDataDir = std::string(PHYSFS_getUserDir()); + mLocalDataDir += "/Mana"; #else - localDataDir = std::string(PHYSFS_getUserDir()) + + mLocalDataDir = std::string(PHYSFS_getUserDir()) + "/.local/share/mana"; #endif } - if (mkdir_r(localDataDir.c_str())) + if (mkdir_r(mLocalDataDir.c_str())) { logger->error(strprintf(_("%s doesn't exist and can't be created! " - "Exiting."), localDataDir.c_str())); + "Exiting."), mLocalDataDir.c_str())); } - configDir = options.configDir; + mConfigDir = mOptions.configDir; - if (configDir.empty()){ + if (mConfigDir.empty()){ #ifdef __APPLE__ - configDir = localDataDir; + mConfigDir = mLocalDataDir; #elif defined WIN32 - configDir = getSpecialFolderLocation(CSIDL_APPDATA); - if (configDir.empty()) - configDir = localDataDir; + mConfigDir = getSpecialFolderLocation(CSIDL_APPDATA); + if (mConfigDir.empty()) + mConfigDir = mLocalDataDir; else - configDir += "/mana/" + branding.getValue("appName", "Mana"); + mConfigDir += "/mana/" + branding.getValue("appName", "Mana"); #else - configDir = std::string(PHYSFS_getUserDir()) + + mConfigDir = std::string(PHYSFS_getUserDir()) + "/.config/mana/" + branding.getValue("appShort", "mana"); #endif } - if (mkdir_r(configDir.c_str())) + if (mkdir_r(mConfigDir.c_str())) { logger->error(strprintf(_("%s doesn't exist and can't be created! " - "Exiting."), configDir.c_str())); + "Exiting."), mConfigDir.c_str())); } } /** * Initialize configuration. */ -void Client::initConfiguration(const Options &options) +void Client::initConfiguration() { // 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); @@ -1046,17 +1063,17 @@ void Client::initConfiguration(const Options &options) FILE *configFile = 0; std::string configPath; - configPath = configDir + "/config.xml"; + configPath = mConfigDir + "/config.xml"; configFile = fopen(configPath.c_str(), "r"); // If we can't read it, it doesn't exist ! - if (configFile == NULL) + if (!configFile) { // We reopen the file in write mode and we create it configFile = fopen(configPath.c_str(), "wt"); } - if (configFile == NULL) + if (!configFile) { logger->log("Can't create %s. Using defaults.", configPath.c_str()); } @@ -1076,50 +1093,50 @@ void Client::initUpdatesDir() std::stringstream updates; // If updatesHost is currently empty, fill it from config file - if (updateHost.empty()) + if (mUpdateHost.empty()) { - updateHost = + mUpdateHost = 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); + if (mUpdateHost.at(mUpdateHost.size() - 1) == '/') + mUpdateHost.resize(mUpdateHost.size() - 1); // Parse out any "http://" or "ftp://", and set the updates directory size_t pos; - pos = updateHost.find("://"); - if (pos != updateHost.npos) + pos = mUpdateHost.find("://"); + if (pos != mUpdateHost.npos) { - if (pos + 3 < updateHost.length()) + if (pos + 3 < mUpdateHost.length()) { - updates << "updates/" << updateHost.substr(pos + 3); - updatesDir = updates.str(); + updates << "updates/" << mUpdateHost.substr(pos + 3); + mUpdatesDir = updates.str(); } else { - logger->log("Error: Invalid update host: %s", updateHost.c_str()); + logger->log("Error: Invalid update host: %s", mUpdateHost.c_str()); errorMessage = strprintf(_("Invalid update host: %s"), - updateHost.c_str()); - state = STATE_ERROR; + mUpdateHost.c_str()); + mState = STATE_ERROR; } } else { logger->log("Warning: no protocol was specified for the update host"); - updates << "updates/" << updateHost; - updatesDir = updates.str(); + updates << "updates/" << mUpdateHost; + mUpdatesDir = updates.str(); } ResourceManager *resman = ResourceManager::getInstance(); // Verify that the updates directory exists. Create if necessary. - if (!resman->isDirectory("/" + updatesDir)) + if (!resman->isDirectory("/" + mUpdatesDir)) { - if (!resman->mkdir("/" + updatesDir)) + if (!resman->mkdir("/" + mUpdatesDir)) { #if defined WIN32 - std::string newDir = localDataDir + "\\" + updatesDir; + std::string newDir = mLocalDataDir + "\\" + mUpdatesDir; std::string::size_type loc = newDir.find("/", 0); while (loc != std::string::npos) @@ -1134,43 +1151,39 @@ void Client::initUpdatesDir() logger->log("Error: %s can't be made, but doesn't exist!", newDir.c_str()); errorMessage = _("Error creating updates directory!"); - state = STATE_ERROR; + mState = STATE_ERROR; } #else logger->log("Error: %s/%s can't be made, but doesn't exist!", - localDataDir.c_str(), updatesDir.c_str()); + mLocalDataDir.c_str(), mUpdatesDir.c_str()); errorMessage = _("Error creating updates directory!"); - state = STATE_ERROR; + mState = STATE_ERROR; #endif } } } -void Client::initScreenshotDir(const std::string &dir) +void Client::initScreenshotDir() { - if (!dir.empty()) - screenshotDir = dir; + if (!mOptions.screenshotDir.empty()) + mScreenshotDir = mOptions.screenshotDir; else { std::string configScreenshotDir = config.getValue("screenshotDirectory", ""); if (!configScreenshotDir.empty()) - screenshotDir = configScreenshotDir; + mScreenshotDir = configScreenshotDir; else { #ifdef WIN32 - screenshotDir = getSpecialFolderLocation(CSIDL_MYPICTURES); - if (screenshotDir.empty()) - screenshotDir = getSpecialFolderLocation(CSIDL_DESKTOP); + mScreenshotDir = getSpecialFolderLocation(CSIDL_MYPICTURES); + if (mScreenshotDir.empty()) + mScreenshotDir = getSpecialFolderLocation(CSIDL_DESKTOP); #else - 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()); + mScreenshotDir = std::string(PHYSFS_getUserDir()) + "Desktop"; #endif } - config.setValue("screenshotDirectory", screenshotDir); + config.setValue("screenshotDirectory", mScreenshotDir); if (config.getValue("useScreenshotDirectorySuffix", true)) { @@ -1180,20 +1193,12 @@ void Client::initScreenshotDir(const std::string &dir) if (!configScreenshotSuffix.empty()) { - screenshotDir += "/" + configScreenshotSuffix; + mScreenshotDir += "/" + configScreenshotSuffix; config.setValue("screenshotDirectorySuffix", configScreenshotSuffix); } } } - - if (mkdir_r(screenshotDir.c_str())) - { - logger->log("Directory %s doesn't exist and can't be created! " - "Setting screenshot directory to home.", - screenshotDir.c_str()); - screenshotDir = std::string(PHYSFS_getUserDir()); - } } void Client::accountLogin(LoginData *loginData) diff --git a/src/client.h b/src/client.h index f0fdd508..233ee646 100644 --- a/src/client.h +++ b/src/client.h @@ -160,52 +160,56 @@ public: int exec(); static void setState(State state) - { instance()->state = state; } + { instance()->mState = state; } static State getState() - { return instance()->state; } + { return instance()->mState; } + + static const std::string &getPackageDirectory() + { return instance()->mPackageDir; } static const std::string &getConfigDirectory() - { return instance()->configDir; } + { return instance()->mConfigDir; } static const std::string &getLocalDataDirectory() - { return instance()->localDataDir; } + { return instance()->mLocalDataDir; } static const std::string &getScreenshotDirectory() - { return instance()->screenshotDir; } + { return instance()->mScreenshotDir; } void optionChanged(const std::string &name); void action(const gcn::ActionEvent &event); private: - void initHomeDir(const Options &options); - void initConfiguration(const Options &options); + void initHomeDir(); + void initConfiguration(); void initUpdatesDir(); - void initScreenshotDir(const std::string &dir); + void initScreenshotDir(); void accountLogin(LoginData *loginData); static Client *mInstance; - Options options; + Options mOptions; - std::string configDir; - std::string localDataDir; - std::string updateHost; - std::string updatesDir; - std::string screenshotDir; + std::string mPackageDir; + std::string mConfigDir; + std::string mLocalDataDir; + std::string mUpdateHost; + std::string mUpdatesDir; + std::string mScreenshotDir; - ServerInfo currentServer; + ServerInfo mCurrentServer; - Window *currentDialog; - QuitDialog *quitDialog; - Desktop *desktop; - Button *setupButton; + Window *mCurrentDialog; + QuitDialog *mQuitDialog; + Desktop *mDesktop; + Button *mSetupButton; - State state; - State oldstate; + State mState; + State mOldState; - SDL_Surface *icon; + SDL_Surface *mIcon; SDL_TimerID mLogicCounterId; SDL_TimerID mSecondsCounterId; diff --git a/src/game.cpp b/src/game.cpp index b3670641..0f45d436 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -82,6 +82,7 @@ #include "resources/resourcemanager.h" #include "utils/gettext.h" +#include "utils/mkdir.h" #include <guichan/exception.hpp> #include <guichan/focushandler.hpp> @@ -268,25 +269,17 @@ Game::~Game() destroyGuiWindows(); - delete beingManager; - delete player_node; - delete floorItemManager; - delete channelManager; - delete commandHandler; - delete joystick; - delete particleEngine; - delete viewport; - - viewport->setMap(NULL); - - delete mCurrentMap; + del_0(beingManager) + del_0(player_node) + del_0(floorItemManager) + del_0(channelManager) + del_0(commandHandler) + del_0(joystick) + del_0(particleEngine) + del_0(viewport) + del_0(mCurrentMap) map_path = ""; - player_node = NULL; - beingManager = NULL; - floorItemManager = NULL; - joystick = NULL; - mInstance = 0; } @@ -300,14 +293,24 @@ static bool saveScreenshot() std::stringstream filenameSuffix; std::stringstream filename; std::fstream testExists; + std::string screenshotDirectory = Client::getScreenshotDirectory(); bool found = false; + if (mkdir_r(screenshotDirectory.c_str()) != 0) + { + logger->log("Directory %s doesn't exist and can't be created! " + "Setting screenshot directory to home.", + screenshotDirectory.c_str()); + screenshotDirectory = std::string(PHYSFS_getUserDir()); + } + do { screenshotCount++; filenameSuffix.str(""); filename.str(""); - filename << Client::getScreenshotDirectory() << "/"; - filenameSuffix << "Mana_Screenshot_" << screenshotCount << ".png"; + filename << screenshotDirectory << "/"; + filenameSuffix << branding.getValue("appShort", "Mana") + << "_Screenshot_" << screenshotCount << ".png"; filename << filenameSuffix.str(); testExists.open(filename.str().c_str(), std::ios::in); found = !testExists.is_open(); @@ -593,8 +596,12 @@ void Game::handleInput() case KeyboardConfig::KEY_PICKUP: { const Vector &pos = player_node->getPosition(); - Uint16 x = (int) pos.x / 32; - Uint16 y = (int) pos.y / 32; + Map *map = viewport->getCurrentMap(); + Uint16 x = (int) pos.x / map->getTileWidth(); + Uint16 y = (int) (pos.y - 1) + / map->getTileHeight(); + // y - 1 needed to fix position, otherwise, it's + // off under eAthena. FloorItem *item = floorItemManager->findByCoordinates(x, y); diff --git a/src/gui/beingpopup.cpp b/src/gui/beingpopup.cpp index 7fd99371..33fdff44 100644 --- a/src/gui/beingpopup.cpp +++ b/src/gui/beingpopup.cpp @@ -27,7 +27,7 @@ #include "gui/gui.h" #include "gui/palette.h" -#include "gui/widgets/textbox.h" +#include "gui/widgets/label.h" #include "utils/gettext.h" #include "utils/stringutils.h" @@ -39,14 +39,14 @@ BeingPopup::BeingPopup(): Popup("BeingPopup") { // Being Name - mBeingName = new TextBox(); + mBeingName = new Label("A"); mBeingName->setFont(boldFont); mBeingName->setPosition(getPadding(), getPadding()); - const int fontHeight = getFont()->getHeight(); + const int fontHeight = mBeingName->getHeight() + getPadding(); // Being's party - mBeingParty = new TextBox(); + mBeingParty = new Label("A"); mBeingParty->setPosition(getPadding(), fontHeight); add(mBeingName); @@ -69,12 +69,15 @@ void BeingPopup::show(int x, int y, Player *p) if (!(p->getPartyName().empty())) { - mBeingName->setTextWrapped(p->getName(), 196); - mBeingParty->setTextWrapped(strprintf(_("Party: %s"), - p->getPartyName().c_str()), 196); + mBeingName->setCaption(p->getName()); + mBeingName->adjustSize(); - int minWidth = std::max(mBeingName->getMinWidth(), - mBeingParty->getMinWidth()); + mBeingParty->setCaption(strprintf(_("Party: %s"), + p->getPartyName().c_str())); + mBeingParty->adjustSize(); + + int minWidth = std::max(mBeingName->getWidth(), + mBeingParty->getWidth()); const int height = getFont()->getHeight(); diff --git a/src/gui/beingpopup.h b/src/gui/beingpopup.h index 078b84d9..71d9dd2a 100644 --- a/src/gui/beingpopup.h +++ b/src/gui/beingpopup.h @@ -23,10 +23,8 @@ #include "gui/widgets/popup.h" -#include <guichan/mouselistener.hpp> - +class Label; class Player; -class TextBox; /** * A popup that displays information about a being. @@ -52,8 +50,8 @@ class BeingPopup : public Popup // TODO: Add a version for monsters, NPCs, etc? private: - TextBox *mBeingName; - TextBox *mBeingParty; + Label *mBeingName; + Label *mBeingParty; static gcn::Color getColor(); }; diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp index 2711161e..2161e04c 100644 --- a/src/gui/emotepopup.cpp +++ b/src/gui/emotepopup.cpp @@ -29,10 +29,11 @@ #include "localplayer.h" #include "log.h" +#include "gui/skin.h" + #include "resources/emotedb.h" #include "resources/image.h" #include "resources/iteminfo.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -56,8 +57,7 @@ EmotePopup::EmotePopup(): mEmotes.push_back(EmoteDB::getAnimation(i)); } - ResourceManager *resman = ResourceManager::getInstance(); - mSelectionImage = resman->getImage("graphics/gui/selection.png"); + mSelectionImage = SkinLoader::getImageFromTheme("selection.png"); if (!mSelectionImage) logger->error("Unable to load selection.png"); @@ -119,6 +119,8 @@ void EmotePopup::mousePressed(gcn::MouseEvent &event) void EmotePopup::mouseMoved(gcn::MouseEvent &event) { + Popup::mouseMoved(event); + mHoveredEmoteIndex = getIndexAt(event.getX(), event.getY()); } diff --git a/src/gui/emotepopup.h b/src/gui/emotepopup.h index de957925..62a3f24a 100644 --- a/src/gui/emotepopup.h +++ b/src/gui/emotepopup.h @@ -42,8 +42,7 @@ namespace gcn { * * \ingroup GUI */ -class EmotePopup : public Popup, - public gcn::MouseListener +class EmotePopup : public Popup { public: /** diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index e82a33b9..1e36523c 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -26,7 +26,6 @@ #include "gui/sdlinput.h" #include "gui/skin.h" #include "gui/truetypefont.h" -#include "gui/viewport.h" #include "gui/widgets/window.h" #include "gui/widgets/windowcontainer.h" @@ -95,6 +94,7 @@ Gui::Gui(Graphics *graphics): // Initialize top GUI widget WindowContainer *guiTop = new WindowContainer; + guiTop->setFocusable(true); guiTop->setDimension(gcn::Rectangle(0, 0, graphics->getWidth(), graphics->getHeight())); guiTop->setOpaque(false); @@ -209,9 +209,8 @@ void Gui::setUseCustomCursor(bool customCursor) SDL_ShowCursor(SDL_DISABLE); // Load the mouse cursor - ResourceManager *resman = ResourceManager::getInstance(); - mMouseCursors = - resman->getImageSet("graphics/gui/mouse.png", 40, 40); + mMouseCursors = SkinLoader::getImageSetFromTheme("mouse.png", + 40, 40); if (!mMouseCursors) logger->error("Unable to load mouse cursors."); diff --git a/src/gui/gui.h b/src/gui/gui.h index 7bd76c4a..112abcee 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -107,6 +107,9 @@ class Gui : public gcn::Gui CURSOR_RESIZE_DOWN, CURSOR_RESIZE_DOWN_LEFT, CURSOR_RESIZE_DOWN_RIGHT, + CURSOR_FIGHT, + CURSOR_PICKUP, + CURSOR_TALK, CURSOR_TOTAL }; diff --git a/src/gui/itempopup.cpp b/src/gui/itempopup.cpp index c22a9c33..1d41449d 100644 --- a/src/gui/itempopup.cpp +++ b/src/gui/itempopup.cpp @@ -168,6 +168,8 @@ gcn::Color ItemPopup::getColor(ItemType type) void ItemPopup::mouseMoved(gcn::MouseEvent &event) { + Popup::mouseMoved(event); + // When the mouse moved on top of the popup, hide it setVisible(false); } diff --git a/src/gui/itempopup.h b/src/gui/itempopup.h index 79aba523..67d1eb2f 100644 --- a/src/gui/itempopup.h +++ b/src/gui/itempopup.h @@ -34,8 +34,7 @@ class TextBox; /** * A popup that displays information about an item. */ -class ItemPopup : public Popup, - public gcn::MouseListener +class ItemPopup : public Popup { public: /** diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index f439420b..e9f76436 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -49,23 +49,17 @@ #define MAX_SERVERLIST 5 -ServerInfo::Type stringToServerType(const std::string &type) +static ServerInfo::Type stringToServerType(const std::string &type) { if (compareStrI(type, "eathena") == 0) - { return ServerInfo::EATHENA; - } else if (compareStrI(type, "manaserv") == 0) - { return ServerInfo::MANASERV; - } - else - { - return ServerInfo::UNKNOWN; - } + + return ServerInfo::UNKNOWN; } -std::string serverTypeToString(ServerInfo::Type type) +static std::string serverTypeToString(ServerInfo::Type type) { switch (type) { @@ -78,6 +72,18 @@ std::string serverTypeToString(ServerInfo::Type type) } } +static unsigned short defaultPortForServerType(ServerInfo::Type type) +{ + switch (type) + { + default: + case ServerInfo::EATHENA: + return 6901; + case ServerInfo::MANASERV: + return 9601; + } +} + ServersListModel::ServersListModel(ServerInfos *servers, ServerDialog *parent): mServers(servers), mParent(parent) @@ -138,33 +144,33 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): mServerNameField = new TextField(mServerInfo->hostname); mPortField = new TextField(toString(mServerInfo->port)); - ServerInfo currentServer; - // Add the most used servers from config if they are not in the online list - std::string currentConfig = ""; - for (int i = 0; i <= MAX_SERVERLIST; i++) + // Add the most used servers from config + for (int i = 0; i <= MAX_SERVERLIST; ++i) { - currentServer.clear(); - - currentConfig = "MostUsedServerName" + toString(i); - currentServer.hostname = config.getValue(currentConfig, ""); + const std::string index = toString(i); + const std::string nameKey = "MostUsedServerName" + index; + const std::string typeKey = "MostUsedServerType" + index; + const std::string portKey = "MostUsedServerPort" + index; - currentConfig = "MostUsedServerPort" + toString(i); - currentServer.port = (short) config.getValue(currentConfig, - DEFAULT_PORT); + ServerInfo server; + server.hostname = config.getValue(nameKey, ""); + server.type = stringToServerType(config.getValue(typeKey, "")); - currentConfig = "MostUsedServerType" + toString(i); - currentServer.type = stringToServerType(config - .getValue(currentConfig, "")); + const int defaultPort = defaultPortForServerType(server.type); + server.port = (unsigned short) config.getValue(portKey, defaultPort); - if (!currentServer.hostname.empty() && currentServer.port != 0) + if (server.isValid()) { - mServers.push_back(currentServer); + server.save = true; + mServers.push_back(server); } } mServersListModel = new ServersListModel(&mServers, this); mServersList = new ListBox(mServersListModel); + mServersList->addMouseListener(this); + ScrollArea *usedScroll = new ScrollArea(mServersList); usedScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); @@ -175,7 +181,8 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): mQuitButton = new Button(_("Quit"), "quit", this); mConnectButton = new Button(_("Connect"), "connect", this); - mManualEntryButton = new Button(_("Add Entry"), "addEntry", this); + mManualEntryButton = new Button(_("Custom Server"), "addEntry", this); + mDeleteButton = new Button(_("Delete"), "remove", this); mServerNameField->setActionEventId("connect"); mPortField->setActionEventId("connect"); @@ -184,20 +191,20 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): mPortField->addActionListener(this); mManualEntryButton->addActionListener(this); mServersList->addSelectionListener(this); - mServersList->setSelected(0); usedScroll->setVerticalScrollAmount(0); place(0, 0, serverLabel); - place(1, 0, mServerNameField, 3).setPadding(3); + place(1, 0, mServerNameField, 4).setPadding(3); place(0, 1, portLabel); - place(1, 1, mPortField, 3).setPadding(3); + place(1, 1, mPortField, 4).setPadding(3); place(0, 2, typeLabel); - place(1, 2, mTypeField, 3).setPadding(3); - place(0, 3, usedScroll, 4, 5).setPadding(3); - place(0, 8, mDescription, 4); + place(1, 2, mTypeField, 4).setPadding(3); + place(0, 3, usedScroll, 5, 5).setPadding(3); + place(0, 8, mDescription, 5); place(0, 9, mManualEntryButton); - place(2, 9, mQuitButton); - place(3, 9, mConnectButton); + place(1, 9, mDeleteButton); + place(3, 9, mQuitButton); + place(4, 9, mConnectButton); // Make sure the list has enough height getLayout().setRowHeight(3, 80); @@ -208,6 +215,7 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): center(); setFieldsReadOnly(true); + mServersList->setSelected(0); // Do this after for the Delete button setVisible(true); if (mServerNameField->getText().empty()) @@ -247,7 +255,8 @@ void ServerDialog::action(const gcn::ActionEvent &event) else if (event.getId() == "connect") { // Check login - if (mServerNameField->getText().empty() || mPortField->getText().empty()) + if (mServerNameField->getText().empty() + || mPortField->getText().empty()) { OkDialog *dlg = new OkDialog(_("Error"), _("Please type both the address and the port of a server.")); @@ -261,7 +270,6 @@ void ServerDialog::action(const gcn::ActionEvent &event) // First, look if the entry is a new one. ServerInfo currentServer; - ServerInfo tempServer; currentServer.hostname = mServerNameField->getText(); currentServer.port = (short) atoi(mPortField->getText().c_str()); switch (mTypeField->getSelected()) @@ -284,21 +292,27 @@ void ServerDialog::action(const gcn::ActionEvent &event) serverTypeToString(currentServer.type)); // now add the rest of the list... - std::string currentConfig = ""; int configCount = 1; - for (int i = 0; i < mServersListModel->getNumberOfElements(); i++) + for (int i = 0; i < mServersListModel->getNumberOfElements(); ++i) { - tempServer = mServersListModel->getServer(i); + const ServerInfo server = mServersListModel->getServer(i); + + // Only save servers that were loaded from settings + if (!server.save) + continue; // ensure, that our server will not be added twice - if (tempServer != currentServer) + if (server != currentServer) { - currentConfig = "MostUsedServerName" + toString(configCount); - config.setValue(currentConfig, toString(tempServer.hostname)); - currentConfig = "MostUsedServerPort" + toString(configCount); - config.setValue(currentConfig, toString(tempServer.port)); - currentConfig = "MostUsedServerType" + toString(configCount); - config.setValue(currentConfig, serverTypeToString(tempServer.type)); + const std::string index = toString(configCount); + const std::string nameKey = "MostUsedServerName" + index; + const std::string typeKey = "MostUsedServerType" + index; + const std::string portKey = "MostUsedServerPort" + index; + + config.setValue(nameKey, toString(server.hostname)); + config.setValue(typeKey, serverTypeToString(server.type)); + config.setValue(portKey, toString(server.port)); + configCount++; } @@ -321,6 +335,12 @@ void ServerDialog::action(const gcn::ActionEvent &event) { setFieldsReadOnly(false); } + else if (event.getId() == "remove") + { + int index = mServersList->getSelected(); + mServersList->setSelected(0); + mServersListModel->remove(index); + } } void ServerDialog::keyPressed(gcn::KeyEvent &keyEvent) @@ -337,11 +357,14 @@ void ServerDialog::keyPressed(gcn::KeyEvent &keyEvent) } } -void ServerDialog::valueChanged(const gcn::SelectionEvent &event) +void ServerDialog::valueChanged(const gcn::SelectionEvent &) { const int index = mServersList->getSelected(); if (index == -1) + { + mDeleteButton->setEnabled(false); return; + } // Update the server and post fields according to the new selection const ServerInfo myServer = mServersListModel->getServer(index); @@ -350,16 +373,27 @@ void ServerDialog::valueChanged(const gcn::SelectionEvent &event) mPortField->setText(toString(myServer.port)); switch (myServer.type) { - case ServerInfo::UNKNOWN: - mTypeField->setSelected(2); - break; case ServerInfo::EATHENA: + case ServerInfo::UNKNOWN: mTypeField->setSelected(0); break; case ServerInfo::MANASERV: mTypeField->setSelected(1); + break; } setFieldsReadOnly(true); + + mDeleteButton->setEnabled(myServer.save); +} + +void ServerDialog::mouseClicked(gcn::MouseEvent &mouseEvent) +{ + if (mouseEvent.getClickCount() == 2 && + mouseEvent.getSource() == mServersList) + { + action(gcn::ActionEvent(mConnectButton, + mConnectButton->getActionEventId())); + } } void ServerDialog::logic() @@ -391,39 +425,38 @@ void ServerDialog::logic() Window::logic(); } -void ServerDialog::setFieldsReadOnly(const bool readOnly) +void ServerDialog::setFieldsReadOnly(bool readOnly) { - if (readOnly) + if (!readOnly) { - mServerNameField->setEnabled(false); - mPortField->setEnabled(false); - mManualEntryButton->setVisible(true); - mDescription->setVisible(true); - } - else - { - mManualEntryButton->setVisible(false); - - mDescription->setVisible(false); mDescription->setCaption(std::string()); mServersList->setSelected(-1); mServerNameField->setText(std::string()); - mServerNameField->setEnabled(true); - - mPortField->setText(toString(DEFAULT_PORT)); - mPortField->setEnabled(true); + mPortField->setText(std::string()); mServerNameField->requestFocus(); } + + mManualEntryButton->setEnabled(readOnly); + mDeleteButton->setEnabled(false); + mDescription->setVisible(readOnly); + + mServerNameField->setEnabled(!readOnly); + mPortField->setEnabled(!readOnly); + mTypeField->setEnabled(!readOnly); } void ServerDialog::downloadServerList() { - // try to load the configuration value for the onlineServerList - std::string listFile = config.getValue("onlineServerList", "void"); - // if there is no entry, try to load the file from the default updatehost - if (listFile == "void") + // Try to load the configuration value for the onlineServerList + std::string listFile = branding.getValue("onlineServerList", std::string()); + + if (listFile.empty()) + listFile = config.getValue("onlineServerList", std::string()); + + // Fall back to manasource.org when neither branding nor config set it + if (listFile.empty()) listFile = "http://manasource.org/serverlist.xml"; mDownload = new Net::Download(this, listFile, &downloadUpdate); @@ -433,65 +466,74 @@ void ServerDialog::downloadServerList() void ServerDialog::loadServers() { - ServerInfo currentServer; + XML::Document doc(mDir + "/serverlist.xml", false); + xmlNodePtr rootNode = doc.rootNode(); - xmlDocPtr doc = xmlReadFile((mDir + "/serverlist.xml").c_str(), NULL, 0); + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "serverlist")) + { + logger->log("Error loading server list!"); + return; + } - if (doc != NULL) + int version = XML::getProperty(rootNode, "version", 0); + if (version != 1) { - xmlNodePtr rootNode = xmlDocGetRootElement(doc); - int version = XML::getProperty(rootNode, "version", 3); + logger->log("Error: unsupported online server list version: %d", + version); + return; + } + + for_each_xml_child_node(serverNode, rootNode) + { + if (!xmlStrEqual(serverNode->name, BAD_CAST "server")) + continue; + + ServerInfo server; + + std::string type = XML::getProperty(serverNode, "type", "unknown"); - if (version != 1) + server.type = stringToServerType(type); + server.name = XML::getProperty(serverNode, "name", std::string()); + + if (server.type == ServerInfo::UNKNOWN) { - logger->log("Online server list has wrong version"); - return; + logger->log("Unknown server type: %s", type.c_str()); + continue; } - for_each_xml_child_node(server, rootNode) + for_each_xml_child_node(subNode, serverNode) { - if (xmlStrEqual(server->name, BAD_CAST "server")) - { - std::string type = XML::getProperty(server, "type", "unknown"); - - currentServer.clear(); - currentServer.name = XML::getProperty(server, "name", std::string()); + if (!xmlStrEqual(subNode->name, BAD_CAST "connection")) + continue; - for_each_xml_child_node(subnode, server) - { - if (xmlStrEqual(subnode->name, BAD_CAST "connection")) - { - currentServer.type = stringToServerType(type); - currentServer.hostname = XML::getProperty(subnode, "hostname", std::string()); - currentServer.port = XML::getProperty(subnode, "port", DEFAULT_PORT); - } - } + server.hostname = XML::getProperty(subNode, "hostname", ""); + server.port = XML::getProperty(subNode, "port", 0); + if (server.port == 0) + { + // If no port is given, use the default for the given type + server.port = defaultPortForServerType(server.type); + } + } - MutexLocker lock(&mMutex); - // add the server to the local list (if it's not already present) - ServerInfos::iterator it; - bool found = false; - for (it = mServers.begin(); it != mServers.end(); it++) - { - if ((*it) == currentServer) - { - (*it).name = currentServer.name; - found = true; - break; - } - } - - if (!found) - mServers.push_back(currentServer); + MutexLocker lock(&mMutex); + // Add the server to the local list if it's not already present + ServerInfos::iterator it; + bool found = false; + for (it = mServers.begin(); it != mServers.end(); it++) + { + if ((*it) == server) + { + // Use the name listed in the server list + (*it).name = server.name; + found = true; + break; } } - xmlFreeDoc(doc); + if (!found) + mServers.push_back(server); } - - MutexLocker lock(&mMutex); - mDownloadStatus = DOWNLOADING_COMPLETE; } int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status, @@ -518,9 +560,12 @@ int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status, { float progress = (float) remaining / total; - 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 + else if (progress < 0.0f) + progress = 0.0f; // no idea how this could ever happen, but why not check for it anyway. + else if (progress > 1.0f) + progress = 1.0f; MutexLocker lock(&sd->mMutex); sd->mDownloadStatus = DOWNLOADING_IN_PROGRESS; @@ -530,6 +575,9 @@ int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status, if (finished) { sd->loadServers(); + + MutexLocker lock(&sd->mMutex); + sd->mDownloadStatus = DOWNLOADING_COMPLETE; } return 0; diff --git a/src/gui/serverdialog.h b/src/gui/serverdialog.h index c4af6ab2..3d7dca9d 100644 --- a/src/gui/serverdialog.h +++ b/src/gui/serverdialog.h @@ -32,6 +32,7 @@ #include <guichan/actionlistener.hpp> #include <guichan/keylistener.hpp> #include <guichan/listmodel.hpp> +#include <guichan/mouselistener.hpp> #include <guichan/selectionlistener.hpp> #include <string> @@ -68,18 +69,24 @@ class ServersListModel : public gcn::ListModel ServerInfo getServer(int elementIndex) const { return mServers->at(elementIndex); } + /** + * Removes the entry. + */ + void remove(int elementIndex) + { mServers->erase(mServers->begin() + elementIndex); } + private: ServerInfos *mServers; ServerDialog *mParent; }; /** - * Server and Port List Model + * Server Type List Model */ class TypeListModel : public gcn::ListModel { public: - TypeListModel() { }; + TypeListModel() {} /** * Used to get number of line in the list @@ -128,6 +135,8 @@ class ServerDialog : public Window, */ void valueChanged(const gcn::SelectionEvent &event); + void mouseClicked(gcn::MouseEvent &mouseEvent); + void logic(); protected: @@ -143,7 +152,7 @@ class ServerDialog : public Window, static int downloadUpdate(void *ptr, DownloadStatus status, size_t total, size_t remaining); - void setFieldsReadOnly(const bool readOnly); + void setFieldsReadOnly(bool readOnly); TextField *mServerNameField; TextField *mPortField; @@ -151,6 +160,7 @@ class ServerDialog : public Window, Button *mQuitButton; Button *mConnectButton; Button *mManualEntryButton; + Button *mDeleteButton; ListBox *mServersList; ServersListModel *mServersListModel; diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp index 78c5c998..09c7ccb2 100644 --- a/src/gui/skilldialog.cpp +++ b/src/gui/skilldialog.cpp @@ -25,6 +25,7 @@ #include "log.h" #include "gui/setup.h" +#include "gui/skin.h" #include "gui/widgets/button.h" #include "gui/widgets/container.h" @@ -76,7 +77,7 @@ struct SkillInfo icon->decRef(); } - void setIcon(std::string iconPath) + void setIcon(const std::string &iconPath) { ResourceManager *res = ResourceManager::getInstance(); if (!iconPath.empty()) @@ -85,7 +86,7 @@ struct SkillInfo } else { - icon = res->getImage("graphics/gui/unknown-item.png"); + icon = SkinLoader::getImageFromTheme("unknown-item.png"); } } @@ -99,11 +100,19 @@ typedef std::vector<SkillInfo*> SkillList; class SkillModel : public gcn::ListModel { public: - int getNumberOfElements() { return mVisibleSkills.size(); } - SkillInfo *getSkillAt(int i) { return mVisibleSkills.at(i); } - std::string getElementAt(int i) { return getSkillAt(i)->name; } + int getNumberOfElements() + { return mVisibleSkills.size(); } + + SkillInfo *getSkillAt(int i) const + { return mVisibleSkills.at(i); } + + std::string getElementAt(int i) + { return getSkillAt(i)->name; } + void updateVisibilities(); - void addSkill(SkillInfo *info) { mSkills.push_back(info); } + + void addSkill(SkillInfo *info) + { mSkills.push_back(info); } private: SkillList mSkills; @@ -119,7 +128,11 @@ public: SkillInfo *getSelectedInfo() { - return static_cast<SkillModel*>(mListModel)->getSkillAt(getSelected()); + const int selected = getSelected(); + if (selected < 0 || selected > mListModel->getNumberOfElements()) + return 0; + + return static_cast<SkillModel*>(mListModel)->getSkillAt(selected); } void draw(gcn::Graphics *gcnGraphics) @@ -216,9 +229,8 @@ void SkillDialog::action(const gcn::ActionEvent &event) if (tab) { - SkillInfo *info = tab->getSelectedInfo(); - - Net::getPlayerHandler()->increaseSkill(info->id); + if (SkillInfo *info = tab->getSelectedInfo()) + Net::getPlayerHandler()->increaseSkill(info->id); } } else if (event.getId() == "close") diff --git a/src/gui/skin.cpp b/src/gui/skin.cpp index a682bf8f..22153720 100644 --- a/src/gui/skin.cpp +++ b/src/gui/skin.cpp @@ -23,22 +23,26 @@ #include "gui/skin.h" +#include "client.h" #include "configuration.h" #include "configlistener.h" #include "log.h" #include "resources/image.h" +#include "resources/imageset.h" #include "resources/resourcemanager.h" #include "utils/dtor.h" #include "utils/stringutils.h" #include "utils/xml.h" +#include <physfs.h> + #include <algorithm> +std::string SkinLoader::mThemePath; SkinLoader *SkinLoader::mInstance = 0; - class SkinConfigListener : public ConfigListener { public: @@ -197,7 +201,7 @@ Skin *SkinLoader::readSkin(const std::string &filename) logger->log("Loading skin '%s'.", filename.c_str()); - XML::Document doc(filename); + XML::Document doc(resolveThemePath(filename)); xmlNodePtr rootNode = doc.rootNode(); if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skinset")) @@ -215,8 +219,7 @@ Skin *SkinLoader::readSkin(const std::string &filename) logger->log("SkinLoader::load(): <skinset> defines " "'%s' as a skin image.", skinSetImage.c_str()); - ResourceManager *resman = ResourceManager::getInstance(); - Image *dBorders = resman->getImage("graphics/gui/" + skinSetImage); + Image *dBorders = SkinLoader::getImageFromTheme(skinSetImage); ImageRect border; // iterate <widget>'s @@ -286,8 +289,8 @@ Skin *SkinLoader::readSkin(const std::string &filename) logger->log("Finished loading skin."); // Hard-coded for now until we update the above code to look for window buttons - Image *closeImage = resman->getImage("graphics/gui/close_button.png"); - Image *sticky = resman->getImage("graphics/gui/sticky_button.png"); + Image *closeImage = SkinLoader::getImageFromTheme("close_button.png"); + Image *sticky = SkinLoader::getImageFromTheme("sticky_button.png"); Image *stickyImageUp = sticky->getSubImage(0, 0, 15, 15); Image *stickyImageDown = sticky->getSubImage(15, 0, 15, 15); sticky->decRef(); @@ -297,3 +300,68 @@ Skin *SkinLoader::readSkin(const std::string &filename) skin->updateAlpha(mMinimumOpacity); return skin; } + +bool SkinLoader::tryThemePath(std::string themePath) +{ + if (!themePath.empty()) + { + themePath = "graphics/gui/" + themePath; + if (PHYSFS_exists(themePath.c_str())) + { + mThemePath = themePath; + return true; + } + } + + return false; +} + +void SkinLoader::prepareThemePath() +{ + // Try theme from settings + if (tryThemePath(config.getValue("theme", ""))) + return; + + // Try theme from branding + if (tryThemePath(branding.getValue("theme", ""))) + return; + + // Use default + mThemePath = "graphics/gui"; +} + +std::string SkinLoader::resolveThemePath(const std::string &path) +{ + // Need to strip off any dye info for the existence tests + int pos = path.find('|'); + std::string file; + if (pos > 0) + file = path.substr(0, pos); + else + file = path; + + // Might be a valid path already + if (PHYSFS_exists(file.c_str())) + return path; + + // Try the theme + file = getThemePath() + "/" + file; + if (PHYSFS_exists(file.c_str())) + return getThemePath() + "/" + path; + + // Backup + return "graphics/gui/" + path; +} + +Image *SkinLoader::getImageFromTheme(const std::string &path) +{ + ResourceManager *resman = ResourceManager::getInstance(); + return resman->getImage(resolveThemePath(path)); +} + +ImageSet *SkinLoader::getImageSetFromTheme(const std::string &path, + int w, int h) +{ + ResourceManager *resman = ResourceManager::getInstance(); + return resman->getImageSet(resolveThemePath(path), w, h); +} diff --git a/src/gui/skin.h b/src/gui/skin.h index 15d55972..091d3001 100644 --- a/src/gui/skin.h +++ b/src/gui/skin.h @@ -31,6 +31,7 @@ class ConfigListener; class Image; +class ImageSet; class Skin { @@ -101,11 +102,24 @@ class SkinLoader static SkinLoader *instance(); static void deleteInstance(); + static void prepareThemePath(); + static std::string getThemePath() { return mThemePath; } + + /** + * Returns the patch to the given gui resource relative to the theme + * or, if it isn't in the theme, relative to 'graphics/gui'. + */ + static std::string resolveThemePath(const std::string &path); + + static Image *getImageFromTheme(const std::string &path); + static ImageSet *getImageSetFromTheme(const std::string &path, + int w, int h); + /** * Loads a skin. */ Skin *load(const std::string &filename, - const std::string &defaultPath); + const std::string &defaultPath = getThemePath()); /** * Updates the alpha values of all of the skins. @@ -141,8 +155,11 @@ class SkinLoader */ ConfigListener *mSkinConfigListener; + static std::string mThemePath; static SkinLoader *mInstance; + static bool tryThemePath(std::string themePath); + /** * Tells if the current skins opacity * should not get less than the given value diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp index 26184cae..5da8018c 100644 --- a/src/gui/socialwindow.cpp +++ b/src/gui/socialwindow.cpp @@ -235,7 +235,8 @@ public: mBrowserBox->setOpaque(false); mBrowserBox->setLinkHandler(this); - mBrowserBox->addRow(strprintf("@@guild|%s@@", _("Create Guild"))); + if (Net::getGuildHandler()->isSupported()) + mBrowserBox->addRow(strprintf("@@guild|%s@@", _("Create Guild"))); mBrowserBox->addRow(strprintf("@@party|%s@@", _("Create Party"))); mBrowserBox->addRow("##3---"); mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel"))); @@ -425,7 +426,10 @@ void SocialWindow::action(const gcn::ActionEvent &event) } else if (event.getId() == "create") { - mCreatePopup->show(mCreateButton); + if (Net::getGuildHandler()->isSupported()) + mCreatePopup->show(mCreateButton); + else + showPartyCreate(); } else if (event.getId() == "invite") { @@ -564,7 +568,7 @@ void SocialWindow::showPartyCreate() } mPartyCreateDialog = new TextDialog(_("Party Name"), - _("Choose your part's name."), this); + _("Choose your party's name."), this); mPartyCreateDialog->setOKButtonActionId("create party"); mPartyCreateDialog->addActionListener(this); } diff --git a/src/gui/specialswindow.cpp b/src/gui/specialswindow.cpp index 1513dcf1..3ca0f037 100644 --- a/src/gui/specialswindow.cpp +++ b/src/gui/specialswindow.cpp @@ -24,6 +24,7 @@ #include "log.h" #include "gui/setup.h" +#include "gui/skin.h" #include "gui/widgets/button.h" #include "gui/widgets/container.h" @@ -219,7 +220,7 @@ SpecialEntry::SpecialEntry(SpecialInfo *info) : if (!info->icon.empty()) mIcon = new Icon(info->icon); else - mIcon = new Icon("graphics/gui/unknown-item.png"); + mIcon = new Icon(SkinLoader::resolveThemePath("unknown-item.png")); mIcon->setPosition(1, 0); add(mIcon); diff --git a/src/gui/speechbubble.cpp b/src/gui/speechbubble.cpp index 3a87992b..f02965d1 100644 --- a/src/gui/speechbubble.cpp +++ b/src/gui/speechbubble.cpp @@ -25,6 +25,7 @@ #include "graphics.h" #include "gui/gui.h" +#include "gui/skin.h" #include "gui/widgets/textbox.h" @@ -33,7 +34,7 @@ #include <guichan/widgets/label.hpp> SpeechBubble::SpeechBubble(): - Popup("Speech", "graphics/gui/speechbubble.xml") + Popup("Speech", "speechbubble.xml") { setContentSize(140, 46); setMinWidth(29); diff --git a/src/gui/textdialog.h b/src/gui/textdialog.h index 6db09e71..825d9ddc 100644 --- a/src/gui/textdialog.h +++ b/src/gui/textdialog.h @@ -43,8 +43,7 @@ public: */ TextDialog(const std::string &title, const std::string &msg, Window *parent = NULL); - - + ~TextDialog(); /** @@ -61,8 +60,8 @@ public: * Set the OK button action id */ void setOKButtonActionId(const std::string &name); - - static const bool isActive() { return instances > 0; } + + static bool isActive() { return instances > 0; } private: static int instances; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 763d0c43..1451b935 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -53,10 +53,7 @@ Viewport::Viewport(): mMouseY(0), mPixelViewX(0.0f), mPixelViewY(0.0f), - mTileViewX(0), - mTileViewY(0), mShowDebugPath(false), - mVisibleNames(false), mPlayerFollowMouse(false), mLocalWalkTime(-1) { @@ -67,21 +64,20 @@ Viewport::Viewport(): mScrollRadius = (int) config.getValue("ScrollRadius", 0); mScrollCenterOffsetX = (int) config.getValue("ScrollCenterOffsetX", 0); mScrollCenterOffsetY = (int) config.getValue("ScrollCenterOffsetY", 0); - mVisibleNames = config.getValue("visiblenames", 1); config.addListener("ScrollLaziness", this); config.addListener("ScrollRadius", this); - config.addListener("visiblenames", this); mPopupMenu = new PopupMenu; mBeingPopup = new BeingPopup; + + setFocusable(true); } Viewport::~Viewport() { delete mPopupMenu; - - config.removeListener("visiblenames", this); + delete mBeingPopup; } void Viewport::setMap(Map *map) @@ -109,10 +105,6 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) Graphics *graphics = static_cast<Graphics*>(gcnGraphics); - // Ensure the client doesn't freak out if a feature localplayer uses - // is dependent on a map. - player_node->setMapInitialized(true); - // Avoid freaking out when tick_time overflows if (tick_time < lastTick) { @@ -184,9 +176,6 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) mPixelViewY = viewYmax; } - mTileViewX = (int) (mPixelViewX + 16) / 32; - mTileViewY = (int) (mPixelViewY + 16) / 32; - // Draw tiles and sprites if (mMap) { @@ -312,25 +301,18 @@ void Viewport::mousePressed(gcn::MouseEvent &event) const int pixelX = event.getX() + (int) mPixelViewX; const int pixelY = event.getY() + (int) mPixelViewY; - const int tileX = pixelX / mMap->getTileWidth(); - const int tileY = pixelY / mMap->getTileHeight(); // Right click might open a popup if (event.getButton() == gcn::MouseEvent::RIGHT) { - Being *being; - FloorItem *floorItem; - - if ((being = beingManager->findBeingByPixel(pixelX, pixelY)) && - being != player_node) + if (mHoverBeing && mHoverBeing != player_node) { - mPopupMenu->showPopup(event.getX(), event.getY(), being); + mPopupMenu->showPopup(event.getX(), event.getY(), mHoverBeing); return; } - else if ((floorItem = floorItemManager->findByCoordinates(tileX, - tileY))) + else if (mHoverItem) { - mPopupMenu->showPopup(event.getX(), event.getY(), floorItem); + mPopupMenu->showPopup(event.getX(), event.getY(), mHoverItem); return; } } @@ -345,35 +327,32 @@ void Viewport::mousePressed(gcn::MouseEvent &event) // Left click can cause different actions if (event.getButton() == gcn::MouseEvent::LEFT) { - FloorItem *item; - Being *being; - // Interact with some being - if ((being = beingManager->findBeingByPixel(pixelX, pixelY))) + if (mHoverBeing) { - switch (being->getType()) + switch (mHoverBeing->getType()) { // Talk to NPCs case Being::NPC: - dynamic_cast<NPC*>(being)->talk(); + static_cast<NPC*>(mHoverBeing)->talk(); break; // Attack or walk to monsters or players case Being::MONSTER: case Being::PLAYER: // Ignore it if its dead - if (!being->isAlive()) + if (!mHoverBeing->isAlive()) break; - if (player_node->withinAttackRange(being) || + if (player_node->withinAttackRange(mHoverBeing) || keyboard.isKeyActive(keyboard.KEY_ATTACK)) { - player_node->attack(being, + player_node->attack(mHoverBeing, !keyboard.isKeyActive(keyboard.KEY_TARGET)); } else { - player_node->setGotoTarget(being); + player_node->setGotoTarget(mHoverBeing); } break; default: @@ -381,9 +360,9 @@ void Viewport::mousePressed(gcn::MouseEvent &event) } // Picks up a item if we clicked on one } - else if ((item = floorItemManager->findByCoordinates(tileX, tileY))) + else if (mHoverItem) { - player_node->pickUp(item); + player_node->pickUp(mHoverItem); } else if (player_node->getCurrentAction() == Being::SIT) { @@ -433,8 +412,10 @@ void Viewport::mouseDragged(gcn::MouseEvent &event) if (mLocalWalkTime != player_node->getWalkTime()) { mLocalWalkTime = player_node->getWalkTime(); - int destX = event.getX() / 32 + mTileViewX; - int destY = event.getY() / 32 + mTileViewY; + int destX = (event.getX() + mPixelViewX + 16) / + mMap->getTileWidth(); + int destY = (event.getY() + mPixelViewY + 16) / + mMap->getTileHeight(); player_node->setDestination(destX, destY); } } @@ -464,9 +445,6 @@ void Viewport::optionChanged(const std::string &name) { mScrollLaziness = (int) config.getValue("ScrollLaziness", 32); mScrollRadius = (int) config.getValue("ScrollRadius", 32); - - if (name == "visiblenames") - mVisibleNames = config.getValue("visiblenames", 1); } void Viewport::mouseMoved(gcn::MouseEvent &event) @@ -478,11 +456,42 @@ void Viewport::mouseMoved(gcn::MouseEvent &event) const int x = (event.getX() + (int) mPixelViewX); const int y = (event.getY() + (int) mPixelViewY); - mSelectedBeing = beingManager->findBeingByPixel(x, y); - if (Player *p = dynamic_cast<Player*>(mSelectedBeing)) + mHoverBeing = beingManager->findBeingByPixel(x, y); + if (Player *p = dynamic_cast<Player*>(mHoverBeing)) mBeingPopup->show(getMouseX(), getMouseY(), p); else mBeingPopup->setVisible(false); + + mHoverItem = floorItemManager->findByCoordinates(x / mMap->getTileWidth(), + y / mMap->getTileHeight()); + + if (mHoverBeing) + { + switch (mHoverBeing->getType()) + { + // NPCs + case Being::NPC: + gui->setCursorType(Gui::CURSOR_TALK); + break; + + // Monsters + case Being::MONSTER: + gui->setCursorType(Gui::CURSOR_FIGHT); + break; + default: + gui->setCursorType(Gui::CURSOR_POINTER); + break; + } + // Item mouseover + } + else if (mHoverItem) + { + gui->setCursorType(Gui::CURSOR_PICKUP); + } + else + { + gui->setCursorType(Gui::CURSOR_POINTER); + } } void Viewport::toggleDebugPath() @@ -496,3 +505,7 @@ void Viewport::toggleDebugPath() } } +void Viewport::hideBeingPopup() +{ + mBeingPopup->setVisible(false); +} diff --git a/src/gui/viewport.h b/src/gui/viewport.h index 5b92d950..e4944cd6 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -152,6 +152,11 @@ class Viewport : public WindowContainer, public gcn::MouseListener, */ Map *getCurrentMap() const { return mMap; } + /** + * Hides the BeingPopup. + */ + void hideBeingPopup(); + private: /** * Finds a path from the player to the mouse, and draws it. This is for @@ -179,20 +184,18 @@ class Viewport : public WindowContainer, public gcn::MouseListener, int mMouseY; /**< Current mouse position in pixels. */ float mPixelViewX; /**< Current viewpoint in pixels. */ float mPixelViewY; /**< Current viewpoint in pixels. */ - int mTileViewX; /**< Current viewpoint in tiles. */ - int mTileViewY; /**< Current viewpoint in tiles. */ int mShowDebugPath; /**< Show a path from player to pointer. */ - bool mVisibleNames; /**< Show target names. */ bool mPlayerFollowMouse; int mLocalWalkTime; /**< Timestamp before the next walk can be sent. */ PopupMenu *mPopupMenu; /**< Popup menu. */ - Being *mSelectedBeing; /**< Current selected being. */ - BeingPopup *mBeingPopup; + Being *mHoverBeing; /**< Being mouse is currently over. */ + FloorItem *mHoverItem; /**< FloorItem mouse is currently over. */ + BeingPopup *mBeingPopup; /**< Being information popup. */ }; -extern Viewport *viewport; /**< The viewport */ +extern Viewport *viewport; /**< The viewport. */ #endif diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp index f5a9ea18..92386739 100644 --- a/src/gui/widgets/avatarlistbox.cpp +++ b/src/gui/widgets/avatarlistbox.cpp @@ -25,6 +25,7 @@ #include "gui/chat.h" #include "gui/gui.h" #include "gui/palette.h" +#include "gui/skin.h" #include "resources/image.h" #include "resources/resourcemanager.h" @@ -44,8 +45,8 @@ AvatarListBox::AvatarListBox(AvatarListModel *model): if (instances == 1) { - onlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-green.png"); - offlineIcon = ResourceManager::getInstance()->getImage("graphics/gui/circle-gray.png"); + onlineIcon = SkinLoader::getImageFromTheme("circle-green.png"); + offlineIcon = SkinLoader::getImageFromTheme("circle-gray.png"); } setWidth(200); diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 6589c96e..36a47859 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -28,7 +28,6 @@ #include "gui/skin.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -54,10 +53,10 @@ struct ButtonData }; static ButtonData const data[BUTTON_COUNT] = { - { "graphics/gui/button.png", 0, 0 }, - { "graphics/gui/buttonhi.png", 9, 4 }, - { "graphics/gui/buttonpress.png", 16, 19 }, - { "graphics/gui/button_disabled.png", 25, 23 } + { "button.png", 0, 0 }, + { "buttonhi.png", 9, 4 }, + { "buttonpress.png", 16, 19 }, + { "button_disabled.png", 25, 23 } }; ImageRect Button::button[BUTTON_COUNT]; @@ -85,14 +84,13 @@ void Button::init() if (mInstances == 0) { // Load the skin - ResourceManager *resman = ResourceManager::getInstance(); Image *btn[BUTTON_COUNT]; int a, x, y, mode; for (mode = 0; mode < BUTTON_COUNT; mode++) { - btn[mode] = resman->getImage(data[mode].file); + btn[mode] = SkinLoader::getImageFromTheme(data[mode].file); a = 0; for (y = 0; y < 3; y++) { diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp index dc6d94b3..0fefbfe9 100644 --- a/src/gui/widgets/checkbox.cpp +++ b/src/gui/widgets/checkbox.cpp @@ -28,7 +28,6 @@ #include "gui/skin.h" #include "resources/image.h" -#include "resources/resourcemanager.h" int CheckBox::instances = 0; float CheckBox::mAlpha = 1.0; @@ -45,8 +44,7 @@ CheckBox::CheckBox(const std::string &caption, bool selected): { if (instances == 0) { - ResourceManager *resman = ResourceManager::getInstance(); - Image *checkBox = resman->getImage("graphics/gui/checkbox.png"); + Image *checkBox = SkinLoader::getImageFromTheme("checkbox.png"); checkBoxNormal = checkBox->getSubImage(0, 0, 9, 10); checkBoxChecked = checkBox->getSubImage(9, 0, 9, 10); checkBoxDisabled = checkBox->getSubImage(18, 0, 9, 10); @@ -114,21 +112,29 @@ void CheckBox::drawBox(gcn::Graphics* graphics) Image *box; if (isEnabled()) + { if (isSelected()) + { if (mHasMouse) box = checkBoxCheckedHi; else box = checkBoxChecked; + } else + { if (mHasMouse) box = checkBoxNormalHi; else box = checkBoxNormal; + } + } else + { if (isSelected()) box = checkBoxDisabledChecked; else box = checkBoxDisabled; + } updateAlpha(); diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index e7cd949a..2a80cc11 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -20,6 +20,7 @@ #include "gui/widgets/desktop.h" +#include "configuration.h" #include "graphics.h" #include "log.h" #include "main.h" @@ -32,6 +33,8 @@ #include "resources/resourcemanager.h" #include "resources/wallpaper.h" +#include "utils/stringutils.h" + Desktop::Desktop() : mWallpaper(0) { @@ -39,7 +42,14 @@ Desktop::Desktop() Wallpaper::loadWallpapers(); - mVersionLabel = new Label(FULL_VERSION); + std::string appName = branding.getValue("appName", ""); + + if (appName.empty()) + mVersionLabel = new Label(FULL_VERSION); + else + mVersionLabel = new Label(strprintf("%s (Mana %s)", appName.c_str(), + FULL_VERSION)); + mVersionLabel->setBackgroundColor(gcn::Color(255, 255, 255, 128)); add(mVersionLabel, 25, 2); } diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp index 32b42553..eb0cdef2 100644 --- a/src/gui/widgets/dropdown.cpp +++ b/src/gui/widgets/dropdown.cpp @@ -32,7 +32,6 @@ #include "gui/widgets/scrollarea.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -54,17 +53,16 @@ DropDown::DropDown(gcn::ListModel *listModel): if (instances == 0) { // Load the background skin - ResourceManager *resman = ResourceManager::getInstance(); // Get the button skin buttons[1][0] = - resman->getImage("graphics/gui/vscroll_up_default.png"); + SkinLoader::getImageFromTheme("vscroll_up_default.png"); buttons[0][0] = - resman->getImage("graphics/gui/vscroll_down_default.png"); + SkinLoader::getImageFromTheme("vscroll_down_default.png"); buttons[1][1] = - resman->getImage("graphics/gui/vscroll_up_pressed.png"); + SkinLoader::getImageFromTheme("vscroll_up_pressed.png"); buttons[0][1] = - resman->getImage("graphics/gui/vscroll_down_pressed.png"); + SkinLoader::getImageFromTheme("vscroll_down_pressed.png"); buttons[0][0]->setAlpha(mAlpha); buttons[0][1]->setAlpha(mAlpha); @@ -72,7 +70,7 @@ DropDown::DropDown(gcn::ListModel *listModel): buttons[1][1]->setAlpha(mAlpha); // get the border skin - Image *boxBorder = resman->getImage("graphics/gui/deepbox.png"); + Image *boxBorder = SkinLoader::getImageFromTheme("deepbox.png"); int gridx[4] = {0, 3, 28, 31}; int gridy[4] = {0, 3, 28, 31}; int a = 0, x, y; diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp index 41be172f..dd13c679 100644 --- a/src/gui/widgets/emoteshortcutcontainer.cpp +++ b/src/gui/widgets/emoteshortcutcontainer.cpp @@ -32,10 +32,10 @@ #include "log.h" #include "gui/palette.h" +#include "gui/skin.h" #include "resources/emotedb.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -49,9 +49,7 @@ EmoteShortcutContainer::EmoteShortcutContainer(): addMouseListener(this); addWidgetListener(this); - ResourceManager *resman = ResourceManager::getInstance(); - - mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png"); + mBackgroundImg = SkinLoader::getImageFromTheme("item_shortcut_bgr.png"); mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8)); diff --git a/src/gui/widgets/itemcontainer.cpp b/src/gui/widgets/itemcontainer.cpp index f801822c..b4270912 100644 --- a/src/gui/widgets/itemcontainer.cpp +++ b/src/gui/widgets/itemcontainer.cpp @@ -32,6 +32,7 @@ #include "gui/outfitwindow.h" #include "gui/palette.h" #include "gui/sdlinput.h" +#include "gui/skin.h" #include "gui/viewport.h" #include "net/net.h" @@ -39,7 +40,6 @@ #include "resources/image.h" #include "resources/iteminfo.h" -#include "resources/resourcemanager.h" #include "utils/stringutils.h" @@ -67,9 +67,7 @@ ItemContainer::ItemContainer(Inventory *inventory, bool forceQuantity): mItemPopup = new ItemPopup; setFocusable(true); - ResourceManager *resman = ResourceManager::getInstance(); - - mSelImg = resman->getImage("graphics/gui/selection.png"); + mSelImg = SkinLoader::getImageFromTheme("selection.png"); if (!mSelImg) logger->error("Unable to load selection.png"); diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp index 66e053d8..92a3e7d0 100644 --- a/src/gui/widgets/itemshortcutcontainer.cpp +++ b/src/gui/widgets/itemshortcutcontainer.cpp @@ -32,11 +32,11 @@ #include "gui/inventorywindow.h" #include "gui/itempopup.h" #include "gui/palette.h" +#include "gui/skin.h" #include "gui/viewport.h" #include "resources/image.h" #include "resources/iteminfo.h" -#include "resources/resourcemanager.h" #include "utils/stringutils.h" @@ -50,9 +50,7 @@ ItemShortcutContainer::ItemShortcutContainer(): mItemPopup = new ItemPopup; - ResourceManager *resman = ResourceManager::getInstance(); - - mBackgroundImg = resman->getImage("graphics/gui/item_shortcut_bgr.png"); + mBackgroundImg = SkinLoader::getImageFromTheme("item_shortcut_bgr.png"); mMaxItems = itemShortcut->getItemCount(); mBackgroundImg->setAlpha(config.getValue("guialpha", 0.8)); diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp index 23da2afd..24395db7 100644 --- a/src/gui/widgets/playerbox.cpp +++ b/src/gui/widgets/playerbox.cpp @@ -26,8 +26,9 @@ #include "graphics.h" #include "player.h" +#include "gui/skin.h" + #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -43,8 +44,7 @@ PlayerBox::PlayerBox(const Player *player): if (instances == 0) { // Load the background skin - ResourceManager *resman = ResourceManager::getInstance(); - Image *textbox = resman->getImage("graphics/gui/deepbox.png"); + Image *textbox = SkinLoader::getImageFromTheme("deepbox.png"); int bggridx[4] = {0, 3, 28, 31}; int bggridy[4] = {0, 3, 28, 31}; int a = 0, x, y; diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp index 391b0eed..970b21ec 100644 --- a/src/gui/widgets/popup.cpp +++ b/src/gui/widgets/popup.cpp @@ -27,6 +27,7 @@ #include "log.h" #include "gui/skin.h" +#include "gui/viewport.h" #include "gui/widgets/windowcontainer.h" @@ -186,3 +187,9 @@ void Popup::position(int x, int y) setVisible(true); requestMoveToTop(); } + +void Popup::mouseMoved(gcn::MouseEvent &event) +{ + if (viewport) + viewport->hideBeingPopup(); +} diff --git a/src/gui/widgets/popup.h b/src/gui/widgets/popup.h index 449c2f7b..5c9164f6 100644 --- a/src/gui/widgets/popup.h +++ b/src/gui/widgets/popup.h @@ -28,6 +28,8 @@ #include "gui/widgets/container.h" +#include <guichan/mouselistener.hpp> + class Skin; class WindowContainer; @@ -43,7 +45,7 @@ class WindowContainer; * * \ingroup GUI */ -class Popup : public Container +class Popup : public Container, public gcn::MouseListener { public: /** @@ -55,7 +57,7 @@ class Popup : public Container * @param skin The location where the Popup's skin XML can be found. */ Popup(const std::string &name = "", - const std::string &skin = "graphics/gui/gui.xml"); + const std::string &skin = "window.xml"); /** * Destructor. Deletes all the added widgets. @@ -94,6 +96,8 @@ class Popup : public Container */ void setLocationRelativeTo(gcn::Widget *widget); + void mouseMoved(gcn::MouseEvent &event); + /** * Sets the minimum width of the popup. */ diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index db2a8692..31c32132 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -30,7 +30,6 @@ #include "gui/skin.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -59,8 +58,7 @@ ProgressBar::ProgressBar(float progress, if (mInstances == 0) { - ResourceManager *resman = ResourceManager::getInstance(); - Image *dBorders = resman->getImage("graphics/gui/vscroll_grey.png"); + Image *dBorders = SkinLoader::getImageFromTheme("vscroll_grey.png"); mBorder.grid[0] = dBorders->getSubImage(0, 0, 4, 4); mBorder.grid[1] = dBorders->getSubImage(4, 0, 3, 4); mBorder.grid[2] = dBorders->getSubImage(7, 0, 4, 4); diff --git a/src/gui/widgets/progressindicator.cpp b/src/gui/widgets/progressindicator.cpp index d1b6bb87..f88f6045 100644 --- a/src/gui/widgets/progressindicator.cpp +++ b/src/gui/widgets/progressindicator.cpp @@ -20,6 +20,8 @@ #include "progressindicator.h" +#include "gui/skin.h" + #include "resources/animation.h" #include "resources/imageset.h" #include "resources/resourcemanager.h" @@ -31,9 +33,8 @@ ProgressIndicator::ProgressIndicator() { - ResourceManager *rm = ResourceManager::getInstance(); - ImageSet *images = rm->getImageSet("graphics/gui/progress-indicator.png", - 32, 32); + ImageSet *images = + SkinLoader::getImageSetFromTheme("progress-indicator.png", 32, 32); Animation *anim = new Animation; for (ImageSet::size_type i = 0; i < images->size(); ++i) diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp index adbc4dd7..41c8faf7 100644 --- a/src/gui/widgets/radiobutton.cpp +++ b/src/gui/widgets/radiobutton.cpp @@ -24,8 +24,9 @@ #include "configuration.h" #include "graphics.h" +#include "gui/skin.h" + #include "resources/image.h" -#include "resources/resourcemanager.h" int RadioButton::instances = 0; float RadioButton::mAlpha = 1.0; @@ -43,13 +44,12 @@ RadioButton::RadioButton(const std::string &caption, const std::string &group, { if (instances == 0) { - ResourceManager *resman = ResourceManager::getInstance(); - radioNormal = resman->getImage("graphics/gui/radioout.png"); - radioChecked = resman->getImage("graphics/gui/radioin.png"); - radioDisabled = resman->getImage("graphics/gui/radioout.png"); - radioDisabledChecked = resman->getImage("graphics/gui/radioin.png"); - radioNormalHi = resman->getImage("graphics/gui/radioout_highlight.png"); - radioCheckedHi = resman->getImage("graphics/gui/radioin_highlight.png"); + radioNormal = SkinLoader::getImageFromTheme("radioout.png"); + radioChecked = SkinLoader::getImageFromTheme("radioin.png"); + radioDisabled = SkinLoader::getImageFromTheme("radioout.png"); + radioDisabledChecked = SkinLoader::getImageFromTheme("radioin.png"); + radioNormalHi = SkinLoader::getImageFromTheme("radioout_highlight.png"); + radioCheckedHi = SkinLoader::getImageFromTheme("radioin_highlight.png"); radioNormal->setAlpha(mAlpha); radioChecked->setAlpha(mAlpha); radioDisabled->setAlpha(mAlpha); diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp index 106118da..d0b9b845 100644 --- a/src/gui/widgets/resizegrip.cpp +++ b/src/gui/widgets/resizegrip.cpp @@ -24,8 +24,9 @@ #include "configuration.h" #include "graphics.h" +#include "gui/skin.h" + #include "resources/image.h" -#include "resources/resourcemanager.h" #include <guichan/graphics.hpp> @@ -38,8 +39,7 @@ ResizeGrip::ResizeGrip(const std::string &image) if (mInstances == 0) { // Load the grip image - ResourceManager *resman = ResourceManager::getInstance(); - gripImage = resman->getImage(image); + gripImage = SkinLoader::getImageFromTheme(image); gripImage->setAlpha(mAlpha); } diff --git a/src/gui/widgets/resizegrip.h b/src/gui/widgets/resizegrip.h index 4cc195cc..5ef93f29 100644 --- a/src/gui/widgets/resizegrip.h +++ b/src/gui/widgets/resizegrip.h @@ -39,7 +39,7 @@ class ResizeGrip : public gcn::Widget /** * Constructor. */ - ResizeGrip(const std::string &image = "graphics/gui/resize.png"); + ResizeGrip(const std::string &image = "resize.png"); /** * Destructor. diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index b3e28329..dea99e8e 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -27,7 +27,6 @@ #include "gui/skin.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -96,8 +95,7 @@ void ScrollArea::init() if (instances == 0) { // Load the background skin - ResourceManager *resman = ResourceManager::getInstance(); - Image *textbox = resman->getImage("graphics/gui/deepbox.png"); + Image *textbox = SkinLoader::getImageFromTheme("deepbox.png"); const int bggridx[4] = {0, 3, 28, 31}; const int bggridy[4] = {0, 3, 28, 31}; int a = 0, x, y; @@ -118,8 +116,8 @@ void ScrollArea::init() textbox->decRef(); // Load vertical scrollbar skin - Image *vscroll = resman->getImage("graphics/gui/vscroll_grey.png"); - Image *vscrollHi = resman->getImage("graphics/gui/vscroll_highlight.png"); + Image *vscroll = SkinLoader::getImageFromTheme("vscroll_grey.png"); + Image *vscrollHi = SkinLoader::getImageFromTheme("vscroll_highlight.png"); int vsgridx[4] = {0, 4, 7, 11}; int vsgridy[4] = {0, 4, 15, 19}; @@ -147,21 +145,21 @@ void ScrollArea::init() vscrollHi->decRef(); buttons[UP][0] = - resman->getImage("graphics/gui/vscroll_up_default.png"); + SkinLoader::getImageFromTheme("vscroll_up_default.png"); buttons[DOWN][0] = - resman->getImage("graphics/gui/vscroll_down_default.png"); + SkinLoader::getImageFromTheme("vscroll_down_default.png"); buttons[LEFT][0] = - resman->getImage("graphics/gui/hscroll_left_default.png"); + SkinLoader::getImageFromTheme("hscroll_left_default.png"); buttons[RIGHT][0] = - resman->getImage("graphics/gui/hscroll_right_default.png"); + SkinLoader::getImageFromTheme("hscroll_right_default.png"); buttons[UP][1] = - resman->getImage("graphics/gui/vscroll_up_pressed.png"); + SkinLoader::getImageFromTheme("vscroll_up_pressed.png"); buttons[DOWN][1] = - resman->getImage("graphics/gui/vscroll_down_pressed.png"); + SkinLoader::getImageFromTheme("vscroll_down_pressed.png"); buttons[LEFT][1] = - resman->getImage("graphics/gui/hscroll_left_pressed.png"); + SkinLoader::getImageFromTheme("hscroll_left_pressed.png"); buttons[RIGHT][1] = - resman->getImage("graphics/gui/hscroll_right_pressed.png"); + SkinLoader::getImageFromTheme("hscroll_right_pressed.png"); } instances++; diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp index f02c6b5c..af36518a 100644 --- a/src/gui/widgets/slider.cpp +++ b/src/gui/widgets/slider.cpp @@ -27,7 +27,6 @@ #include "gui/skin.h" #include "resources/image.h" -#include "resources/resourcemanager.h" Image *Slider::hStart, *Slider::hMid, *Slider::hEnd, *Slider::hGrip; Image *Slider::vStart, *Slider::vMid, *Slider::vEnd, *Slider::vGrip; @@ -83,9 +82,8 @@ void Slider::init() // Load resources if (mInstances == 0) { - ResourceManager *resman = ResourceManager::getInstance(); - Image *slider = resman->getImage("graphics/gui/slider.png"); - Image *sliderHi = resman->getImage("graphics/gui/slider_hilight.png"); + Image *slider = SkinLoader::getImageFromTheme("slider.png"); + Image *sliderHi = SkinLoader::getImageFromTheme("slider_hilight.png"); x = 0; y = 0; w = 15; h = 6; diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index 68dc2190..17145eae 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -30,7 +30,6 @@ #include "gui/widgets/tabbedarea.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/dtor.h" @@ -55,10 +54,10 @@ struct TabData }; static TabData const data[TAB_COUNT] = { - { "graphics/gui/tab.png", 0, 0 }, - { "graphics/gui/tab_hilight.png", 9, 4 }, - { "graphics/gui/tabselected.png", 16, 19 }, - { "graphics/gui/tab.png", 25, 23 } + { "tab.png", 0, 0 }, + { "tab_hilight.png", 9, 4 }, + { "tabselected.png", 16, 19 }, + { "tab.png", 25, 23 } }; ImageRect Tab::tabImg[TAB_COUNT]; @@ -91,14 +90,13 @@ void Tab::init() if (mInstances == 0) { // Load the skin - ResourceManager *resman = ResourceManager::getInstance(); Image *tab[TAB_COUNT]; int a, x, y, mode; for (mode = 0; mode < TAB_COUNT; mode++) { - tab[mode] = resman->getImage(data[mode].file); + tab[mode] = SkinLoader::getImageFromTheme(data[mode].file); a = 0; for (y = 0; y < 3; y++) { diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index 278b4cb9..e599c37d 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -29,7 +29,6 @@ #include "gui/skin.h" #include "resources/image.h" -#include "resources/resourcemanager.h" #include "utils/copynpaste.h" #include "utils/dtor.h" @@ -53,8 +52,7 @@ TextField::TextField(const std::string &text, bool loseFocusOnTab): if (instances == 0) { // Load the skin - ResourceManager *resman = ResourceManager::getInstance(); - Image *textbox = resman->getImage("graphics/gui/deepbox.png"); + Image *textbox = SkinLoader::getImageFromTheme("deepbox.png"); int gridx[4] = {0, 3, 28, 31}; int gridy[4] = {0, 3, 28, 31}; int a = 0, x, y; diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 8505f552..83c918cf 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -27,6 +27,7 @@ #include "gui/gui.h" #include "gui/palette.h" #include "gui/skin.h" +#include "gui/viewport.h" #include "gui/widgets/layout.h" #include "gui/widgets/resizegrip.h" @@ -430,6 +431,9 @@ void Window::mouseMoved(gcn::MouseEvent &event) default: gui->setCursorType(Gui::CURSOR_POINTER); } + + if (viewport) + viewport->hideBeingPopup(); } void Window::mouseDragged(gcn::MouseEvent &event) diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h index a54016bc..b72be9d4 100644 --- a/src/gui/widgets/window.h +++ b/src/gui/widgets/window.h @@ -57,7 +57,7 @@ class Window : public gcn::Window, gcn::WidgetListener * @param skin The location where the window's skin XML can be found. */ Window(const std::string &caption = "Window", bool modal = false, - Window *parent = NULL, const std::string &skin = "graphics/gui/gui.xml"); + Window *parent = NULL, const std::string &skin = "window.xml"); /** * Destructor. Deletes all the added widgets. diff --git a/src/item.cpp b/src/item.cpp index e20ef57a..378c7efe 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -21,6 +21,8 @@ #include "item.h" +#include "gui/skin.h" + #include "resources/image.h" #include "resources/iteminfo.h" #include "resources/resourcemanager.h" @@ -60,8 +62,8 @@ void Item::setId(int id) mDrawImage = resman->getImage(imagePath); if (!mImage) - mImage = resman->getImage("graphics/gui/unknown-item.png"); + mImage = SkinLoader::getImageFromTheme("unknown-item.png"); if (!mDrawImage) - mDrawImage = resman->getImage("graphics/gui/unknown-item.png"); + mDrawImage = SkinLoader::getImageFromTheme("unknown-item.png"); } diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index 8d1f0bcd..7b462c25 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -156,15 +156,24 @@ bool KeyboardConfig::hasConflicts() { for (j = i, j++; j < KEY_TOTAL; j++) { - // Allow for item shortcut and emote keys to overlap - // as well as emote and ignore keys, but no other keys - if (!((((i >= KEY_SHORTCUT_1) && (i <= KEY_SHORTCUT_12)) && - ((j >= KEY_EMOTE_1) && (j <= KEY_EMOTE_12))) || - ((i == KEY_TOGGLE_CHAT) && (j == KEY_OK)) || - ((i == KEY_EMOTE) && - (j == KEY_IGNORE_INPUT_1 || j == KEY_IGNORE_INPUT_2))) && - (mKey[i].value == mKey[j].value) - ) + // Allow collisions between shortcut and emote keys + if ((i >= KEY_SHORTCUT_1 && i <= KEY_SHORTCUT_12) && (j >= KEY_EMOTE_1 && j <= KEY_EMOTE_12)) + continue; + + // Why? + if (i == KEY_TOGGLE_CHAT && j == KEY_OK) + continue; + + // Ignore keys can collide with anything. + if (j == KEY_IGNORE_INPUT_1 || j == KEY_IGNORE_INPUT_2) + continue; + + // If the one of the keys is not set, then no conflict can happen. + if (mKey[i].value == -1 || mKey[j].value == -1) + continue; + + // Finally test to see if a conflict DOES exist. + if (mKey[i].value == mKey[j].value) { mBindError = strprintf(_("Conflict \"%s\" and \"%s\" keys. " "Resolve them, or gameplay may result" diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 8ce03bba..8c918a97 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -43,6 +43,7 @@ #include "gui/ministatus.h" #include "gui/palette.h" #include "gui/skilldialog.h" +#include "gui/skin.h" #include "gui/statuswindow.h" #include "gui/storagewindow.h" @@ -102,11 +103,6 @@ LocalPlayer::LocalPlayer(int id, int job): mLocalWalkTime(-1), mMessageTime(0) { - // Variable to keep the local player from doing certain actions before a map - // is initialized. e.g. drawing a player's name using the TextManager, since - // it appears to be dependant upon map coordinates for updating drawing. - mMapInitialized = false; - mUpdateName = true; mTextColor = &guiPalette->getColor(Palette::PLAYER); @@ -1050,18 +1046,12 @@ void LocalPlayer::handleStatusEffect(StatusEffect *effect, int effectId) void LocalPlayer::initTargetCursor() { // Load target cursors - loadTargetCursor("graphics/gui/target-cursor-blue-s.png", 44, 35, - false, TC_SMALL); - loadTargetCursor("graphics/gui/target-cursor-red-s.png", 44, 35, - true, TC_SMALL); - loadTargetCursor("graphics/gui/target-cursor-blue-m.png", 62, 44, - false, TC_MEDIUM); - loadTargetCursor("graphics/gui/target-cursor-red-m.png", 62, 44, - true, TC_MEDIUM); - loadTargetCursor("graphics/gui/target-cursor-blue-l.png", 82, 60, - false, TC_LARGE); - loadTargetCursor("graphics/gui/target-cursor-red-l.png", 82, 60, - true, TC_LARGE); + loadTargetCursor("target-cursor-blue-s.png", 44, 35, false, TC_SMALL); + loadTargetCursor("target-cursor-red-s.png", 44, 35, true, TC_SMALL); + loadTargetCursor("target-cursor-blue-m.png", 62, 44, false, TC_MEDIUM); + loadTargetCursor("target-cursor-red-m.png", 62, 44, true, TC_MEDIUM); + loadTargetCursor("target-cursor-blue-l.png", 82, 60, false, TC_LARGE); + loadTargetCursor("target-cursor-red-l.png", 82, 60, true, TC_LARGE); } void LocalPlayer::loadTargetCursor(const std::string &filename, @@ -1071,9 +1061,8 @@ void LocalPlayer::loadTargetCursor(const std::string &filename, assert(size > -1); assert(size < 3); - ResourceManager *resman = ResourceManager::getInstance(); - - ImageSet *currentImageSet = resman->getImageSet(filename, width, height); + ImageSet *currentImageSet = SkinLoader::getImageSetFromTheme(filename, + width, height); Animation *anim = new Animation; for (unsigned int i = 0; i < currentImageSet->size(); ++i) diff --git a/src/localplayer.h b/src/localplayer.h index 919b5540..69fd4d0f 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -391,17 +391,6 @@ class LocalPlayer : public Player */ bool getCheckNameSetting() const { return mUpdateName; } - /** - * Set if the current map is initialized. - */ - void setMapInitialized(bool initialized) - { mMapInitialized = initialized; } - - /** - * Tells if the current map is initialized. - */ - bool isMapInitialized() const { return mMapInitialized; } - /** Keeps the Equipment related values */ const std::auto_ptr<Equipment> mEquipment; @@ -410,8 +399,6 @@ class LocalPlayer : public Player /** Whether or not the name settings have changed */ bool mUpdateName; - bool mMapInitialized; /**< Whether or not the map is available yet */ - virtual void handleStatusEffect(StatusEffect *effect, int effectId); // Colors don't change for local player @@ -55,7 +55,7 @@ #elif defined WIN32 #include "winver.h" #elif defined __APPLE__ -#define PACKAGE_VERSION "0.0.29.1" +#define PACKAGE_VERSION "1.0.0" #endif #ifdef PACKAGE_VERSION @@ -64,6 +64,33 @@ #define FULL_VERSION "Unknown Version" #endif +#ifdef PACKAGE_OS +// If it's already been defined, let's not change it +#elif defined __APPLE__ +#define PACKAGE_OS "Apple" +#elif defined __FreeBSD__ || defined __DragonFly__ +#define PACKAGE_OS "FreeBSD" +#elif defined __NetBSD__ +#define PACKAGE_OS "NetBSD" +#elif defined __OpenBSD__ +#define PACKAGE_OS "OpenBSD" +#elif defined __linux__ || defined __linux +#define PACKAGE_OS "Linux" +#elif defined __GNU__ +#define PACKAGE_OS "GNU Hurd" +#elif defined WIN32 || defined _WIN32 || defined __WIN32__ || defined __NT__ \ + || defined WIN64 || defined _WIN64 || defined __WIN64__ +#define PACKAGE_OS "Windows" +#else +#define PACKAGE_OS "Other" +#endif + +#ifdef PACKAGE_VERSION +#define PACKAGE_EXTENDED_VERSION "Mana/" PACKAGE_VERSION " (" PACKAGE_OS "; %s)" +#else +#define PACKAGE_EXTENDED_VERSION "Mana (" PACKAGE_OS "; %s)" +#endif + #ifndef PKG_DATADIR #define PKG_DATADIR "" #endif diff --git a/src/net/download.cpp b/src/net/download.cpp index ba5b6b35..2b96a6b9 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -20,9 +20,12 @@ #include "net/download.h" +#include "configuration.h" #include "log.h" #include "main.h" +#include "utils/stringutils.h" + #include <curl/curl.h> #include <SDL.h> @@ -217,11 +220,9 @@ int Download::downloadThread(void *ptr) curl_easy_setopt(d->mCurl, CURLOPT_WRITEDATA, file); } -#ifdef PACKAGE_VERSION - curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT, "Mana/" PACKAGE_VERSION); -#else - curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT, "Mana"); -#endif + curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT, + strprintf(PACKAGE_EXTENDED_VERSION, branding + .getValue("appShort", "mana").c_str()).c_str()); curl_easy_setopt(d->mCurl, CURLOPT_ERRORBUFFER, d->mError); curl_easy_setopt(d->mCurl, CURLOPT_URL, d->mUrl.c_str()); curl_easy_setopt(d->mCurl, CURLOPT_NOPROGRESS, 0); diff --git a/src/net/ea/generalhandler.cpp b/src/net/ea/generalhandler.cpp index 6ca853fb..021ae08d 100644 --- a/src/net/ea/generalhandler.cpp +++ b/src/net/ea/generalhandler.cpp @@ -38,6 +38,7 @@ #include "net/ea/chathandler.h" #include "net/ea/charserverhandler.h" #include "net/ea/gamehandler.h" +#include "net/ea/guildhandler.h" #include "net/ea/inventoryhandler.h" #include "net/ea/itemhandler.h" #include "net/ea/loginhandler.h" @@ -79,6 +80,7 @@ GeneralHandler::GeneralHandler(): mCharHandler(new CharServerHandler), mChatHandler(new ChatHandler), mGameHandler(new GameHandler), + mGuildHandler(new GuildHandler), mInventoryHandler(new InventoryHandler), mItemHandler(new ItemHandler), mLoginHandler(new LoginHandler), @@ -162,6 +164,7 @@ void GeneralHandler::load() mNetwork->registerHandler(mChatHandler.get()); mNetwork->registerHandler(mCharHandler.get()); mNetwork->registerHandler(mGameHandler.get()); + mNetwork->registerHandler(mGuildHandler.get()); mNetwork->registerHandler(mInventoryHandler.get()); mNetwork->registerHandler(mItemHandler.get()); mNetwork->registerHandler(mLoginHandler.get()); diff --git a/src/net/ea/generalhandler.h b/src/net/ea/generalhandler.h index 579b27b5..464f8bc8 100644 --- a/src/net/ea/generalhandler.h +++ b/src/net/ea/generalhandler.h @@ -60,6 +60,7 @@ class GeneralHandler : public MessageHandler, public Net::GeneralHandler MessageHandlerPtr mCharHandler; MessageHandlerPtr mChatHandler; MessageHandlerPtr mGameHandler; + MessageHandlerPtr mGuildHandler; MessageHandlerPtr mInventoryHandler; MessageHandlerPtr mItemHandler; MessageHandlerPtr mLoginHandler; diff --git a/src/net/ea/messageout.cpp b/src/net/ea/messageout.cpp index 9e7f2b15..844580a9 100644 --- a/src/net/ea/messageout.cpp +++ b/src/net/ea/messageout.cpp @@ -125,4 +125,4 @@ void MessageOut::writeCoordinates(unsigned short x, unsigned short y, data[2] |= direction; } -} +} // namespace EAthena diff --git a/src/net/ea/network.cpp b/src/net/ea/network.cpp index 3b8ad509..0467241f 100644 --- a/src/net/ea/network.cpp +++ b/src/net/ea/network.cpp @@ -475,4 +475,4 @@ Uint16 Network::readWord(int pos) #endif } -} +} // namespace EAthena diff --git a/src/net/ea/network.h b/src/net/ea/network.h index baaefb4a..0b391bf0 100644 --- a/src/net/ea/network.h +++ b/src/net/ea/network.h @@ -125,6 +125,6 @@ class Network static Network *mInstance; }; -} +} // namespace EAthena #endif // NET_EA_NETWORK_H diff --git a/src/net/ea/npchandler.cpp b/src/net/ea/npchandler.cpp index 06a39045..dfd56cf1 100644 --- a/src/net/ea/npchandler.cpp +++ b/src/net/ea/npchandler.cpp @@ -72,10 +72,12 @@ void NpcHandler::handleMessage(Net::MessageIn &msg) if (msg.getId() == SMSG_NPC_CLOSE) { closeDialog(npcId); + return; } else if (msg.getId() == SMSG_NPC_NEXT) { nextDialog(npcId); + return; } else { diff --git a/src/net/guildhandler.h b/src/net/guildhandler.h index 75683944..1696b2d5 100644 --- a/src/net/guildhandler.h +++ b/src/net/guildhandler.h @@ -32,6 +32,10 @@ namespace Net { class GuildHandler { public: + virtual ~GuildHandler() {} + + virtual bool isSupported() { return false; } + virtual void create(const std::string &name) = 0; virtual void invite(int guildId, const std::string &name) = 0; @@ -56,8 +60,6 @@ class GuildHandler bool response) = 0; virtual void endAlliance(int guildId, int otherGuildId) = 0; - - virtual ~GuildHandler() {} }; } diff --git a/src/net/manaserv/guildhandler.h b/src/net/manaserv/guildhandler.h index 1b6d51b5..9929d135 100644 --- a/src/net/manaserv/guildhandler.h +++ b/src/net/manaserv/guildhandler.h @@ -33,6 +33,8 @@ class GuildHandler : public Net::GuildHandler, public MessageHandler public: GuildHandler(); + bool isSupported() { return true; } + void handleMessage(Net::MessageIn &msg); void create(const std::string &name); diff --git a/src/net/manaserv/messageout.cpp b/src/net/manaserv/messageout.cpp index 887d91d6..8779c5f6 100644 --- a/src/net/manaserv/messageout.cpp +++ b/src/net/manaserv/messageout.cpp @@ -61,4 +61,4 @@ void MessageOut::writeInt32(Sint32 value) mPos += 4; } -} +} // namespace ManaServ diff --git a/src/net/serverinfo.h b/src/net/serverinfo.h index ae06984b..63d50ce4 100644 --- a/src/net/serverinfo.h +++ b/src/net/serverinfo.h @@ -41,10 +41,13 @@ public: std::string hostname; unsigned short port; + bool save; + ServerInfo() { type = UNKNOWN; port = 0; + save = false; } ServerInfo(const ServerInfo &info) @@ -53,6 +56,12 @@ public: name = info.name; hostname = info.hostname; port = info.port; + save = info.save; + } + + bool isValid() const + { + return !(hostname.empty() || port == 0 || type == UNKNOWN); } void clear() @@ -63,13 +72,13 @@ public: port = 0; } - bool operator==(const ServerInfo &other) + bool operator==(const ServerInfo &other) const { return (type == other.type && hostname == other.hostname && port == other.port); } - bool operator!=(const ServerInfo &other) + bool operator!=(const ServerInfo &other) const { return (type != other.type || hostname != other.hostname || port != other.port); diff --git a/src/npc.cpp b/src/npc.cpp index d104e840..38aecab8 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -86,7 +86,7 @@ void NPC::setSprite(unsigned int slot, int id, const std::string &color) // Do nothing } -const bool NPC::isTalking() +bool NPC::isTalking() { return NpcDialog::isActive() || BuyDialog::isActive() || SellDialog::isActive() || BuySellDialog::isActive() || @@ -55,7 +55,7 @@ class NPC : public Player virtual int getNumberOfLayers() const { return 1; } - static const bool isTalking(); + static bool isTalking(); protected: /** diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 8b5ecca3..24f346f7 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -21,6 +21,7 @@ #include "resources/resourcemanager.h" +#include "client.h" #include "log.h" #include "resources/dye.h" @@ -211,7 +212,7 @@ std::string ResourceManager::getPath(const std::string &file) else { // if not found in search path return the default path - path = std::string(PKG_DATADIR) + std::string("data") + "/" + file; + path = Client::getPackageDirectory() + "/" + file; } return path; diff --git a/src/text.cpp b/src/text.cpp index 0b6b77ea..ce09146f 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -28,6 +28,7 @@ #include "gui/gui.h" #include "gui/palette.h" +#include "gui/skin.h" #include "resources/resourcemanager.h" #include "resources/image.h" @@ -49,8 +50,7 @@ Text::Text(const std::string &text, int x, int y, if (textManager == 0) { textManager = new TextManager; - ResourceManager *resman = ResourceManager::getInstance(); - Image *sbImage = resman->getImage("graphics/gui/bubble.png|W:#" + Image *sbImage = SkinLoader::getImageFromTheme("bubble.png|W:#" + config.getValue("speechBubblecolor", "000000")); mBubble.grid[0] = sbImage->getSubImage(0, 0, 5, 5); mBubble.grid[1] = sbImage->getSubImage(5, 0, 5, 5); diff --git a/src/utils/mkdir.cpp b/src/utils/mkdir.cpp index 223abe71..43f5264e 100644 --- a/src/utils/mkdir.cpp +++ b/src/utils/mkdir.cpp @@ -24,10 +24,10 @@ #if defined WIN32 #include <windows.h> -#else -#include <sys/stat.h> #endif +#include <sys/stat.h> + #ifdef _MKDIR_TEST_ // compile with -D_MKDIR_TEST_ to get a standalone binary #include <cstdio> @@ -67,12 +67,24 @@ int mkdir_r(const char *pathname) { *p = '/'; continue; } + + // check if the name already exists, but not as directory + struct stat statbuf; + if (!stat(tmp, &statbuf)) + { + if (S_ISDIR(statbuf.st_mode)) + { + *p = '/'; + continue; + } + else + return -1; + } + #if defined WIN32 - if (!CreateDirectory(tmp, 0) && - GetLastError() != ERROR_ALREADY_EXISTS) + if (!CreateDirectory(tmp, 0)) #else - if (mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) && - errno != EEXIST) + if (mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) #endif { #if defined WIN32 diff --git a/update-creator.sh b/update-creator.sh index e0c5463f..edda5613 100755 --- a/update-creator.sh +++ b/update-creator.sh @@ -4,4 +4,5 @@ find -name \*.cpp \ -o -name \*.am \ -o -name \*.txt \ -o -name \*.xml \ + -o -name \*.mana \ | sort > mana.files |