diff options
author | Andrei Karas <akaras@inbox.ru> | 2013-11-09 17:59:14 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2013-11-09 17:59:14 +0300 |
commit | db1e60556c72b1b87ff2a384c556ccca724c46d6 (patch) | |
tree | 22a5f4e9c4f436ef8e746e0a2d688de80c1597a6 /src | |
parent | c2bb49be52a92deccec7428b6859242688fc8987 (diff) | |
parent | 1716861f0ee2f7a3714c5b44bb0f017c3d8d3b2c (diff) | |
download | plus-db1e60556c72b1b87ff2a384c556ccca724c46d6.tar.gz plus-db1e60556c72b1b87ff2a384c556ccca724c46d6.tar.bz2 plus-db1e60556c72b1b87ff2a384c556ccca724c46d6.tar.xz plus-db1e60556c72b1b87ff2a384c556ccca724c46d6.zip |
Merge branch 'master' into stable
Diffstat (limited to 'src')
132 files changed, 1763 insertions, 661 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 254704a88..e516662e8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -420,6 +420,7 @@ SET(SRCS net/npchandler.h net/net.cpp net/net.h + net/netconsts.h net/partyhandler.h net/playerhandler.h net/sdltcpnet.cpp @@ -553,6 +554,8 @@ SET(SRCS utils/stringutils.cpp utils/stringutils.h utils/stringvector.h + utils/timer.cpp + utils/timer.h utils/mutex.h utils/mkdir.cpp utils/mkdir.h diff --git a/src/Makefile.am b/src/Makefile.am index 9f07e72f7..ec6622a88 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = subdir-objects -bin_PROGRAMS = manaplus +bin_PROGRAMS = manaplus dyecmd manaplus_CXXFLAGS = -DPKG_DATADIR=\""$(pkgdatadir)/"\" \ -DLOCALEDIR=\""$(localedir)"\" \ @@ -25,16 +25,137 @@ else manaplus_SOURCES = endif +if USE_INTERNALGUICHAN +dyecmd_CXXFLAGS = -I$(srcdir)/guichan/include -DUSE_INTERNALGUICHAN +dyecmd_SOURCES = guichan/actionevent.cpp \ + guichan/cliprectangle.cpp \ + guichan/color.cpp \ + guichan/event.cpp \ + guichan/exception.cpp \ + guichan/font.cpp \ + guichan/graphics.cpp \ + guichan/rectangle.cpp \ + guichan/widget.cpp \ + guichan/include/guichan/actionevent.hpp \ + guichan/include/guichan/cliprectangle.hpp \ + guichan/include/guichan/color.hpp \ + guichan/include/guichan/event.hpp \ + guichan/include/guichan/exception.hpp \ + guichan/include/guichan/font.hpp \ + guichan/include/guichan/graphics.hpp \ + guichan/include/guichan/rectangle.hpp \ + guichan/include/guichan/widget.hpp +else +dyecmd_CXXFLAGS = +dyecmd_SOURCES = +endif + +dyecmd_SOURCES += dyetool/dyemain.cpp \ + animatedsprite.cpp \ + animatedsprite.h \ + animationdelayload.cpp \ + animationdelayload.h \ + configuration.cpp \ + configuration.h \ + graphicsmanager.cpp \ + graphicsmanager.h \ + graphicsvertexes.cpp \ + graphicsvertexes.h \ + logger.cpp \ + logger.h \ + navigationmanager.cpp \ + navigationmanager.h \ + walklayer.cpp \ + walklayer.h \ + render/graphics.cpp \ + render/graphics.h \ + render/renderers.cpp \ + render/renderers.h \ + render/sdl2softwaregraphics.cpp \ + render/sdl2softwaregraphics.h \ + render/sdl2graphics.cpp \ + render/sdl2graphics.h \ + render/sdlgraphics.cpp \ + render/sdlgraphics.h \ + resources/action.cpp \ + resources/action.h \ + resources/animation.cpp \ + resources/animation.h \ + resources/db/palettedb.cpp \ + resources/db/palettedb.h \ + resources/dye.cpp \ + resources/dye.h \ + resources/image.cpp \ + resources/image.h \ + resources/imagehelper.cpp \ + resources/imagehelper.h \ + resources/imageset.cpp \ + resources/imageset.h \ + resources/imagewriter.cpp \ + resources/imagewriter.h \ + resources/resource.cpp \ + resources/resource.h \ + resources/resourcemanager.cpp \ + resources/resourcemanager.h \ + resources/sdl2softwareimagehelper.cpp \ + resources/sdl2softwareimagehelper.h \ + resources/sdl2imagehelper.cpp \ + resources/sdl2imagehelper.h \ + resources/sdlimagehelper.cpp \ + resources/sdlimagehelper.h \ + resources/sdlmusic.cpp \ + resources/sdlmusic.h \ + resources/soundeffect.cpp \ + resources/soundeffect.h \ + resources/subimage.cpp \ + resources/subimage.h \ + resources/surfaceimagehelper.cpp \ + resources/surfaceimagehelper.h \ + resources/spritedef.cpp \ + resources/spritedef.h \ + utils/mkdir.cpp \ + utils/mkdir.h \ + utils/paths.cpp \ + utils/paths.h \ + utils/physfsrwops.cpp \ + utils/physfsrwops.h \ + utils/physfstools.cpp \ + utils/physfstools.h \ + utils/sdl2helper.cpp \ + utils/sdl2helper.h \ + utils/sdlhelper.cpp \ + utils/sdlhelper.h \ + utils/stringutils.cpp \ + utils/stringutils.h \ + utils/timer.cpp \ + utils/timer.h \ + utils/xml.cpp \ + utils/xml.h \ + utils/translation/podict.cpp \ + utils/translation/podict.h + if USE_MUMBLE manaplus_CXXFLAGS += -DUSE_MUMBLE endif +if ENABLE_CHECKS +manaplus_CXXFLAGS += -DENABLE_CHECKS +endif + if USE_SDL2 +if USE_INTERNALSDLGFX +dyecmd_CXXFLAGS += -I$(srcdir)/sdl2gfx -DUSE_SDL2 +dyecmd_SOURCES += sdl2gfx/SDL2_framerate.c \ + sdl2gfx/SDL2_framerate.h \ + sdl2gfx/SDL2_rotozoom.c \ + sdl2gfx/SDL2_rotozoom.h + manaplus_CXXFLAGS += -I$(srcdir)/sdl2gfx -DUSE_SDL2 -manaplus_SOURCES += sdl2gfx/SDL_framerate.c \ - sdl2gfx/SDL_framerate.h \ - sdl2gfx/SDL_rotozoom.c \ - sdl2gfx/SDL_rotozoom.h +manaplus_SOURCES += sdl2gfx/SDL2_framerate.c \ + sdl2gfx/SDL2_framerate.h \ + sdl2gfx/SDL2_rotozoom.c \ + sdl2gfx/SDL2_rotozoom.h +endif endif if USE_INTERNALGUICHAN @@ -430,6 +551,7 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ net/messageout.h \ net/net.cpp \ net/net.h \ + net/netconsts.h \ net/npchandler.h \ net/partyhandler.h \ net/playerhandler.h \ @@ -473,8 +595,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/image.h \ resources/imagehelper.cpp \ resources/imagehelper.h \ - resources/imageset.h \ resources/imageset.cpp \ + resources/imageset.h \ resources/imagewriter.cpp \ resources/imagewriter.h \ resources/db/itemdb.cpp \ @@ -568,6 +690,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ utils/stringutils.cpp \ utils/stringutils.h \ utils/stringvector.h \ + utils/timer.cpp \ + utils/timer.h \ utils/mutex.h \ utils/xml.cpp \ utils/xml.h \ @@ -914,6 +1038,7 @@ manaplus_SOURCES += \ animatedsprite_unittest.cc \ gui/sdlfont_unittest.cc \ gui/widgets/browserbox_unittest.cc \ + utils/files_unittest.cc \ utils/stringutils_unittest.cc \ resources/dye_unittest.cc endif diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp index e34482c13..7d3b653a8 100644 --- a/src/actionmanager.cpp +++ b/src/actionmanager.cpp @@ -139,6 +139,13 @@ impHandler(moveRight) return false; } +impHandler(moveForward) +{ + if (inputManager.isActionActive(Input::KEY_EMOTE)) + return directRight(event); + return false; +} + impHandler(emote) { const int emotion = 1 + event.action - Input::KEY_EMOTE_1; diff --git a/src/actionmanager.h b/src/actionmanager.h index 8f15e4442..2088eddf7 100644 --- a/src/actionmanager.h +++ b/src/actionmanager.h @@ -31,6 +31,7 @@ namespace ActionManager decHandler(moveDown); decHandler(moveLeft); decHandler(moveRight); + decHandler(moveForward); decHandler(emote); decHandler(outfit); decHandler(moveToPoint); diff --git a/src/actormanager.cpp b/src/actormanager.cpp index f37cc9a18..d7a272284 100644 --- a/src/actormanager.cpp +++ b/src/actormanager.cpp @@ -212,6 +212,7 @@ ActorManager::ActorManager() : ActorManager::~ActorManager() { config.removeListeners(this); + CHECKLISTENERS storeAttackList(); clear(); } diff --git a/src/being/actorsprite.cpp b/src/being/actorsprite.cpp index 5dc114380..327996e2d 100644 --- a/src/being/actorsprite.cpp +++ b/src/being/actorsprite.cpp @@ -21,7 +21,6 @@ #include "being/actorsprite.h" -#include "client.h" #include "configuration.h" #include "imagesprite.h" #include "statuseffect.h" @@ -34,6 +33,7 @@ #include "resources/resourcemanager.h" #include "utils/checkutils.h" +#include "utils/timer.h" #include "debug.h" diff --git a/src/being/being.cpp b/src/being/being.cpp index fdd706bbe..cda6557e4 100644 --- a/src/being/being.cpp +++ b/src/being/being.cpp @@ -68,6 +68,7 @@ #include "gui/widgets/tabs/langtab.h" #include "utils/gettext.h" +#include "utils/timer.h" #include "debug.h" @@ -214,6 +215,7 @@ Being::Being(const int id, const Type type, const uint16_t subtype, Being::~Being() { config.removeListener("visiblenames", this); + CHECKLISTENERS delete [] mSpriteRemap; mSpriteRemap = nullptr; diff --git a/src/being/compoundsprite.cpp b/src/being/compoundsprite.cpp index f7adddf50..3a615aa2b 100644 --- a/src/being/compoundsprite.cpp +++ b/src/being/compoundsprite.cpp @@ -21,7 +21,6 @@ #include "being/compoundsprite.h" -#include "client.h" #include "configuration.h" #include "game.h" @@ -39,6 +38,9 @@ #include "utils/dtor.h" #include "utils/sdlcheckutils.h" +#include "utils/timer.h" + +#include <SDL_endian.h> #include "debug.h" diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp index 6df48dec7..974660db3 100644 --- a/src/being/localplayer.cpp +++ b/src/being/localplayer.cpp @@ -67,6 +67,7 @@ #include "resources/iteminfo.h" #include "utils/gettext.h" +#include "utils/timer.h" #include "mumblemanager.h" diff --git a/src/client.cpp b/src/client.cpp index 8f1110162..e2ce0af74 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -75,12 +75,14 @@ #include "gui/widgets/button.h" #include "gui/widgets/desktop.h" +#include "net/chathandler.h" #include "net/gamehandler.h" #include "net/generalhandler.h" #include "net/guildhandler.h" #include "net/inventoryhandler.h" #include "net/loginhandler.h" #include "net/net.h" +#include "net/netconsts.h" #include "net/partyhandler.h" #include "resources/imagehelper.h" @@ -114,6 +116,7 @@ #include "utils/process.h" #include "utils/sdlcheckutils.h" #include "utils/sdlhelper.h" +#include "utils/timer.h" #include "utils/translation/translationmanager.h" @@ -146,34 +149,28 @@ #include "debug.h" -/** - * Tells the max tick value, - * setting it back to zero (and start again). - */ -static const int MAX_TICK_VALUE = INT_MAX / 2; +#if defined __native_client__ +#define _nacl_dir std::string("/persistent/manaplus") +#endif + +#ifdef ANDROID +#ifdef USE_SDL2 +int loadingProgressCounter = 1; +#endif +#endif std::string errorMessage; ErrorListener errorListener; LoginData loginData; -Configuration config; // XML file configuration reader -Configuration serverConfig; // XML file server configuration reader -Configuration features; // XML file features -Configuration branding; // XML branding information reader -Configuration paths; // XML default paths information reader Client *client = nullptr; -Logger *logger = nullptr; // Log object ChatLogger *chatLogger = nullptr; // Chat log object KeyboardConfig keyboard; UserPalette *userPalette = nullptr; -Graphics *mainGraphics = nullptr; SoundManager soundManager; RenderType openGLMode = RENDER_SOFTWARE; -static uint32_t nextTick(uint32_t interval, void *param A_UNUSED); -static uint32_t nextSecond(uint32_t interval, void *param A_UNUSED); - void ErrorListener::action(const gcn::ActionEvent &event) { if (event.getId() == "yes") @@ -181,12 +178,6 @@ void ErrorListener::action(const gcn::ActionEvent &event) client->setState(STATE_CHOOSE_SERVER); } -volatile int tick_time; /**< Tick counter */ -volatile int fps = 0; /**< Frames counted in the last second */ -volatile int lps = 0; /**< Logic processed per second */ -volatile int frame_count = 0; /**< Counts the frames during one second */ -volatile int logic_count = 0; /**< Counts the logic during one second */ -volatile int cur_time; volatile bool runCounters; bool isSafeMode = false; int serverVersion = 0; @@ -199,60 +190,6 @@ int textures_count = 0; extern "C" char const *_nl_locale_name_default(void); #endif -/** - * Advances game logic counter. - * Called every 10 milliseconds by SDL_AddTimer() - * @see MILLISECONDS_IN_A_TICK value - */ -static uint32_t nextTick(uint32_t interval, void *param A_UNUSED) -{ - tick_time++; - if (tick_time == MAX_TICK_VALUE) - tick_time = 0; - return interval; -} - -/** - * Updates fps. - * Called every seconds by SDL_AddTimer() - */ -static uint32_t nextSecond(uint32_t interval, void *param A_UNUSED) -{ - fps = frame_count; - lps = logic_count; - frame_count = 0; - logic_count = 0; - - return interval; -} - -/** - * @return the elapsed time in milliseconds - * between two tick values. - */ -int get_elapsed_time(const int startTime) -{ - const int time = tick_time; - if (startTime <= time) - { - return (time - startTime) * MILLISECONDS_IN_A_TICK; - } - else - { - return (time + (MAX_TICK_VALUE - startTime)) - * MILLISECONDS_IN_A_TICK; - } -} - -int get_elapsed_time1(const int startTime) -{ - const int time = tick_time; - if (startTime <= time) - return time - startTime; - else - return time + (MAX_TICK_VALUE - startTime); -} - class AccountListener final : public gcn::ActionListener { public: @@ -274,7 +211,6 @@ class LoginListener final : public gcn::ActionListener Client::Client(const Options &options) : gcn::ActionListener(), mOptions(options), - mPackageDir(), mConfigDir(), mServerConfigDir(), mLocalDataDir(), @@ -303,13 +239,6 @@ Client::Client(const Options &options) : mState(STATE_CHOOSE_SERVER), mOldState(STATE_START), mIcon(nullptr), -#ifdef USE_SDL2 - mLogicCounterId(0), - mSecondsCounterId(0), -#else - mLogicCounterId(nullptr), - mSecondsCounterId(nullptr), -#endif mCaption(), mFpsManager(), mSkin(nullptr), @@ -387,86 +316,7 @@ void Client::gameInit() "Exiting.", mLocalDataDir.c_str())); } -#ifdef ANDROID -#ifdef USE_SDL2 - extractAssets(); - - const std::string zipName = std::string(getenv( - "APPDIR")).append("/data.zip"); - const std::string dirName = std::string(getenv( - "APPDIR")).append("/data"); - Files::extractZip(zipName, "data", dirName); - Files::extractLocale(); -#endif -#endif - -#ifdef ENABLE_NLS - std::string lang = config.getStringValue("lang"); -#ifdef WIN32 - if (lang.empty()) - lang = std::string(_nl_locale_name_default()); - - putenv(const_cast<char*>(("LANG=" + lang).c_str())); - putenv(const_cast<char*>(("LANGUAGE=" + lang).c_str())); - // mingw doesn't like LOCALEDIR to be defined for some reason - if (lang != "C") - bindTextDomain("manaplus", "translations/"); -#else - if (!lang.empty()) - { - setEnv("LANG", lang.c_str()); - setEnv("LANGUAGE", lang.c_str()); - } -#ifdef ANDROID -#ifdef USE_SDL2 - bindTextDomain("manaplus", (std::string(getenv("APPDIR")).append( - "/locale")).c_str()); -#else - bindTextDomain("manaplus", (std::string(PhysFs::getBaseDir()) - .append("/locale")).c_str()); -#endif -#else -#ifdef ENABLE_PORTABLE - bindTextDomain("manaplus", (std::string(PhysFs::getBaseDir()) - .append("../locale/")).c_str()); -#else -#ifdef __APPLE__ - bindTextDomain("manaplus", (std::string(PhysFs::getBaseDir()) - .append("ManaPlus.app/Contents/Resources/locale/")).c_str()); -#else - bindTextDomain("manaplus", LOCALEDIR); -#endif -#endif -#endif -#endif - char *locale = setlocale(LC_MESSAGES, lang.c_str()); - if (locale) - { - logger->log("locale: %s", locale); - } - else - { - locale = setlocale(LC_MESSAGES, (lang + ".utf8").c_str()); - if (locale) - logger->log("locale: %s", locale); - else - logger->log("locale empty"); - } - bind_textdomain_codeset("manaplus", "UTF-8"); - textdomain("manaplus"); -#endif - -#if defined(WIN32) || defined(__APPLE__) - if (config.getBoolValue("centerwindow")) - setEnv("SDL_VIDEO_CENTERED", "1"); - else - setEnv("SDL_VIDEO_CENTERED", "0"); -#endif - - if (config.getBoolValue("allowscreensaver")) - setEnv("SDL_VIDEO_ALLOW_SCREENSAVER", "1"); - else - setEnv("SDL_VIDEO_ALLOW_SCREENSAVER", "0"); + initLang(); chatLogger = new ChatLogger; if (mOptions.chatLogDir.empty()) @@ -504,72 +354,9 @@ void Client::gameInit() SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE); SDL_EventState(SDL_USEREVENT, SDL_IGNORE); - if (mOptions.test.empty()) - { - mCaption = strprintf("%s %s", - branding.getStringValue("appName").c_str(), - SMALL_VERSION); - } - else - { - mCaption = strprintf( - "Please wait - VIDEO MODE TEST - %s %s - Please wait", - branding.getStringValue("appName").c_str(), - SMALL_VERSION); - } - - resman->addToSearchPath(PKG_DATADIR "data/perserver/default", false); - resman->addToSearchPath("data/perserver/default", false); - -#if defined __APPLE__ - CFBundleRef mainBundle = CFBundleGetMainBundle(); - CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); - char path[PATH_MAX]; - if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (uint8_t*)path, - PATH_MAX)) - { - fprintf(stderr, "Can't find Resources directory\n"); - } - CFRelease(resourcesURL); - // possible crash - strncat(path, "/data", PATH_MAX - 1); - resman->addToSearchPath(path, false); -// possible this need for support run client from dmg images. -// mPackageDir = path; -#endif - resman->addToSearchPath(PKG_DATADIR "data", false); - mPackageDir = PKG_DATADIR "data"; - resman->addToSearchPath("data", false); - -#ifdef ANDROID -#ifdef USE_SDL2 - if (getenv("APPDIR")) - { - const std::string appDir = getenv("APPDIR"); - resman->addToSearchPath(appDir + "/data", false); - resman->addToSearchPath(appDir + "/data/perserver/default", false); - } -#endif -#endif - // Add branding/data to PhysFS search path - if (!mOptions.brandingPath.empty()) - { - std::string path = mOptions.brandingPath; - - // Strip blah.mana from the path -#ifdef WIN32 - const int loc1 = path.find_last_of('/'); - const int loc2 = path.find_last_of('\\'); - const int loc = static_cast<int>(std::max(loc1, loc2)); -#else - const int loc = static_cast<int>(path.find_last_of('/')); -#endif - if (loc > 0) - { - resman->addToSearchPath(path.substr( - 0, loc + 1).append("data"), false); - } - } + initGraphics(); + extractDataDir(); + mountDataDir(); if (mOptions.dataPath.empty() && !branding.getStringValue("dataPath").empty()) @@ -594,42 +381,7 @@ void Client::gameInit() resman->addToSearchPath(mLocalDataDir, false); TranslationManager::loadCurrentLang(); -#if defined(USE_OPENGL) && !defined(ANDROID) && !defined(__APPLE__) - if (!mOptions.safeMode && mOptions.test.empty() - && !config.getBoolValue("videodetected")) - { - graphicsManager.detectVideoSettings(); - } -#endif - - openGLMode = intToRenderType(config.getIntValue("opengl")); -#ifdef USE_OPENGL - OpenGLImageHelper::setBlur(config.getBoolValue("blur")); - SurfaceImageHelper::SDLSetEnableAlphaCache( - config.getBoolValue("alphaCache") && !openGLMode); - ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0F - || openGLMode); -#else - SurfaceImageHelper::SDLSetEnableAlphaCache( - config.getBoolValue("alphaCache")); - ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0F); -#endif - logVars(); - Cpu::detect(); - graphicsManager.initGraphics(mOptions.noOpenGL); - graphicsManager.detectPixelSize(); - runCounters = config.getBoolValue("packetcounters"); - applyVSync(); - graphicsManager.setVideoMode(); - checkConfigVersion(); - getConfigDefaults2(config.getDefaultValues()); - applyGrabMode(); - applyGamma(); - - SDL::SetWindowTitle(mainGraphics->getWindow(), mCaption.c_str()); - setIcon(); - - mainGraphics->_beginDraw(); + initTitle(); Theme::selectSkin(); touchManager.init(); @@ -643,22 +395,7 @@ void Client::gameInit() gui = new Gui(); gui->postInit(mainGraphics); - // Initialize sound engine - try - { - if (config.getBoolValue("sound")) - soundManager.init(); - - soundManager.setSfxVolume(config.getIntValue("sfxVolume")); - soundManager.setMusicVolume(config.getIntValue("musicVolume")); - } - catch (const char *const err) - { - mState = STATE_ERROR; - errorMessage = err; - logger->log("Warning: %s", err); - } - + initSoundManager(); eventsManager.init(); // Initialize keyboard @@ -667,18 +404,8 @@ void Client::gameInit() // Initialise player relations player_relations.init(); - Joystick::init(); - - userPalette = new UserPalette; - setupWindow = new Setup; - setupWindow->postInit(); - helpWindow = new HelpWindow; - didYouKnowWindow = new DidYouKnowWindow; - didYouKnowWindow->postInit(); - - soundManager.playMusic(branding.getValue( - "loginMusic", "Magick - Real.ogg")); + createWindows(); // Initialize default server mCurrentServer.hostname = mOptions.serverName; @@ -713,25 +440,15 @@ void Client::gameInit() if (mState != STATE_ERROR) mState = STATE_CHOOSE_SERVER; - // Initialize logic and seconds counters - tick_time = 0; - mLogicCounterId = SDL_AddTimer(MILLISECONDS_IN_A_TICK, nextTick, nullptr); - mSecondsCounterId = SDL_AddTimer(1000, nextSecond, nullptr); + startTimers(); const int fpsLimit = config.getIntValue("fpslimit"); mLimitFps = fpsLimit > 0; SDL_initFramerate(&mFpsManager); setFramerate(fpsLimit); - config.addListener("fpslimit", this); - config.addListener("guialpha", this); - config.addListener("gamma", this); - config.addListener("enableGamma", this); - config.addListener("particleEmitterSkip", this); - config.addListener("vsync", this); - config.addListener("repeateDelay", this); - config.addListener("repeateInterval", this); - config.addListener("logInput", this); + initConfigListeners(); + setGuiAlpha(config.getFloatValue("guialpha")); optionChanged("fpslimit"); @@ -752,15 +469,302 @@ Client::~Client() gameClear(); else testsClear(); + CHECKLISTENERS +} + +void Client::initConfigListeners() +{ + config.addListener("fpslimit", this); + config.addListener("guialpha", this); + config.addListener("gamma", this); + config.addListener("enableGamma", this); + config.addListener("particleEmitterSkip", this); + config.addListener("vsync", this); + config.addListener("repeateDelay", this); + config.addListener("repeateInterval", this); + config.addListener("logInput", this); +} + +void Client::initSoundManager() +{ + // Initialize sound engine + try + { + if (config.getBoolValue("sound")) + soundManager.init(); + + soundManager.setSfxVolume(config.getIntValue("sfxVolume")); + soundManager.setMusicVolume(config.getIntValue("musicVolume")); + } + catch (const char *const err) + { + mState = STATE_ERROR; + errorMessage = err; + logger->log("Warning: %s", err); + } + soundManager.playMusic(branding.getValue( + "loginMusic", "Magick - Real.ogg")); +} + +void Client::createWindows() +{ + userPalette = new UserPalette; + setupWindow = new Setup; + setupWindow->postInit(); + helpWindow = new HelpWindow; + didYouKnowWindow = new DidYouKnowWindow; + didYouKnowWindow->postInit(); +} + +void Client::initGraphics() +{ +#if defined(USE_OPENGL) +#if !defined(ANDROID) && !defined(__APPLE__) && !defined(__native_client__) + if (!mOptions.safeMode && mOptions.test.empty() + && !config.getBoolValue("videodetected")) + { + graphicsManager.detectVideoSettings(); + } +#endif +#endif + +#if defined(WIN32) || defined(__APPLE__) + if (config.getBoolValue("centerwindow")) + setEnv("SDL_VIDEO_CENTERED", "1"); + else + setEnv("SDL_VIDEO_CENTERED", "0"); +#endif + + if (config.getBoolValue("allowscreensaver")) + setEnv("SDL_VIDEO_ALLOW_SCREENSAVER", "1"); + else + setEnv("SDL_VIDEO_ALLOW_SCREENSAVER", "0"); + + openGLMode = intToRenderType(config.getIntValue("opengl")); +#ifdef USE_OPENGL + OpenGLImageHelper::setBlur(config.getBoolValue("blur")); + SurfaceImageHelper::SDLSetEnableAlphaCache( + config.getBoolValue("alphaCache") && !openGLMode); + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0F + || openGLMode); +#else + SurfaceImageHelper::SDLSetEnableAlphaCache( + config.getBoolValue("alphaCache")); + ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0F); +#endif + logVars(); + Cpu::detect(); + graphicsManager.initGraphics(mOptions.noOpenGL); + graphicsManager.detectPixelSize(); + runCounters = config.getBoolValue("packetcounters"); + applyVSync(); + graphicsManager.setVideoMode(); + checkConfigVersion(); + getConfigDefaults2(config.getDefaultValues()); + applyGrabMode(); + applyGamma(); + + mainGraphics->_beginDraw(); +} + +void Client::initTitle() +{ + if (mOptions.test.empty()) + { + mCaption = strprintf("%s %s", + branding.getStringValue("appName").c_str(), + SMALL_VERSION); + } + else + { + mCaption = strprintf( + "Please wait - VIDEO MODE TEST - %s %s - Please wait", + branding.getStringValue("appName").c_str(), + SMALL_VERSION); + } + + SDL::SetWindowTitle(mainGraphics->getWindow(), mCaption.c_str()); + setIcon(); +} + +#ifdef ANDROID +#ifdef USE_SDL2 +static void updateProgress(int cnt) +{ + const int progress = cnt + loadingProgressCounter; + const int h = mainGraphics->mHeight; + mainGraphics->setColor(gcn::Color(255, 255, 255)); + const int maxSize = mainGraphics->mWidth - 100; + const int width = maxSize * progress / 450; + mainGraphics->fillRectangle(gcn::Rectangle(50, h - 100, width, 50)); + mainGraphics->updateScreen(); +} + +static void setProgress(const int val) +{ + loadingProgressCounter = val; + updateProgress(loadingProgressCounter); +} +#endif +#endif + +void Client::extractDataDir() +{ +#ifdef ANDROID +#ifdef USE_SDL2 + Files::setCopyCallBack(&updateProgress); + setProgress(0); + extractAssets(); + + const std::string zipName = std::string(getenv( + "APPDIR")).append("/data.zip"); + const std::string dirName = std::string(getenv( + "APPDIR")).append("/data"); + Files::extractZip(zipName, "data", dirName); + Files::extractLocale(); +#endif +#endif + +#if defined __native_client__ + const std::string dirName = _nacl_dir.append("/data"); + Files::extractZip("/http/data.zip", "data", dirName); +#endif +} + +void Client::mountDataDir() +{ + const ResourceManager *const resman = ResourceManager::getInstance(); + resman->addToSearchPath(PKG_DATADIR "data/perserver/default", false); + resman->addToSearchPath("data/perserver/default", false); + +#if defined __APPLE__ + CFBundleRef mainBundle = CFBundleGetMainBundle(); + CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle); + char path[PATH_MAX]; + if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (uint8_t*)path, + PATH_MAX)) + { + fprintf(stderr, "Can't find Resources directory\n"); + } + CFRelease(resourcesURL); + // possible crash + strncat(path, "/data", PATH_MAX - 1); + resman->addToSearchPath(path, false); +// possible this need for support run client from dmg images. +// mPackageDir = path; +#endif + resman->addToSearchPath(PKG_DATADIR "data", false); + setPackageDir(PKG_DATADIR "data"); + resman->addToSearchPath("data", false); + +#ifdef ANDROID +#ifdef USE_SDL2 + if (getenv("APPDIR")) + { + const std::string appDir = getenv("APPDIR"); + resman->addToSearchPath(appDir + "/data", false); + resman->addToSearchPath(appDir + "/data/perserver/default", false); + } +#endif +#endif + +#if defined __native_client__ + resman->addToSearchPath(_nacl_dir.append("/data"), false); +#endif + + // Add branding/data to PhysFS search path + if (!mOptions.brandingPath.empty()) + { + std::string path = mOptions.brandingPath; + + // Strip blah.manaplus from the path +#ifdef WIN32 + const int loc1 = path.find_last_of('/'); + const int loc2 = path.find_last_of('\\'); + const int loc = static_cast<int>(std::max(loc1, loc2)); +#else + const int loc = static_cast<int>(path.find_last_of('/')); +#endif + if (loc > 0) + { + resman->addToSearchPath(path.substr( + 0, loc + 1).append("data"), false); + } + } } -void Client::bindTextDomain(const char *const name, const char *const path) +void Client::initLang() { - const char *const dir = bindtextdomain(name, path); +#ifdef ENABLE_NLS + std::string lang = config.getStringValue("lang"); +#ifdef WIN32 + if (lang.empty()) + lang = std::string(_nl_locale_name_default()); + + putenv(const_cast<char*>(("LANG=" + lang).c_str())); + putenv(const_cast<char*>(("LANGUAGE=" + lang).c_str())); + // mingw doesn't like LOCALEDIR to be defined for some reason + if (lang != "C") + bindTextDomain("translations/"); +#else // WIN32 + + if (!lang.empty()) + { + setEnv("LANG", lang.c_str()); + setEnv("LANGUAGE", lang.c_str()); + } +#ifdef ANDROID +#ifdef USE_SDL2 + bindTextDomain((std::string(getenv("APPDIR")).append("/locale")).c_str()); +#else // USE_SDL2 + + bindTextDomain((std::string(PhysFs::getBaseDir()).append( + "/locale")).c_str()); +#endif // USE_SDL2 +#else // ANDROID +#ifdef ENABLE_PORTABLE + bindTextDomain((std::string(PhysFs::getBaseDir()).append( + "../locale/")).c_str()); +#else // ENABLE_PORTABLE +#ifdef __APPLE__ + bindTextDomain((std::string(PhysFs::getBaseDir()) + .append("ManaPlus.app/Contents/Resources/locale/")).c_str()); +#else // __APPLE__ + + bindTextDomain(LOCALEDIR); +#endif // __APPLE__ +#endif // ENABLE_PORTABLE +#endif // ANDROID +#endif // WIN32 + + char *locale = setlocale(LC_MESSAGES, lang.c_str()); + if (locale) + { + logger->log("locale: %s", locale); + } + else + { + locale = setlocale(LC_MESSAGES, (lang + ".utf8").c_str()); + if (locale) + logger->log("locale: %s", locale); + else + logger->log("locale empty"); + } + bind_textdomain_codeset("manaplus", "UTF-8"); + textdomain("manaplus"); +#endif // ENABLE_NLS + +} + +void Client::bindTextDomain(const char *const path) +{ +#ifdef ENABLE_NLS + const char *const dir = bindtextdomain("manaplus", path); if (dir) logger->log("bindtextdomain: %s", dir); else logger->log("bindtextdomain failed"); +#endif } void Client::setEnv(const char *const name, const char *const value) @@ -792,6 +796,8 @@ void Client::gameClear() logger->log1("Quitting1"); config.removeListeners(this); + eventsManager.shutdown(); + delete setupWindow; setupWindow = nullptr; delete helpWindow; @@ -799,8 +805,7 @@ void Client::gameClear() delete didYouKnowWindow; didYouKnowWindow = nullptr; - SDL_RemoveTimer(mLogicCounterId); - SDL_RemoveTimer(mSecondsCounterId); + stopTimers(); // Unload XML databases CharDB::unload(); @@ -819,6 +824,9 @@ void Client::gameClear() if (Net::getLoginHandler()) Net::getLoginHandler()->clearWorlds(); + if (Net::getChatHandler()) + Net::getChatHandler()->clear(); + #ifdef USE_MUMBLE delete mumbleManager; mumbleManager = nullptr; @@ -1413,6 +1421,7 @@ int Client::gameExec() if (!BeingInfo::unknown) BeingInfo::unknown = new BeingInfo; + initFeatures(); TranslationManager::loadCurrentLang(); PlayerInfo::stateChange(mState); @@ -1944,6 +1953,8 @@ void Client::initLocalDataDir() #elif defined __ANDROID__ mLocalDataDir = getSdStoragePath() + branding.getValue( "appShort", "ManaPlus") + "/local"; +#elif defined __native_client__ + mLocalDataDir = _nacl_dir.append("/local"); #else mLocalDataDir = std::string(PhysFs::getUserDir()) + ".local/share/mana"; @@ -2001,6 +2012,8 @@ void Client::initConfigDir() #elif defined __ANDROID__ mConfigDir = getSdStoragePath() + branding.getValue( "appShort", "ManaPlus").append("/config"); +#elif defined __native_client__ + mConfigDir = _nacl_dir.append("/config"); #else mConfigDir = std::string(PhysFs::getUserDir()).append( "/.config/mana/").append(branding.getValue("appShort", "mana")); @@ -2716,6 +2729,8 @@ void Client::closeDialogs() BuySellDialog::closeAll(); NpcDialog::closeAll(); SellDialog::closeAll(); + if (Net::getInventoryHandler()) + Net::getInventoryHandler()->closeStorage(); } bool Client::isTmw() const @@ -2983,6 +2998,7 @@ void Client::extractAssets() logger->log("asset size: %d", size2); fwrite(buf, 1, size2, file); SDL_RWclose(rw); + setProgress(loadingProgressCounter + 1); } else { @@ -3001,6 +3017,7 @@ void Client::extractAssets() int size2 = SDL_RWread(rw, buf, 1, size); fwrite(buf, 1, size2, file2); SDL_RWclose(rw); + setProgress(loadingProgressCounter + 1); } fclose(file2); diff --git a/src/client.h b/src/client.h index 48801b274..dcf761847 100644 --- a/src/client.h +++ b/src/client.h @@ -30,7 +30,12 @@ #include <guichan/actionlistener.hpp> #include <SDL.h> + +#ifdef USE_SDL2 +#include <SDL2_framerate.h> +#else #include <SDL_framerate.h> +#endif #include <string> @@ -46,17 +51,6 @@ class Skin; class Window; class QuitDialog; -/** - * Set the milliseconds value of a tick time. - */ -static const int MILLISECONDS_IN_A_TICK = 10; - -static const uint16_t DEFAULT_PORT = 6901; - -extern volatile int fps; -extern volatile int lps; -extern volatile int tick_time; -extern volatile int cur_time; extern bool isSafeMode; extern int serverVersion; extern unsigned int tmwServerVersion; @@ -74,13 +68,6 @@ extern ErrorListener errorListener; extern LoginData loginData; /** - * Returns elapsed time. (Warning: supposes the delay is always < 100 seconds) - */ -int get_elapsed_time(const int startTime) A_WARN_UNUSED; - -int get_elapsed_time1(const int startTime) A_WARN_UNUSED; - -/** * All client states. */ enum State @@ -233,9 +220,6 @@ public: State getState() const A_WARN_UNUSED { return mState; } - const std::string &getPackageDirectory() const A_WARN_UNUSED - { return mPackageDir; } - const std::string &getConfigDirectory() const A_WARN_UNUSED { return mConfigDir; } @@ -342,6 +326,22 @@ public: const bool modal); private: + void createWindows(); + + void initLang(); + + void initSoundManager(); + + void initConfigListeners(); + + void initGraphics(); + + void initTitle(); + + void extractDataDir(); + + void mountDataDir(); + void initRootDir(); void initHomeDir(); @@ -378,7 +378,7 @@ private: static Client *mInstance; - static void bindTextDomain(const char *const name, const char *const path); + static void bindTextDomain(const char *const path); static void setEnv(const char *const name, const char *const value); @@ -390,7 +390,6 @@ private: Options mOptions; - std::string mPackageDir; std::string mConfigDir; std::string mServerConfigDir; std::string mLocalDataDir; @@ -424,9 +423,6 @@ private: SDL_Surface *mIcon; - SDL_TimerID mLogicCounterId; - SDL_TimerID mSecondsCounterId; - std::string mCaption; FPSmanager mFpsManager; Skin *mSkin; diff --git a/src/commands.cpp b/src/commands.cpp index 36ea69a0c..75347a9aa 100644 --- a/src/commands.cpp +++ b/src/commands.cpp @@ -77,6 +77,7 @@ #include "utils/gettext.h" #include "utils/process.h" +#include "utils/timer.h" #include "debug.h" @@ -742,6 +743,9 @@ impHandler(follow) if (!player_node) return; + if (!features.getBoolValue("allowFollow")) + return; + if (!args.empty()) player_node->setFollow(args); else if (tab && tab->getType() == ChatTab::TAB_WHISPER) diff --git a/src/configuration.cpp b/src/configuration.cpp index 489755341..55ad392f3 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -37,6 +37,12 @@ std::map<std::string, int> optionsCount; #define GETLOG() #endif +Configuration config; // XML file configuration reader +Configuration serverConfig; // XML file server configuration reader +Configuration features; // XML file features +Configuration branding; // XML branding information reader +Configuration paths; // XML default paths information reader + const std::string unusedKeys[] = { "AttackRange", @@ -842,6 +848,27 @@ void Configuration::removeListener(const std::string &key, mListenerMap[key].remove(listener); } +#ifdef ENABLE_CHECKS +void Configuration::checkListeners(ConfigListener *const listener, + const char *const file, + const unsigned line) +{ + FOR_EACH (ListenerMapIterator, it, mListenerMap) + { + Listeners listeners = it->second; + FOR_EACH (ListenerIterator, it2, listeners) + { + if (*it2 == listener) + { + logger->log("detected not cleaned listener: %p, %s:%u", + static_cast<void*>(listener), file, line); + exit(1); + } + } + } +} +#endif + void Configuration::removeListeners(ConfigListener *const listener) { FOR_EACH (ListenerMapIterator, it, mListenerMap) diff --git a/src/configuration.h b/src/configuration.h index 54e5e2ca7..774678b50 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -282,6 +282,12 @@ class Configuration final : public ConfigurationObject void removeListeners(ConfigListener *const listener); +#ifdef ENABLE_CHECKS + void checkListeners(ConfigListener *const listener, + const char *const file, + const unsigned line); +#endif + void setValue(const std::string &key, const std::string &value); void incValue(const std::string &key); diff --git a/src/debug.h b/src/debug.h index 31b2b457b..bd304c4bd 100644 --- a/src/debug.h +++ b/src/debug.h @@ -44,6 +44,7 @@ #ifdef DEBUG_SDL_SURFACES #define MIMG_LoadPNG_RW(src) FakeIMG_LoadPNG_RW(src, __FILE__, __LINE__) +#define MIMG_LoadJPG_RW(src) FakeIMG_LoadJPG_RW(src, __FILE__, __LINE__) #define MSDL_FreeSurface(s) FakeSDL_FreeSurface(s, __FILE__, __LINE__) #define MSDL_CreateRGBSurface(flags, w, h, d, r, g, b, a) \ FakeSDL_CreateRGBSurface(flags, w, h, d, r, g, b, a, __FILE__, __LINE__) @@ -60,6 +61,7 @@ #else // ENABLE_SDL_DEBUG #define MIMG_LoadPNG_RW(src) IMG_LoadPNG_RW(src) +#define MIMG_LoadJPG_RW(src) IMG_LoadJPG_RW(src) #define MSDL_FreeSurface(surface) SDL_FreeSurface(surface) #define MSDL_CreateRGBSurface(flags, w, h, d, r, g, b, a) \ SDL_CreateRGBSurface(flags, w, h, d, r, g, b, a) @@ -84,3 +86,16 @@ #define MPHYSFSRWOPS_openRead(name) PHYSFSRWOPS_openRead(name) #endif // DEBUG_PHYSFS + + +#ifdef ENABLE_CHECKS + +#define CHECKLISTENERS \ + config.checkListeners(this, __FILE__, __LINE__); \ + serverConfig.checkListeners(this, __FILE__, __LINE__); + +#else // ENABLE_CHECKS + +#define CHECKLISTENERS + +#endif // ENABLE_CHECKS diff --git a/src/defaults.cpp b/src/defaults.cpp index 0b71b1db7..d4b2a5379 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -21,7 +21,6 @@ #include "defaults.h" -#include "client.h" #include "graphicsmanager.h" #include "being/being.h" @@ -30,6 +29,12 @@ #include "render/graphics.h" +#include "net/netconsts.h" + +#ifndef USE_SDL2 +#include <SDL_keyboard.h> +#endif + #include "debug.h" VariableData* createData(const int defData) @@ -129,7 +134,11 @@ DefaultsData* getConfigDefaults() AddDEF("fpslimit", 60); AddDEF("theme", ""); AddDEF("showChatColorsList", true); +#ifdef __native_client__ + AddDEF("customcursor", false); +#else AddDEF("customcursor", true); +#endif AddDEF("showDidYouKnow", true); #endif AddDEF("showEmotesButton", true); @@ -182,7 +191,6 @@ DefaultsData* getConfigDefaults() AddDEF("npcFont", "fonts/dejavusans.ttf"); AddDEF("showBackground", true); AddDEF("enableTradeTab", true); - AddDEF("logToChat", false); AddDEF("cyclePlayers", true); AddDEF("cycleMonsters", true); AddDEF("cycleNPC", true); @@ -492,6 +500,7 @@ DefaultsData* getFeaturesDefaults() { DefaultsData *const configData = new DefaultsData; AddDEF("languageTab", false); + AddDEF("allowFollow", true); return configData; } diff --git a/src/dyetool/dyemain.cpp b/src/dyetool/dyemain.cpp new file mode 100644 index 000000000..7952f841c --- /dev/null +++ b/src/dyetool/dyemain.cpp @@ -0,0 +1,100 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "logger.h" + +#include "graphicsmanager.h" +#include "sdlshared.h" + +#include "resources/image.h" +#include "resources/imagehelper.h" +#include "resources/imagewriter.h" +#include "resources/resourcemanager.h" +#include "resources/sdlimagehelper.h" + +#ifdef USE_SDL2 +#include "resources/surfaceimagehelper.h" +#endif + +#include "utils/gettext.h" +#include "utils/physfstools.h" + +#include <iostream> + +#include <SDL.h> + +#include "debug.h" + +int serverVersion = 0; + +static void printHelp() +{ + std::cout << _("dyecmd srcfile dyestring dstfile") << std::endl; + std::cout << _("or") << std::endl; + std::cout << _("dyecmd srcdyestring dstfile") << std::endl; +} + +int main(int argc, char **argv) +{ + if (argc < 3 || argc > 4) + { + printHelp(); + return 1; + } + + logger = new Logger; + logger->setLogToStandardOut(false); + + PhysFs::init(argv[0]); + SDL_Init(SDL_INIT_VIDEO); + + graphicsManager.createWindow(10, 10, 0, SDL_ANYFORMAT); + +#ifdef USE_SDL2 + imageHelper = new SurfaceImageHelper; +#else + imageHelper = new SDLImageHelper; +#endif + + ResourceManager *resman = new ResourceManager; + resman->setWriteDir("."); + resman->addToSearchPath(".", false); + resman->addToSearchPath("/", false); + std::string src = argv[1]; + std::string dst; + if (argc == 4) + { + src.append("|").append(argv[2]); + dst = argv[3]; + } + else + { + dst = argv[2]; + } + + Image *image = resman->getImage(src); + if (!image) + { + printf("Error loading image\n"); + return 1; + } + ImageWriter::writePNG(image->getSDLSurface(), dst); + return 0; +} diff --git a/src/eventsmanager.cpp b/src/eventsmanager.cpp index 4786e4402..17cb11ae6 100644 --- a/src/eventsmanager.cpp +++ b/src/eventsmanager.cpp @@ -44,12 +44,22 @@ EventsManager::EventsManager() : { } +EventsManager::~EventsManager() +{ + CHECKLISTENERS +} + void EventsManager::init() { mLogInput = config.getBoolValue("logInput"); config.addListener("logInput", this); } +void EventsManager::shutdown() +{ + config.removeListeners(this); +} + bool EventsManager::handleCommonEvents(const SDL_Event &event) { if (mLogInput) diff --git a/src/eventsmanager.h b/src/eventsmanager.h index 0cf891729..8ca6aa974 100644 --- a/src/eventsmanager.h +++ b/src/eventsmanager.h @@ -36,8 +36,12 @@ class EventsManager final : public ConfigListener A_DELETE_COPY(EventsManager) + virtual ~EventsManager(); + void init(); + void shutdown(); + bool handleEvents(); bool handleCommonEvents(const SDL_Event &event); diff --git a/src/flooritem.cpp b/src/flooritem.cpp index f0679e55b..1976574ab 100644 --- a/src/flooritem.cpp +++ b/src/flooritem.cpp @@ -22,7 +22,6 @@ #include "flooritem.h" -#include "client.h" #include "configuration.h" #include "render/graphics.h" @@ -37,6 +36,8 @@ #include "debug.h" +extern int serverVersion; + FloorItem::FloorItem(const int id, const int itemId, const int x, const int y, const int amount, const unsigned char color) : ActorSprite(id), diff --git a/src/game.cpp b/src/game.cpp index 9b6b5a339..80d27a4a1 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -105,6 +105,7 @@ #include "utils/physfstools.h" #include "utils/process.h" #include "utils/sdlcheckutils.h" +#include "utils/timer.h" #include <sstream> #include <string> @@ -314,9 +315,6 @@ static void createGuiWindows() gmChatTab = new GmTab(chatWindow); } - if (config.getBoolValue("logToChat")) - logger->setChatWindow(chatWindow); - if (!isSafeMode && chatWindow) chatWindow->loadState(); @@ -338,7 +336,6 @@ static void destroyGuiWindows() { Net::getGeneralHandler()->gameEnded(); - logger->setChatWindow(nullptr); if (whoIsOnline) whoIsOnline->setAllowUpdate(false); @@ -854,6 +851,12 @@ void Game::handleMove() setValidSpeed(); player_node->cancelFollow(); } + else if (inputManager.isActionActive(Input::KEY_MOVE_FORWARD)) + { + direction = player_node->getDirection(); + setValidSpeed(); + player_node->cancelFollow(); + } if (!inputManager.isActionActive(Input::KEY_EMOTE) || direction == 0) moveInDirection(direction); diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index d6d8d508f..ace00663e 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -364,6 +364,14 @@ void GraphicsManager::setVideoMode() int width = res[0]; int height = res[1]; +#elif defined __native_client__ +#ifdef USE_SDL2 + // not implimented +#else + const SDL_VideoInfo* info = SDL_GetVideoInfo(); + int width = info->current_w; + int height = info->current_h; +#endif #else int width = config.getIntValue("screenwidth"); int height = config.getIntValue("screenheight"); @@ -445,9 +453,11 @@ void GraphicsManager::updateExtensions() { // get extensions in old way char const *extensions = reinterpret_cast<char const *>( glGetString(GL_EXTENSIONS)); - logger->log1(extensions); - - splitToStringSet(mExtensions, extensions, ' '); + if (extensions) + { + logger->log1(extensions); + splitToStringSet(mExtensions, extensions, ' '); + } } } diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index d32e81fe8..0c75dd4e4 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -69,6 +69,11 @@ class GuiConfigListener final : public ConfigListener A_DELETE_COPY(GuiConfigListener) + virtual ~GuiConfigListener() + { + CHECKLISTENERS + } + void optionChanged(const std::string &name) { if (!mGui) diff --git a/src/gui/palette.cpp b/src/gui/palette.cpp index 0f7d76e85..b47203f8f 100644 --- a/src/gui/palette.cpp +++ b/src/gui/palette.cpp @@ -23,7 +23,7 @@ #include "gui/palette.h" -#include "client.h" +#include "utils/timer.h" #include <cmath> diff --git a/src/gui/palette.h b/src/gui/palette.h index f9980291f..fdde01737 100644 --- a/src/gui/palette.h +++ b/src/gui/palette.h @@ -28,7 +28,12 @@ #include <guichan/color.hpp> +#if defined __native_client__ +#include <stdlib.h> +#else #include <cstdlib> +#endif + #include <map> #include <string> #include <set> diff --git a/src/gui/popups/itempopup.cpp b/src/gui/popups/itempopup.cpp index 72fd3e0bd..a2998cacb 100644 --- a/src/gui/popups/itempopup.cpp +++ b/src/gui/popups/itempopup.cpp @@ -23,7 +23,6 @@ #include "gui/popups/itempopup.h" -#include "client.h" #include "configuration.h" #include "item.h" #include "units.h" @@ -43,6 +42,8 @@ #include "debug.h" +extern int serverVersion; + ItemPopup::ItemPopup() : Popup("ItemPopup", "itempopup.xml"), mItemName(new Label(this)), diff --git a/src/gui/popups/popupmenu.cpp b/src/gui/popups/popupmenu.cpp index 4f6bb3372..a9ca65b36 100644 --- a/src/gui/popups/popupmenu.cpp +++ b/src/gui/popups/popupmenu.cpp @@ -2574,8 +2574,11 @@ void PopupMenu::addPlayerRelation(const std::string &name) void PopupMenu::addFollow() { - // TRANSLATORS: popup menu item - mBrowserBox->addRow("follow", _("Follow")); + if (features.getBoolValue("allowFollow")) + { + // TRANSLATORS: popup menu item + mBrowserBox->addRow("follow", _("Follow")); + } // TRANSLATORS: popup menu item // TRANSLATORS: imitate player mBrowserBox->addRow("imitation", _("Imitation")); diff --git a/src/gui/sdlfont.cpp b/src/gui/sdlfont.cpp index 985ddf69b..b0596418d 100644 --- a/src/gui/sdlfont.cpp +++ b/src/gui/sdlfont.cpp @@ -23,7 +23,6 @@ #include "gui/sdlfont.h" -#include "client.h" #include "logger.h" #include "main.h" @@ -39,6 +38,8 @@ #include "utils/paths.h" #include "utils/physfsrwops.h" #include "utils/sdlcheckutils.h" +#include "utils/stringutils.h" +#include "utils/timer.h" #include <guichan/exception.hpp> diff --git a/src/gui/setupactiondata.h b/src/gui/setupactiondata.h index 6fa33f673..45ff55e83 100644 --- a/src/gui/setupactiondata.h +++ b/src/gui/setupactiondata.h @@ -1419,6 +1419,12 @@ static SetupActionData setupActionData7[] = }, { // TRANSLATORS: input action name + N_("Move Forward"), + Input::KEY_MOVE_FORWARD, + "", + }, + { + // TRANSLATORS: input action name N_("Move to navigation point shortcuts"), Input::KEY_NO_VALUE, "" diff --git a/src/gui/theme.cpp b/src/gui/theme.cpp index f523df908..3381b156a 100644 --- a/src/gui/theme.cpp +++ b/src/gui/theme.cpp @@ -234,6 +234,7 @@ Theme::~Theme() { delete_all(mSkins); config.removeListener("guialpha", this); + CHECKLISTENERS delete_all(mProgressColors); } diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 05807126f..d2dddb4d8 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -98,6 +98,7 @@ Viewport::Viewport() : Viewport::~Viewport() { config.removeListeners(this); + CHECKLISTENERS delete mPopupMenu; mPopupMenu = nullptr; delete mBeingPopup; diff --git a/src/gui/widgets/avatarlistbox.cpp b/src/gui/widgets/avatarlistbox.cpp index d4eefe69c..123f7f843 100644 --- a/src/gui/widgets/avatarlistbox.cpp +++ b/src/gui/widgets/avatarlistbox.cpp @@ -71,6 +71,7 @@ AvatarListBox::AvatarListBox(const Widget2 *const widget, AvatarListBox::~AvatarListBox() { config.removeListeners(this); + CHECKLISTENERS instances--; @@ -112,7 +113,7 @@ void AvatarListBox::draw(gcn::Graphics *gcnGraphics) // Draw the list elements graphics->setColorAll(mForegroundColor, mForegroundColor2); ImageCollection vertexes; - const bool useCaching = openGLMode != RENDER_SAFE_OPENGL; + const bool useCaching = isBatchDrawRenders(openGLMode); for (int i = 0, y = 0; i < model->getNumberOfElements(); diff --git a/src/gui/widgets/browserbox.cpp b/src/gui/widgets/browserbox.cpp index 5cd9b54f7..8d1550f43 100644 --- a/src/gui/widgets/browserbox.cpp +++ b/src/gui/widgets/browserbox.cpp @@ -23,8 +23,6 @@ #include "gui/widgets/browserbox.h" -#include "client.h" - #include "input/inputmanager.h" #include "gui/gui.h" @@ -36,6 +34,9 @@ #include "resources/imageset.h" #include "resources/resourcemanager.h" +#include "utils/stringutils.h" +#include "utils/timer.h" + #include <guichan/graphics.hpp> #include <guichan/font.hpp> #include <guichan/cliprectangle.hpp> diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 0c71bf8bd..e1f95c334 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -471,7 +471,7 @@ void Button::draw(gcn::Graphics *graphics) } } - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (recalc) { diff --git a/src/gui/widgets/emotepage.cpp b/src/gui/widgets/emotepage.cpp index ce61a865f..5af84e88d 100644 --- a/src/gui/widgets/emotepage.cpp +++ b/src/gui/widgets/emotepage.cpp @@ -73,7 +73,7 @@ void EmotePage::draw(gcn::Graphics *graphics) unsigned int x = 0; unsigned int y = 0; - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mRedraw) { diff --git a/src/gui/widgets/popup.cpp b/src/gui/widgets/popup.cpp index 774640fc3..7a43b2c47 100644 --- a/src/gui/widgets/popup.cpp +++ b/src/gui/widgets/popup.cpp @@ -101,7 +101,7 @@ void Popup::draw(gcn::Graphics *graphics) if (mSkin) { - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mRedraw) { diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index b0972a314..de30feeef 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -177,7 +177,7 @@ void ProgressBar::render(Graphics *graphics) if (!mSkin) return; - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mRedraw || graphics->getRedraw()) { diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index b537dd2ed..e97dad715 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -257,7 +257,7 @@ void ScrollArea::draw(gcn::Graphics *graphics) BLOCK_START("ScrollArea::draw") if (mVBarVisible || mHBarVisible) { - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (!mOpaque) updateCalcFlag(graphics); @@ -315,7 +315,19 @@ void ScrollArea::draw(gcn::Graphics *graphics) } updateAlpha(); - drawChildren(graphics); + + if (mRedraw) + { + Graphics *g = static_cast<Graphics *const>(graphics); + const bool redraw = g->getRedraw(); + g->setRedraw(true); + drawChildren(graphics); + g->setRedraw(redraw); + } + else + { + drawChildren(graphics); + } mRedraw = false; BLOCK_END("ScrollArea::draw") } @@ -358,7 +370,7 @@ void ScrollArea::drawFrame(gcn::Graphics *graphics) updateCalcFlag(graphics); - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mRedraw) { @@ -787,6 +799,7 @@ void ScrollArea::mouseReleased(gcn::MouseEvent& event) } } gcn::ScrollArea::mouseReleased(event); + mRedraw = true; } void ScrollArea::mouseDragged(gcn::MouseEvent &event) @@ -830,6 +843,7 @@ void ScrollArea::mouseDragged(gcn::MouseEvent &event) } event.consume(); + mRedraw = true; } gcn::Rectangle ScrollArea::getVerticalBarDimension() const diff --git a/src/gui/widgets/shortcutcontainer.cpp b/src/gui/widgets/shortcutcontainer.cpp index d7d9eae41..2fb5c4099 100644 --- a/src/gui/widgets/shortcutcontainer.cpp +++ b/src/gui/widgets/shortcutcontainer.cpp @@ -90,7 +90,7 @@ void ShortcutContainer::drawBackground(Graphics *g) { if (mBackgroundImg) { - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mRedraw) { diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp index a500a8014..20fc6b21b 100644 --- a/src/gui/widgets/slider.cpp +++ b/src/gui/widgets/slider.cpp @@ -23,6 +23,7 @@ #include "gui/widgets/slider.h" #include "client.h" +#include "graphicsvertexes.h" #include "input/keydata.h" #include "input/keyevent.h" @@ -44,7 +45,9 @@ static std::string const data[2] = Slider::Slider(const double scaleEnd) : gcn::Slider(scaleEnd), Widget2(), - mHasMouse(false) + mVertexes(new ImageCollection), + mHasMouse(false), + mRedraw(true) { init(); } @@ -52,7 +55,9 @@ Slider::Slider(const double scaleEnd) : Slider::Slider(const double scaleStart, const double scaleEnd) : gcn::Slider(scaleStart, scaleEnd), Widget2(), - mHasMouse(false) + mVertexes(new ImageCollection), + mHasMouse(false), + mRedraw(true) { init(); } @@ -62,6 +67,8 @@ Slider::~Slider() if (gui) gui->removeDragged(this); + delete mVertexes; + mVertexes = nullptr; mInstances--; if (mInstances == 0 && Theme::instance()) { @@ -127,79 +134,196 @@ void Slider::draw(gcn::Graphics *graphics) int x = 0; const int y = mHasMouse ? (h - buttons[1].grid[HSTART]->getHeight()) / 2 : (h - buttons[0].grid[HSTART]->getHeight()) / 2; + Graphics *const g = static_cast<Graphics*>(graphics); updateAlpha(); - if (!mHasMouse) + if (isBatchDrawRenders(openGLMode)) { - static_cast<Graphics*>(graphics)->drawImage( - buttons[0].grid[HSTART], x, y); - - const int width = buttons[0].grid[HSTART]->getWidth(); - w -= width + buttons[0].grid[HEND]->getWidth(); - x += width; - - if (buttons[0].grid[HMID]) + if (mRedraw || g->getRedraw()) { - const Image *const hMid = buttons[0].grid[HMID]; - static_cast<Graphics*>(graphics)-> - drawImagePattern(hMid, x, y, w, hMid->getHeight()); + mRedraw = false; + mVertexes->clear(); + if (!mHasMouse) + { + g->calcTile(mVertexes, buttons[0].grid[HSTART], x, y); + + const int width = buttons[0].grid[HSTART]->getWidth(); + w -= width + buttons[0].grid[HEND]->getWidth(); + x += width; + + if (buttons[0].grid[HMID]) + { + const Image *const hMid = buttons[0].grid[HMID]; + g->calcImagePattern(mVertexes, hMid, x, y, + w, hMid->getHeight()); + } + + x += w; + g->calcTile(mVertexes, buttons[0].grid[HEND], x, y); + + const Image *const img = buttons[0].grid[HGRIP]; + if (img) + { + g->calcTile(mVertexes, img, getMarkerPosition(), + (mDimension.height - img->getHeight()) / 2); + } + } + else + { + g->calcTile(mVertexes, buttons[1].grid[HSTART], x, y); + + const int width = buttons[1].grid[HSTART]->getWidth(); + w -= width; + if (buttons[1].grid[HEND]) + w -= buttons[1].grid[HEND]->getWidth(); + x += width; + + if (buttons[1].grid[HMID]) + { + const Image *const hMid = buttons[1].grid[HMID]; + g->calcImagePattern(mVertexes, hMid, x, y, + w, hMid->getHeight()); + } + + x += w; + if (buttons[1].grid[HEND]) + g->calcTile(mVertexes, buttons[1].grid[HEND], x, y); + + const Image *const img = buttons[1].grid[HGRIP]; + if (img) + { + g->calcTile(mVertexes, img, getMarkerPosition(), + (mDimension.height - img->getHeight()) / 2); + } + } } - - x += w; - static_cast<Graphics*>(graphics)->drawImage( - buttons[0].grid[HEND], x, y); + g->drawTile(mVertexes); } else { - static_cast<Graphics*>(graphics)->drawImage( - buttons[1].grid[HSTART], x, y); + if (!mHasMouse) + { + g->drawImage(buttons[0].grid[HSTART], x, y); + const int width = buttons[0].grid[HSTART]->getWidth(); + w -= width + buttons[0].grid[HEND]->getWidth(); + x += width; - const int width = buttons[1].grid[HSTART]->getWidth(); - w -= width; - if (buttons[1].grid[HEND]) - w -= buttons[1].grid[HEND]->getWidth(); - x += width; + if (buttons[0].grid[HMID]) + { + const Image *const hMid = buttons[0].grid[HMID]; + g->drawImagePattern(hMid, x, y, w, hMid->getHeight()); + } - if (buttons[1].grid[HMID]) - { - const Image *const hMid = buttons[1].grid[HMID]; - static_cast<Graphics*>(graphics)->drawImagePattern( - hMid, x, y, w, - hMid->getHeight()); - } + x += w; + g->drawImage(buttons[0].grid[HEND], x, y); - x += w; - if (buttons[1].grid[HEND]) + const Image *const img = buttons[0].grid[HGRIP]; + if (img) + { + g->drawImage(img, getMarkerPosition(), + (mDimension.height - img->getHeight()) / 2); + } + } + else { - static_cast<Graphics*>(graphics)->drawImage( - buttons[1].grid[HEND], x, y); + g->drawImage(buttons[1].grid[HSTART], x, y); + + const int width = buttons[1].grid[HSTART]->getWidth(); + w -= width; + if (buttons[1].grid[HEND]) + w -= buttons[1].grid[HEND]->getWidth(); + x += width; + + if (buttons[1].grid[HMID]) + { + const Image *const hMid = buttons[1].grid[HMID]; + g->drawImagePattern(hMid, x, y, w, hMid->getHeight()); + } + + x += w; + if (buttons[1].grid[HEND]) + g->drawImage(buttons[1].grid[HEND], x, y); + + const Image *const img = buttons[1].grid[HGRIP]; + if (img) + { + g->drawImage(img, getMarkerPosition(), + (mDimension.height - img->getHeight()) / 2); + } } } - drawMarker(graphics); BLOCK_END("Slider::draw") } -void Slider::drawMarker(gcn::Graphics *const graphics) const -{ - const Image *const img = (mHasMouse ? buttons[1].grid[HGRIP] - : buttons[0].grid[HGRIP]); - if (!img) - return; - - static_cast<Graphics*>(graphics)->drawImage(img, getMarkerPosition(), - (mDimension.height - img->getHeight()) / 2); -} - void Slider::mouseEntered(gcn::MouseEvent& event A_UNUSED) { mHasMouse = true; + mRedraw = true; } void Slider::mouseExited(gcn::MouseEvent& event A_UNUSED) { mHasMouse = false; + mRedraw = true; +} + +void Slider::mousePressed(gcn::MouseEvent &mouseEvent) +{ + if (mouseEvent.getButton() == gcn::MouseEvent::LEFT + && mouseEvent.getX() >= 0 + && mouseEvent.getX() <= getWidth() + && mouseEvent.getY() >= 0 + && mouseEvent.getY() <= getHeight()) + { + if (getOrientation() == HORIZONTAL) + { + setValue2(markerPositionToValue( + mouseEvent.getX() - getMarkerLength() / 2)); + } + else + { + setValue2(markerPositionToValue(getHeight() + - mouseEvent.getY() - getMarkerLength() / 2)); + } + + distributeActionEvent(); + } +} + +void Slider::mouseDragged(gcn::MouseEvent &mouseEvent) +{ + if (getOrientation() == HORIZONTAL) + { + setValue2(markerPositionToValue(mouseEvent.getX() + - getMarkerLength() / 2)); + } + else + { + setValue2(markerPositionToValue(getHeight() + - mouseEvent.getY() - getMarkerLength() / 2)); + } + + distributeActionEvent(); + + mouseEvent.consume(); +} + +void Slider::mouseWheelMovedUp(gcn::MouseEvent &mouseEvent) +{ + setValue2(getValue() + getStepLength()); + distributeActionEvent(); + + mouseEvent.consume(); +} + +void Slider::mouseWheelMovedDown(gcn::MouseEvent &mouseEvent) +{ + setValue2(getValue() - getStepLength()); + distributeActionEvent(); + + mouseEvent.consume(); } void Slider::keyPressed(gcn::KeyEvent& keyEvent) @@ -210,13 +334,13 @@ void Slider::keyPressed(gcn::KeyEvent& keyEvent) { if (action == Input::KEY_GUI_RIGHT) { - setValue(getValue() + getStepLength()); + setValue2(getValue() + getStepLength()); distributeActionEvent(); keyEvent.consume(); } else if (action == Input::KEY_GUI_LEFT) { - setValue(getValue() - getStepLength()); + setValue2(getValue() - getStepLength()); distributeActionEvent(); keyEvent.consume(); } @@ -225,15 +349,21 @@ void Slider::keyPressed(gcn::KeyEvent& keyEvent) { if (action == Input::KEY_GUI_UP) { - setValue(getValue() + getStepLength()); + setValue2(getValue() + getStepLength()); distributeActionEvent(); keyEvent.consume(); } else if (action == Input::KEY_GUI_DOWN) { - setValue(getValue() - getStepLength()); + setValue2(getValue() - getStepLength()); distributeActionEvent(); keyEvent.consume(); } } } + +void Slider::setValue2(const double value) +{ + setValue(value); + mRedraw = true; +} diff --git a/src/gui/widgets/slider.h b/src/gui/widgets/slider.h index e54c9e374..79ef2b961 100644 --- a/src/gui/widgets/slider.h +++ b/src/gui/widgets/slider.h @@ -29,6 +29,8 @@ #include "localconsts.h" +class ImageCollection; + /** * Slider widget. Same as the Guichan slider but with custom look. * @@ -66,11 +68,6 @@ class Slider final : public gcn::Slider, void draw(gcn::Graphics *graphics) override final; /** - * Draws the marker. - */ - void drawMarker(gcn::Graphics *const graphics) const; - - /** * Called when the mouse enteres the widget area. */ void mouseEntered(gcn::MouseEvent& event) override final; @@ -80,8 +77,18 @@ class Slider final : public gcn::Slider, */ void mouseExited(gcn::MouseEvent& event) override final; + void mousePressed(gcn::MouseEvent &mouseEvent) override final; + + void mouseDragged(gcn::MouseEvent &mouseEvent) override final; + + void mouseWheelMovedUp(gcn::MouseEvent &mouseEvent) override final; + + void mouseWheelMovedDown(gcn::MouseEvent &mouseEvent) override final; + void keyPressed(gcn::KeyEvent& keyEvent) override final; + void setValue2(const double value); + enum SLIDER_ENUM { HSTART = 0, @@ -104,7 +111,9 @@ class Slider final : public gcn::Slider, static ImageRect buttons[2]; static float mAlpha; static int mInstances; + ImageCollection *mVertexes; bool mHasMouse; + bool mRedraw; }; #endif // GUI_WIDGETS_SLIDER_H diff --git a/src/gui/widgets/tabs/guildchattab.cpp b/src/gui/widgets/tabs/guildchattab.cpp index 4188a8843..69a4faaf3 100644 --- a/src/gui/widgets/tabs/guildchattab.cpp +++ b/src/gui/widgets/tabs/guildchattab.cpp @@ -49,6 +49,7 @@ GuildChatTab::GuildChatTab(const Widget2 *const widget) : GuildChatTab::~GuildChatTab() { config.removeListeners(this); + CHECKLISTENERS } bool GuildChatTab::handleCommand(const std::string &type, diff --git a/src/gui/widgets/tabs/tab.cpp b/src/gui/widgets/tabs/tab.cpp index 1f09f28fd..cdaa84d14 100644 --- a/src/gui/widgets/tabs/tab.cpp +++ b/src/gui/widgets/tabs/tab.cpp @@ -207,7 +207,7 @@ void Tab::draw(gcn::Graphics *graphics) Graphics *const g = static_cast<Graphics*>(graphics); // draw tab - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { const ImageRect &rect = skin->getBorder(); if (mRedraw || mode != mMode || g->getRedraw()) diff --git a/src/gui/widgets/tabs/whispertab.cpp b/src/gui/widgets/tabs/whispertab.cpp index 7ad14ac65..58849b623 100644 --- a/src/gui/widgets/tabs/whispertab.cpp +++ b/src/gui/widgets/tabs/whispertab.cpp @@ -51,20 +51,17 @@ WhisperTab::~WhisperTab() void WhisperTab::handleInput(const std::string &msg) { + std::string newMsg; if (chatWindow) - { - Net::getChatHandler()->privateMessage(mNick, - chatWindow->doReplace(msg)); - } + newMsg = chatWindow->doReplace(msg); else - { - Net::getChatHandler()->privateMessage(mNick, msg); - } + newMsg = msg; + Net::getChatHandler()->privateMessage(mNick, newMsg); if (player_node) - chatLog(player_node->getName(), msg); + chatLog(player_node->getName(), newMsg); else - chatLog("?", msg); + chatLog("?", newMsg); } void WhisperTab::handleCommand(const std::string &msg) diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index 04527e1ae..a361e1a12 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -39,6 +39,7 @@ #include "resources/image.h" #include "utils/copynpaste.h" +#include "utils/timer.h" #include <guichan/font.hpp> diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 542b0141f..02f6cf35e 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -216,7 +216,7 @@ void Window::draw(gcn::Graphics *graphics) Graphics *const g = static_cast<Graphics*>(graphics); bool update = false; - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mResizeHandles != mOldResizeHandles) { diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp index 5d7f792d9..332843a86 100644 --- a/src/gui/windowmenu.cpp +++ b/src/gui/windowmenu.cpp @@ -180,6 +180,7 @@ WindowMenu::WindowMenu(const Widget2 *const widget) : WindowMenu::~WindowMenu() { config.removeListener("autohideButtons", this); + CHECKLISTENERS delete mTextPopup; mTextPopup = nullptr; diff --git a/src/gui/windows/botcheckerwindow.cpp b/src/gui/windows/botcheckerwindow.cpp index b502dd01d..61dc7286c 100644 --- a/src/gui/windows/botcheckerwindow.cpp +++ b/src/gui/windows/botcheckerwindow.cpp @@ -344,6 +344,7 @@ BotCheckerWindow::BotCheckerWindow(): BotCheckerWindow::~BotCheckerWindow() { config.removeListener("enableBotCheker", this); + CHECKLISTENERS } void BotCheckerWindow::slowLogic() diff --git a/src/gui/windows/charselectdialog.cpp b/src/gui/windows/charselectdialog.cpp index 763ddebd7..c7ea77784 100644 --- a/src/gui/windows/charselectdialog.cpp +++ b/src/gui/windows/charselectdialog.cpp @@ -236,7 +236,7 @@ void CharSelectDialog::action(const gcn::ActionEvent &event) else if (eventId == "delete" && mCharacterEntries[selected]->getCharacter()) { - new CharDeleteConfirm(this, selected); + (new CharDeleteConfirm(this, selected))->postInit(); return; } else if (eventId == "info") @@ -393,7 +393,7 @@ void CharSelectDialog::keyPressed(gcn::KeyEvent &keyEvent) if (idx >= 0 && mCharacterEntries[idx] && mCharacterEntries[idx]->getCharacter()) { - new CharDeleteConfirm(this, idx); + (new CharDeleteConfirm(this, idx))->postInit(); } break; } diff --git a/src/gui/windows/chatwindow.cpp b/src/gui/windows/chatwindow.cpp index eade8b063..79cf0eff3 100644 --- a/src/gui/windows/chatwindow.cpp +++ b/src/gui/windows/chatwindow.cpp @@ -310,6 +310,7 @@ ChatWindow::ChatWindow(): ChatWindow::~ChatWindow() { config.removeListeners(this); + CHECKLISTENERS saveState(); config.setValue("ReturnToggles", mReturnToggles); removeAllWhispers(); diff --git a/src/gui/windows/debugwindow.cpp b/src/gui/windows/debugwindow.cpp index 7fec86369..cb5e06c3d 100644 --- a/src/gui/windows/debugwindow.cpp +++ b/src/gui/windows/debugwindow.cpp @@ -22,7 +22,6 @@ #include "gui/windows/debugwindow.h" -#include "client.h" #include "game.h" #include "main.h" @@ -43,6 +42,8 @@ #include "net/packetcounters.h" #include "utils/gettext.h" +#include "utils/stringutils.h" +#include "utils/timer.h" #include "debug.h" diff --git a/src/gui/windows/editdialog.cpp b/src/gui/windows/editdialog.cpp index f3c583d00..a4711784e 100644 --- a/src/gui/windows/editdialog.cpp +++ b/src/gui/windows/editdialog.cpp @@ -26,8 +26,6 @@ #include "utils/gettext.h" -#include <guichan/font.hpp> - #include "debug.h" EditDialog::EditDialog(const std::string &title, const std::string &msg, @@ -47,17 +45,16 @@ void EditDialog::postInit() // TRANSLATORS: edit dialog label Button *const okButton = new Button(this, _("OK"), mEventOk, this); - const int numRows = 1; - const int fontHeight = getFont()->getHeight(); - const int height = numRows * fontHeight; const int pad = getPadding(); - - setContentSize(mDefaultWidth, height + fontHeight + okButton->getHeight()); + const int pad2 = pad * 2; mTextField->setPosition(pad, pad); - mTextField->setWidth(mDefaultWidth - 2 * pad); - + mTextField->setWidth(mDefaultWidth - pad2); + const int buttonPadding = getOption("buttonPadding", 8) + + mTextField->getHeight(); + setContentSize(mDefaultWidth, okButton->getHeight() + + buttonPadding + pad2); okButton->setPosition((mDefaultWidth - okButton->getWidth()) / 2, - height + getOption("buttonPadding", 8)); + buttonPadding + pad); add(mTextField); add(okButton); diff --git a/src/gui/windows/equipmentwindow.cpp b/src/gui/windows/equipmentwindow.cpp index 688fb814a..9f1ed11bf 100644 --- a/src/gui/windows/equipmentwindow.cpp +++ b/src/gui/windows/equipmentwindow.cpp @@ -169,7 +169,7 @@ void EquipmentWindow::draw(gcn::Graphics *graphics) gcn::Font *const font = getFont(); const int fontHeight = font->getHeight(); - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mLastRedraw) { diff --git a/src/gui/windows/minimap.cpp b/src/gui/windows/minimap.cpp index 9ac4a9e26..7aefa285b 100644 --- a/src/gui/windows/minimap.cpp +++ b/src/gui/windows/minimap.cpp @@ -87,6 +87,7 @@ Minimap::~Minimap() { config.setValue(getWindowName() + "Show", mShow); config.removeListeners(this); + CHECKLISTENERS if (mMapImage) { diff --git a/src/gui/windows/npcdialog.cpp b/src/gui/windows/npcdialog.cpp index 3b5d0d772..1c2a6cc1d 100644 --- a/src/gui/windows/npcdialog.cpp +++ b/src/gui/windows/npcdialog.cpp @@ -209,6 +209,7 @@ void NpcDialog::postInit() NpcDialog::~NpcDialog() { config.removeListeners(this); + CHECKLISTENERS clearLayout(); if (mPlayerBox) diff --git a/src/gui/windows/outfitwindow.cpp b/src/gui/windows/outfitwindow.cpp index 306576475..704f3ce60 100644 --- a/src/gui/windows/outfitwindow.cpp +++ b/src/gui/windows/outfitwindow.cpp @@ -307,6 +307,7 @@ void OutfitWindow::copyOutfit(const int src, const int dst) for (unsigned int i = 0; i < OUTFIT_ITEM_COUNT; i++) mItems[dst][i] = mItems[src][i]; + save(); } void OutfitWindow::draw(gcn::Graphics *graphics) @@ -440,6 +441,7 @@ void OutfitWindow::mousePressed(gcn::MouseEvent &event) mItems[mCurrentOutfit][index] = dragDrop.getSelected(); mItemColors[mCurrentOutfit][index] = dragDrop.getSelectedColor(); dragDrop.deselect(); + save(); } } @@ -472,6 +474,7 @@ void OutfitWindow::mouseReleased(gcn::MouseEvent &event) mItemColors[mCurrentOutfit][index] = dragDrop.getItemColor(); dragDrop.clear(); dragDrop.deselect(); + save(); } } if (mItemClicked) @@ -629,6 +632,7 @@ void OutfitWindow::copyFromEquiped(const int dst) break; } } + save(); } void OutfitWindow::wearAwayOutfit() @@ -654,4 +658,5 @@ void OutfitWindow::clearCurrentOutfit() mItems[mCurrentOutfit][f] = -1; mItemColors[mCurrentOutfit][f] = 1; } + save(); } diff --git a/src/gui/windows/tradewindow.cpp b/src/gui/windows/tradewindow.cpp index 1e25ae862..f0052e46b 100644 --- a/src/gui/windows/tradewindow.cpp +++ b/src/gui/windows/tradewindow.cpp @@ -444,7 +444,7 @@ void TradeWindow::initTrade(const std::string &nick) Item *const item = inv->findItem(mAutoAddItem->getId(), mAutoAddItem->getColor()); if (item) - tradeItem(item, mAutoAddItem->getQuantity()); + tradeItem(item, mAutoAddAmount); } } if (mAutoMoney) diff --git a/src/gui/windows/whoisonline.cpp b/src/gui/windows/whoisonline.cpp index c4f096c72..2e32e13fe 100644 --- a/src/gui/windows/whoisonline.cpp +++ b/src/gui/windows/whoisonline.cpp @@ -142,6 +142,7 @@ void WhoIsOnline::postInit() WhoIsOnline::~WhoIsOnline() { config.removeListeners(this); + CHECKLISTENERS if (mThread && SDL_GetThreadID(mThread)) SDL_WaitThread(mThread, nullptr); diff --git a/src/guichan/include/guichan/widgets/slider.hpp b/src/guichan/include/guichan/widgets/slider.hpp index c4229a514..c925df45f 100644 --- a/src/guichan/include/guichan/widgets/slider.hpp +++ b/src/guichan/include/guichan/widgets/slider.hpp @@ -207,21 +207,6 @@ namespace gcn */ double getStepLength() const; - // Inherited from MouseListener. - - virtual void mousePressed(MouseEvent& mouseEvent) override; - - virtual void mouseDragged(MouseEvent& mouseEvent) override; - - virtual void mouseWheelMovedUp(MouseEvent& mouseEvent) override; - - virtual void mouseWheelMovedDown(MouseEvent& mouseEvent) override; - - - // Inherited from KeyListener - - virtual void keyPressed(KeyEvent& keyEvent) override; - protected: /** * Converts a marker position to a value in the scale. diff --git a/src/guichan/widgets/slider.cpp b/src/guichan/widgets/slider.cpp index 322f2ef76..9a328f2cc 100644 --- a/src/guichan/widgets/slider.cpp +++ b/src/guichan/widgets/slider.cpp @@ -120,47 +120,6 @@ namespace gcn mScaleEnd = scaleEnd; } - void Slider::mousePressed(MouseEvent& mouseEvent) - { - if (mouseEvent.getButton() == gcn::MouseEvent::LEFT - && mouseEvent.getX() >= 0 - && mouseEvent.getX() <= getWidth() - && mouseEvent.getY() >= 0 - && mouseEvent.getY() <= getHeight()) - { - if (getOrientation() == HORIZONTAL) - { - setValue(markerPositionToValue( - mouseEvent.getX() - getMarkerLength() / 2)); - } - else - { - setValue(markerPositionToValue(getHeight() - - mouseEvent.getY() - getMarkerLength() / 2)); - } - - distributeActionEvent(); - } - } - - void Slider::mouseDragged(MouseEvent& mouseEvent) - { - if (getOrientation() == HORIZONTAL) - { - setValue(markerPositionToValue(mouseEvent.getX() - - getMarkerLength() / 2)); - } - else - { - setValue(markerPositionToValue(getHeight() - - mouseEvent.getY() - getMarkerLength() / 2)); - } - - distributeActionEvent(); - - mouseEvent.consume(); - } - void Slider::setValue(double value) { if (value > getScaleEnd()) @@ -193,10 +152,6 @@ namespace gcn mMarkerLength = length; } - void Slider::keyPressed(KeyEvent& keyEvent A_UNUSED) - { - } - void Slider::setOrientation(Slider::Orientation orientation) { mOrientation = orientation; @@ -254,20 +209,4 @@ namespace gcn { return valueToMarkerPosition(getValue()); } - - void Slider::mouseWheelMovedUp(MouseEvent& mouseEvent) - { - setValue(getValue() + getStepLength()); - distributeActionEvent(); - - mouseEvent.consume(); - } - - void Slider::mouseWheelMovedDown(MouseEvent& mouseEvent) - { - setValue(getValue() - getStepLength()); - distributeActionEvent(); - - mouseEvent.consume(); - } } // namespace gcn diff --git a/src/guildmanager.cpp b/src/guildmanager.cpp index 1eae0b0eb..ab79337ed 100644 --- a/src/guildmanager.cpp +++ b/src/guildmanager.cpp @@ -36,6 +36,8 @@ #include "net/chathandler.h" #include "net/net.h" +#include "utils/timer.h" + #include "debug.h" static const int requestTimeout = 5; diff --git a/src/input/inputmanager.cpp b/src/input/inputmanager.cpp index e395aad8e..c84044771 100644 --- a/src/input/inputmanager.cpp +++ b/src/input/inputmanager.cpp @@ -20,7 +20,6 @@ #include "input/inputmanager.h" -#include "client.h" #include "configuration.h" #include "game.h" #include "touchmanager.h" @@ -30,21 +29,25 @@ #include "input/joystick.h" #include "input/keyboardconfig.h" #include "input/keyboarddata.h" +#ifdef USE_SDL2 #include "input/multitouchmanager.h" +#endif #include "gui/gui.h" #include "gui/sdlinput.h" #include "gui/widgets/tabs/setup_input.h" +#include "gui/windows/chatwindow.h" #include "gui/windows/inventorywindow.h" #include "gui/windows/npcdialog.h" #include "gui/windows/npcpostdialog.h" #include "gui/windows/setup.h" #include "gui/windows/textdialog.h" #include "gui/windows/tradewindow.h" +#include "gui/windows/quitdialog.h" -#include "gui/windows/chatwindow.h" +#include "utils/timer.h" #include <guichan/exception.hpp> #include <guichan/focushandler.hpp> diff --git a/src/input/joystick.cpp b/src/input/joystick.cpp index 99a751525..aa7aa3ee9 100644 --- a/src/input/joystick.cpp +++ b/src/input/joystick.cpp @@ -29,6 +29,8 @@ #include "input/inputmanager.h" +#include "utils/timer.h" + #include "debug.h" int Joystick::joystickCount = 0; diff --git a/src/input/keyboarddata.h b/src/input/keyboarddata.h index e9703eac7..42b8f9fc6 100644 --- a/src/input/keyboarddata.h +++ b/src/input/keyboarddata.h @@ -1967,7 +1967,14 @@ static const KeyData keyData[Input::KEY_TOTAL] = { Input::GRP_CHAT, nullptr, Input::KEY_NO_VALUE, 50, - COND_DEFAULT | COND_INGAME} + COND_DEFAULT | COND_INGAME}, + {"keyMoveForward", + INPUT_UNKNOWN, Input::KEY_NO_VALUE, + INPUT_UNKNOWN, Input::KEY_NO_VALUE, + Input::GRP_DEFAULT, + &ActionManager::moveForward, + Input::KEY_NO_VALUE, 50, + COND_GAME} }; #endif // INPUT_KEYBOARDDATA_H diff --git a/src/input/keydata.h b/src/input/keydata.h index bb5d27fd1..aea8c9244 100644 --- a/src/input/keydata.h +++ b/src/input/keydata.h @@ -341,6 +341,7 @@ namespace Input KEY_SHOW_KEYBOARD, KEY_SHOW_WINDOWS, KEY_CHAT_MOD, + KEY_MOVE_FORWARD, KEY_TOTAL }; } // namespace Input diff --git a/src/logger.cpp b/src/logger.cpp index 12a51070d..972d333e4 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -25,8 +25,6 @@ #include <iostream> #include <sstream> -#include "gui/widgets/tabs/chattab.h" - #ifdef WIN32 #include <windows.h> #elif defined __APPLE__ @@ -62,10 +60,11 @@ << static_cast<int>((tv.tv_usec / 10000) % 100) \ << "] "; +Logger *logger = nullptr; // Log object + Logger::Logger() : mLogFile(), mLogToStandardOut(true), - mChatWindow(nullptr), mDebugLog(false) { } @@ -95,6 +94,7 @@ void Logger::log(const std::string &str) log("%s", str.c_str()); } +#ifdef ENABLEDEBUGLOG void Logger::dlog(const std::string &str) { if (!mDebugLog) @@ -114,10 +114,8 @@ void Logger::dlog(const std::string &str) if (mLogToStandardOut) std::cout << timeStr.str() << str << std::endl; - - if (mChatWindow && debugChatTab) - debugChatTab->chatLog(str, BY_LOGGER); } +#endif void Logger::log1(const char *const buf) { @@ -135,9 +133,6 @@ void Logger::log1(const char *const buf) if (mLogToStandardOut) std::cout << timeStr.str() << buf << std::endl; - - if (mChatWindow && debugChatTab) - debugChatTab->chatLog(buf, BY_LOGGER); } void Logger::log(const char *const log_text, ...) @@ -170,9 +165,6 @@ void Logger::log(const char *const log_text, ...) if (mLogToStandardOut) std::cout << timeStr.str() << buf << std::endl; - if (mChatWindow && debugChatTab) - debugChatTab->chatLog(buf, BY_LOGGER); - // Delete temporary buffer delete [] buf; } diff --git a/src/logger.h b/src/logger.h index 8b484e8f5..71a194467 100644 --- a/src/logger.h +++ b/src/logger.h @@ -66,12 +66,6 @@ class Logger final { mLogToStandardOut = value; } /** - * Enables logging to chat window - */ - void setChatWindow(ChatWindow *const window) - { mChatWindow = window; } - - /** * Enters a message in the log. The message will be timestamped. */ void log(const char *const log_text, ...) @@ -94,10 +88,12 @@ class Logger final */ void log(const std::string &str); +#ifdef ENABLEDEBUGLOG /** * Enters debug message in the log. The message will be timestamped. */ void dlog(const std::string &str); +#endif void setDebugLog(const bool n) { mDebugLog = n; } @@ -118,7 +114,6 @@ class Logger final private: std::ofstream mLogFile; bool mLogToStandardOut; - ChatWindow *mChatWindow; bool mDebugLog; }; diff --git a/src/main.cpp b/src/main.cpp index 193610156..65b6e98ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -291,24 +291,11 @@ int main(int argc, char *argv[]) _exit(0); } - // Initialize PhysicsFS #ifdef ANDROID mkdir_r(getSdStoragePath().c_str()); - - if (!PHYSFS_init((getRealPath(".").append("/fakebinary")).c_str())) -#else - if (!PHYSFS_init(argv[0])) #endif - { - std::cout << "Error while initializing PhysFS: " - << PHYSFS_getLastError() << std::endl; - return 1; - } - - PhysFs::updateDirSeparator(); - - atexit((void(*)()) PHYSFS_deinit); + PhysFs::init(argv[0]); XML::initXML(); #if SDL_IMAGE_VERSION_ATLEAST(1, 2, 11) IMG_Init(IMG_INIT_PNG); diff --git a/src/main.h b/src/main.h index 70ad551c8..7bdcd2f25 100644 --- a/src/main.h +++ b/src/main.h @@ -45,8 +45,8 @@ * different interfaces, which have different implementations for each server. */ -#define SMALL_VERSION "1.3.10.27" -#define CHECK_VERSION "01.03.10.27" +#define SMALL_VERSION "1.3.11.10" +#define CHECK_VERSION "01.03.11.10" #ifdef HAVE_CONFIG_H #include "../config.h" @@ -76,6 +76,8 @@ || defined WIN64 || defined _WIN64 || defined __WIN64__ \ || defined __MINGW32__ || defined _MSC_VER #define PACKAGE_OS "Windows" +#elif defined __native_client__ +#define PACKAGE_OS "nacl" #else #define PACKAGE_OS "Other" #endif diff --git a/src/map.cpp b/src/map.cpp index 564f673da..dac9fc71f 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -45,6 +45,7 @@ #include "utils/dtor.h" #include "utils/mkdir.h" #include "utils/physfstools.h" +#include "utils/timer.h" #include <climits> #include <queue> @@ -172,6 +173,7 @@ Map::Map(const int width, const int height, mDrawY(-1), mDrawScrollX(-1), mDrawScrollY(-1), + mMask(1), mAtlas(nullptr), mHeights(nullptr), mRedrawMap(true), @@ -198,6 +200,7 @@ Map::Map(const int width, const int height, Map::~Map() { config.removeListeners(this); + CHECKLISTENERS // delete metadata, layers, tilesets and overlays delete [] mMetaTiles; @@ -280,11 +283,15 @@ void Map::initializeAmbientLayers() Image *const img = resman->getImage(getProperty(name + "image")); if (img) { + int mask = atoi(getProperty(name + "mask").c_str()); + if (!mask) + mask = 1; mForegrounds.push_back(new AmbientLayer(img, getFloatProperty(name + "parallax"), getFloatProperty(name + "scrollX"), getFloatProperty(name + "scrollY"), - getBoolProperty(name + "keepratio"))); + getBoolProperty(name + "keepratio"), + mask)); // The AmbientLayer takes control over the image. img->decRef(); @@ -300,11 +307,15 @@ void Map::initializeAmbientLayers() if (img) { + int mask = atoi(getProperty(name + "mask").c_str()); + if (!mask) + mask = 1; mBackgrounds.push_back(new AmbientLayer(img, getFloatProperty(name + "parallax"), getFloatProperty(name + "scrollX"), getFloatProperty(name + "scrollY"), - getBoolProperty(name + "keepratio"))); + getBoolProperty(name + "keepratio"), + mask)); // The AmbientLayer takes control over the image. img->decRef(); @@ -430,6 +441,9 @@ void Map::draw(Graphics *const graphics, int scrollX, int scrollY) layeri != layeri_end && !overFringe; ++ layeri) { MapLayer *const layer = *layeri; + if (!(layer->mMask & mMask)) + continue; + if (layer->isFringeLayer()) { layer->setSpecialLayer(mSpecialLayer); @@ -597,11 +611,21 @@ void Map::updateAmbientLayers(const float scrollX, const float scrollY) const float dy = scrollY - mLastAScrollY; const int timePassed = get_elapsed_time(lastTick); - FOR_EACH (AmbientLayerVectorCIter, i, mBackgrounds) - (*i)->update(timePassed, dx, dy); + // need check mask to update or not to update - FOR_EACH (AmbientLayerVectorCIter, i, mForegrounds) - (*i)->update(timePassed, dx, dy); + FOR_EACH (AmbientLayerVectorIter, i, mBackgrounds) + { + AmbientLayer *const layer = *i; + if (layer && (layer->mMask & mMask)) + layer->update(timePassed, dx, dy); + } + + FOR_EACH (AmbientLayerVectorIter, i, mForegrounds) + { + AmbientLayer *const layer = *i; + if (layer && (layer->mMask & mMask)) + layer->update(timePassed, dx, dy); + } mLastAScrollX = scrollX; mLastAScrollY = scrollY; @@ -637,8 +661,10 @@ void Map::drawAmbientLayers(Graphics *const graphics, const LayerType type, // Draw overlays FOR_EACHP (AmbientLayerVectorCIter, i, layers) { - if (*i) - (*i)->draw(graphics, graphics->mWidth, graphics->mHeight); + const AmbientLayer *const layer = *i; + // need check mask to draw or not to draw + if (layer && (layer->mMask & mMask)) + (layer)->draw(graphics, graphics->mWidth, graphics->mHeight); // Detail 1: only one overlay, higher: all overlays if (detail == 1) @@ -1600,3 +1626,15 @@ uint8_t Map::getHeightOffset(const int x, const int y) const return 0; return mHeights->getHeight(x, y); } + +void Map::setMask(const int mask) +{ + if (mask != mMask) + mRedrawMap = true; + mMask = mask; +} + +void Map::setMusicFile(const std::string &file) +{ + setProperty("music", file); +} @@ -57,6 +57,7 @@ typedef TilePairVector::const_iterator TilePairVectorCIter; typedef std::vector<AmbientLayer*> AmbientLayerVector; typedef AmbientLayerVector::const_iterator AmbientLayerVectorCIter; +typedef AmbientLayerVector::iterator AmbientLayerVectorIter; static const int mapTileSize = 32; @@ -267,6 +268,8 @@ class Map final : public Properties, public ConfigListener const std::string getMusicFile() const A_WARN_UNUSED; + void setMusicFile(const std::string &file); + const std::string getName() const A_WARN_UNUSED; /** @@ -430,6 +433,8 @@ class Map final : public Properties, public ConfigListener uint8_t getHeightOffset(const int x, const int y) const; + void setMask(const int mask); + protected: friend class Actor; friend class Minimap; @@ -545,6 +550,7 @@ class Map final : public Properties, public ConfigListener int mDrawY; int mDrawScrollX; int mDrawScrollY; + int mMask; Resource *mAtlas; MapHeights *mHeights; bool mRedrawMap; diff --git a/src/maplayer.cpp b/src/maplayer.cpp index 67df3930b..1f8278304 100644 --- a/src/maplayer.cpp +++ b/src/maplayer.cpp @@ -43,7 +43,7 @@ #include "debug.h" MapLayer::MapLayer(const int x, const int y, const int width, const int height, - const bool fringeLayer): + const bool fringeLayer, const int mask): mX(x), mY(y), mWidth(width), @@ -52,6 +52,7 @@ MapLayer::MapLayer(const int x, const int y, const int width, const int height, mSpecialLayer(nullptr), mTempLayer(nullptr), mTempRows(), + mMask(mask), mIsFringeLayer(fringeLayer), mHighlightAttackRange(config.getBoolValue("highlightAttackRange")) { @@ -63,6 +64,7 @@ MapLayer::MapLayer(const int x, const int y, const int width, const int height, MapLayer::~MapLayer() { config.removeListener("highlightAttackRange", this); + CHECKLISTENERS delete [] mTiles; delete_all(mTempRows); mTempRows.clear(); diff --git a/src/maplayer.h b/src/maplayer.h index f5b4c88a8..0706e438e 100644 --- a/src/maplayer.h +++ b/src/maplayer.h @@ -102,7 +102,7 @@ class MapLayer final: public ConfigListener * There can be only one fringe layer per map. */ MapLayer(const int x, const int y, const int width, const int height, - const bool isFringeLayer); + const bool isFringeLayer, const int mask); A_DELETE_COPY(MapLayer) @@ -190,6 +190,7 @@ class MapLayer final: public ConfigListener SpecialLayer *mTempLayer; typedef std::vector<MapRowVertexes*> MapRows; MapRows mTempRows; + int mMask; bool mIsFringeLayer; /**< Whether the actors are drawn. */ bool mHighlightAttackRange; }; diff --git a/src/net/chathandler.h b/src/net/chathandler.h index 9fe65499c..e91be671c 100644 --- a/src/net/chathandler.h +++ b/src/net/chathandler.h @@ -52,6 +52,8 @@ class ChatHandler virtual void ignoreAll() const = 0; virtual void unIgnoreAll() const = 0; + + virtual void clear() = 0; }; } // namespace Net diff --git a/src/net/download.cpp b/src/net/download.cpp index 3ccff63c8..38b8d2873 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -39,6 +39,10 @@ ((LIBCURL_VERSION_MAJOR == (a)) && (LIBCURL_VERSION_MINOR == (b)) && \ (LIBCURL_VERSION_PATCH >= (c)))) +#if defined __native_client__ +#include "utils/files.h" +#endif + #include "debug.h" const char *DOWNLOAD_ERROR_MESSAGE_THREAD @@ -360,7 +364,12 @@ int Download::downloadThread(void *ptr) if (!d->mOptions.cancel) { ::remove(d->mFileName.c_str()); - ::rename(outFilename.c_str(), d->mFileName.c_str()); +#if defined __native_client__ + Files::renameFile( +#else + ::rename( +#endif + outFilename.c_str(), d->mFileName.c_str()); // Check if we can open it and no errors were encountered // during renaming diff --git a/src/net/ea/beinghandler.cpp b/src/net/ea/beinghandler.cpp index 4938ea525..daef49b42 100644 --- a/src/net/ea/beinghandler.cpp +++ b/src/net/ea/beinghandler.cpp @@ -25,7 +25,6 @@ #include "net/ea/eaprotocol.h" #include "actormanager.h" -#include "client.h" #include "configuration.h" #include "effectmanager.h" #include "game.h" @@ -39,13 +38,13 @@ #include "input/keyboardconfig.h" +#include "gui/windows/botcheckerwindow.h" +#include "gui/windows/outfitwindow.h" #include "gui/windows/socialwindow.h" #include "gui/windows/killstats.h" #include "gui/windows/questswindow.h" -#include "gui/windows/botcheckerwindow.h" - -#include "gui/windows/outfitwindow.h" +#include "utils/timer.h" #include "resources/iteminfo.h" @@ -53,6 +52,8 @@ #include "debug.h" +extern int serverVersion; + namespace Ea { BeingHandler::BeingHandler(const bool enableSync) : diff --git a/src/net/ea/buysellhandler.cpp b/src/net/ea/buysellhandler.cpp index 15a4385dc..581e706b3 100644 --- a/src/net/ea/buysellhandler.cpp +++ b/src/net/ea/buysellhandler.cpp @@ -22,7 +22,6 @@ #include "net/ea/buysellhandler.h" -#include "client.h" #include "configuration.h" #include "inventory.h" #include "notifications.h" @@ -42,6 +41,8 @@ #include "net/ea/eaprotocol.h" +#include "utils/timer.h" + #include "debug.h" namespace Ea diff --git a/src/net/ea/chathandler.cpp b/src/net/ea/chathandler.cpp index deaef6984..265f59cb1 100644 --- a/src/net/ea/chathandler.cpp +++ b/src/net/ea/chathandler.cpp @@ -48,10 +48,17 @@ namespace Ea ChatHandler::ChatHandler() : mSentWhispers(), mShowAllLang(serverConfig.getValue("showAllLang", 0)), - mShowMotd(config.getBoolValue("showmotd")) + mShowMotd(config.getBoolValue("showmotd")), + mSkipping(true) { } +void ChatHandler::clear() +{ + mShowMotd = config.getBoolValue("showmotd"); + mSkipping = true; +} + void ChatHandler::me(const std::string &text, const std::string &channel) const { // here need string duplication @@ -311,7 +318,7 @@ void ChatHandler::processBeingChat(Net::MessageIn &msg, } void ChatHandler::processChat(Net::MessageIn &msg, const bool normalChat, - const bool channels) const + const bool channels) { BLOCK_START("ChatHandler::processChat") int chatMsgLength = msg.readInt16() - 4; @@ -350,6 +357,15 @@ void ChatHandler::processChat(Net::MessageIn &msg, const bool normalChat, } } + if (chatMsg.find(": ") == std::string::npos && !mShowMotd + && mSkipping && channel.empty()) + { + // skip motd from "new" tmw server + return; + } + + mSkipping = false; + if (pos != std::string::npos) chatMsg.erase(0, pos + 3); diff --git a/src/net/ea/chathandler.h b/src/net/ea/chathandler.h index 3f0e054a5..49909ad6f 100644 --- a/src/net/ea/chathandler.h +++ b/src/net/ea/chathandler.h @@ -49,17 +49,20 @@ class ChatHandler : public Net::ChatHandler const bool channels) const; virtual void processChat(Net::MessageIn &msg, const bool normalChat, - const bool channels) const; + const bool channels); virtual void processMVP(Net::MessageIn &msg) const; virtual void processIgnoreAllResponse(Net::MessageIn &msg) const; + void clear() override final; + protected: typedef std::queue<std::string> WhisperQueue; WhisperQueue mSentWhispers; bool mShowAllLang; bool mShowMotd; + bool mSkipping; }; } // namespace Ea diff --git a/src/net/ea/gui/guildtab.cpp b/src/net/ea/gui/guildtab.cpp index 86f0e65a6..e0a8937d1 100644 --- a/src/net/ea/gui/guildtab.cpp +++ b/src/net/ea/gui/guildtab.cpp @@ -57,6 +57,7 @@ GuildTab::GuildTab(const Widget2 *const widget) : GuildTab::~GuildTab() { config.removeListeners(this); + CHECKLISTENERS } bool GuildTab::handleCommand(const std::string &type, const std::string &args) diff --git a/src/net/ea/gui/partytab.cpp b/src/net/ea/gui/partytab.cpp index 2b93793d3..f3c1d0377 100644 --- a/src/net/ea/gui/partytab.cpp +++ b/src/net/ea/gui/partytab.cpp @@ -58,6 +58,8 @@ PartyTab::PartyTab(const Widget2 *const widget) : PartyTab::~PartyTab() { + config.removeListeners(this); + CHECKLISTENERS } void PartyTab::handleInput(const std::string &msg) diff --git a/src/net/ea/inventoryhandler.cpp b/src/net/ea/inventoryhandler.cpp index be761fa19..8130eb259 100644 --- a/src/net/ea/inventoryhandler.cpp +++ b/src/net/ea/inventoryhandler.cpp @@ -587,4 +587,13 @@ void InventoryHandler::processPlayerArrowEquip(Net::MessageIn &msg) miniStatusWindow->updateArrows(); } +void InventoryHandler::closeStorage() +{ + if (mStorageWindow) + { + mStorageWindow->close(); + mStorageWindow = nullptr; + } +} + } // namespace Ea diff --git a/src/net/ea/inventoryhandler.h b/src/net/ea/inventoryhandler.h index fa0164c00..818c63061 100644 --- a/src/net/ea/inventoryhandler.h +++ b/src/net/ea/inventoryhandler.h @@ -204,6 +204,8 @@ class InventoryHandler : public Net::InventoryHandler void processPlayerArrowEquip(Net::MessageIn &msg); + void closeStorage() override final; + Inventory *getStorage() const { return mStorage; } diff --git a/src/net/ea/network.h b/src/net/ea/network.h index 9298f021f..c608358cd 100644 --- a/src/net/ea/network.h +++ b/src/net/ea/network.h @@ -24,7 +24,6 @@ #define NET_EA_NETWORK_H #include "net/serverinfo.h" - #include "net/sdltcpnet.h" #include <SDL_thread.h> diff --git a/src/net/eathena/beinghandler.cpp b/src/net/eathena/beinghandler.cpp index ab0af709e..652776e28 100644 --- a/src/net/eathena/beinghandler.cpp +++ b/src/net/eathena/beinghandler.cpp @@ -23,7 +23,6 @@ #include "net/eathena/beinghandler.h" #include "actormanager.h" -#include "client.h" #include "guild.h" #include "guildmanager.h" #include "party.h" @@ -44,9 +43,13 @@ #include "resources/db/itemdb.h" +#include "utils/stringutils.h" +#include "utils/timer.h" + #include "debug.h" extern Net::BeingHandler *beingHandler; +extern int serverVersion; namespace EAthena { diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h index f4aa88ea0..f725a4ce5 100644 --- a/src/net/inventoryhandler.h +++ b/src/net/inventoryhandler.h @@ -69,6 +69,8 @@ class InventoryHandler virtual Inventory *getStorage() const = 0; + virtual void closeStorage() = 0; + virtual int convertFromServerSlot(const int eAthenaSlot) const = 0; }; diff --git a/src/net/netconsts.h b/src/net/netconsts.h new file mode 100644 index 000000000..00c91fda5 --- /dev/null +++ b/src/net/netconsts.h @@ -0,0 +1,32 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NET_NETCONSTS_H +#define NET_NETCONSTS_H + +#if defined(__GXX_EXPERIMENTAL_CXX0X__) +#include <cstdint> +#else +#include <stdint.h> +#endif + +static const uint16_t DEFAULT_PORT = 6901; + +#endif // NET_NETCONSTS_H diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 8f91371b1..47d86a240 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -23,7 +23,6 @@ #include "net/tmwa/beinghandler.h" #include "actormanager.h" -#include "client.h" #include "guild.h" #include "guildmanager.h" #include "party.h" @@ -38,10 +37,15 @@ #include "resources/db/itemdb.h" +#include "utils/stringutils.h" +#include "utils/timer.h" + #include "debug.h" extern Net::BeingHandler *beingHandler; +extern int serverVersion; + namespace TmwAthena { diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index 9d4c60e0a..24615ab16 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -78,7 +78,7 @@ int16_t packet_lengths[] = // #0x0200 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 10, 0, 0, 0, 2, -1, 16, 0, 8, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - -1, 122, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + -1, 122, -1, -1, -1, -1, 10, -1, 0, 0, 0, 0, 0, 0, 0, 0, }; static const int packet_lengths_size diff --git a/src/net/tmwa/network.h b/src/net/tmwa/network.h index 7e007742c..83bd34610 100644 --- a/src/net/tmwa/network.h +++ b/src/net/tmwa/network.h @@ -31,7 +31,7 @@ * Protocol version, reported to the eAthena char and mapserver who can adjust * the protocol accordingly. */ -#define CLIENT_PROTOCOL_VERSION 10 +#define CLIENT_PROTOCOL_VERSION 11 #define CLIENT_TMW_PROTOCOL_VERSION 1 namespace TmwAthena diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index 0361e125d..164ecb8c2 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -23,7 +23,8 @@ #include "net/tmwa/playerhandler.h" #include "configuration.h" -#include "client.h" +#include "game.h" +#include "soundmanager.h" #include "net/net.h" @@ -33,9 +34,12 @@ #include "gui/windows/whoisonline.h" +#include "gui/viewport.h" + #include "debug.h" extern Net::PlayerHandler *playerHandler; +extern int serverVersion; namespace TmwAthena { @@ -56,6 +60,8 @@ PlayerHandler::PlayerHandler() : SMSG_PLAYER_STAT_UPDATE_6, SMSG_PLAYER_ARROW_MESSAGE, SMSG_ONLINE_LIST, + SMSG_MAP_MASK, + SMSG_MAP_MUSIC, 0 }; handledMessages = _messages; @@ -108,6 +114,14 @@ void PlayerHandler::handleMessage(Net::MessageIn &msg) processOnlineList(msg); break; + case SMSG_MAP_MASK: + processMapMask(msg); + break; + + case SMSG_MAP_MUSIC: + processMapMusic(msg); + break; + default: break; } @@ -295,4 +309,24 @@ void PlayerHandler::updateStatus(const uint8_t status) const outMsg.writeInt8(0); } +void PlayerHandler::processMapMask(Net::MessageIn &msg) const +{ + const int mask = msg.readInt32(); + msg.readInt32(); // unused + Map *const map = Game::instance()->getCurrentMap(); + if (map) + map->setMask(mask); +} + +void PlayerHandler::processMapMusic(Net::MessageIn &msg) const +{ + const int size = msg.readInt16() - 5; + const std::string music = msg.readString(size); + soundManager.playMusic(music); + + Map *const map = viewport->getMap(); + if (map) + map->setMusicFile(music); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index 102151b05..75022a452 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -54,6 +54,8 @@ class PlayerHandler final : public MessageHandler, public Ea::PlayerHandler void processOnlineList(Net::MessageIn &msg) const; void requestOnlineList() const override final; void updateStatus(const uint8_t status) const override final; + void processMapMask(Net::MessageIn &msg) const; + void processMapMusic(Net::MessageIn &msg) const; void respawn() const override final; }; diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index 9a4e39b85..965c67a50 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -350,6 +350,8 @@ enum #define SMSG_QUEST_SET_VAR 0x0214 #define SMSG_QUEST_PLAYER_VARS 0x0215 #define SMSG_BEING_MOVE3 0x0225 +#define SMSG_MAP_MASK 0x0226 +#define SMSG_MAP_MUSIC 0x0227 #define CMSG_SEND_CLIENT_INFO 0x7533 #define SMSG_UPDATE_HOST2 0x7534 diff --git a/src/render/graphics.cpp b/src/render/graphics.cpp index 4ea219802..5a0adfeef 100644 --- a/src/render/graphics.cpp +++ b/src/render/graphics.cpp @@ -46,6 +46,8 @@ #endif #endif +Graphics *mainGraphics = nullptr; + Graphics::Graphics() : gcn::Graphics(), mWidth(0), diff --git a/src/render/renderers.h b/src/render/renderers.h index 3ce1fdb81..3c79103c1 100644 --- a/src/render/renderers.h +++ b/src/render/renderers.h @@ -34,4 +34,6 @@ enum RenderType RenderType intToRenderType(const int mode); +#define isBatchDrawRenders(val) (val) != RENDER_SAFE_OPENGL + #endif // RENDER_RENDERERS_H diff --git a/src/render/rendererslistsdl.h b/src/render/rendererslistsdl.h index ed808485b..585e4ceba 100644 --- a/src/render/rendererslistsdl.h +++ b/src/render/rendererslistsdl.h @@ -77,7 +77,7 @@ const char *OPENGL_NAME[] = // TRANSLATORS: draw backend N_("Software"), // TRANSLATORS: draw backend - N_("Fast OpenGL"), + N_("Normal OpenGL"), // TRANSLATORS: draw backend N_("Safe OpenGL"), // TRANSLATORS: draw backend diff --git a/src/render/rendererslistsdl2.h b/src/render/rendererslistsdl2.h index 10c5d80f3..0c2f97c33 100644 --- a/src/render/rendererslistsdl2.h +++ b/src/render/rendererslistsdl2.h @@ -80,7 +80,7 @@ const char *OPENGL_NAME[] = // TRANSLATORS: draw backend N_("SDL2 default"), // TRANSLATORS: draw backend - N_("Fast OpenGL"), + N_("Normal OpenGL"), // TRANSLATORS: draw backend N_("Safe OpenGL"), // TRANSLATORS: draw backend diff --git a/src/resources/ambientlayer.cpp b/src/resources/ambientlayer.cpp index 6814b0365..cc9ebdaec 100644 --- a/src/resources/ambientlayer.cpp +++ b/src/resources/ambientlayer.cpp @@ -21,6 +21,8 @@ #include "resources/ambientlayer.h" +#include "map.h" + #include "render/graphics.h" #include "resources/image.h" @@ -31,10 +33,14 @@ AmbientLayer::AmbientLayer(Image *const img, const float parallax, const float speedX, const float speedY, - const bool keepRatio) : - mImage(img), mParallax(parallax), - mPosX(0), mPosY(0), - mSpeedX(speedX), mSpeedY(speedY), + const bool keepRatio, int mask) : + mImage(img), + mParallax(parallax), + mPosX(0), + mPosY(0), + mSpeedX(speedX), + mSpeedY(speedY), + mMask(mask), mKeepRatio(keepRatio) { if (!mImage) diff --git a/src/resources/ambientlayer.h b/src/resources/ambientlayer.h index 18bbfb69a..3403c0455 100644 --- a/src/resources/ambientlayer.h +++ b/src/resources/ambientlayer.h @@ -26,10 +26,13 @@ class Graphics; class Image; +class Map; class AmbientLayer final { public: + friend class Map; + /** * Constructor. * @@ -42,7 +45,7 @@ class AmbientLayer final */ AmbientLayer(Image *const img, const float parallax, const float speedX, const float speedY, - const bool keepRatio = false); + const bool keepRatio, int mask); A_DELETE_COPY(AmbientLayer) @@ -59,6 +62,7 @@ class AmbientLayer final float mPosY; /**< Current layer Y position. */ float mSpeedX; /**< Scrolling speed in X direction. */ float mSpeedY; /**< Scrolling speed in Y direction. */ + int mMask; bool mKeepRatio; /**< Keep overlay ratio on every resolution */ }; diff --git a/src/resources/db/colordb.cpp b/src/resources/db/colordb.cpp index 0e81ff1c0..8f4e1431c 100644 --- a/src/resources/db/colordb.cpp +++ b/src/resources/db/colordb.cpp @@ -21,7 +21,6 @@ #include "resources/db/colordb.h" -#include "client.h" #include "configuration.h" #include "logger.h" @@ -37,6 +36,8 @@ namespace ColorDB::ColorLists mColorLists; } +extern int serverVersion; + void ColorDB::load() { if (mLoaded) diff --git a/src/resources/db/itemdb.cpp b/src/resources/db/itemdb.cpp index cc8c0338b..f7b1f6349 100644 --- a/src/resources/db/itemdb.cpp +++ b/src/resources/db/itemdb.cpp @@ -22,7 +22,6 @@ #include "resources/db/itemdb.h" -#include "client.h" #include "configuration.h" #include "logger.h" @@ -45,6 +44,8 @@ namespace std::map<std::string, ItemSoundEvent> mSoundNames; } // namespace +extern int serverVersion; + // Forward declarations static void loadSpriteRef(ItemInfo *const itemInfo, const XmlNodePtr node); static void loadSoundRef(ItemInfo *const itemInfo, const XmlNodePtr node); diff --git a/src/resources/image.cpp b/src/resources/image.cpp index b217db683..8bf41aa4c 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -33,7 +33,11 @@ #include "utils/sdlcheckutils.h" +#ifdef USE_SDL2 +#include <SDL2_rotozoom.h> +#else #include <SDL_rotozoom.h> +#endif #include "debug.h" @@ -320,30 +324,63 @@ void Image::setAlpha(const float alpha) if (SDL_MUSTLOCK(mSDLSurface)) SDL_LockSurface(mSDLSurface); - // Precompute as much as possible - const int maxHeight = std::min((mBounds.y + mBounds.h), - mSDLSurface->h); - const int maxWidth = std::min((mBounds.x + mBounds.w), - mSDLSurface->w); - const int i1 = mBounds.y * mSDLSurface->w + mBounds.x; - const int i2 = (maxHeight - 1) * mSDLSurface->w + maxWidth - 1; - + const int bx = mBounds.x; + const int by = mBounds.y; + const int bw = mBounds.w; + const int bh = mBounds.h; + const int bxw = bx + bw; + const int sw = mSDLSurface->w; + const int maxHeight = std::min(by + bh, mSDLSurface->h); + const int maxWidth = std::min(bxw, sw); + const int i1 = by * sw + bx; const SDL_PixelFormat * const fmt = mSDLSurface->format; + const uint32_t amask = fmt->Amask; + const uint32_t invMask = ~fmt->Amask; + const uint8_t aloss = fmt->Aloss; + const uint8_t ashift = fmt->Ashift; - for (int i = i1; i <= i2; i++) + if (!bx && bxw == sw) { - // Only change the pixel if it was visible at load time... - const uint8_t sourceAlpha = mAlphaChannel[i]; - if (sourceAlpha > 0) + const int i2 = (maxHeight - 1) * sw + maxWidth - 1; + for (int i = i1; i <= i2; i++) { - const uint8_t a = static_cast<uint8_t>( - static_cast<float>(sourceAlpha) * mAlpha); - - uint32_t c = (static_cast<uint32_t*>( - mSDLSurface->pixels))[i]; - c &= ~fmt->Amask; - c |= ((a >> fmt->Aloss) << fmt->Ashift & fmt->Amask); - (static_cast<uint32_t*>(mSDLSurface->pixels))[i] = c; + const uint8_t sourceAlpha = mAlphaChannel[i]; + if (sourceAlpha > 0) + { + const uint8_t a = static_cast<uint8_t>( + static_cast<float>(sourceAlpha) * mAlpha); + + uint32_t c = (static_cast<uint32_t*>( + mSDLSurface->pixels))[i]; + c &= invMask; + c |= ((a >> aloss) << ashift & amask); + (static_cast<uint32_t*>(mSDLSurface->pixels))[i] = c; + } + } + } + else + { + for (int y = by; y < maxHeight; y ++) + { + const int idx = y * sw; + const int x1 = idx + bx; + const int x2 = idx + maxWidth; + for (int i = x1; i < x2; i ++) + { + const uint8_t sourceAlpha = mAlphaChannel[i]; + if (sourceAlpha > 0) + { + const uint8_t a = static_cast<uint8_t>( + static_cast<float>(sourceAlpha) * mAlpha); + + uint32_t c = (static_cast<uint32_t*>( + mSDLSurface->pixels))[i]; + c &= invMask; + c |= ((a >> aloss) << ashift & amask); + (static_cast<uint32_t*>( + mSDLSurface->pixels))[i] = c; + } + } } } diff --git a/src/resources/image.h b/src/resources/image.h index e4e41b914..ee7191728 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -186,6 +186,9 @@ class Image : public Resource void setAlphaCalculated(const bool b) { mIsAlphaCalculated = b; } + SDL_Surface* getSDLSurface() + { return mSDLSurface; } + SDL_Rect mBounds; protected: diff --git a/src/resources/imagehelper.cpp b/src/resources/imagehelper.cpp index dbbe21769..51ca0d44e 100644 --- a/src/resources/imagehelper.cpp +++ b/src/resources/imagehelper.cpp @@ -120,13 +120,21 @@ SDL_Surface *ImageHelper::loadPng(SDL_RWops *const rw) if (!rw) return nullptr; - if (!IMG_isPNG(rw)) + if (IMG_isPNG(rw)) { - logger->log("Error, image is not png"); + SDL_Surface *const tmpImage = MIMG_LoadPNG_RW(rw); SDL_RWclose(rw); - return nullptr; + return tmpImage; + } + + if (IMG_isJPG(rw)) + { + SDL_Surface *const tmpImage = MIMG_LoadJPG_RW(rw); + SDL_RWclose(rw); + return tmpImage; } - SDL_Surface *const tmpImage = MIMG_LoadPNG_RW(rw); + + logger->log("Error, image is not png"); SDL_RWclose(rw); - return tmpImage; + return nullptr; } diff --git a/src/resources/imagewriter.cpp b/src/resources/imagewriter.cpp index 1db9f139d..3e1eeead5 100644 --- a/src/resources/imagewriter.cpp +++ b/src/resources/imagewriter.cpp @@ -24,6 +24,7 @@ #include "logger.h" +#include <stdlib.h> #include <png.h> #include <SDL_video.h> #include <string> diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 95da2ae36..a1b087102 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -666,6 +666,7 @@ void MapReader::readLayer(const XmlNodePtr node, Map *const map) const bool isFringeLayer = (name.substr(0, 6) == "fringe"); const bool isCollisionLayer = (name.substr(0, 9) == "collision"); const bool isHeightLayer = (name.substr(0, 7) == "heights"); + int mask = 1; MapLayer::Type layerType = MapLayer::TILES; if (isCollisionLayer) @@ -694,12 +695,25 @@ void MapReader::readLayer(const XmlNodePtr node, Map *const map) const std::string pname = XML::getProperty(prop, "name", ""); const std::string value = XML::getProperty(prop, "value", ""); // ignoring any layer if property Hidden is 1 - if (pname == "Hidden" && value == "1") - return; - if (pname == "Version" && value > CHECK_VERSION) - return; - if (pname == "NotVersion" && value <= CHECK_VERSION) - return; + if (pname == "Hidden") + { + if (value == "1") + return; + } + else if (pname == "Version") + { + if (value > CHECK_VERSION) + return; + } + else if (pname == "NotVersion") + { + if (value <= CHECK_VERSION) + return; + } + else if (pname == "Mask") + { + mask = atoi(value.c_str()); + } } } @@ -708,7 +722,7 @@ void MapReader::readLayer(const XmlNodePtr node, Map *const map) if (layerType == MapLayer::TILES) { - layer = new MapLayer(offsetX, offsetY, w, h, isFringeLayer); + layer = new MapLayer(offsetX, offsetY, w, h, isFringeLayer, mask); map->addLayer(layer); } else if (layerType == MapLayer::HEIGHTS) @@ -939,9 +953,9 @@ Map *MapReader::createEmptyMap(const std::string &filename, map->setProperty("_realfilename", filename); updateMusic(map); map->setCustom(true); - MapLayer *layer = new MapLayer(0, 0, 300, 300, false); + MapLayer *layer = new MapLayer(0, 0, 300, 300, false, 1); map->addLayer(layer); - layer = new MapLayer(0, 0, 300, 300, true); + layer = new MapLayer(0, 0, 300, 300, true, 1); map->addLayer(layer); return map; diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 5cdb22e96..193647a6e 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -23,7 +23,6 @@ #include "resources/resourcemanager.h" #include "animationdelayload.h" -#include "client.h" #include "configuration.h" #include "logger.h" #include "navigationmanager.h" @@ -39,9 +38,11 @@ #include "resources/spritedef.h" #include "utils/mkdir.h" +#include "utils/paths.h" #include "utils/physfscheckutils.h" #include "utils/physfsrwops.h" #include "utils/sdlcheckutils.h" +#include "utils/timer.h" #include <SDL_image.h> #include <dirent.h> @@ -427,8 +428,7 @@ std::string ResourceManager::getPath(const std::string &file) const else { // if not found in search path return the default path - path = std::string(client->getPackageDirectory()).append( - dirSeparator).append(file); + path = getPackageDir().append(dirSeparator).append(file); } return path; diff --git a/src/resources/sdl2imagehelper.cpp b/src/resources/sdl2imagehelper.cpp index 2ee72b0ee..c3481a1b5 100644 --- a/src/resources/sdl2imagehelper.cpp +++ b/src/resources/sdl2imagehelper.cpp @@ -27,7 +27,6 @@ #include "resources/dye.h" #include "resources/resourcemanager.h" -#include "client.h" #include "logger.h" #include "main.h" diff --git a/src/resources/sdl2softwareimagehelper.cpp b/src/resources/sdl2softwareimagehelper.cpp index db41a4ddc..2886c3ff6 100644 --- a/src/resources/sdl2softwareimagehelper.cpp +++ b/src/resources/sdl2softwareimagehelper.cpp @@ -27,7 +27,6 @@ #include "resources/dye.h" #include "resources/resourcemanager.h" -#include "client.h" #include "logger.h" #include "main.h" diff --git a/src/resources/sdlimagehelper.cpp b/src/resources/sdlimagehelper.cpp index fa63517fc..f39ecf4cd 100644 --- a/src/resources/sdlimagehelper.cpp +++ b/src/resources/sdlimagehelper.cpp @@ -213,12 +213,15 @@ Image *SDLImageHelper::_SDLload(SDL_Surface *tmpImage) const const SDL_PixelFormat *const fmt = tmpImage->format; if (fmt->Amask) { + const uint32_t amask = fmt->Amask; + const uint8_t ashift = fmt->Ashift; + const uint8_t aloss = fmt->Aloss; + const uint32_t *pixels = static_cast<uint32_t*>(tmpImage->pixels); for (int i = 0; i < sz; ++ i) { - const unsigned v = ((static_cast<uint32_t*>( - tmpImage->pixels))[i] & fmt->Amask) >> fmt->Ashift; - const uint8_t a = static_cast<const uint8_t>((v << fmt->Aloss) - + (v >> (8 - (fmt->Aloss << 1)))); + const unsigned v = (pixels[i] & amask) >> ashift; + const uint8_t a = static_cast<const uint8_t>((v << aloss) + + (v >> (8 - (aloss << 1)))); if (a != 255) hasAlpha = true; diff --git a/src/resources/surfaceimagehelper.cpp b/src/resources/surfaceimagehelper.cpp index b249dfea9..22aa904f5 100644 --- a/src/resources/surfaceimagehelper.cpp +++ b/src/resources/surfaceimagehelper.cpp @@ -27,7 +27,6 @@ #include "resources/dye.h" #include "resources/resourcemanager.h" -#include "client.h" #include "logger.h" #include "main.h" diff --git a/src/sdl2gfx/SDL_framerate.c b/src/sdl2gfx/SDL2_framerate.c index bb1c35fcb..b31b0feb2 100644 --- a/src/sdl2gfx/SDL_framerate.c +++ b/src/sdl2gfx/SDL2_framerate.c @@ -28,7 +28,7 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net Changed for ManaPlus (C) 2013 ManaPlus developers */ -#include "SDL_framerate.h" +#include "SDL2_framerate.h" /*! \brief Internal wrapper to SDL_GetTicks that ensures a non-zero return value. diff --git a/src/sdl2gfx/SDL_framerate.h b/src/sdl2gfx/SDL2_framerate.h index a2e62e944..a2e62e944 100644 --- a/src/sdl2gfx/SDL_framerate.h +++ b/src/sdl2gfx/SDL2_framerate.h diff --git a/src/sdl2gfx/SDL_rotozoom.c b/src/sdl2gfx/SDL2_rotozoom.c index 6313f4008..058074de1 100644 --- a/src/sdl2gfx/SDL_rotozoom.c +++ b/src/sdl2gfx/SDL2_rotozoom.c @@ -34,7 +34,7 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net #include <stdlib.h> #include <string.h> -#include "SDL_rotozoom.h" +#include "SDL2_rotozoom.h" /* ---- Internally used structures */ diff --git a/src/sdl2gfx/SDL_rotozoom.h b/src/sdl2gfx/SDL2_rotozoom.h index f4c236ba4..f4c236ba4 100644 --- a/src/sdl2gfx/SDL_rotozoom.h +++ b/src/sdl2gfx/SDL2_rotozoom.h diff --git a/src/shopitem.cpp b/src/shopitem.cpp index 56f66478e..fd2a7e670 100644 --- a/src/shopitem.cpp +++ b/src/shopitem.cpp @@ -22,13 +22,16 @@ #include "shopitem.h" -#include "client.h" #include "units.h" #include "resources/iteminfo.h" +#include "utils/stringutils.h" + #include "debug.h" +extern int serverVersion; + ShopItem::ShopItem(const int inventoryIndex, const int id, const unsigned char color, const int quantity, const int price) : diff --git a/src/soundmanager.cpp b/src/soundmanager.cpp index 7ddf5d175..be36c0f6a 100644 --- a/src/soundmanager.cpp +++ b/src/soundmanager.cpp @@ -79,6 +79,8 @@ void SoundManager::shutdown() // Unlink the callback function. Mix_HookMusicFinished(nullptr); + + CHECKLISTENERS } void SoundManager::optionChanged(const std::string &value) diff --git a/src/touchmanager.cpp b/src/touchmanager.cpp index bad706867..a60680407 100644 --- a/src/touchmanager.cpp +++ b/src/touchmanager.cpp @@ -67,6 +67,7 @@ TouchManager::~TouchManager() clear(); delete mVertexes; mVertexes = nullptr; + CHECKLISTENERS } void TouchManager::shutdown() @@ -185,7 +186,7 @@ void TouchManager::clear() void TouchManager::draw() { - if (openGLMode != RENDER_SAFE_OPENGL) + if (isBatchDrawRenders(openGLMode)) { if (mRedraw) { diff --git a/src/utils/files.cpp b/src/utils/files.cpp index f4c93e6e6..2d7994f8a 100644 --- a/src/utils/files.cpp +++ b/src/utils/files.cpp @@ -18,18 +18,18 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifdef ANDROID #include "utils/files.h" -#include "logger.h" - +#if defined(ANDROID) || defined(__native_client__) #include "resources/resourcemanager.h" +#include "utils/physfstools.h" +#endif #include "utils/mkdir.h" -#include "utils/physfstools.h" #include "localconsts.h" +#ifdef ANDROID void Files::extractLocale() { // in future need also remove all locales in local dir @@ -60,6 +60,20 @@ void Files::extractLocale() resman->removeFromSearchPath(fileName2); remove(fileName2.c_str()); } +#endif // ANDROID + +#if defined(ANDROID) || defined(__native_client__) + +namespace +{ + int mFilesCount = 0; + Files::CopyFileCallbackPtr mCallbackPtr = nullptr; +} // namespace + +void Files::setCopyCallBack(Files::CopyFileCallbackPtr callback) +{ + mCallbackPtr = callback; +} void Files::copyPhysFsFile(const std::string &inFile, const std::string &outFile) @@ -70,6 +84,13 @@ void Files::copyPhysFsFile(const std::string &inFile, fwrite(buf, 1, size, file); fclose(file); free(buf); +#ifdef ANDROID + if (mCallbackPtr) + { + mCallbackPtr(mFilesCount); + mFilesCount ++; + } +#endif } void Files::copyPhysFsDir(const std::string &inDir, const std::string &outDir) @@ -98,4 +119,40 @@ void Files::extractZip(const std::string &zipName, const std::string &inDir, remove(zipName.c_str()); } -#endif // ANDROID +#endif // ANDROID __native_client__ + +int Files::renameFile(const std::string &srcName, const std::string &dstName) +{ + FILE *srcFile = fopen(srcName.c_str(), "rb"); + if (srcFile == nullptr) + return -1; + FILE *dstFile = fopen(dstName.c_str(), "w+b"); + if (dstFile == nullptr) + { + fclose(srcFile); + return -1; + } + + const int chunkSize = 500000; + char *buf = new char[chunkSize]; + size_t sz = 0; + while ((sz = fread(buf, 1, chunkSize, srcFile))) + { + if (fwrite(buf, 1, sz, dstFile) != sz) + { + delete [] buf; + fclose(srcFile); + fclose(dstFile); + ::remove(dstName.c_str()); + return -1; + } + } + + delete [] buf; + fclose(srcFile); + fclose(dstFile); + if (!::remove(srcName.c_str())) + return 0; + + return -1; +} diff --git a/src/utils/files.h b/src/utils/files.h index bb9a6a11f..f356d7688 100644 --- a/src/utils/files.h +++ b/src/utils/files.h @@ -21,12 +21,18 @@ #ifndef UTILS_FILES_H #define UTILS_FILES_H -#ifdef ANDROID #include <string> namespace Files { +#ifdef ANDROID void extractLocale(); +#endif + +#if defined(ANDROID) || defined(__native_client__) + typedef void (*CopyFileCallbackPtr) (int cnt); + + void setCopyCallBack(CopyFileCallbackPtr callback); void copyPhysFsFile(const std::string &inFile, const std::string &outFile); @@ -34,7 +40,9 @@ namespace Files void extractZip(const std::string &zipName, const std::string &inDir, const std::string &outDir); +#endif // ANDROID __native_client__ + + int renameFile(const std::string &pFrom, const std::string &pTo); } // namespace Files -#endif // ANDROID #endif // UTILS_FILES_H diff --git a/src/utils/files_unittest.cc b/src/utils/files_unittest.cc new file mode 100644 index 000000000..63e1fc271 --- /dev/null +++ b/src/utils/files_unittest.cc @@ -0,0 +1,71 @@ +/* + * The ManaPlus Client + * Copyright (C) 2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/files.h" + +#include "logger.h" + +#include "utils/physfstools.h" + +#include "gtest/gtest.h" + +#include "resources/resourcemanager.h" + +#include "debug.h" + +static void init() +{ + PHYSFS_init("manaplus"); + dirSeparator = "/"; + logger = new Logger(); + ResourceManager *resman = ResourceManager::getInstance(); + resman->addToSearchPath("data", false); + resman->addToSearchPath("../data", false); +} + +TEST(Files, renameFile) +{ + init(); + const int sz = 1234567; + char *buf = new char[sz]; + for (int f = 0; f < sz; f ++) + buf[f] = f; + + const std::string name1 = "file1.test"; + const std::string name2 = "file2.test"; + FILE *file = fopen(name1.c_str(), "w+b"); + fwrite(buf, 1, sz, file); + fclose(file); + + EXPECT_EQ(0, Files::renameFile(name1, name2)); + char *buf2 = new char[sz]; + FILE *file2 = fopen(name2.c_str(), "rb"); + EXPECT_NE(nullptr, file2); + fread(buf2, 1, sz, file2); + fclose(file2); + ::remove(name1.c_str()); + ::remove(name2.c_str()); + + for (int f = 0; f < sz; f ++) + EXPECT_EQ(buf[f], buf2[f]); + + delete [] buf; + delete [] buf2; +} diff --git a/src/utils/gettext.h b/src/utils/gettext.h index ed686cffd..a00e44898 100644 --- a/src/utils/gettext.h +++ b/src/utils/gettext.h @@ -27,10 +27,10 @@ #include "config.h" #endif -#include <libintl.h> - #ifdef ENABLE_NLS +#include <libintl.h> + #define _(s) (const_cast <char*>(gettext(s))) #define N_(s) (const_cast <char*>(s)) diff --git a/src/utils/mkdir.cpp b/src/utils/mkdir.cpp index fc6909710..3108d1afa 100644 --- a/src/utils/mkdir.cpp +++ b/src/utils/mkdir.cpp @@ -112,6 +112,7 @@ int mkdir_r(const char *const pathname) return 0; } #else + /// Create a directory, making leading components first if necessary int mkdir_r(const char *const pathname) { diff --git a/src/utils/paths.cpp b/src/utils/paths.cpp index e3992cd72..e1a4ee03c 100644 --- a/src/utils/paths.cpp +++ b/src/utils/paths.cpp @@ -30,11 +30,18 @@ #include "resources/resourcemanager.h" +#ifdef __native_client__ +#include <limits.h> +#define realpath(N, R) strcpy(R, N) +#endif + #ifdef WIN32 #include "utils/specialfolder.h" #define realpath(N, R) _fullpath((R), (N), _MAX_PATH) #elif defined __OpenBSD__ #include <limits> +#elif defined __native_client__ +#include <limits.h> #endif #ifdef ANDROID @@ -45,10 +52,17 @@ #include "debug.h" +namespace +{ + std::string mPackageDir; +} // namespace + std::string getRealPath(const std::string &str) { -#if defined(__OpenBSD__) || defined(__ANDROID__) +#if defined(__OpenBSD__) || defined(__ANDROID__) || defined(__native_client__) char *realPath = reinterpret_cast<char*>(calloc(PATH_MAX, sizeof(char))); + if (!realPath) + return ""; realpath(str.c_str(), realPath); #else char *realPath = realpath(str.c_str(), nullptr); @@ -186,3 +200,13 @@ std::string getSdStoragePath() return getenv("DATADIR2"); } #endif + +std::string getPackageDir() +{ + return mPackageDir; +} + +void setPackageDir(const std::string &dir) +{ + mPackageDir = dir; +} diff --git a/src/utils/paths.h b/src/utils/paths.h index 6e2d17808..cb0af64ad 100644 --- a/src/utils/paths.h +++ b/src/utils/paths.h @@ -43,4 +43,8 @@ std::string getDesktopDir() A_WARN_UNUSED; std::string getSdStoragePath() A_WARN_UNUSED; #endif +std::string getPackageDir() A_WARN_UNUSED; + +void setPackageDir(const std::string &dir); + #endif // UTILS_PATHS_H diff --git a/src/utils/physfstools.cpp b/src/utils/physfstools.cpp index cf87fa9ab..325f7cddc 100644 --- a/src/utils/physfstools.cpp +++ b/src/utils/physfstools.cpp @@ -20,12 +20,37 @@ #include "utils/physfstools.h" +#include <iostream> +#include <unistd.h> + +#ifdef ANDROID +#include "utils/paths.h" +#endif + #include "localconsts.h" const char *dirSeparator = nullptr; namespace PhysFs { + void init(const char *const name) + { +#if defined(__native_client__) + if (!PHYSFS_init("/fakebinary")) +#elif defined(ANDROID) + if (!PHYSFS_init((getRealPath(".").append("/fakebinary")).c_str())) +#else + if (!PHYSFS_init(name)) +#endif + { + std::cout << "Error while initializing PhysFS: " + << PHYSFS_getLastError() << std::endl; + _exit(1); + } + updateDirSeparator(); + atexit((void(*)()) PHYSFS_deinit); + } + void updateDirSeparator() { dirSeparator = PHYSFS_getDirSeparator(); diff --git a/src/utils/physfstools.h b/src/utils/physfstools.h index cb64a981b..fd760f287 100644 --- a/src/utils/physfstools.h +++ b/src/utils/physfstools.h @@ -25,6 +25,7 @@ namespace PhysFs { + void init(const char *const name); void updateDirSeparator(); const char *getDirSeparator(); const char *getBaseDir(); diff --git a/src/utils/sdlcheckutils.cpp b/src/utils/sdlcheckutils.cpp index 3810672d9..7140e44fe 100644 --- a/src/utils/sdlcheckutils.cpp +++ b/src/utils/sdlcheckutils.cpp @@ -138,6 +138,12 @@ SDL_Surface *FakeIMG_LoadPNG_RW(SDL_RWops *const src, const char *const file, return addSurface("IMG_LoadPNG_RW", IMG_LoadPNG_RW(src), file, line); } +SDL_Surface *FakeIMG_LoadJPG_RW(SDL_RWops *const src, const char *const file, + const unsigned line) +{ + return addSurface("IMG_LoadJPG_RW", IMG_LoadJPG_RW(src), file, line); +} + SDL_Surface *FakeIMG_Load(const char *name, const char *const file, const unsigned line) { diff --git a/src/utils/sdlcheckutils.h b/src/utils/sdlcheckutils.h index b1f1a0821..a2f9bb90a 100644 --- a/src/utils/sdlcheckutils.h +++ b/src/utils/sdlcheckutils.h @@ -35,6 +35,9 @@ struct SDL_Surface; SDL_Surface *FakeIMG_LoadPNG_RW(SDL_RWops *const src, const char *const file, const unsigned line); +SDL_Surface *FakeIMG_LoadJPG_RW(SDL_RWops *const src, const char *const file, + const unsigned line); + void FakeSDL_FreeSurface(SDL_Surface *const surface, const char *const file, const unsigned line); diff --git a/src/utils/timer.cpp b/src/utils/timer.cpp new file mode 100644 index 000000000..f6aab825c --- /dev/null +++ b/src/utils/timer.cpp @@ -0,0 +1,122 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "utils/timer.h" + +#include "SDL_timer.h" + +#include <climits> + +#include "debug.h" + +namespace +{ +#ifdef USE_SDL2 + SDL_TimerID mLogicCounterId(0); + SDL_TimerID mSecondsCounterId(0); +#else + SDL_TimerID mLogicCounterId(nullptr); + SDL_TimerID mSecondsCounterId(nullptr); +#endif +} // namespace + +/** + * Tells the max tick value, + * setting it back to zero (and start again). + */ +static const int MAX_TICK_VALUE = INT_MAX / 2; + +volatile int tick_time; /**< Tick counter */ +volatile int fps = 0; /**< Frames counted in the last second */ +volatile int lps = 0; /**< Logic processed per second */ +volatile int frame_count = 0; /**< Counts the frames during one second */ +volatile int logic_count = 0; /**< Counts the logic during one second */ +volatile int cur_time; + +static uint32_t nextTick(uint32_t interval, void *param A_UNUSED); +static uint32_t nextSecond(uint32_t interval, void *param A_UNUSED); + +/** + * Advances game logic counter. + * Called every 10 milliseconds by SDL_AddTimer() + * @see MILLISECONDS_IN_A_TICK value + */ +static uint32_t nextTick(uint32_t interval, void *param A_UNUSED) +{ + tick_time++; + if (tick_time == MAX_TICK_VALUE) + tick_time = 0; + return interval; +} + +/** + * Updates fps. + * Called every seconds by SDL_AddTimer() + */ +static uint32_t nextSecond(uint32_t interval, void *param A_UNUSED) +{ + fps = frame_count; + lps = logic_count; + frame_count = 0; + logic_count = 0; + + return interval; +} + +/** + * @return the elapsed time in milliseconds + * between two tick values. + */ +int get_elapsed_time(const int startTime) +{ + const int time = tick_time; + if (startTime <= time) + { + return (time - startTime) * MILLISECONDS_IN_A_TICK; + } + else + { + return (time + (MAX_TICK_VALUE - startTime)) + * MILLISECONDS_IN_A_TICK; + } +} + +int get_elapsed_time1(const int startTime) +{ + const int time = tick_time; + if (startTime <= time) + return time - startTime; + else + return time + (MAX_TICK_VALUE - startTime); +} + +void startTimers() +{ + // Initialize logic and seconds counters + tick_time = 0; + mLogicCounterId = SDL_AddTimer(MILLISECONDS_IN_A_TICK, nextTick, nullptr); + mSecondsCounterId = SDL_AddTimer(1000, nextSecond, nullptr); +} + +void stopTimers() +{ + SDL_RemoveTimer(mLogicCounterId); + SDL_RemoveTimer(mSecondsCounterId); +} diff --git a/src/utils/timer.h b/src/utils/timer.h new file mode 100644 index 000000000..40f8cc39d --- /dev/null +++ b/src/utils/timer.h @@ -0,0 +1,49 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011-2013 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef UTILS_TIMER_H +#define UTILS_TIMER_H + +#include "localconsts.h" + +/** + * Set the milliseconds value of a tick time. + */ +static const int MILLISECONDS_IN_A_TICK = 10; + +extern volatile int fps; +extern volatile int lps; +extern volatile int tick_time; +extern volatile int cur_time; +extern volatile int frame_count; +extern volatile int logic_count; + +void startTimers(); + +void stopTimers(); + +/** + * Returns elapsed time. (Warning: supposes the delay is always < 100 seconds) + */ +int get_elapsed_time(const int startTime) A_WARN_UNUSED; + +int get_elapsed_time1(const int startTime) A_WARN_UNUSED; + +#endif // UTILS_TIMER_H diff --git a/src/utils/xml.cpp b/src/utils/xml.cpp index 5f691fd68..b87418079 100644 --- a/src/utils/xml.cpp +++ b/src/utils/xml.cpp @@ -34,9 +34,39 @@ #include "debug.h" -static void xmlNullLogger(void *ctx A_UNUSED, const char *msg A_UNUSED, ...) +static void xmlErrorLogger(void *ctx A_UNUSED, const char *msg A_UNUSED, ...) +#ifdef __GNUC__ +#ifdef __OpenBSD__ + __attribute__((__format__(printf, 2, 3))) +#else + __attribute__((__format__(gnu_printf, 2, 3))) +#endif +#endif +; + +static void xmlErrorLogger(void *ctx A_UNUSED, const char *msg, ...) { - // Does nothing, that's the whole point of it + unsigned size = 1024; + const unsigned msgSize = strlen(msg); + if (msgSize * 3 > size) + size = static_cast<unsigned>(msgSize * 3); + + char* buf = new char[size + 1]; + va_list ap; + + // Use a temporary buffer to fill in the variables + va_start(ap, msg); + vsnprintf(buf, size, msg, ap); + buf[size] = 0; + va_end(ap); + + if (logger) + logger->log1(buf); + else + puts(buf); + + // Delete temporary buffer + delete [] buf; } namespace XML @@ -213,7 +243,7 @@ namespace XML LIBXML_TEST_VERSION; // Suppress libxml2 error messages - xmlSetGenericErrorFunc(nullptr, &xmlNullLogger); + xmlSetGenericErrorFunc(nullptr, &xmlErrorLogger); } // Shutdown libxml |