diff options
author | Andrei Karas <akaras@inbox.ru> | 2012-02-05 15:00:58 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2012-02-05 15:00:58 +0300 |
commit | 9a3a196dbf633a699c26d0227802a42f025c8bfd (patch) | |
tree | dfbdb2ff1e2c54d75a2bf6411d3f70df22518c28 /src | |
parent | fc17ff22d9df50df9c5d1cf3dc0de358001271ed (diff) | |
parent | ece36a40d4e9a838cde01075d7681b8fc517b19f (diff) | |
download | manaverse-9a3a196dbf633a699c26d0227802a42f025c8bfd.tar.gz manaverse-9a3a196dbf633a699c26d0227802a42f025c8bfd.tar.bz2 manaverse-9a3a196dbf633a699c26d0227802a42f025c8bfd.tar.xz manaverse-9a3a196dbf633a699c26d0227802a42f025c8bfd.zip |
Merge branch 'master' into stripped
Conflicts:
src/guichan/gui.cpp
src/guichan/include/guichan/sdl/sdlpixel.hpp
Diffstat (limited to 'src')
175 files changed, 2650 insertions, 1506 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c612629c..f389c4364 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -247,6 +247,8 @@ SET(SRCS gui/debugwindow.h gui/didyouknowwindow.cpp gui/didyouknowwindow.h + gui/editserverdialog.cpp + gui/editserverdialog.h gui/emotepopup.cpp gui/emotepopup.h gui/equipmentwindow.cpp @@ -445,6 +447,8 @@ SET(SRCS resources/wallpaper.h utils/base64.cpp utils/base64.h + utils/checkutils.cpp + utils/checkutils.h utils/copynpaste.cpp utils/copynpaste.h utils/dtor.h @@ -452,6 +456,8 @@ SET(SRCS utils/mathutils.h utils/paths.cpp utils/paths.h + utils/physfsrwops.cpp + utils/physfsrwops.h utils/process.cpp utils/process.h utils/stringutils.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 1893adb80..a241b60b0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -153,6 +153,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ gui/debugwindow.h \ gui/didyouknowwindow.cpp \ gui/didyouknowwindow.h \ + gui/editserverdialog.cpp \ + gui/editserverdialog.h \ gui/emotepopup.cpp \ gui/emotepopup.h \ gui/equipmentwindow.cpp \ @@ -353,6 +355,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/wallpaper.h \ utils/base64.cpp \ utils/base64.h \ + utils/checkutils.cpp \ + utils/checkutils.h \ utils/copynpaste.cpp \ utils/copynpaste.h \ utils/dtor.h \ @@ -362,6 +366,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ utils/mkdir.h \ utils/paths.cpp \ utils/paths.h \ + utils/physfsrwops.cpp \ + utils/physfsrwops.h \ utils/process.cpp \ utils/process.h \ utils/specialfolder.cpp \ diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index c1c139bb9..916b599f9 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -39,6 +39,8 @@ #include "resources/imageset.h" #include "resources/resourcemanager.h" +#include "utils/checkutils.h" + #include "debug.h" #define EFFECTS_FILE "effects.xml" @@ -70,7 +72,7 @@ ActorSprite::~ActorSprite() for (ActorSpriteListenerIterator iter = mActorSpriteListeners.begin(), e = mActorSpriteListeners.end(); iter != e; ++iter) { - if (*iter) + if (reportFalse(*iter)) (*iter)->actorSpriteDestroyed(*this); } } @@ -166,6 +168,9 @@ static bool effects_initialized = false; static EffectDescription *getEffectDescription(XmlNodePtr node, int *id) { + if (!id) + return nullptr; + EffectDescription *ed = new EffectDescription; *id = atoi(XML::getProperty(node, "id", "-1").c_str()); @@ -245,7 +250,7 @@ void ActorSprite::setStatusEffectBlock(int offset, Uint16 newEffects) void ActorSprite::internalTriggerEffect(int effectId, bool sfx, bool gfx) { - if (!particleEngine) + if (reportTrue(!particleEngine)) return; if (player_node) @@ -256,13 +261,13 @@ void ActorSprite::internalTriggerEffect(int effectId, bool sfx, bool gfx) EffectDescription *ed = getEffectDescription(effectId); - if (!ed) + if (reportTrue(!ed)) { logger->log1("Unknown special effect and no default recorded"); return; } - if (gfx && !ed->mGFXEffect.empty() && particleEngine) + if (gfx && !ed->mGFXEffect.empty()) { Particle *selfFX; @@ -287,7 +292,7 @@ void ActorSprite::updateStatusEffect(int index, bool newStatus) void ActorSprite::handleStatusEffect(StatusEffect *effect, int effectId) { - if (!effect) + if (reportTrue(!effect)) return; // TODO: Find out how this is meant to be used @@ -392,7 +397,7 @@ void ActorSprite::load() void ActorSprite::unload() { - if (!loaded) + if (reportTrue(!loaded)) return; cleanupTargetCursors(); @@ -476,7 +481,7 @@ void ActorSprite::cleanupTargetCursors() void ActorSprite::loadTargetCursor(const std::string &filename, int width, int height, int type, int size) { - if (size < TC_SMALL || size >= NUM_TC) + if (reportTrue(size < TC_SMALL || size >= NUM_TC)) return; ImageSet *currentImageSet = Theme::getImageSetFromTheme( diff --git a/src/actorspritemanager.h b/src/actorspritemanager.h index 7960c6301..a78e3ad49 100644 --- a/src/actorspritemanager.h +++ b/src/actorspritemanager.h @@ -231,10 +231,10 @@ class ActorSpriteManager: public ConfigListener void addIgnoreAttackMob(std::string name); - std::list<std::string> getPriorityAttackMobs() + std::list<std::string> getPriorityAttackMobs() const { return mPriorityAttackMobs; } - std::list<std::string> getAttackMobs() + std::list<std::string> getAttackMobs() const { return mAttackMobs; } void setPriorityAttackMobs(std::list<std::string> mobs) @@ -243,29 +243,29 @@ class ActorSpriteManager: public ConfigListener void setAttackMobs(std::list<std::string> mobs) { mAttackMobs = mobs; } - int getPriorityAttackMobsSize() + int getPriorityAttackMobsSize() const { return mPriorityAttackMobs.size(); } - int getAttackMobsSize() + int getAttackMobsSize() const { return mAttackMobs.size(); } - std::list<std::string> getIgnoreAttackMobs() + std::list<std::string> getIgnoreAttackMobs() const { return mIgnoreAttackMobs; } - std::set<std::string> getAttackMobsSet() + std::set<std::string> getAttackMobsSet() const { return mAttackMobsSet; } - std::set<std::string> getPriorityAttackMobsSet() + std::set<std::string> getPriorityAttackMobsSet() const { return mPriorityAttackMobsSet; } - std::set<std::string> getIgnoreAttackMobsSet() + std::set<std::string> getIgnoreAttackMobsSet() const { return mIgnoreAttackMobsSet; } void rebuildPriorityAttackMobs(); void rebuildAttackMobs(); - bool isInAttackList(const std::string &name) + bool isInAttackList(const std::string &name) const { return mAttackMobsSet.find(name) != mAttackMobsSet.end(); } bool isInPriorityAttackList(const std::string &name) @@ -280,10 +280,10 @@ class ActorSpriteManager: public ConfigListener != mIgnoreAttackMobsSet.end(); } - std::map<std::string, int> getAttackMobsMap() + std::map<std::string, int> getAttackMobsMap() const { return mAttackMobsMap; } - std::map<std::string, int> getPriorityAttackMobsMap() + std::map<std::string, int> getPriorityAttackMobsMap() const { return mPriorityAttackMobsMap; } int getAttackMobIndex(std::string name); diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index f4f3451cb..11329b321 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -285,7 +285,7 @@ int AnimatedSprite::getHeight() const return 0; } -std::string AnimatedSprite::getIdPath() +std::string AnimatedSprite::getIdPath() const { if (!mSprite) return ""; diff --git a/src/animatedsprite.h b/src/animatedsprite.h index 4a41eac52..d28badfc1 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -71,10 +71,10 @@ class AnimatedSprite : public Sprite bool setSpriteDirection(SpriteDirection direction); - int getNumberOfLayers() + int getNumberOfLayers() const { return 1; } - std::string getIdPath(); + std::string getIdPath() const; unsigned int getCurrentFrame() const; diff --git a/src/being.cpp b/src/being.cpp index 39d0bd450..9edfaad7b 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -2517,26 +2517,31 @@ void Being::saveComment(const std::string &name, resman->saveTextFile(dir, "comment.txt", name + "\n" + comment); } +void Being::setState(Uint8 state) +{ + mAdvanced = true; + bool shop = (state & FLAG_SHOP); + bool away = (state & FLAG_AWAY); + bool inactive = (state & FLAG_INACTIVE); + bool needUpdate = (shop != mShop || away != mAway + || inactive != mInactive); + + mShop = shop; + mAway = away; + mInactive = inactive; + + if (needUpdate) + { + updateName(); + addToCache(); + } +} + void Being::setEmote(Uint8 emotion, int emote_time) { if ((emotion & FLAG_SPECIAL) == FLAG_SPECIAL) { - mAdvanced = true; - bool shop = (emotion & FLAG_SHOP); - bool away = (emotion & FLAG_AWAY); - bool inactive = (emotion & FLAG_INACTIVE); - bool needUpdate = (shop != mShop || away != mAway - || inactive != mInactive); - - mShop = shop; - mAway = away; - mInactive = inactive; - - if (needUpdate) - { - updateName(); - addToCache(); - } + setState(emotion); } else { diff --git a/src/being.h b/src/being.h index 6052644c9..8b3db1919 100644 --- a/src/being.h +++ b/src/being.h @@ -102,6 +102,7 @@ class Being : public ActorSprite, public ConfigListener FLAG_SHOP = 1, FLAG_AWAY = 2, FLAG_INACTIVE = 4, + FLAG_GENDER = 128, FLAG_SPECIAL = 128 + 64 }; @@ -488,7 +489,7 @@ class Being : public ActorSprite, public ConfigListener virtual void setDirectionDelayed(Uint8 direction) { mDirectionDelayed = direction; } - Uint8 getDirectionDelayed() + Uint8 getDirectionDelayed() const { return mDirectionDelayed; } /** @@ -546,6 +547,8 @@ class Being : public ActorSprite, public ConfigListener */ void setEmote(Uint8 emotion, int emote_time); + void setState(Uint8 state); + /** * Get the current Emoticon type displayed above * the being. @@ -585,7 +588,7 @@ class Being : public ActorSprite, public ConfigListener void setIsReachable(int n) { mIsReachable = n; } - int isReachable() + int isReachable() const { return mIsReachable; } static void reReadConfig(); @@ -678,7 +681,7 @@ class Being : public ActorSprite, public ConfigListener void setMaxHP(int hp); - int getHP() + int getHP() const { return mHP; } Uint8 calcDirection(int dstX, int dstY) const; @@ -688,22 +691,22 @@ class Being : public ActorSprite, public ConfigListener void setAttackDelay(int n) { mAttackDelay = n; } - int getAttackDelay() + int getAttackDelay() const { return mAttackDelay; } - int getMinHit() + int getMinHit() const { return mMinHit; } void setMinHit(int n) { mMinHit = n; } - int getMaxHit() + int getMaxHit() const { return mMaxHit; } void setMaxHit(int n) { mMaxHit = n; } - int getCriticalHit() + int getCriticalHit() const { return mCriticalHit; } void setCriticalHit(int n) @@ -715,7 +718,7 @@ class Being : public ActorSprite, public ConfigListener void undressItemById(int id); - int getGoodStatus() + int getGoodStatus() const { return mGoodStatus; } void setGoodStatus(int n) @@ -727,7 +730,7 @@ class Being : public ActorSprite, public ConfigListener void updateComment(); - std::string getComment() + const std::string getComment() const { return mComment; } void setComment(std::string n) @@ -740,15 +743,18 @@ class Being : public ActorSprite, public ConfigListener static void saveComment(const std::string &name, const std::string &comment, int type); - bool isAdvanced() + bool isAdvanced() const { return mAdvanced; } void setAdvanced(bool n) { mAdvanced = n; addToCache(); } - bool isShopEnabled() + bool isShopEnabled() const { return mShop; } + void enableShop(bool b) + { mShop = b; } + /** * Sets the attack range. */ diff --git a/src/channel.h b/src/channel.h index 559002296..cf52743f0 100644 --- a/src/channel.h +++ b/src/channel.h @@ -46,7 +46,8 @@ class Channel /** * Get the id associated witht his channel. */ - int getId() const { return mId; } + int getId() const + { return mId; } /** * Get this channel's name. @@ -72,7 +73,7 @@ class Channel void setAnnouncement(const std::string &channelAnnouncement) { mAnnouncement = channelAnnouncement; } - ChannelTab *getTab() + ChannelTab *getTab() const { return mTab; } protected: diff --git a/src/chatlogger.cpp b/src/chatlogger.cpp index ad86de8e9..33763e561 100644 --- a/src/chatlogger.cpp +++ b/src/chatlogger.cpp @@ -39,7 +39,6 @@ #include "logger.h" #include "configuration.h" - #include "utils/mkdir.h" #include "utils/stringutils.h" @@ -204,3 +203,10 @@ void ChatLogger::loadLast(std::string name, std::list<std::string> &list, if (logFile.is_open()) logFile.close(); } + +void ChatLogger::clear() +{ + mLogDir = ""; + mServerName = ""; + mLogFileName = ""; +} diff --git a/src/chatlogger.h b/src/chatlogger.h index 91805a8bc..bb02d8127 100644 --- a/src/chatlogger.h +++ b/src/chatlogger.h @@ -59,6 +59,8 @@ class ChatLogger void setBaseLogDir(const std::string &logDir) { mBaseLogDir = logDir; } + void clear(); + private: /** * Sets the file to log to and opens it diff --git a/src/client.cpp b/src/client.cpp index 1c4629178..c21194834 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -167,7 +167,7 @@ volatile int frame_count = 0; /**< Counts the frames during one second */ volatile int cur_time; volatile bool runCounters; bool isSafeMode = false; -int serverVersion; +int serverVersion = 0; int start_time; int textures_count = 0; @@ -251,7 +251,7 @@ Client::Client(const Options &options): mServerConfigDir(""), mUsersDir(""), mNpcsDir(""), - mRootDir(""), + mGame(nullptr), mCurrentDialog(nullptr), mQuitDialog(nullptr), mDesktop(nullptr), @@ -524,9 +524,12 @@ void Client::gameInit() const int bpp = 0; const bool fullscreen = config.getBoolValue("screen"); const bool hwaccel = config.getBoolValue("hwaccel"); + const bool enableResize = config.getBoolValue("enableresize"); + const bool noFrame = config.getBoolValue("noframe"); // Try to set the desired video mode - if (!mainGraphics->setVideoMode(width, height, bpp, fullscreen, hwaccel)) + if (!mainGraphics->setVideoMode(width, height, bpp, + fullscreen, hwaccel, enableResize, noFrame)) { logger->log(strprintf("Couldn't set %dx%dx%d video mode: %s", width, height, bpp, SDL_GetError())); @@ -544,7 +547,7 @@ void Client::gameInit() config.setValueInt("screenheight", oldHeight); config.setValue("screen", oldFullscreen); if (!mainGraphics->setVideoMode(oldWidth, oldHeight, bpp, - oldFullscreen, hwaccel)) + oldFullscreen, hwaccel, enableResize, noFrame)) { logger->error(strprintf("Couldn't restore %dx%dx%d " "video mode: %s", oldWidth, oldHeight, bpp, @@ -612,6 +615,7 @@ void Client::gameInit() { mCurrentServer.hostname = branding.getValue("defaultServer", "").c_str(); + mOptions.serverName = mCurrentServer.hostname; } if (mCurrentServer.port == 0) @@ -815,15 +819,14 @@ int Client::gameExec() if (!mumbleManager) mumbleManager = new MumbleManager(); - Game *game = nullptr; SDL_Event event; while (mState != STATE_EXIT) { - if (game) + if (mGame) { // Let the game handle the events while it is active - game->handleInput(); + mGame->handleInput(); } else { @@ -839,6 +842,10 @@ int Client::gameExec() case SDL_KEYDOWN: default: break; + + case SDL_VIDEORESIZE: + resizeVideo(event.resize.w, event.resize.h, false); + break; } guiInput->pushInput(event); @@ -857,8 +864,8 @@ int Client::gameExec() { if (gui) gui->logic(); - if (game) - game->logic(); + if (mGame) + mGame->logic(); sound.logic(); @@ -966,10 +973,8 @@ int Client::gameExec() top->add(mThemesButton); #endif - int screenWidth = config.getIntValue("screenwidth"); - int screenHeight = config.getIntValue("screenheight"); - - mDesktop->setSize(screenWidth, screenHeight); + mDesktop->setSize(mainGraphics->getWidth(), + mainGraphics->getHeight()); } if (mState == STATE_SWITCH_LOGIN && mOldState == STATE_GAME) @@ -984,8 +989,8 @@ int Client::gameExec() if (mOldState == STATE_GAME) { - delete game; - game = nullptr; + delete mGame; + mGame = nullptr; Game::clearInstance(); ResourceManager *resman = ResourceManager::getInstance(); if (resman) @@ -995,6 +1000,8 @@ int Client::gameExec() Net::getNpcHandler()->clearDialogs(); Net::getGuildHandler()->clear(); Net::getPartyHandler()->clear(); + if (chatLogger) + chatLogger->clear(); } mOldState = mState; @@ -1231,6 +1238,10 @@ int Client::gameExec() CharSelectDialog::Focus); } + // Choosing character on the command line should work only + // once, clear it so that 'switch character' works. + mOptions.character.clear(); + break; case STATE_CONNECT_GAME: @@ -1286,7 +1297,7 @@ int Client::gameExec() logger->log1("State: GAME"); if (Net::getGeneralHandler()) Net::getGeneralHandler()->reloadPartially(); - game = new Game; + mGame = new Game; break; case STATE_LOGIN_ERROR: @@ -1563,7 +1574,7 @@ void Client::initLocalDataDir() // Use Application Directory instead of .mana mLocalDataDir = std::string(PHYSFS_getUserDir()) + "/Library/Application Support/" + - branding.getValue("appName", "Mana"); + branding.getValue("appName", "ManaPlus"); #elif defined __HAIKU__ mLocalDataDir = std::string(PHYSFS_getUserDir()) + "/config/data/Mana"; @@ -1597,13 +1608,13 @@ void Client::initConfigDir() #elif defined __HAIKU__ mConfigDir = std::string(PHYSFS_getUserDir()) + "/config/settings/Mana" + - branding.getValue("appName", "Mana"); + branding.getValue("appName", "ManaPlus"); #elif defined WIN32 mConfigDir = getSpecialFolderLocation(CSIDL_APPDATA); if (mConfigDir.empty()) mConfigDir = mLocalDataDir; else - mConfigDir += "/mana/" + branding.getValue("appShort", "Mana"); + mConfigDir += "/mana/" + branding.getValue("appShort", "mana"); #else mConfigDir = std::string(PHYSFS_getUserDir()) + "/.config/mana/" + branding.getValue("appShort", "mana"); @@ -1855,7 +1866,7 @@ void Client::initScreenshotDir() if (config.getBoolValue("useScreenshotDirectorySuffix")) { std::string configScreenshotSuffix = - branding.getValue("appShort", "Mana"); + branding.getValue("appShort", "mana"); if (!configScreenshotSuffix.empty()) { @@ -1917,7 +1928,7 @@ bool Client::createConfig(std::string &configPath) // Use Application Directory instead of .mana oldHomeDir = std::string(PHYSFS_getUserDir()) + "/Library/Application Support/" + - branding.getValue("appName", "Mana"); + branding.getValue("appName", "ManaPlus"); #else oldHomeDir = std::string(PHYSFS_getUserDir()) + "/." + branding.getValue("appShort", "mana"); @@ -2349,3 +2360,58 @@ bool Client::isTmw() } return false; } + +void Client::resizeVideo(int width, int height, bool always) +{ + // Keep a minimum size. This isn't adhered to by the actual window, but + // it keeps some window positions from getting messed up. + width = std::max(640, width); + height = std::max(480, height); + + if (!mainGraphics) + return; + if (!always && mainGraphics->mWidth == width + && mainGraphics->mHeight == height) + { + return; + } + + if (mainGraphics->resizeScreen(width, height)) + { + if (gui) + gui->videoResized(); + + if (mDesktop) + mDesktop->setSize(width, height); + + if (mSetupButton) + { +// mSetupButton->setPosition(width - mSetupButton->getWidth() - 3, 3); + + int x = width - mSetupButton->getWidth() - 3; + mSetupButton->setPosition(x, 3); + +#ifndef WIN32 + x -= mPerfomanceButton->getWidth() + 6; + mPerfomanceButton->setPosition(x, 3); + + x -= mVideoButton->getWidth() + 6; + mVideoButton->setPosition(x, 3); + + x -= mThemesButton->getWidth() + 6; + mThemesButton->setPosition(x, 3); +#endif + } + + if (mGame) + mGame->videoResized(width, height); + + if (gui) + gui->draw(); + + // Since everything appears to have worked out, remember to store the + // new size in the configuration. + config.setValue("screenwidth", width); + config.setValue("screenheight", height); + } +} diff --git a/src/client.h b/src/client.h index 27e6249bd..6c93adbdf 100644 --- a/src/client.h +++ b/src/client.h @@ -38,6 +38,7 @@ class Button; class Desktop; +class Game; class LoginData; class Window; class QuitDialog; @@ -257,6 +258,9 @@ public: static std::string getServerName() { return instance()->mServerName; } + static void resize(int width, int height, bool always = false) + { instance()->resizeVideo(width, height, always); } + static void setGuiAlpha(float n); static float getGuiAlpha(); @@ -281,6 +285,8 @@ public: void writePacketLimits(std::string packetLimitsName); + void resizeVideo(int width, int height, bool always); + static bool limitPackets(int type); static bool checkPackets(int type); @@ -334,6 +340,7 @@ private: ServerInfo mCurrentServer; + Game *mGame; Window *mCurrentDialog; QuitDialog *mQuitDialog; Desktop *mDesktop; diff --git a/src/commandhandler.cpp b/src/commandhandler.cpp index 0f1e60a25..4022d8d58 100644 --- a/src/commandhandler.cpp +++ b/src/commandhandler.cpp @@ -54,6 +54,7 @@ #include "net/guildhandler.h" #include "net/net.h" #include "net/partyhandler.h" +#include "net/playerhandler.h" #include "net/tradehandler.h" #ifdef DEBUG_DUMP_LEAKS @@ -664,6 +665,9 @@ void CommandHandler::handleNavigate(const std::string &args, bool CommandHandler::parse2Int(const std::string &args, int *x, int *y) { + if (!x || !y) + return false; + bool isValid = false; const std::string::size_type pos = args.find(" "); if (pos != std::string::npos) @@ -748,7 +752,10 @@ void CommandHandler::handlePseudoAway(const std::string &args, ChatTab *tab A_UNUSED) { if (player_node) + { player_node->setPseudoAway(args); + player_node->updateStatus(); + } } void CommandHandler::handleFollow(const std::string &args, ChatTab *tab) @@ -1185,6 +1192,9 @@ void showRes(std::string str, ResourceManager::Resources *res); void showRes(std::string str, ResourceManager::Resources *res) { + if (!res) + return; + if (debugChatTab) debugChatTab->chatLog(str + toString(res->size())); logger->log(str + toString(res->size())); diff --git a/src/compoundsprite.cpp b/src/compoundsprite.cpp index e76a55dcf..61fb3d4e0 100644 --- a/src/compoundsprite.cpp +++ b/src/compoundsprite.cpp @@ -61,10 +61,6 @@ CompoundSprite::CompoundSprite() : CompoundSprite::~CompoundSprite() { - SpriteIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) - delete (*it); - clear(); // delete mImage; @@ -78,7 +74,7 @@ bool CompoundSprite::reset() bool ret = false; SpriteIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) ret |= (*it)->reset(); @@ -93,7 +89,7 @@ bool CompoundSprite::play(std::string action) bool ret = false; SpriteIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) ret |= (*it)->play(action); @@ -108,7 +104,7 @@ bool CompoundSprite::update(int time) bool ret = false; SpriteIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) ret |= (*it)->update(time); @@ -118,11 +114,14 @@ bool CompoundSprite::update(int time) return ret; } -bool CompoundSprite::draw(Graphics* graphics, int posX, int posY) const +bool CompoundSprite::draw(Graphics *graphics, int posX, int posY) const { if (mNeedsRedraw) updateImages(); + if (mSprites.empty()) // Nothing to draw + return false; + if (mAlpha == 1.0f && mImage) { return graphics->drawImage(mImage, posX + mOffsetX, posY + mOffsetY); @@ -144,7 +143,7 @@ bool CompoundSprite::draw(Graphics* graphics, int posX, int posY) const void CompoundSprite::drawSprites(Graphics* graphics, int posX, int posY) const { SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) { @@ -158,7 +157,7 @@ void CompoundSprite::drawSpritesSDL(Graphics* graphics, int posX, int posY) const { SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) (*it)->draw(graphics, posX, posY); @@ -170,7 +169,7 @@ int CompoundSprite::getWidth() const Sprite *base = nullptr; SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if ((base = (*it))) break; @@ -187,7 +186,7 @@ int CompoundSprite::getHeight() const Sprite *base = nullptr; SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if ((base = (*it))) break; @@ -199,7 +198,7 @@ int CompoundSprite::getHeight() const return 0; } -const Image* CompoundSprite::getImage() const +const Image *CompoundSprite::getImage() const { return mImage; } @@ -209,7 +208,7 @@ bool CompoundSprite::setSpriteDirection(SpriteDirection direction) bool ret = false; SpriteIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) ret |= (*it)->setSpriteDirection(direction); @@ -230,7 +229,7 @@ int CompoundSprite::getNumberOfLayers() const unsigned int CompoundSprite::getCurrentFrame() const { SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) return (*it)->getCurrentFrame(); @@ -242,7 +241,7 @@ unsigned int CompoundSprite::getCurrentFrame() const unsigned int CompoundSprite::getFrameCount() const { SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) return (*it)->getFrameCount(); @@ -251,42 +250,43 @@ unsigned int CompoundSprite::getFrameCount() const return 0; } -void CompoundSprite::addSprite(Sprite* sprite) +void CompoundSprite::addSprite(Sprite *sprite) { - push_back(sprite); + mSprites.push_back(sprite); mNeedsRedraw = true; } void CompoundSprite::setSprite(int layer, Sprite* sprite) { // Skip if it won't change anything - if (at(layer) == sprite) + if (mSprites.at(layer) == sprite) return; - if (at(layer)) - delete at(layer); - at(layer) = sprite; + if (mSprites.at(layer)) + delete mSprites.at(layer); + mSprites[layer] = sprite; mNeedsRedraw = true; } void CompoundSprite::removeSprite(int layer) { // Skip if it won't change anything - if (at(layer) == nullptr) + if (!mSprites.at(layer)) return; - delete at(layer); - at(layer) = nullptr; + delete mSprites.at(layer); + mSprites.at(layer) = nullptr; mNeedsRedraw = true; } void CompoundSprite::clear() { // Skip if it won't change anything - if (empty()) - return; - - std::vector<Sprite*>::clear(); + if (!mSprites.empty()) + { + delete_all(mSprites); + mSprites.clear(); + } mNeedsRedraw = true; delete_all(imagesCache); imagesCache.clear(); @@ -297,10 +297,11 @@ void CompoundSprite::clear() void CompoundSprite::ensureSize(size_t layerCount) { // Skip if it won't change anything - if (size() >= layerCount) + if (mSprites.size() >= layerCount) return; - resize(layerCount, nullptr); +// resize(layerCount, nullptr); + mSprites.resize(layerCount); } /** @@ -308,7 +309,7 @@ void CompoundSprite::ensureSize(size_t layerCount) */ unsigned int CompoundSprite::getCurrentFrame(unsigned int layer) { - if (layer >= size()) + if (layer >= mSprites.size()) return 0; Sprite *s = getSprite(layer); @@ -323,7 +324,7 @@ unsigned int CompoundSprite::getCurrentFrame(unsigned int layer) */ unsigned int CompoundSprite::getFrameCount(unsigned int layer) { - if (layer >= size()) + if (layer >= mSprites.size()) return 0; Sprite *s = getSprite(layer); @@ -418,7 +419,8 @@ void CompoundSprite::setAlpha(float alpha) #endif { SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++ it) + for (it = mSprites.begin(), it_end = mSprites.end(); + it != it_end; ++ it) { if (*it) (*it)->setAlpha(alpha); @@ -490,8 +492,8 @@ bool CompoundSprite::updateFromCache() const if (ic && ic->data.size() == size()) { bool fail(false); - SpriteConstIterator it1 = begin(); - SpriteConstIterator it1_end = end(); + SpriteConstIterator it1 = mSprites.begin(); + SpriteConstIterator it1_end = mSprites.end(); VectorPointers::const_iterator it2 = ic->data.begin(); VectorPointers::const_iterator it2_end = ic->data.end(); @@ -535,7 +537,7 @@ void CompoundSprite::initCurrentCacheItem() const // mCacheItem->alpha = mAlpha; SpriteConstIterator it, it_end; - for (it = begin(), it_end = end(); it != it_end; ++ it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) mCacheItem->data.push_back((*it)->getHash()); @@ -548,7 +550,7 @@ bool CompoundSprite::updateNumber(unsigned num) { SpriteConstIterator it, it_end; bool res(false); - for (it = begin(), it_end = end(); it != it_end; ++ it) + for (it = mSprites.begin(), it_end = mSprites.end(); it != it_end; ++ it) { if (*it) { diff --git a/src/compoundsprite.h b/src/compoundsprite.h index 1c04e44d2..1b9eeca34 100644 --- a/src/compoundsprite.h +++ b/src/compoundsprite.h @@ -44,11 +44,11 @@ class CompoundItem Image *alphaImage; }; -class CompoundSprite : public Sprite, private std::vector<Sprite*> +class CompoundSprite : public Sprite { public: - typedef CompoundSprite::iterator SpriteIterator; - typedef CompoundSprite::const_iterator SpriteConstIterator; + typedef std::vector<Sprite*>::iterator SpriteIterator; + typedef std::vector<Sprite*>::const_iterator SpriteConstIterator; CompoundSprite(); @@ -60,7 +60,7 @@ public: virtual bool update(int time); - virtual bool draw(Graphics* graphics, int posX, int posY) const; + virtual bool draw(Graphics *graphics, int posX, int posY) const; /** * Gets the width in pixels of the first sprite in the list. @@ -72,7 +72,7 @@ public: */ virtual int getHeight() const; - virtual const Image* getImage() const; + virtual const Image *getImage() const; virtual bool setSpriteDirection(SpriteDirection direction); @@ -83,17 +83,17 @@ public: unsigned int getFrameCount() const; size_t size() const - { return std::vector<Sprite*>::size(); } + { return mSprites.size(); } bool empty() const - { return std::vector<Sprite*>::empty(); } + { return mSprites.empty(); } - void addSprite(Sprite* sprite); + void addSprite(Sprite *sprite); - void setSprite(int layer, Sprite* sprite); + void setSprite(int layer, Sprite *sprite); Sprite *getSprite(int layer) const - { return at(layer); } + { return mSprites.at(layer); } void removeSprite(int layer); @@ -144,6 +144,7 @@ private: bool mEnableAlphaFix; bool mDisableAdvBeingCaching; bool mDisableBeingCaching; + std::vector<Sprite*> mSprites; }; #endif // COMPOUNDSPRITE_H diff --git a/src/configuration.h b/src/configuration.h index 00479933e..122badfd5 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -253,10 +253,10 @@ class Configuration : public ConfigurationObject void setSilent(const std::string &key, const std::string &value); inline void setValue(const std::string &key, const char *value) - { setValue(key, std::string(value)); } + { if (value) setValue(key, std::string(value)); } inline void setSilent(const std::string &key, const char *value) - { setSilent(key, std::string(value)); } + { if (value) setSilent(key, std::string(value)); } inline void setValue(const std::string &key, float value) { setValue(key, toString(value)); } diff --git a/src/debug.h b/src/debug.h index 4b3934922..64a83e51c 100644 --- a/src/debug.h +++ b/src/debug.h @@ -23,6 +23,19 @@ //#define DEBUG_JOYSTICK 1 #ifdef ENABLE_MEM_DEBUG + //define _DEBUG_NEW_EMULATE_MALLOC 1 #include "debug/debug_new.h" + +#define reportFalse(val) reportFalse1(val, __FILE__, __LINE__) +#define reportFalse1(val, file, line) reportFalseReal(val, file, line) + +#define reportTrue(val) reportTrue1(val, __FILE__, __LINE__) +#define reportTrue1(val, file, line) reportTrueReal(val, file, line) + +#else + +#define reportFalse(val) (val) +#define reportTrue(val) (val) + #endif diff --git a/src/defaults.cpp b/src/defaults.cpp index 8c0b84ae2..1bce806ff 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -225,6 +225,8 @@ DefaultsData* getConfigDefaults() AddDEF(configData, "selectedJoystick", 0); AddDEF(configData, "useInactiveJoystick", false); AddDEF(configData, "testInfo", ""); + AddDEF(configData, "enableresize", true); + AddDEF(configData, "noframe", false); return configData; } @@ -234,8 +236,8 @@ DefaultsData* getBrandingDefaults() // Init config defaults AddDEF(brandingData, "wallpapersPath", ""); AddDEF(brandingData, "wallpapersFile", ""); - AddDEF(brandingData, "appName", "Mana"); - AddDEF(brandingData, "appIcon", "icons/mana.png"); + AddDEF(brandingData, "appName", "ManaPlus"); + AddDEF(brandingData, "appIcon", "icons/manaplus"); AddDEF(brandingData, "loginMusic", "Magick - Real.ogg"); AddDEF(brandingData, "defaultServer", ""); AddDEF(brandingData, "defaultPort", DEFAULT_PORT); diff --git a/src/dropshortcut.cpp b/src/dropshortcut.cpp index 79f895490..5b01f7f4f 100644 --- a/src/dropshortcut.cpp +++ b/src/dropshortcut.cpp @@ -133,6 +133,13 @@ void DropShortcut::dropItems(int cnt) if (!player_node) return; + + if (player_node->isServerBuggy()) + { + dropItem(player_node->getQuickDropCounter()); + return; + } + int n = 0; for (int f = 0; f < 9; f++) { diff --git a/src/emoteshortcut.h b/src/emoteshortcut.h index cc33f4177..d7f1e7b79 100644 --- a/src/emoteshortcut.h +++ b/src/emoteshortcut.h @@ -21,7 +21,7 @@ #ifndef EMOTESHORTCUT_H #define EMOTESHORTCUT_H -#define SHORTCUT_EMOTES 44 +#define SHORTCUT_EMOTES 48 /** * The class which keeps track of the emote shortcuts. diff --git a/src/equipment.h b/src/equipment.h index 6e4d04c21..50acd60d3 100644 --- a/src/equipment.h +++ b/src/equipment.h @@ -90,7 +90,7 @@ class Equipment void setBackend(Backend *backend) { mBackend = backend; } - Backend *getBackend() + Backend *getBackend() const { return mBackend; } private: diff --git a/src/flooritem.h b/src/flooritem.h index 7e7da33a0..95427c252 100644 --- a/src/flooritem.h +++ b/src/flooritem.h @@ -83,7 +83,7 @@ class FloorItem : public ActorSprite unsigned char getColor() const { return mColor; } - bool getShowMsg() + bool getShowMsg() const { return mShowMsg; } void setShowMsg(bool n) diff --git a/src/game.cpp b/src/game.cpp index 14a988700..0d5c1113e 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -287,6 +287,9 @@ static void createGuiWindows() if (setupWindow) setupWindow->externalUpdate(); + if (player_node) + player_node->updateStatus(); + Mana::Event::trigger(CHANNEL_GAME, Mana::Event(EVENT_GUIWINDOWSLOADED)); } @@ -373,8 +376,7 @@ Game::Game(): // Create the viewport viewport = new Viewport; - viewport->setDimension(gcn::Rectangle(0, 0, mainGraphics->mWidth, - mainGraphics->mHeight)); + viewport->setSize(mainGraphics->mWidth, mainGraphics->mHeight); gcn::Container *top = static_cast<gcn::Container*>(gui->getTop()); top->add(viewport); @@ -490,7 +492,7 @@ static bool saveScreenshot() filenameSuffix.str(""); filename.str(""); filename << screenshotDirectory << "/"; - filenameSuffix << branding.getValue("appShort", "ManaPlus") + filenameSuffix << branding.getValue("appName", "ManaPlus") << "_Screenshot_" << screenshotCount << ".png"; filename << filenameSuffix.str(); testExists.open(filename.str().c_str(), std::ios::in); @@ -724,10 +726,10 @@ bool Game::handleOutfitsKeys(SDL_Event &event, bool &used) { bool wearOutfit = false; bool copyOutfit = false; - if (keyboard.isKeyActive(keyboard.KEY_WEAR_OUTFIT)) + if (keyboard.isActionActive(keyboard.KEY_WEAR_OUTFIT)) wearOutfit = true; - if (keyboard.isKeyActive(keyboard.KEY_COPY_OUTFIT)) + if (keyboard.isActionActive(keyboard.KEY_COPY_OUTFIT)) copyOutfit = true; if (wearOutfit || copyOutfit) @@ -744,15 +746,15 @@ bool Game::handleOutfitsKeys(SDL_Event &event, bool &used) } else { - if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT)) + if (keyboard.isActionActive(keyboard.KEY_MOVE_RIGHT)) outfitWindow->wearNextOutfit(); - else if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT)) + else if (keyboard.isActionActive(keyboard.KEY_MOVE_LEFT)) outfitWindow->wearPreviousOutfit(); } setValidSpeed(); return true; } - else if (keyboard.isKeyActive(keyboard.KEY_MOVE_TO_POINT)) + else if (keyboard.isActionActive(keyboard.KEY_MOVE_TO_POINT)) { int num = outfitWindow->keyToNumber( event.key.keysym.sym); @@ -773,7 +775,7 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) && !player_node->getAway()) { NpcDialog *dialog = NpcDialog::getActive(); - if (keyboard.isKeyActive(keyboard.KEY_OK) + if (keyboard.isActionActive(keyboard.KEY_OK) && (!dialog || !dialog->isTextInputFocused())) { // Close the Browser if opened @@ -790,7 +792,7 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) dialog->action(gcn::ActionEvent(nullptr, "ok")); } } - if (chatWindow && keyboard.isKeyActive( + if (chatWindow && keyboard.isActionActive( keyboard.KEY_TOGGLE_CHAT)) { if (!InventoryWindow::isAnyInputFocused()) @@ -801,9 +803,9 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) } if (dialog) { - if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP)) + if (keyboard.isActionActive(keyboard.KEY_MOVE_UP)) dialog->move(1); - else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN)) + else if (keyboard.isActionActive(keyboard.KEY_MOVE_DOWN)) dialog->move(-1); } } @@ -813,27 +815,27 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) !InventoryWindow::isAnyInputFocused()) || (event.key.keysym.mod & KMOD_ALT))) { - if (keyboard.isKeyActive(keyboard.KEY_PREV_CHAT_TAB)) + if (keyboard.isActionActive(keyboard.KEY_PREV_CHAT_TAB)) { chatWindow->prevTab(); return true; } - else if (keyboard.isKeyActive(keyboard.KEY_NEXT_CHAT_TAB)) + else if (keyboard.isActionActive(keyboard.KEY_NEXT_CHAT_TAB)) { chatWindow->nextTab(); return true; } - else if (keyboard.isKeyActive(keyboard.KEY_PREV_SOCIAL_TAB)) + else if (keyboard.isActionActive(keyboard.KEY_PREV_SOCIAL_TAB)) { socialWindow->prevTab(); return true; } - else if (keyboard.isKeyActive(keyboard.KEY_NEXT_SOCIAL_TAB)) + else if (keyboard.isActionActive(keyboard.KEY_NEXT_SOCIAL_TAB)) { socialWindow->nextTab(); return true; } - else if (keyboard.isKeyActive(keyboard.KEY_CLOSE_CHAT_TAB)) + else if (keyboard.isActionActive(keyboard.KEY_CLOSE_CHAT_TAB)) { chatWindow->closeTab(); return true; @@ -963,9 +965,9 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) case KeyboardConfig::KEY_MOVE_TO_TARGET: if (player_node) { - if (!keyboard.isKeyActive( + if (!keyboard.isActionActive( keyboard.KEY_TARGET_ATTACK) - && !keyboard.isKeyActive(keyboard.KEY_ATTACK)) + && !keyboard.isActionActive(keyboard.KEY_ATTACK)) { player_node->moveToTarget(); } @@ -975,9 +977,9 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) case KeyboardConfig::KEY_MOVE_TO_HOME: if (player_node) { - if (!keyboard.isKeyActive( + if (!keyboard.isActionActive( keyboard.KEY_TARGET_ATTACK) - && !keyboard.isKeyActive(keyboard.KEY_ATTACK)) + && !keyboard.isActionActive(keyboard.KEY_ATTACK)) { player_node->moveToHome(); } @@ -1077,6 +1079,7 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) if (player_node) { player_node->changeAwayMode(); + player_node->updateStatus(); setValidSpeed(); } break; @@ -1099,8 +1102,8 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) if (!NpcDialog::isAnyInputFocused() && !InventoryWindow::isAnyInputFocused() - && !keyboard.isKeyActive(keyboard.KEY_TARGET) - && !keyboard.isKeyActive(keyboard.KEY_UNTARGET)) + && !keyboard.isActionActive(keyboard.KEY_TARGET) + && !keyboard.isActionActive(keyboard.KEY_UNTARGET)) { if (setupWindow && setupWindow->isVisible()) { @@ -1146,7 +1149,7 @@ bool Game::handleSwitchKeys(SDL_Event &event, bool &used) // Player sit action if (player_node) { - if (keyboard.isKeyActive(keyboard.KEY_EMOTE)) + if (keyboard.isActionActive(keyboard.KEY_EMOTE)) player_node->updateSit(); else player_node->toggleSit(); @@ -1319,8 +1322,8 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) // Ignore input if either "ignore" key is pressed // Stops the character moving about if the user's window manager // uses "ignore+arrow key" to switch virtual desktops. - if (keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_1) || - keyboard.isKeyActive(keyboard.KEY_IGNORE_INPUT_2)) + if (keyboard.isActionActive(keyboard.KEY_IGNORE_INPUT_1) || + keyboard.isActionActive(keyboard.KEY_IGNORE_INPUT_2)) { return; } @@ -1328,14 +1331,14 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) unsigned char direction = 0; // Translate pressed keys to movement and direction - if (keyboard.isKeyActive(keyboard.KEY_MOVE_UP) || + if (keyboard.isActionActive(keyboard.KEY_MOVE_UP) || (joystick && joystick->isUp())) { direction |= Being::UP; setValidSpeed(); player_node->cancelFollow(); } - else if (keyboard.isKeyActive(keyboard.KEY_MOVE_DOWN) || + else if (keyboard.isActionActive(keyboard.KEY_MOVE_DOWN) || (joystick && joystick->isDown())) { direction |= Being::DOWN; @@ -1343,23 +1346,23 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) player_node->cancelFollow(); } - if (keyboard.isKeyActive(keyboard.KEY_MOVE_LEFT) || + if (keyboard.isActionActive(keyboard.KEY_MOVE_LEFT) || (joystick && joystick->isLeft())) { direction |= Being::LEFT; setValidSpeed(); player_node->cancelFollow(); } - else if (keyboard.isKeyActive(keyboard.KEY_MOVE_RIGHT) || + else if (keyboard.isActionActive(keyboard.KEY_MOVE_RIGHT) || (joystick && joystick->isRight())) { direction |= Being::RIGHT; setValidSpeed(); player_node->cancelFollow(); } - else if (!keyboard.isKeyActive(keyboard.KEY_EMOTE)) + else if (!keyboard.isActionActive(keyboard.KEY_EMOTE)) { - if (keyboard.isKeyActive(keyboard.KEY_DIRECT_UP)) + if (keyboard.isActionActive(keyboard.KEY_DIRECT_UP)) { if (player_node->getDirection() != Being::UP) { @@ -1370,7 +1373,7 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) } } } - else if (keyboard.isKeyActive(keyboard.KEY_DIRECT_DOWN)) + else if (keyboard.isActionActive(keyboard.KEY_DIRECT_DOWN)) { if (player_node->getDirection() != Being::DOWN) { @@ -1381,7 +1384,7 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) } } } - else if (keyboard.isKeyActive(keyboard.KEY_DIRECT_LEFT)) + else if (keyboard.isActionActive(keyboard.KEY_DIRECT_LEFT)) { if (player_node->getDirection() != Being::LEFT) { @@ -1392,7 +1395,7 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) } } } - else if (keyboard.isKeyActive(keyboard.KEY_DIRECT_RIGHT)) + else if (keyboard.isActionActive(keyboard.KEY_DIRECT_RIGHT)) { if (player_node->getDirection() != Being::RIGHT) { @@ -1405,7 +1408,7 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) } } - if (keyboard.isKeyActive(keyboard.KEY_EMOTE) && direction != 0) + if (keyboard.isActionActive(keyboard.KEY_EMOTE) && direction != 0) { if (player_node->getDirection() != direction) { @@ -1449,18 +1452,19 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) || joyAttack) && mValidSpeed) { // Attacking monsters - if (keyboard.isKeyActive(keyboard.KEY_ATTACK)) + if (keyboard.isActionActive(keyboard.KEY_ATTACK)) { if (player_node->getTarget()) player_node->attack(player_node->getTarget(), true); } - if ((keyboard.isKeyActive(keyboard.KEY_TARGET_ATTACK) || joyAttack) - && !keyboard.isKeyActive(keyboard.KEY_MOVE_TO_TARGET)) + if ((keyboard.isActionActive(keyboard.KEY_TARGET_ATTACK) + || joyAttack) + && !keyboard.isActionActive(keyboard.KEY_MOVE_TO_TARGET)) { Being *target = nullptr; - bool newTarget = !keyboard.isKeyActive(keyboard.KEY_TARGET); + bool newTarget = !keyboard.isActionActive(keyboard.KEY_TARGET); // A set target has highest priority if (!player_node->getTarget()) { @@ -1477,27 +1481,27 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) } } - if (!keyboard.isKeyActive(keyboard.KEY_EMOTE)) + if (!keyboard.isActionActive(keyboard.KEY_EMOTE)) { // Target the nearest player/monster/npc - if ((keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER) || - keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) || - keyboard.isKeyActive(keyboard.KEY_TARGET_NPC) || + if ((keyboard.isActionActive(keyboard.KEY_TARGET_PLAYER) || + keyboard.isActionActive(keyboard.KEY_TARGET_CLOSEST) || + keyboard.isActionActive(keyboard.KEY_TARGET_NPC) || (joystick && joystick->buttonPressed(3))) && - !keyboard.isKeyActive(keyboard.KEY_TARGET) && - !keyboard.isKeyActive(keyboard.KEY_UNTARGET)) + !keyboard.isActionActive(keyboard.KEY_TARGET) && + !keyboard.isActionActive(keyboard.KEY_UNTARGET)) { ActorSprite::Type currentTarget = ActorSprite::UNKNOWN; - if (keyboard.isKeyActive(keyboard.KEY_TARGET_CLOSEST) || + if (keyboard.isActionActive(keyboard.KEY_TARGET_CLOSEST) || (joystick && joystick->buttonPressed(3))) { currentTarget = ActorSprite::MONSTER; } - else if (keyboard.isKeyActive(keyboard.KEY_TARGET_PLAYER)) + else if (keyboard.isActionActive(keyboard.KEY_TARGET_PLAYER)) { currentTarget = ActorSprite::PLAYER; } - else if (keyboard.isKeyActive(keyboard.KEY_TARGET_NPC)) + else if (keyboard.isActionActive(keyboard.KEY_TARGET_NPC)) { currentTarget = ActorSprite::NPC; } @@ -1521,7 +1525,7 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) // Talk to the nearest NPC if 't' pressed if (wasDown && keyboard.getKeyIndex(event.key.keysym.sym) == KeyboardConfig::KEY_TALK && - !keyboard.isKeyActive(keyboard.KEY_EMOTE)) + !keyboard.isActionActive(keyboard.KEY_EMOTE)) { Being *target = player_node->getTarget(); @@ -1535,15 +1539,15 @@ void Game::handleMoveAndAttack(SDL_Event &event, bool wasDown) } // Stop attacking if the right key is pressed - if (!keyboard.isKeyActive(keyboard.KEY_ATTACK) - && !keyboard.isKeyActive(keyboard.KEY_EMOTE)) + if (!keyboard.isActionActive(keyboard.KEY_ATTACK) + && !keyboard.isActionActive(keyboard.KEY_EMOTE)) { - if (keyboard.isKeyActive(keyboard.KEY_TARGET) + if (keyboard.isActionActive(keyboard.KEY_TARGET) || (joystick && joystick->buttonPressed(4))) { player_node->stopAttack(); } - else if (keyboard.isKeyActive(keyboard.KEY_UNTARGET)) + else if (keyboard.isActionActive(keyboard.KEY_UNTARGET)) { player_node->untarget(); } @@ -1585,6 +1589,8 @@ void Game::handleActive(SDL_Event &event) player_node->setHalfAway(true); } } + if (player_node) + player_node->updateStatus(); } if (player_node) player_node->updateName(); @@ -1630,8 +1636,13 @@ void Game::handleInput() updateHistory(event); checkKeys(); + if (event.type == SDL_VIDEORESIZE) + { + // Let the client deal with this one (it'll pass down from there) + Client::resize(event.resize.w, event.resize.h); + } // Keyboard events (for discontinuous keys) - if (event.type == SDL_KEYDOWN) + else if (event.type == SDL_KEYDOWN) { wasDown = true; @@ -1661,7 +1672,7 @@ void Game::handleInput() } if (chatWindow && !chatWindow->isInputFocused() - && keyboard.isKeyActive(keyboard.KEY_RIGHT_CLICK)) + && keyboard.isActionActive(keyboard.KEY_RIGHT_CLICK)) { int mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); @@ -1674,7 +1685,7 @@ void Game::handleInput() } // Mode switch to emotes - if (keyboard.isKeyActive(keyboard.KEY_EMOTE)) + if (keyboard.isActionActive(keyboard.KEY_EMOTE)) { // Emotions int emotion = keyboard.getKeyEmoteOffset(event.key.keysym.sym); @@ -1728,8 +1739,8 @@ void Game::handleInput() return; // If pressed outfits keys, stop processing keys. - if (keyboard.isKeyActive(keyboard.KEY_WEAR_OUTFIT) - || keyboard.isKeyActive(keyboard.KEY_COPY_OUTFIT) + if (keyboard.isActionActive(keyboard.KEY_WEAR_OUTFIT) + || keyboard.isActionActive(keyboard.KEY_COPY_OUTFIT) || (setupWindow && setupWindow->isVisible())) { return; @@ -1934,3 +1945,11 @@ void Game::closeDialogs() deathNotice = nullptr; } } + +void Game::videoResized(int width, int height) +{ + if (viewport) + viewport->setSize(width, height); + if (windowMenu) + windowMenu->setPosition(width - 3 - windowMenu->getWidth(), 3); +} diff --git a/src/game.h b/src/game.h index c6d942fe1..4469d3774 100644 --- a/src/game.h +++ b/src/game.h @@ -91,7 +91,7 @@ class Game /** * Returns the currently active map. */ - Map *getCurrentMap() + Map *getCurrentMap() const { return mCurrentMap; } const std::string &getCurrentMapName() const @@ -108,6 +108,8 @@ class Game static void closeDialogs(); + void videoResized(int width, int height); + private: void updateHistory(SDL_Event &event); diff --git a/src/graphics.cpp b/src/graphics.cpp index bbd398aa5..5848d8c14 100644 --- a/src/graphics.cpp +++ b/src/graphics.cpp @@ -47,13 +47,15 @@ Graphics::Graphics(): mBlitMode(BLIT_NORMAL), mRedraw(false), mDoubleBuffer(false), - mSecure(false) + mSecure(false), + mOpenGL(0), + mEnableResize(false), + mNoFrame(false) { mRect.x = 0; mRect.y = 0; mRect.w = 0; mRect.h = 0; - mOpenGL = 0; } Graphics::~Graphics() @@ -61,7 +63,8 @@ Graphics::~Graphics() _endDraw(); } -bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) +bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame) { logger->log("Setting video mode %dx%d %s", w, h, fs ? "fullscreen" : "windowed"); @@ -73,15 +76,22 @@ bool Graphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) mBpp = bpp; mFullscreen = fs; mHWAccel = hwaccel; + mEnableResize = resize; + mNoFrame = noFrame; if (fs) displayFlags |= SDL_FULLSCREEN; + else if (resize) + displayFlags |= SDL_RESIZABLE; if (hwaccel) displayFlags |= SDL_HWSURFACE | SDL_DOUBLEBUF; else displayFlags |= SDL_SWSURFACE; + if (noFrame) + displayFlags |= SDL_NOFRAME; + setTarget(SDL_SetVideoMode(w, h, bpp, displayFlags)); if (!mTarget) @@ -138,7 +148,37 @@ bool Graphics::setFullscreen(bool fs) if (mFullscreen == fs) return true; - return setVideoMode(mWidth, mHeight, mBpp, fs, mHWAccel); + return setVideoMode(mWidth, mHeight, mBpp, fs, mHWAccel, + mEnableResize, mNoFrame); +} + +bool Graphics::resizeScreen(int width, int height) +{ + if (mWidth == width && mHeight == height) + return true; + + const int prevWidth = mWidth; + const int prevHeight = mHeight; + + _endDraw(); + + bool success = setVideoMode(width, height, mBpp, + mFullscreen, mHWAccel, mEnableResize, mNoFrame); + + // If it didn't work, try to restore the previous size. If that didn't + // work either, bail out (but then we're in deep trouble). + if (!success) + { + if (!setVideoMode(prevWidth, prevHeight, mBpp, + mFullscreen, mHWAccel, mEnableResize, mNoFrame)) + { + return false; + } + } + + _beginDraw(); + + return success; } int Graphics::getWidth() const diff --git a/src/graphics.h b/src/graphics.h index 4c47e690d..5d496d654 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -96,8 +96,8 @@ class Graphics : public gcn::SDLGraphics /** * Try to create a window with the given settings. */ - virtual bool setVideoMode(int w, int h, int bpp, - bool fs, bool hwaccel); + virtual bool setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame); /** * Set fullscreen mode. @@ -105,6 +105,11 @@ class Graphics : public gcn::SDLGraphics bool setFullscreen(bool fs); /** + * Resize the window to the specified size. + */ + bool resizeScreen(int width, int height); + + /** * Blits an image onto the screen. * * @return <code>true</code> if the image was blitted properly @@ -220,7 +225,7 @@ class Graphics : public gcn::SDLGraphics void setBlitMode(BlitMode mode) { mBlitMode = mode; } - BlitMode getBlitMode() + BlitMode getBlitMode() const { return mBlitMode; } void fillRectangle(const gcn::Rectangle& rectangle); @@ -258,30 +263,33 @@ class Graphics : public gcn::SDLGraphics void setRedraw(bool n) { mRedraw = n; } - bool getRedraw() + bool getRedraw() const { return mRedraw; } void setSecure(bool n) { mSecure = n; } - bool getSecure() + bool getSecure() const { return mSecure; } - int getBpp() + int getBpp() const { return mBpp; } - bool getFullScreen() + bool getFullScreen() const { return mFullscreen; } - bool getHWAccel() + bool getHWAccel() const { return mHWAccel; } - bool getDoubleBuffer() + bool getDoubleBuffer() const { return mDoubleBuffer; } int getOpenGL() { return mOpenGL; } + void setNoFrame(bool n) + { mNoFrame = n; } + int mWidth; int mHeight; @@ -298,6 +306,8 @@ class Graphics : public gcn::SDLGraphics SDL_Rect mRect; bool mSecure; int mOpenGL; + bool mEnableResize; + bool mNoFrame; }; extern Graphics *mainGraphics; diff --git a/src/graphicsvertexes.h b/src/graphicsvertexes.h index 046bf90ce..4245e8bf5 100644 --- a/src/graphicsvertexes.h +++ b/src/graphicsvertexes.h @@ -153,7 +153,7 @@ class GraphicsVertexes SDLGraphicsVertexes sdl[5]; #ifdef USE_OPENGL - OpenGL1GraphicsVertexes ogl1[5]; +// OpenGL1GraphicsVertexes ogl1[5]; OpenGLGraphicsVertexes ogl[5]; #endif diff --git a/src/gui/charcreatedialog.cpp b/src/gui/charcreatedialog.cpp index a1233fdcc..8d4767a15 100644 --- a/src/gui/charcreatedialog.cpp +++ b/src/gui/charcreatedialog.cpp @@ -47,6 +47,7 @@ #include "resources/chardb.h" #include "resources/colordb.h" #include "resources/itemdb.h" +#include "resources/iteminfo.h" #include "utils/gettext.h" #include "utils/stringutils.h" @@ -55,14 +56,27 @@ #include "debug.h" +const static Being::Action actions[] = +{ + Being::STAND, Being::SIT, Being::MOVE, Being::ATTACK, Being::DEAD +}; + +const static int directions[] = +{ + Being::DOWN, Being::RIGHT, Being::UP, Being::LEFT +}; + CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): - Window(_("Create Character"), true, parent, "charcreate.xml"), + Window(_("New Character"), true, parent, "charcreate.xml"), mCharSelectDialog(parent), mRace(0), - mSlot(slot) + mSlot(slot), + mAction(0), + mDirection(0) { setStickyButtonLock(true); setSticky(true); + setWindowName("NewCharacter"); mPlayer = new Being(0, ActorSprite::PLAYER, mRace, nullptr); mPlayer->setGender(GENDER_MALE); @@ -79,9 +93,9 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mHairStyle = (rand() % maxHairStyle) + minHairStyle; mHairColor = (rand() % maxHairColor) + minHairColor; - updateHair(); mNameField = new TextField(""); + mNameField->setMaximum(24); mNameLabel = new Label(_("Name:")); // TRANSLATORS: This is a narrow symbol used to denote 'next'. // You may change this symbol if your language uses another. @@ -90,15 +104,20 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): // You may change this symbol if your language uses another. mPrevHairColorButton = new Button(_("<"), "prevcolor", this); mHairColorLabel = new Label(_("Hair color:")); + mHairColorNameLabel = new Label(""); mNextHairStyleButton = new Button(_(">"), "nextstyle", this); mPrevHairStyleButton = new Button(_("<"), "prevstyle", this); mHairStyleLabel = new Label(_("Hair style:")); + mHairStyleNameLabel = new Label(""); + mActionButton = new Button(_("^"), "action", this); + mRotateButton = new Button(_(">"), "rotate", this); if (serverVersion >= 2) { mNextRaceButton = new Button(_(">"), "nextrace", this); mPrevRaceButton = new Button(_("<"), "prevrace", this); mRaceLabel = new Label(_("Race:")); + mRaceNameLabel = new Label(""); } mCreateButton = new Button(_("Create"), "create", this); @@ -124,31 +143,42 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): mAttributesLeft = new Label( strprintf(_("Please distribute %d points"), 99)); - int w = 280; - int h = 330; + int w = 480; + int h = 350; setContentSize(w, h); - mPlayerBox->setDimension(gcn::Rectangle(145, 35, 110, 87)); - mNameLabel->setPosition(5, 5); + mPlayerBox->setDimension(gcn::Rectangle(350, 40, 110, 90)); + mActionButton->setPosition(375, 140); + mRotateButton->setPosition(405, 140); + + mNameLabel->setPosition(5, 10); mNameField->setDimension( - gcn::Rectangle(60, 5, w - 60 - 7, mNameField->getHeight())); - mPrevHairColorButton->setPosition(155, 35); - mNextHairColorButton->setPosition(230, 35); - mHairColorLabel->setPosition(5, 40); - mPrevHairStyleButton->setPosition(155, 64); - mNextHairStyleButton->setPosition(230, 64); - mHairStyleLabel->setPosition(5, 70); + gcn::Rectangle(60, 10, 300, mNameField->getHeight())); + + int leftX = 120; + int rightX = 300; + int labelX = 5; + int nameX = 145; + mPrevHairColorButton->setPosition(leftX, 40); + mNextHairColorButton->setPosition(rightX, 40); + mHairColorLabel->setPosition(labelX, 45); + mHairColorNameLabel->setPosition(nameX, 45); + mPrevHairStyleButton->setPosition(leftX, 69); + mNextHairStyleButton->setPosition(rightX, 69); + mHairStyleLabel->setPosition(labelX, 74); + mHairStyleNameLabel->setPosition(nameX, 74); if (serverVersion >= 2) { - mPrevRaceButton->setPosition(155, 93); - mNextRaceButton->setPosition(230, 93); - mRaceLabel->setPosition(5, 100); + mPrevRaceButton->setPosition(leftX, 103); + mNextRaceButton->setPosition(rightX, 103); + mRaceLabel->setPosition(labelX, 108); + mRaceNameLabel->setPosition(nameX, 108); } mAttributesLeft->setPosition(15, 280); updateSliders(); mCancelButton->setPosition( - w - 5 - mCancelButton->getWidth(), + w / 2, h - 5 - mCancelButton->getHeight()); mCreateButton->setPosition( mCancelButton->getX() - 5 - mCreateButton->getWidth(), @@ -163,15 +193,20 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): add(mNextHairColorButton); add(mPrevHairColorButton); add(mHairColorLabel); + add(mHairColorNameLabel); add(mNextHairStyleButton); add(mPrevHairStyleButton); add(mHairStyleLabel); + add(mHairStyleNameLabel); + add(mActionButton); + add(mRotateButton); if (serverVersion >= 2) { add(mNextRaceButton); add(mPrevRaceButton); add(mRaceLabel); + add(mRaceNameLabel); } add(mAttributesLeft); @@ -184,6 +219,12 @@ CharCreateDialog::CharCreateDialog(CharSelectDialog *parent, int slot): center(); setVisible(true); mNameField->requestFocus(); + + updateHair(); + if (serverVersion >= 2) + updateRace(); + + updatePlayer(); } CharCreateDialog::~CharCreateDialog() @@ -197,7 +238,8 @@ CharCreateDialog::~CharCreateDialog() void CharCreateDialog::action(const gcn::ActionEvent &event) { - if (event.getId() == "create") + const std::string id = event.getId(); + if (id == "create") { if ( #ifdef MANASERV_SUPPORT @@ -232,51 +274,65 @@ void CharCreateDialog::action(const gcn::ActionEvent &event) true, this); } } - else if (event.getId() == "cancel") + else if (id == "cancel") { scheduleDelete(); } - else if (event.getId() == "nextcolor") + else if (id == "nextcolor") { - mHairColor++; + mHairColor ++; updateHair(); } - else if (event.getId() == "prevcolor") + else if (id == "prevcolor") { - mHairColor--; + mHairColor --; updateHair(); } - else if (event.getId() == "nextstyle") + else if (id == "nextstyle") { - mHairStyle++; + mHairStyle ++; updateHair(); } - else if (event.getId() == "prevstyle") + else if (id == "prevstyle") { - mHairStyle--; + mHairStyle --; updateHair(); } - else if (event.getId() == "nextrace") + else if (id == "nextrace") { - mRace++; + mRace ++; updateRace(); } - else if (event.getId() == "prevrace") + else if (id == "prevrace") { - mRace--; + mRace --; updateRace(); } - else if (event.getId() == "statslider") + else if (id == "statslider") { updateSliders(); } - else if (event.getId() == "gender") + else if (id == "gender") { if (mMale->isSelected()) mPlayer->setGender(GENDER_MALE); else mPlayer->setGender(GENDER_FEMALE); } + else if (id == "action") + { + mAction ++; + if (mAction >= 5) + mAction = 0; + updatePlayer(); + } + else if (id == "rotate") + { + mDirection ++; + if (mDirection >= 4) + mDirection = 0; + updatePlayer(); + } } std::string CharCreateDialog::getName() const @@ -357,34 +413,34 @@ void CharCreateDialog::setAttributes(const std::vector<std::string> &labels, mAttributeSlider.resize(labels.size()); mAttributeValue.resize(labels.size()); - int w = 200; - int h = 330; + int w = 480; + int h = 350; for (unsigned i = 0; i < labels.size(); i++) { mAttributeLabel[i] = new Label(labels[i]); mAttributeLabel[i]->setWidth(70); - mAttributeLabel[i]->setPosition(5, 140 + i*20); + mAttributeLabel[i]->setPosition(5, 145 + i * 24); mAttributeLabel[i]->adjustSize(); add(mAttributeLabel[i]); mAttributeSlider[i] = new Slider(min, max); - mAttributeSlider[i]->setDimension(gcn::Rectangle(140, 140 + i * 20, - 100, 10)); + mAttributeSlider[i]->setDimension(gcn::Rectangle(140, 145 + i * 24, + 150, 12)); mAttributeSlider[i]->setActionEventId("statslider"); mAttributeSlider[i]->addActionListener(this); add(mAttributeSlider[i]); mAttributeValue[i] = new Label(toString(min)); - mAttributeValue[i]->setPosition(245, 140 + i*20); + mAttributeValue[i]->setPosition(295, 145 + i * 24); add(mAttributeValue[i]); } - mAttributesLeft->setPosition(15, 280); + mAttributesLeft->setPosition(15, 300); updateSliders(); mCancelButton->setPosition( - w - 5 - mCancelButton->getWidth(), + w / 2, h - 5 - mCancelButton->getHeight()); mCreateButton->setPosition( mCancelButton->getX() - 5 - mCreateButton->getWidth(), @@ -420,12 +476,17 @@ void CharCreateDialog::updateHair() mHairStyle += Being::getNumOfHairstyles(); if (mHairStyle < (signed)minHairStyle || mHairStyle > (signed)maxHairStyle) mHairStyle = minHairStyle; + const ItemInfo &item = ItemDB::get(-mHairStyle); + mHairStyleNameLabel->setCaption(item.getName()); + mHairStyleNameLabel->adjustSize(); mHairColor %= ColorDB::getHairSize(); if (mHairColor < 0) mHairColor += ColorDB::getHairSize(); if (mHairColor < (signed)minHairColor || mHairColor > (signed)maxHairColor) mHairColor = minHairColor; + mHairColorNameLabel->setCaption(ColorDB::getHairColorName(mHairColor)); + mHairColorNameLabel->adjustSize(); mPlayer->setSprite(Net::getCharHandler()->hairSprite(), mHairStyle * -1, ColorDB::getHairColor(mHairColor)); @@ -448,4 +509,22 @@ void CharCreateDialog::updateRace() } mPlayer->setSubtype(mRace); + const ItemInfo &item = ItemDB::get(id); + mRaceNameLabel->setCaption(item.getName()); + mRaceNameLabel->adjustSize(); +} + +void CharCreateDialog::logic() +{ + if (mPlayer) + mPlayer->logic(); +} + +void CharCreateDialog::updatePlayer() +{ + if (mPlayer) + { + mPlayer->setDirection(directions[mDirection]); + mPlayer->setAction(actions[mAction]); + } } diff --git a/src/gui/charcreatedialog.h b/src/gui/charcreatedialog.h index e369f1777..ceafcc08e 100644 --- a/src/gui/charcreatedialog.h +++ b/src/gui/charcreatedialog.h @@ -37,6 +37,7 @@ class LocalPlayer; class PlayerBox; +class TextField; /** * Character creation dialog. @@ -69,6 +70,10 @@ class CharCreateDialog : public Window, public gcn::ActionListener void setFixedGender(bool fixed, Gender gender = GENDER_FEMALE); + void logic(); + + void updatePlayer(); + private: int getDistributedPoints() const; @@ -90,17 +95,23 @@ class CharCreateDialog : public Window, public gcn::ActionListener CharSelectDialog *mCharSelectDialog; - gcn::TextField *mNameField; + TextField *mNameField; gcn::Label *mNameLabel; gcn::Button *mNextHairColorButton; gcn::Button *mPrevHairColorButton; gcn::Label *mHairColorLabel; + gcn::Label *mHairColorNameLabel; gcn::Button *mNextHairStyleButton; gcn::Button *mPrevHairStyleButton; gcn::Label *mHairStyleLabel; + gcn::Label *mHairStyleNameLabel; gcn::Button *mNextRaceButton; gcn::Button *mPrevRaceButton; gcn::Label *mRaceLabel; + gcn::Label *mRaceNameLabel; + + gcn::Button *mActionButton; + gcn::Button *mRotateButton; gcn::RadioButton *mMale; gcn::RadioButton *mFemale; @@ -129,6 +140,9 @@ class CharCreateDialog : public Window, public gcn::ActionListener unsigned minHairColor; unsigned maxHairStyle; unsigned minHairStyle; + + unsigned mAction; + unsigned mDirection; }; #endif // CHAR_CREATE_DIALOG_H diff --git a/src/gui/charselectdialog.cpp b/src/gui/charselectdialog.cpp index 638691bab..d2b74a632 100644 --- a/src/gui/charselectdialog.cpp +++ b/src/gui/charselectdialog.cpp @@ -386,7 +386,7 @@ bool CharSelectDialog::selectByName(const std::string &name, Net::Character *character = mCharacterEntries[i]->getCharacter(); if (mCharacterEntries[i] && character) { - if (character->dummy->getName() == name) + if ( character->dummy && character->dummy->getName() == name) { if (mCharacterEntries[i]) mCharacterEntries[i]->requestFocus(); diff --git a/src/gui/chatwindow.cpp b/src/gui/chatwindow.cpp index 899bbdc36..6831ad5b6 100644 --- a/src/gui/chatwindow.cpp +++ b/src/gui/chatwindow.cpp @@ -548,6 +548,9 @@ void ChatWindow::removeTab(ChatTab *tab) void ChatWindow::addTab(ChatTab *tab) { + if (!tab) + return; + mChatTabs->addTab(tab, tab->mScrollArea); // Update UI @@ -764,18 +767,18 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event) mCurHist = mHistory.end(); mChatInput->setText(""); } - else if (keyboard.isKeyActive(keyboard.KEY_AUTOCOMPLETE_CHAT) && + else if (keyboard.isActionActive(keyboard.KEY_AUTOCOMPLETE_CHAT) && mChatInput->getText() != "") { autoComplete(); return; } - else if (keyboard.isKeyActive(keyboard.KEY_DEACTIVATE_CHAT) && + else if (keyboard.isActionActive(keyboard.KEY_DEACTIVATE_CHAT) && mChatInput->isVisible()) { mChatInput->processVisible(false); } - else if (keyboard.isKeyActive(keyboard.KEY_CHAT_PREV_HISTORY) && + else if (keyboard.isActionActive(keyboard.KEY_CHAT_PREV_HISTORY) && mChatInput->isVisible()) { ChatTab *tab = getFocused(); @@ -807,7 +810,7 @@ void ChatWindow::keyPressed(gcn::KeyEvent &event) mChatInput->getText().length())); } } - else if (keyboard.isKeyActive(keyboard.KEY_CHAT_NEXT_HISTORY) && + else if (keyboard.isActionActive(keyboard.KEY_CHAT_NEXT_HISTORY) && mChatInput->isVisible()) { ChatTab *tab = getFocused(); diff --git a/src/gui/editdialog.h b/src/gui/editdialog.h index 69f86edca..ef260acfb 100644 --- a/src/gui/editdialog.h +++ b/src/gui/editdialog.h @@ -57,7 +57,7 @@ class EditDialog : public Window, public gcn::ActionListener */ void action(const gcn::ActionEvent &event); - std::string getMsg() + std::string getMsg() const { return mTextField->getText(); } private: diff --git a/src/gui/editserverdialog.cpp b/src/gui/editserverdialog.cpp new file mode 100644 index 000000000..8a4a9579d --- /dev/null +++ b/src/gui/editserverdialog.cpp @@ -0,0 +1,239 @@ +/* + * The Mana Client + * Copyright (C) 2011-2012 The Mana Developers + * Copyright (C) 2012 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 "gui/editserverdialog.h" + +#include "configuration.h" + +#include "gui/okdialog.h" +#include "gui/sdlinput.h" +#include "gui/serverdialog.h" + +#include "gui/widgets/button.h" +#include "gui/widgets/dropdown.h" +#include "gui/widgets/label.h" +#include "gui/widgets/layout.h" +#include "gui/widgets/textfield.h" + +#include "utils/gettext.h" + +std::string TypeListModel::getElementAt(int elementIndex) +{ + if (elementIndex == 0) + return "TmwAthena"; + else if (elementIndex == 1) + return "Evol"; +#ifdef MANASERV_SUPPORT + else if (elementIndex == 2) + return "ManaServ"; +#endif + else + return "Unknown"; +} + +EditServerDialog::EditServerDialog(ServerDialog *parent, ServerInfo server, + int index) : + Window(_("Edit Server"), true, parent), + mServerDialog(parent), + mServer(server), + mIndex(index) +{ + setWindowName("EditServerDialog"); + + Label *nameLabel = new Label(_("Name:")); + Label *serverAdressLabel = new Label(_("Address:")); + Label *portLabel = new Label(_("Port:")); + Label *typeLabel = new Label(_("Server type:")); + Label *descriptionLabel = new Label(_("Description:")); + mServerAddressField = new TextField(std::string()); + mPortField = new TextField(std::string()); + mPortField->setNumeric(true); + mPortField->setRange(1, 65535); + + mTypeListModel = new TypeListModel(); + mTypeField = new DropDown(mTypeListModel); + mTypeField->setSelected(0); // TmwAthena by default for now. + + mNameField = new TextField(std::string()); + mDescriptionField = new TextField(std::string()); + + mOkButton = new Button(_("OK"), "addServer", this); + mCancelButton = new Button(_("Cancel"), "cancel", this); + + mServerAddressField->addActionListener(this); + mPortField->addActionListener(this); + + place(0, 0, nameLabel); + place(1, 0, mNameField, 4).setPadding(3); + place(0, 1, serverAdressLabel); + place(1, 1, mServerAddressField, 4).setPadding(3); + place(0, 2, portLabel); + place(1, 2, mPortField, 4).setPadding(3); + place(0, 3, typeLabel); + place(1, 3, mTypeField).setPadding(3); + place(0, 4, descriptionLabel); + place(1, 4, mDescriptionField, 4).setPadding(3); + place(4, 5, mOkButton); + place(3, 5, mCancelButton); + + // Do this manually instead of calling reflowLayout so we can enforce a + // minimum width. + int width = 0, height = 0; + getLayout().reflow(width, height); + if (width < 300) + { + width = 300; + getLayout().reflow(width, height); + } + if (height < 120) + { + height = 120; + getLayout().reflow(width, height); + } + + setContentSize(width, height); + + setMinWidth(getWidth()); + setMinHeight(getHeight()); + setDefaultSize(getWidth(), getHeight(), ImageRect::CENTER); + + setResizable(false); + addKeyListener(this); + + loadWindowState(); + + mNameField->setText(mServer.name); + mDescriptionField->setText(mServer.description); + mServerAddressField->setText(mServer.hostname); + mPortField->setText(toString(mServer.port)); + + switch (mServer.type) + { + case ServerInfo::MANASERV: +#ifdef MANASERV_SUPPORT + mTypeField->setSelected(2); + break; +#endif + default: + case ServerInfo::UNKNOWN: + case ServerInfo::TMWATHENA: + mTypeField->setSelected(0); + break; + case ServerInfo::EVOL: + mTypeField->setSelected(1); + break; + } + + setLocationRelativeTo(getParentWindow()); + setVisible(true); + + mNameField->requestFocus(); +} + +EditServerDialog::~EditServerDialog() +{ + delete mTypeListModel; +} + +void EditServerDialog::logic() +{ + Window::logic(); +} + +void EditServerDialog::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "ok") + { + // Give focus back to the server dialog. + mServerAddressField->requestFocus(); + } + if (event.getId() == "addServer") + { + // Check the given information + if (mServerAddressField->getText().empty() + || mPortField->getText().empty()) + { + OkDialog *dlg = new OkDialog(_("Error"), + _("Please at least type both the address and the port " + "of the server.")); + dlg->addActionListener(this); + } + else + { + mCancelButton->setEnabled(false); + mOkButton->setEnabled(false); + + mServer.name = mNameField->getText(); + mServer.description = mDescriptionField->getText(); + mServer.hostname = mServerAddressField->getText(); + mServer.port = (short) atoi(mPortField->getText().c_str()); + + if (mTypeField) + { + switch (mTypeField->getSelected()) + { + case 0: + mServer.type = ServerInfo::TMWATHENA; + break; + case 1: + mServer.type = ServerInfo::EVOL; + break; +#ifdef MANASERV_SUPPORT + case 2: + mServer.type = ServerInfo::MANASERV; + break; +#endif + default: + mServer.type = ServerInfo::UNKNOWN; + } + } + else + { + mServer.type = ServerInfo::TMWATHENA; + } + + // Tell the server has to be saved + mServer.save = true; + + //Add server + mServerDialog->updateServer(mServer, mIndex); + scheduleDelete(); + } + } + else if (event.getId() == "cancel") + { + scheduleDelete(); + } +} + +void EditServerDialog::keyPressed(gcn::KeyEvent &keyEvent) +{ + gcn::Key key = keyEvent.getKey(); + + if (key.getValue() == Key::ESCAPE) + { + scheduleDelete(); + } + else if (key.getValue() == Key::ENTER) + { + action(gcn::ActionEvent(nullptr, mOkButton->getActionEventId())); + } +} diff --git a/src/gui/editserverdialog.h b/src/gui/editserverdialog.h new file mode 100644 index 000000000..6035b0e50 --- /dev/null +++ b/src/gui/editserverdialog.h @@ -0,0 +1,104 @@ +/* + * The Mana Client + * Copyright (C) 2011-2012 The Mana Developers + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The Mana 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 EDITSERVERDIALOG_H +#define EDITSERVERDIALOG_H + +class Button; +class Label; +class TextField; +class DropDown; +class ServerDialog; +class TypeListModel; + +#include "gui/widgets/window.h" + +#include "net/serverinfo.h" + +#include <guichan/actionlistener.hpp> +#include <guichan/keylistener.hpp> +#include <guichan/listmodel.hpp> + + +/** + * Server Type List Model + */ +class TypeListModel : public gcn::ListModel +{ + public: + TypeListModel() {} + + /** + * Used to get number of line in the list + */ + int getNumberOfElements() +#ifdef MANASERV_SUPPORT + { return 3; } +#else + { return 2; } +#endif + + /** + * Used to get an element from the list + */ + std::string getElementAt(int elementIndex); +}; + +/** + * The custom server addition dialog. + * + * \ingroup Interface + */ +class EditServerDialog : public Window, + public gcn::ActionListener, + public gcn::KeyListener +{ + public: + EditServerDialog(ServerDialog *parent, ServerInfo server, int index); + + ~EditServerDialog(); + + /** + * Called when receiving actions from the widgets. + */ + void action(const gcn::ActionEvent &event); + + void keyPressed(gcn::KeyEvent &keyEvent); + + void logic(); + + private: + TextField *mServerAddressField; + TextField *mPortField; + TextField *mNameField; + TextField *mDescriptionField; + Button *mOkButton; + Button *mCancelButton; + + DropDown *mTypeField; + TypeListModel *mTypeListModel; + + ServerDialog *mServerDialog; + ServerInfo mServer; + int mIndex; +}; + +#endif // EDITSERVERDIALOG_H diff --git a/src/gui/equipmentwindow.h b/src/gui/equipmentwindow.h index daeaeb3d7..1e7b84533 100644 --- a/src/gui/equipmentwindow.h +++ b/src/gui/equipmentwindow.h @@ -84,7 +84,7 @@ class EquipmentWindow : public Window, public gcn::ActionListener void mousePressed(gcn::MouseEvent& mouseEvent); - Item* getEquipment(int i) + Item* getEquipment(int i) const { return mEquipment ? mEquipment->getEquipment(i) : nullptr; } void setBeing(Being *being); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index bd855a598..1d8b45872 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -99,20 +99,19 @@ Gui::Gui(Graphics *graphics): // Initialize top GUI widget WindowContainer *guiTop = new WindowContainer; guiTop->setFocusable(true); - guiTop->setDimension(gcn::Rectangle(0, 0, - graphics->mWidth, graphics->mHeight)); + guiTop->setSize(graphics->mWidth, graphics->mHeight); guiTop->setOpaque(false); Window::setWindowContainer(guiTop); setTop(guiTop); + const std::vector<std::string> langs = getLang(); + const bool isJapan = (!langs.empty() && langs[0].size() > 3 + && langs[0].substr(0, 3) == "ja_"); + // Set global font const int fontSize = config.getIntValue("fontSize"); - std::string fontFile = config.getValue("font", ""); - - std::vector<std::string> langs = getLang(); - if (!langs.empty() && langs[0].size() > 3 - && langs[0].substr(0, 3) == "ja_") + if (isJapan) { fontFile = config.getValue("japanFont", ""); if (fontFile.empty()) @@ -134,6 +133,15 @@ Gui::Gui(Graphics *graphics): // Set particle font fontFile = config.getValue("particleFont", ""); + + if (isJapan) + { + fontFile = config.getValue("japanFont", ""); + if (fontFile.empty()) + fontFile = branding.getStringValue("japanFont"); + } + + if (fontFile.empty()) fontFile = branding.getStringValue("particleFont"); @@ -278,6 +286,20 @@ void Gui::draw() mGraphics->popClipArea(); } +void Gui::videoResized() +{ + WindowContainer *top = static_cast<WindowContainer*>(getTop()); + + if (top) + { + int oldWidth = top->getWidth(); + int oldHeight = top->getHeight(); + + top->setSize(mainGraphics->mWidth, mainGraphics->mHeight); + top->adjustAfterResize(oldWidth, oldHeight); + } +} + void Gui::setUseCustomCursor(bool customCursor) { if (customCursor != mCustomCursor) diff --git a/src/gui/gui.h b/src/gui/gui.h index cadcc89ac..5ace42323 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -70,6 +70,11 @@ class Gui : public gcn::Gui */ void draw(); + /** + * Called when the application window has been resized. + */ + void videoResized(); + gcn::FocusHandler *getFocusHandler() const { return mFocusHandler; } diff --git a/src/gui/inventorywindow.cpp b/src/gui/inventorywindow.cpp index 01e2bdd17..23f1e6fcf 100644 --- a/src/gui/inventorywindow.cpp +++ b/src/gui/inventorywindow.cpp @@ -340,13 +340,13 @@ void InventoryWindow::action(const gcn::ActionEvent &event) { if (isStorageActive()) { - Net::getInventoryHandler()->moveItem(Inventory::INVENTORY, + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, item->getInvIndex(), item->getQuantity(), Inventory::STORAGE); } else { - if (keyboard.isKeyActive(keyboard.KEY_MOD)) + if (keyboard.isActionActive(keyboard.KEY_MOD)) { Net::getInventoryHandler()->dropItem( item, item->getQuantity()); @@ -386,11 +386,11 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event) { Window::mouseClicked(event); - const bool mod = (isStorageActive() && keyboard.isKeyActive( + const bool mod = (isStorageActive() && keyboard.isActionActive( keyboard.KEY_MOD)); const bool mod2 = (tradeWindow && tradeWindow->isVisible() - && keyboard.isKeyActive(keyboard.KEY_MOD)); + && keyboard.isActionActive(keyboard.KEY_MOD)); if (!mod && !mod2 && event.getButton() == gcn::MouseEvent::RIGHT) { @@ -431,7 +431,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event) } else { - Net::getInventoryHandler()->moveItem(Inventory::INVENTORY, + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, item->getInvIndex(), item->getQuantity(), Inventory::STORAGE); } @@ -445,7 +445,7 @@ void InventoryWindow::mouseClicked(gcn::MouseEvent &event) } else { - Net::getInventoryHandler()->moveItem(Inventory::STORAGE, + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, item->getInvIndex(), item->getQuantity(), Inventory::INVENTORY); } diff --git a/src/gui/inventorywindow.h b/src/gui/inventorywindow.h index 2b35ec9c4..9d4be5afc 100644 --- a/src/gui/inventorywindow.h +++ b/src/gui/inventorywindow.h @@ -115,7 +115,7 @@ class InventoryWindow : public Window, void slotsChanged(Inventory* inventory); - bool isMainInventory() + bool isMainInventory() const { return mInventory->isMainInventory(); } /** diff --git a/src/gui/itemamountwindow.cpp b/src/gui/itemamountwindow.cpp index 9e2a97681..3b01b559f 100644 --- a/src/gui/itemamountwindow.cpp +++ b/src/gui/itemamountwindow.cpp @@ -113,14 +113,12 @@ void ItemAmountWindow::finish(Item *item, int amount, int price, Usage usage) Net::getInventoryHandler()->splitItem(item, amount); break; case StoreAdd: - Net::getInventoryHandler()->moveItem(Inventory::INVENTORY, - item->getInvIndex(), amount, - Inventory::STORAGE); + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, + item->getInvIndex(), amount, Inventory::STORAGE); break; case StoreRemove: - Net::getInventoryHandler()->moveItem(Inventory::STORAGE, - item->getInvIndex(), amount, - Inventory::INVENTORY); + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, + item->getInvIndex(), amount, Inventory::INVENTORY); break; case ShopBuyAdd: if (shopWindow) diff --git a/src/gui/logindialog.cpp b/src/gui/logindialog.cpp index b1c80b102..ef8fd6bf0 100644 --- a/src/gui/logindialog.cpp +++ b/src/gui/logindialog.cpp @@ -88,6 +88,7 @@ LoginDialog::LoginDialog(LoginData *data, std::string serverName, mUpdateHost(updateHost), mServerName(serverName) { + gcn::Label *serverLabel1 = new Label(_("Server:")); gcn::Label *serverLabel2 = new Label(serverName); serverLabel2->adjustSize(); @@ -131,12 +132,11 @@ LoginDialog::LoginDialog(LoginData *data, std::string serverName, mPassField->addActionListener(this); place(0, 0, serverLabel1); - place(1, 0, serverLabel2, 8).setPadding(1); - + place(1, 0, serverLabel2, 8); place(0, 1, userLabel); place(0, 2, passLabel); - place(1, 1, mUserField, 8).setPadding(1); - place(1, 2, mPassField, 8).setPadding(1); + place(1, 1, mUserField, 8); + place(1, 2, mPassField, 8); place(0, 6, mUpdateTypeLabel, 1); place(1, 6, mUpdateTypeDropDown, 8); place(0, 7, mCustomUpdateHost, 9); @@ -146,9 +146,8 @@ LoginDialog::LoginDialog(LoginData *data, std::string serverName, place(2, 10, mServerButton); place(3, 10, mLoginButton); - reflowLayout(); - addKeyListener(this); + setContentSize(300, 200); center(); setVisible(true); @@ -178,7 +177,8 @@ void LoginDialog::action(const gcn::ActionEvent &event) mLoginData->remember = mKeepCheck->isSelected(); int updateType = mUpdateTypeDropDown->getSelected(); - if (mCustomUpdateHost->isSelected()) + if (mCustomUpdateHost->isSelected() + && mUpdateHostText->getText().empty()) { updateType |= LoginData::Upd_Custom; serverConfig.setValue("customUpdateHost", diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp index 265748b6f..3e5b30a9c 100644 --- a/src/gui/npcdialog.cpp +++ b/src/gui/npcdialog.cpp @@ -26,6 +26,7 @@ #include "client.h" #include "gui/setup.h" +#include "gui/viewport.h" #include "gui/widgets/browserbox.h" #include "gui/widgets/button.h" @@ -62,7 +63,10 @@ NpcDialog::NpcDialog(int npcId) : mDefaultInt(0), mInputState(NPC_INPUT_NONE), mActionState(NPC_ACTION_WAIT), - mLastNextTime(0) + mLastNextTime(0), + mCameraMode(-1), + mCameraX(0), + mCameraY(0) { // Basic Window Setup setWindowName("NpcText"); @@ -220,6 +224,7 @@ void NpcDialog::action(const gcn::ActionEvent &event) return; nextDialog(); + addText(std::string(), false); } else if (mActionState == NPC_ACTION_CLOSE || mActionState == NPC_ACTION_WAIT) @@ -301,6 +306,7 @@ void NpcDialog::nextDialog() void NpcDialog::closeDialog() { + restoreCamera(); Net::getNpcHandler()->closeDialog(mNpcId); } @@ -504,4 +510,34 @@ void NpcDialog::buildLayout() redraw(); mScrollArea->setVerticalScrollAmount(mScrollArea->getVerticalMaxScroll()); -}
\ No newline at end of file +} + +void NpcDialog::saveCamera() +{ + if (!viewport || mCameraMode >= 0) + return; + + mCameraMode = viewport->getCameraMode(); + mCameraX = viewport->getCameraRelativeX(); + mCameraY = viewport->getCameraRelativeY(); +} + +void NpcDialog::restoreCamera() +{ + if (!viewport || mCameraMode == -1) + return; + + if (!mCameraMode) + { + if (viewport->getCameraMode() != mCameraMode) + viewport->toggleCameraMode(); + } + else + { + if (viewport->getCameraMode() != mCameraMode) + viewport->toggleCameraMode(); + viewport->setCameraRelativeX(mCameraX); + viewport->setCameraRelativeY(mCameraY); + } + mCameraMode = -1; +} diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h index e76897499..d4288d5c9 100644 --- a/src/gui/npcdialog.h +++ b/src/gui/npcdialog.h @@ -154,7 +154,8 @@ class NpcDialog : public Window, public gcn::ActionListener, /** * Returns true if any instances exist. */ - static bool isActive() { return !instances.empty(); } + static bool isActive() + { return !instances.empty(); } /** * Returns the first active instance. Useful for pushing user @@ -172,6 +173,10 @@ class NpcDialog : public Window, public gcn::ActionListener, */ static void destroyAll(); + void saveCamera(); + + void restoreCamera(); + private: typedef std::list<NpcDialog*> DialogList; static DialogList instances; @@ -230,6 +235,9 @@ class NpcDialog : public Window, public gcn::ActionListener, NpcInputState mInputState; NpcActionState mActionState; int mLastNextTime; + int mCameraMode; + int mCameraX; + int mCameraY; }; #endif // NPCDIALOG_H diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp index 74e8dbe46..73484f1d5 100644 --- a/src/gui/outfitwindow.cpp +++ b/src/gui/outfitwindow.cpp @@ -491,375 +491,32 @@ void OutfitWindow::unequipNotInOutfit(int outfit) } } +static const SDLKey numsTbl[] = +{ + SDLK_1, SDLK_2, SDLK_3, SDLK_4, SDLK_5, SDLK_6, SDLK_7, SDLK_8, SDLK_9, + SDLK_0, SDLK_MINUS, SDLK_EQUALS, SDLK_BACKSPACE, SDLK_INSERT, SDLK_HOME, + SDLK_q, SDLK_w, SDLK_e, SDLK_r, SDLK_t, SDLK_y, SDLK_u, SDLK_i, SDLK_o, + SDLK_p, SDLK_LEFTBRACKET, SDLK_RIGHTBRACKET, SDLK_BACKSLASH, SDLK_a, + SDLK_s, SDLK_d, SDLK_f, SDLK_g, SDLK_h, SDLK_j, SDLK_k, SDLK_l, + SDLK_SEMICOLON, SDLK_QUOTE, SDLK_z, SDLK_x, SDLK_c, SDLK_v, SDLK_b, SDLK_n, + SDLK_m, SDLK_COMMA, SDLK_PERIOD, SDLK_SLASH +}; + int OutfitWindow::keyToNumber(SDLKey key) const { - int outfitNum = -1; - switch (key) + for (unsigned f = 0; f < sizeof(numsTbl) / sizeof(SDLKey); f ++) { - case SDLK_1: - case SDLK_2: - case SDLK_3: - case SDLK_4: - case SDLK_5: - case SDLK_6: - case SDLK_7: - case SDLK_8: - case SDLK_9: - outfitNum = key - SDLK_1; - break; - - case SDLK_0: - outfitNum = 9; - break; - - case SDLK_MINUS: - outfitNum = 10; - break; - - case SDLK_EQUALS: - outfitNum = 11; - break; - - case SDLK_BACKSPACE: - outfitNum = 12; - break; - - case SDLK_INSERT: - outfitNum = 13; - break; - - case SDLK_HOME: - outfitNum = 14; - break; - - case SDLK_q: - outfitNum = 15; - break; - - case SDLK_w: - outfitNum = 16; - break; - - case SDLK_e: - outfitNum = 17; - break; - - case SDLK_r: - outfitNum = 18; - break; - - case SDLK_t: - outfitNum = 19; - break; - - case SDLK_y: - outfitNum = 20; - break; - - case SDLK_u: - outfitNum = 21; - break; - - case SDLK_i: - outfitNum = 22; - break; - - case SDLK_o: - outfitNum = 23; - break; - - case SDLK_p: - outfitNum = 24; - break; - - case SDLK_LEFTBRACKET: - outfitNum = 25; - break; - - case SDLK_RIGHTBRACKET: - outfitNum = 26; - break; - - case SDLK_BACKSLASH: - outfitNum = 27; - break; - - case SDLK_a: - outfitNum = 28; - break; - - case SDLK_s: - outfitNum = 29; - break; - - case SDLK_d: - outfitNum = 30; - break; - - case SDLK_f: - outfitNum = 31; - break; - - case SDLK_g: - outfitNum = 32; - break; - - case SDLK_h: - outfitNum = 33; - break; - - case SDLK_j: - outfitNum = 34; - break; - - case SDLK_k: - outfitNum = 35; - break; - - case SDLK_l: - outfitNum = 36; - break; - - case SDLK_SEMICOLON: - outfitNum = 37; - break; - - case SDLK_QUOTE: - outfitNum = 38; - break; - - case SDLK_z: - outfitNum = 39; - break; - - - case SDLK_x: - outfitNum = 40; - break; - - case SDLK_c: - outfitNum = 41; - break; - - case SDLK_v: - outfitNum = 42; - break; - - case SDLK_b: - outfitNum = 43; - break; - - case SDLK_n: - outfitNum = 44; - break; - - case SDLK_m: - outfitNum = 45; - break; - - case SDLK_COMMA: - outfitNum = 46; - break; - - case SDLK_PERIOD: - outfitNum = 47; - break; - - case SDLK_SLASH: - outfitNum = 48; - break; - - default: - break; + if (numsTbl[f] == key) + return f; } - - return outfitNum; + return -1; } -SDLKey OutfitWindow::numberToKey(int number) const +SDLKey OutfitWindow::numberToKey(unsigned number) const { - SDLKey key = SDLK_UNKNOWN; - switch (number) - { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - key = static_cast<SDLKey>( - static_cast<unsigned int>(SDLK_1) + number); - break; - - case 9: - key = SDLK_0; - break; - - case 10: - key = SDLK_MINUS; - break; - - case 11: - key = SDLK_EQUALS; - break; - - case 12: - key = SDLK_BACKSPACE; - break; - - case 13: - key = SDLK_INSERT; - break; - - case 14: - key = SDLK_HOME; - break; - - case 15: - key = SDLK_q; - break; - - case 16: - key = SDLK_w; - break; - - case 17: - key = SDLK_e; - break; - - case 18: - key = SDLK_r; - break; - - case 19: - key = SDLK_t; - break; - - case 20: - key = SDLK_y; - break; - - case 21: - key = SDLK_u; - break; - - case 22: - key = SDLK_i; - break; - - case 23: - key = SDLK_o; - break; - - case 24: - key = SDLK_p; - break; - - case 25: - key = SDLK_LEFTBRACKET; - break; - - case 26: - key = SDLK_RIGHTBRACKET; - break; - - case 27: - key = SDLK_BACKSLASH; - break; - - case 28: - key = SDLK_a; - break; - - case 29: - key = SDLK_s; - break; - - case 30: - key = SDLK_d; - break; - - case 31: - key = SDLK_f; - break; - - case 32: - key = SDLK_g; - break; - - case 33: - key = SDLK_h; - break; - - case 34: - key = SDLK_j; - break; - - case 35: - key = SDLK_k; - break; - - case 36: - key = SDLK_l; - break; - - case 37: - key = SDLK_SEMICOLON; - break; - - case 38: - key = SDLK_QUOTE; - break; - - case 39: - key = SDLK_z; - break; - - - case 40: - key = SDLK_x; - break; - - case 41: - key = SDLK_c; - break; - - case 42: - key = SDLK_v; - break; - - case 43: - key = SDLK_b; - break; - - case 44: - key = SDLK_n; - break; - - case 45: - key = SDLK_m; - break; - - case 46: - key = SDLK_COMMA; - break; - - case 47: - key = SDLK_PERIOD; - break; - - case 48: - key = SDLK_SLASH; - break; - - default: - break; - } - - return key; + if (number >= sizeof(numsTbl) / sizeof(SDLKey)) + return SDLK_UNKNOWN; + return numsTbl[number]; } std::string OutfitWindow::keyName(int number) diff --git a/src/gui/outfitwindow.h b/src/gui/outfitwindow.h index b2b46c7e7..6f67c472d 100644 --- a/src/gui/outfitwindow.h +++ b/src/gui/outfitwindow.h @@ -72,7 +72,7 @@ class OutfitWindow : public Window, gcn::ActionListener void setItemSelected(Item *item); - bool isItemSelected() + bool isItemSelected() const { return mItemSelected > 0; } void wearOutfit(int outfit, bool unwearEmpty = true, @@ -90,7 +90,7 @@ class OutfitWindow : public Window, gcn::ActionListener int keyToNumber(SDLKey key) const A_PURE; - SDLKey numberToKey(int number) const A_PURE; + SDLKey numberToKey(unsigned number) const A_PURE; void next(); diff --git a/src/gui/palette.h b/src/gui/palette.h index 36d87e305..7d5d93830 100644 --- a/src/gui/palette.h +++ b/src/gui/palette.h @@ -98,9 +98,7 @@ class Palette * @return the gradient type of the color with the given index */ inline GradientType getGradientType(int type) const - { - return mColors[type].grad; - } + { return mColors[type].grad; } /** * Get the character used by the specified color. @@ -110,9 +108,7 @@ class Palette * @return the color char of the color with the given index */ inline char getColorChar(int type) const - { - return mColors[type].ch; - } + { return mColors[type].ch; } /** * Gets the gradient delay for the specified type. @@ -122,7 +118,7 @@ class Palette * @return the gradient delay of the color with the given index */ inline int getGradientDelay(int type) const - { return mColors[type].delay; } + { return mColors[type].delay; } /** * Updates all colors, that are non-static. diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index cd3a4c5ad..142acc69c 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -1184,19 +1184,19 @@ void PopupMenu::handleLink(const std::string &link, int cnt = 10; if (cnt > mItem->getQuantity()) cnt = mItem->getQuantity(); - Net::getInventoryHandler()->moveItem(Inventory::INVENTORY, + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, mItem->getInvIndex(), cnt, Inventory::STORAGE); } else if (link == "store half" && mItem) { - Net::getInventoryHandler()->moveItem(Inventory::INVENTORY, + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, mItem->getInvIndex(), mItem->getQuantity() / 2, Inventory::STORAGE); } else if (link == "store all" && mItem) { - Net::getInventoryHandler()->moveItem(Inventory::INVENTORY, + Net::getInventoryHandler()->moveItem2(Inventory::INVENTORY, mItem->getInvIndex(), mItem->getQuantity(), Inventory::STORAGE); } @@ -1235,19 +1235,19 @@ void PopupMenu::handleLink(const std::string &link, int cnt = 10; if (cnt > mItem->getQuantity()) cnt = mItem->getQuantity(); - Net::getInventoryHandler()->moveItem(Inventory::STORAGE, + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, mItem->getInvIndex(), cnt, Inventory::INVENTORY); } else if (link == "retrieve half" && mItem) { - Net::getInventoryHandler()->moveItem(Inventory::STORAGE, + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, mItem->getInvIndex(), mItem->getQuantity() / 2, Inventory::INVENTORY); } else if (link == "retrieve all" && mItem) { - Net::getInventoryHandler()->moveItem(Inventory::STORAGE, + Net::getInventoryHandler()->moveItem2(Inventory::STORAGE, mItem->getInvIndex(), mItem->getQuantity(), Inventory::INVENTORY); } diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index 39ff19a89..59bdf9660 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -28,6 +28,7 @@ #include "logger.h" #include "main.h" +#include "gui/editserverdialog.h" #include "gui/gui.h" #include "gui/logindialog.h" #include "gui/okdialog.h" @@ -117,8 +118,8 @@ std::string ServersListModel::getElementAt(int elementIndex) const ServerInfo &server = mServers->at(elementIndex); std::string myServer; myServer += server.hostname; - myServer += ":"; - myServer += toString(server.port); +// myServer += ":"; +// myServer += toString(server.port); return myServer; } @@ -138,20 +139,6 @@ void ServersListModel::setVersionString(int index, const std::string &version) } } -std::string TypeListModel::getElementAt(int elementIndex) -{ - if (elementIndex == 0) - return "TmwAthena"; - else if (elementIndex == 1) - return "Evol"; -#ifdef MANASERV_SUPPORT - else if (elementIndex == 2) - return "ManaServ"; -#endif - else - return "Unknown"; -} - class ServersListBox : public ListBox { public: @@ -196,20 +183,24 @@ public: graphics->setColor(mTextColor); int top; + int x = 2; if (!info.name.empty()) { graphics->setFont(boldFont); + x += boldFont->getWidth(info.name) + 15; graphics->drawText(info.name, 2, y); - top = y + height / 2; + top = y + boldFont->getHeight() + 2; } else { - top = y + height / 4; + top = y + height / 4 + 2; } graphics->setFont(getFont()); + if (!info.description.empty()) + graphics->drawText(info.description, x, y); graphics->drawText(model->getElementAt(i), 2, top); if (info.version.first > 0) @@ -224,7 +215,7 @@ public: unsigned int getRowHeight() const { - return 2 * getFont()->getHeight(); + return 2 * getFont()->getHeight() + 5; } private: gcn::Color mHighlightColor; @@ -249,11 +240,6 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): setWindowName("ServerDialog"); - Label *serverLabel = new Label(_("Server:")); - Label *portLabel = new Label(_("Port:")); - - mServerNameField = new TextField(mServerInfo->hostname); - mPortField = new TextField(toString(mServerInfo->port)); mPersistentIPCheckBox = new CheckBox(_("Use same ip for game sub servers"), config.getBoolValue("usePersistentIP"), this, "persitent ip"); @@ -268,66 +254,33 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): ScrollArea *usedScroll = new ScrollArea(mServersList); usedScroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER); - Label *typeLabel = new Label(_("Server type:")); - mTypeListModel = new TypeListModel(); - mTypeField = new DropDown(mTypeListModel); - switch (serverInfo->type) - { - case ServerInfo::MANASERV: -#ifdef MANASERV_SUPPORT - mTypeField->setSelected(2); - break; -#endif - default: - case ServerInfo::UNKNOWN: - case ServerInfo::TMWATHENA: - mTypeField->setSelected(0); - break; - case ServerInfo::EVOL: - mTypeField->setSelected(1); - break; - } - int n = 1; + int n = 0; mDescription = new Label(std::string()); mQuitButton = new Button(_("Quit"), "quit", this); mLoadButton = new Button(_("Load"), "load", this); mConnectButton = new Button(_("Connect"), "connect", this); - mManualEntryButton = new Button(_("Custom Server"), "addEntry", this); + mAddEntryButton = new Button(_("Add"), "addEntry", this); + mEditEntryButton = new Button(_("Edit"), "editEntry", this); mDeleteButton = new Button(_("Delete"), "remove", this); - mServerNameField->setActionEventId("connect"); - mPortField->setActionEventId("connect"); - - mServerNameField->addActionListener(this); - mPortField->addActionListener(this); - mManualEntryButton->addActionListener(this); mServersList->addSelectionListener(this); usedScroll->setVerticalScrollAmount(0); - place(0, 0, serverLabel); - place(1, 0, mServerNameField, 5).setPadding(3); - place(0, 1, portLabel); - place(1, 1, mPortField, 5).setPadding(3); - place(0, 2, typeLabel); - place(1, 2, mTypeField, 5).setPadding(3); - place(0, 2 + n, usedScroll, 6, 5).setPadding(3); - place(0, 7 + n, mDescription, 6); - place(0, 8 + n, mPersistentIPCheckBox, 6); - place(0, 9 + n, mManualEntryButton); - place(1, 9 + n, mDeleteButton); - place(2, 9 + n, mLoadButton); - place(4, 9 + n, mQuitButton); - place(5, 9 + n, mConnectButton); + place(0, 0 + n, usedScroll, 7, 5).setPadding(3); + place(0, 5 + n, mDescription, 7); + place(0, 6 + n, mPersistentIPCheckBox, 7); + place(0, 7 + n, mAddEntryButton); + place(1, 7 + n, mEditEntryButton); + place(2, 7 + n, mLoadButton); + place(3, 7 + n, mDeleteButton); + place(5, 7 + n, mQuitButton); + place(6, 7 + n, mConnectButton); // Make sure the list has enough height - getLayout().setRowHeight(3, 80); + getLayout().setRowHeight(0, 80); -/* - reflowLayout(400, 300); - setDefaultSize(400, 300, ImageRect::CENTER); -*/ // Do this manually instead of calling reflowLayout so we can enforce a // minimum width. int width = 0, height = 0; @@ -349,21 +302,10 @@ ServerDialog::ServerDialog(ServerInfo *serverInfo, const std::string &dir): loadWindowState(); - setFieldsReadOnly(true); mServersList->setSelected(0); // Do this after for the Delete button setVisible(true); - if (mServerNameField->getText().empty()) - { - mServerNameField->requestFocus(); - } - else - { - if (mPortField->getText().empty()) - mPortField->requestFocus(); - else - mConnectButton->requestFocus(); - } + mConnectButton->requestFocus(); loadServers(true); @@ -381,82 +323,48 @@ ServerDialog::~ServerDialog() } delete mServersListModel; mServersListModel = nullptr; - delete mTypeListModel; - mTypeListModel = nullptr; } void ServerDialog::action(const gcn::ActionEvent &event) { - if (event.getId() == "ok") - { - // Give focus back to the server dialog. - mServerNameField->requestFocus(); - } - else if (event.getId() == "connect") + if (event.getId() == "connect") { - // Check login - if (mServerNameField->getText().empty() - || mPortField->getText().empty()) - { - OkDialog *dlg = new OkDialog(_("Error"), - _("Please type both the address and the port of a server.")); - dlg->addActionListener(this); - } - else - { - if (mDownload) - mDownload->cancel(); - - mQuitButton->setEnabled(false); - mConnectButton->setEnabled(false); - mLoadButton->setEnabled(false); + if (Client::getState() == STATE_CONNECT_SERVER) + return; - mServerInfo->hostname = mServerNameField->getText(); - mServerInfo->port = static_cast<short>( - atoi(mPortField->getText().c_str())); + if (mDownload) + mDownload->cancel(); - if (mTypeField) - { - switch (mTypeField->getSelected()) - { - case 0: - mServerInfo->type = ServerInfo::TMWATHENA; - break; - case 1: - mServerInfo->type = ServerInfo::EVOL; - break; -#ifdef MANASERV_SUPPORT - case 2: - mServerInfo->type = ServerInfo::MANASERV; - break; -#endif - default: - mServerInfo->type = ServerInfo::UNKNOWN; - } - } - else - { - mServerInfo->type = ServerInfo::TMWATHENA; - } + mQuitButton->setEnabled(false); + mConnectButton->setEnabled(false); + mLoadButton->setEnabled(false); - // Save the selected server - mServerInfo->save = true; + int index = mServersList->getSelected(); + if (index < 0) + return; - if (chatLogger) - chatLogger->setServerName(mServerInfo->hostname); + ServerInfo server = mServers.at(index); + mServerInfo->hostname = server.hostname; + mServerInfo->port = server.port; + mServerInfo->type = server.type; + mServerInfo->name = server.name; + mServerInfo->description = server.description; + mServerInfo->save = true; - saveCustomServers(*mServerInfo); + if (chatLogger) + chatLogger->setServerName(mServerInfo->hostname); - if (!LoginDialog::savedPasswordKey.empty()) - { - if (mServerInfo->hostname != LoginDialog::savedPasswordKey) - LoginDialog::savedPassword = ""; - } + saveCustomServers(*mServerInfo); - config.setValue("usePersistentIP", - mPersistentIPCheckBox->isSelected()); - Client::setState(STATE_CONNECT_SERVER); + if (!LoginDialog::savedPasswordKey.empty()) + { + if (mServerInfo->hostname != LoginDialog::savedPasswordKey) + LoginDialog::savedPassword = ""; } + + config.setValue("usePersistentIP", + mPersistentIPCheckBox->isSelected()); + Client::setState(STATE_CONNECT_SERVER); } else if (event.getId() == "quit") { @@ -470,15 +378,23 @@ void ServerDialog::action(const gcn::ActionEvent &event) } else if (event.getId() == "addEntry") { - setFieldsReadOnly(false); + new EditServerDialog(this, ServerInfo(), -1); + } + else if (event.getId() == "editEntry") + { + int index = mServersList->getSelected(); + if (index >= 0) + new EditServerDialog(this, mServers.at(index), index); } else if (event.getId() == "remove") { int index = mServersList->getSelected(); - mServersList->setSelected(0); - mServers.erase(mServers.begin() + index); - - saveCustomServers(); + if (index >= 0) + { + mServersList->setSelected(0); + mServers.erase(mServers.begin() + index); + saveCustomServers(); + } } } @@ -503,34 +419,6 @@ void ServerDialog::valueChanged(const gcn::SelectionEvent &) // Update the server and post fields according to the new selection const ServerInfo &myServer = mServersListModel->getServer(index); - mDescription->setCaption(myServer.description); - mServerNameField->setText(myServer.hostname); - mPortField->setText(toString(myServer.port)); - if (mTypeField) - { - switch (myServer.type) - { - case ServerInfo::TMWATHENA: - case ServerInfo::UNKNOWN: -#ifdef MANASERV_SUPPORT - default: - mTypeField->setSelected(0); - break; - case ServerInfo::MANASERV: - mTypeField->setSelected(2); - break; -#else - case ServerInfo::MANASERV: - default: - mTypeField->setSelected(0); - break; -#endif - case ServerInfo::EVOL: - mTypeField->setSelected(1); - break; - } - } - setFieldsReadOnly(true); mDeleteButton->setEnabled(myServer.save); } @@ -577,30 +465,6 @@ void ServerDialog::logic() Window::logic(); } -void ServerDialog::setFieldsReadOnly(bool readOnly) -{ - if (!readOnly) - { - mDescription->setCaption(std::string()); - mServersList->setSelected(-1); - - mServerNameField->setText(std::string()); - mPortField->setText(std::string("6901")); - - mServerNameField->requestFocus(); - } - - mManualEntryButton->setEnabled(readOnly); - mDeleteButton->setEnabled(false); - mLoadButton->setEnabled(readOnly); - mDescription->setVisible(readOnly); - - mServerNameField->setEnabled(!readOnly); - mPortField->setEnabled(!readOnly); - if (mTypeField) - mTypeField->setEnabled(!readOnly); -} - void ServerDialog::downloadServerList() { // Try to load the configuration value for the onlineServerList @@ -647,6 +511,9 @@ void ServerDialog::loadServers(bool addNew) return; } + const std::string lang = getLangShort(); + const std::string description2 = "description_" + lang; + for_each_xml_child_node(serverNode, rootNode) { if (!xmlNameEqual(serverNode, "server")) @@ -696,7 +563,9 @@ void ServerDialog::loadServers(bool addNew) server.port = defaultPortForServerType(server.type); } } - else if (xmlNameEqual(subNode, "description")) + else if ((xmlNameEqual(subNode, "description") + && server.description.empty()) || (!lang.empty() + && xmlNameEqual(subNode, description2.c_str()))) { server.description = reinterpret_cast<const char*>( subNode->xmlChildrenNode->content); @@ -716,6 +585,7 @@ void ServerDialog::loadServers(bool addNew) // Use the name listed in the server list mServers[i].name = server.name; mServers[i].version = server.version; + mServers[i].description = server.description; mServersListModel->setVersionString(i, version); found = true; break; @@ -731,12 +601,16 @@ void ServerDialog::loadCustomServers() for (int i = 0; i < MAX_SERVERLIST; ++i) { const std::string index = toString(i); - const std::string nameKey = "MostUsedServerName" + index; + const std::string nameKey = "MostUsedServerDescName" + index; + const std::string descKey = "MostUsedServerDescription" + index; + const std::string hostKey = "MostUsedServerName" + index; const std::string typeKey = "MostUsedServerType" + index; const std::string portKey = "MostUsedServerPort" + index; ServerInfo server; - server.hostname = config.getValue(nameKey, ""); + server.name = config.getValue(nameKey, ""); + server.description = config.getValue(descKey, ""); + server.hostname = config.getValue(hostKey, ""); server.type = ServerInfo::parseType(config.getValue(typeKey, "")); const int defaultPort = defaultPortForServerType(server.type); @@ -752,21 +626,29 @@ void ServerDialog::loadCustomServers() } } -void ServerDialog::saveCustomServers(const ServerInfo ¤tServer) +void ServerDialog::saveCustomServers(const ServerInfo ¤tServer, + int index) { // Make sure the current server is mentioned first if (currentServer.isValid()) { - ServerInfos::iterator i, i_end = mServers.end(); - for (i = mServers.begin(); i != i_end; ++i) + if (index >= 0 && (unsigned)index < mServers.size()) { - if (*i == currentServer) + mServers[index] = currentServer; + } + else + { + ServerInfos::iterator i, i_end = mServers.end(); + for (i = mServers.begin(); i != i_end; ++i) { - mServers.erase(i); - break; + if (*i == currentServer) + { + mServers.erase(i); + break; + } } + mServers.insert(mServers.begin(), currentServer); } - mServers.insert(mServers.begin(), currentServer); } int savedServerCount = 0; @@ -780,15 +662,19 @@ void ServerDialog::saveCustomServers(const ServerInfo ¤tServer) if (!(server.save && server.isValid())) continue; - const std::string index = toString(savedServerCount); - const std::string nameKey = "MostUsedServerName" + index; - const std::string typeKey = "MostUsedServerType" + index; - const std::string portKey = "MostUsedServerPort" + index; + const std::string num = toString(savedServerCount); + const std::string nameKey = "MostUsedServerDescName" + num; + const std::string descKey = "MostUsedServerDescription" + num; + const std::string hostKey = "MostUsedServerName" + num; + const std::string typeKey = "MostUsedServerType" + num; + const std::string portKey = "MostUsedServerPort" + num; - config.setValue(nameKey, toString(server.hostname)); + config.setValue(nameKey, toString(server.name)); + config.setValue(descKey, toString(server.description)); + config.setValue(hostKey, toString(server.hostname)); config.setValue(typeKey, serverTypeToString(server.type)); config.setValue(portKey, toString(server.port)); - ++savedServerCount; + ++ savedServerCount; } // Insert an invalid entry at the end to make the loading stop there @@ -799,7 +685,7 @@ void ServerDialog::saveCustomServers(const ServerInfo ¤tServer) int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status, size_t total, size_t remaining) { - if (status == DOWNLOAD_STATUS_CANCELLED) + if (!ptr || status == DOWNLOAD_STATUS_CANCELLED) return -1; ServerDialog *sd = reinterpret_cast<ServerDialog*>(ptr); @@ -853,3 +739,8 @@ int ServerDialog::downloadUpdate(void *ptr, DownloadStatus status, return 0; } + +void ServerDialog::updateServer(ServerInfo server, int index) +{ + saveCustomServers(server, index); +} diff --git a/src/gui/serverdialog.h b/src/gui/serverdialog.h index d2fe0d25b..c23fb8776 100644 --- a/src/gui/serverdialog.h +++ b/src/gui/serverdialog.h @@ -83,30 +83,6 @@ class ServersListModel : public gcn::ListModel ServerDialog *mParent; }; -/** - * Server Type List Model - */ -class TypeListModel : public gcn::ListModel -{ - public: - TypeListModel() {} - - /** - * Used to get number of line in the list - */ - int getNumberOfElements() -#ifdef MANASERV_SUPPORT - { return 3; } -#else - { return 2; } -#endif - - /** - * Used to get an element from the list - */ - std::string getElementAt(int elementIndex); -}; - /** * The server choice dialog. @@ -147,12 +123,17 @@ class ServerDialog : public Window, void logic(); + void updateServer(ServerInfo server, int index); + protected: friend class ServersListModel; + MutexLocker lock() { return MutexLocker(&mMutex); } private: + friend class EditServerDialog; + /** * Called to load a list of available server from an online xml file. */ @@ -160,28 +141,23 @@ class ServerDialog : public Window, void loadServers(bool addNew = true); void loadCustomServers(); - void saveCustomServers(const ServerInfo ¤tServer = ServerInfo()); + void saveCustomServers(const ServerInfo ¤tServer = ServerInfo(), + int index = -1); static int downloadUpdate(void *ptr, DownloadStatus status, size_t total, size_t remaining); - void setFieldsReadOnly(bool readOnly); - - TextField *mServerNameField; - TextField *mPortField; Label *mDescription; Button *mQuitButton; Button *mConnectButton; - Button *mManualEntryButton; + Button *mAddEntryButton; + Button *mEditEntryButton; Button *mDeleteButton; Button *mLoadButton; ListBox *mServersList; ServersListModel *mServersListModel; - DropDown *mTypeField; - TypeListModel *mTypeListModel; - const std::string &mDir; enum ServerDialogDownloadStatus diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index bac474950..3408fba33 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -75,7 +75,7 @@ Setup::Setup(): nullptr }; int x = width; - for (const char **curBtn = buttonNames; *curBtn; ++curBtn) + for (const char **curBtn = buttonNames; *curBtn; ++ curBtn) { Button *btn = new Button(gettext(*curBtn), *curBtn, this); x -= btn->getWidth() + 5; diff --git a/src/gui/setup_relations.cpp b/src/gui/setup_relations.cpp index 9ddef9e1a..571856a14 100644 --- a/src/gui/setup_relations.cpp +++ b/src/gui/setup_relations.cpp @@ -193,6 +193,8 @@ public: std::string getPlayerAt(int index) const { + if (index < 0 || index >= (signed)mPlayers->size()) + return ""; return (*mPlayers)[index]; } @@ -257,10 +259,7 @@ Setup_Relations::Setup_Relations(): mIgnoreActionChoicesBox = new DropDown(mIgnoreActionChoicesModel); for (int i = 0; i < COLUMNS_NR; i++) - { - mPlayerTableTitleModel->set(0, i, - new Label(gettext(table_titles[i]))); - } + mPlayerTableTitleModel->set(0, i, new Label(gettext(table_titles[i]))); mPlayerTitleTable->setLinewiseSelection(true); diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 259388fd0..9a5b30ea7 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -143,11 +143,11 @@ ModeListModel::ModeListModel() } else { - for (int i = 0; modes[i]; ++i) + for (int i = 0; modes[i]; ++ i) { const std::string modeString = toString(static_cast<int>(modes[i]->w)) + "x" - + toString(static_cast<int>(modes[i]->h)); + + toString(static_cast<int>(modes[i]->h)); mVideoModes.push_back(modeString); } } @@ -281,6 +281,8 @@ Setup_Video::Setup_Video(): mOpacity(config.getFloatValue("guialpha")), mFps(config.getIntValue("fpslimit")), mAltFps(config.getIntValue("altfpslimit")), + mEnableResize(config.getBoolValue("enableresize")), + mNoFrame(config.getBoolValue("noframe")), mSpeechMode(static_cast<Being::Speech>( config.getIntValue("speech"))), mModeListModel(new ModeListModel), @@ -296,6 +298,8 @@ Setup_Video::Setup_Video(): // TRANSLATORS: Refers to "Show own name" mPickupParticleCheckBox(new CheckBox(_("as particle"), mPickupParticleEnabled)), + mEnableResizeCheckBox(new CheckBox(_("Enable resize"), mEnableResize)), + mNoFrameCheckBox(new CheckBox(_("No frame"), mNoFrame)), mSpeechSlider(new Slider(0, 3)), mSpeechLabel(new Label("")), mAlphaSlider(new Slider(0.1, 1.0)), @@ -367,6 +371,8 @@ Setup_Video::Setup_Video(): mParticleDetailSlider->setActionEventId("particledetailslider"); mParticleDetailField->setActionEventId("particledetailfield"); mOpenGLDropDown->setActionEventId("opengl"); + mEnableResizeCheckBox->setActionEventId("enableresize"); + mNoFrameCheckBox->setActionEventId("noframe"); mModeList->addActionListener(this); mCustomCursorCheckBox->addActionListener(this); @@ -383,6 +389,8 @@ Setup_Video::Setup_Video(): mParticleDetailSlider->addActionListener(this); mParticleDetailField->addKeyListener(this); mOpenGLDropDown->addActionListener(this); + mEnableResizeCheckBox->addActionListener(this); + mNoFrameCheckBox->addActionListener(this); mSpeechLabel->setCaption(speechModeToString(mSpeechMode)); mSpeechSlider->setValue(mSpeechMode); @@ -397,8 +405,8 @@ Setup_Video::Setup_Video(): LayoutHelper h(this); ContainerPlacer place = h.getPlacer(0, 0); - place(0, 0, scrollArea, 1, 5).setPadding(2); - place(0, 5, mOpenGLDropDown, 1); + place(0, 0, scrollArea, 1, 6).setPadding(2); + place(0, 6, mOpenGLDropDown, 1); // place(0, 6, mHwAccelCheckBox, 6); @@ -406,34 +414,36 @@ Setup_Video::Setup_Video(): place(1, 1, mCustomCursorCheckBox, 3); - place(1, 2, mParticleEffectsCheckBox, 2); + place(1, 2, mEnableResizeCheckBox, 2); + place(1, 3, mNoFrameCheckBox, 2); - place(1, 3, mPickupNotifyLabel, 4); + place(1, 4, mParticleEffectsCheckBox, 2); - place(1, 4, mPickupChatCheckBox, 1); - place(2, 4, mPickupParticleCheckBox, 2); + place(1, 5, mPickupNotifyLabel, 4); + place(1, 6, mPickupChatCheckBox, 1); + place(2, 6, mPickupParticleCheckBox, 2); - place(0, 6, mAlphaSlider); - place(1, 6, alphaLabel, 3); + place(0, 7, mAlphaSlider); + place(1, 7, alphaLabel, 3); - place(0, 7, mFpsSlider); - place(1, 7, mFpsCheckBox).setPadding(3); - place(2, 7, mFpsLabel).setPadding(1); + place(0, 9, mFpsSlider); + place(1, 9, mFpsCheckBox).setPadding(3); + place(2, 9, mFpsLabel).setPadding(1); - place(0, 8, mAltFpsSlider); - place(1, 8, mAltFpsLabel).setPadding(3); + place(0, 10, mAltFpsSlider); + place(1, 10, mAltFpsLabel).setPadding(3); - place(0, 9, mSpeechSlider); - place(1, 9, speechLabel); - place(2, 9, mSpeechLabel, 3).setPadding(2); + place(0, 11, mSpeechSlider); + place(1, 11, speechLabel); + place(2, 11, mSpeechLabel, 3).setPadding(2); - place(0, 10, mOverlayDetailSlider); - place(1, 10, overlayDetailLabel); - place(2, 10, mOverlayDetailField, 3).setPadding(2); + place(0, 12, mOverlayDetailSlider); + place(1, 12, overlayDetailLabel); + place(2, 12, mOverlayDetailField, 3).setPadding(2); - place(0, 11, mParticleDetailSlider); - place(1, 11, particleDetailLabel); - place(2, 11, mParticleDetailField, 3).setPadding(2); + place(0, 13, mParticleDetailSlider); + place(1, 13, particleDetailLabel); + place(2, 13, mParticleDetailField, 3).setPadding(2); int width = 600; @@ -540,6 +550,8 @@ void Setup_Video::apply() mOpenGLEnabled = config.getIntValue("opengl"); mPickupChatEnabled = config.getBoolValue("showpickupchat"); mPickupParticleEnabled = config.getBoolValue("showpickupparticle"); + mEnableResize = config.getBoolValue("enableresize"); + mNoFrame = config.getBoolValue("noframe"); } void Setup_Video::cancel() @@ -560,6 +572,8 @@ void Setup_Video::cancel() mFpsLabel->setCaption(mFpsCheckBox->isSelected() ? toString(mFps) : _("None")); mAltFpsLabel->setCaption(_("Alt FPS limit: ") + toString(mAltFps)); + mEnableResizeCheckBox->setSelected(mEnableResize); + mNoFrameCheckBox->setSelected(mNoFrame); config.setValue("screen", mFullScreenEnabled); @@ -578,6 +592,8 @@ void Setup_Video::cancel() config.setValue("opengl", mOpenGLEnabled); config.setValue("showpickupchat", mPickupChatEnabled); config.setValue("showpickupparticle", mPickupParticleEnabled); + config.setValue("enableresize", mEnableResize); + config.setValue("noframe", mNoFrame); } void Setup_Video::action(const gcn::ActionEvent &event) @@ -614,6 +630,7 @@ void Setup_Video::action(const gcn::ActionEvent &event) // TODO: Find out why the drawing area doesn't resize without a restart. if (width != mainGraphics->mWidth || height != mainGraphics->mHeight) { +#if defined(_WIN32) if (width < mainGraphics->mWidth || height < mainGraphics->mHeight) new OkDialog(_("Screen Resolution Changed"), _("Restart your client for the change to take effect.") @@ -622,6 +639,9 @@ void Setup_Video::action(const gcn::ActionEvent &event) else new OkDialog(_("Screen Resolution Changed"), _("Restart your client for the change to take effect.")); +#else + Client::resize(width, height); +#endif } config.setValue("oldscreen", config.getBoolValue("screen")); @@ -711,6 +731,14 @@ void Setup_Video::action(const gcn::ActionEvent &event) mAltFpsSlider->setValue(mAltFps); mAltFpsSlider->setEnabled(mAltFps > 0); } + else if (id == "enableresize") + { + config.setValue("enableresize", mEnableResizeCheckBox->isSelected()); + } + else if (id == "noframe") + { + config.setValue("noframe", mNoFrameCheckBox->isSelected()); + } } void Setup_Video::externalUpdated() diff --git a/src/gui/setup_video.h b/src/gui/setup_video.h index 0c82ab272..31d45d93d 100644 --- a/src/gui/setup_video.h +++ b/src/gui/setup_video.h @@ -62,6 +62,8 @@ class Setup_Video : public SetupTab, public gcn::KeyListener float mOpacity; int mFps; int mAltFps; + bool mEnableResize; + bool mNoFrame; Being::Speech mSpeechMode; ModeListModel *mModeListModel; @@ -85,6 +87,9 @@ class Setup_Video : public SetupTab, public gcn::KeyListener gcn::CheckBox *mPickupChatCheckBox; gcn::CheckBox *mPickupParticleCheckBox; + gcn::CheckBox *mEnableResizeCheckBox; + gcn::CheckBox *mNoFrameCheckBox; + gcn::Slider *mSpeechSlider; gcn::Label *mSpeechLabel; gcn::Slider *mAlphaSlider; diff --git a/src/gui/shopwindow.cpp b/src/gui/shopwindow.cpp index b6b87edb7..1a27b8b0c 100644 --- a/src/gui/shopwindow.cpp +++ b/src/gui/shopwindow.cpp @@ -55,6 +55,7 @@ #include "net/net.h" #include "net/chathandler.h" #include "net/npchandler.h" +#include "net/playerhandler.h" #include "net/tradehandler.h" #include "resources/iteminfo.h" @@ -206,11 +207,15 @@ void ShopWindow::action(const gcn::ActionEvent &event) && mBuyShopItemList->getSelected() >= 0) { mBuyShopItems->del(mBuyShopItemList->getSelected()); + if (isShopEmpty() && player_node) + player_node->updateStatus(); } else if (event.getId() == "delete sell" && mSellShopItemList && mSellShopItemList->getSelected() >= 0) { mSellShopItems->del(mSellShopItemList->getSelected()); + if (isShopEmpty() && player_node) + player_node->updateStatus(); } else if (event.getId() == "announce buy" && mBuyShopItems && mBuyShopItems->getNumberOfElements() > 0) @@ -306,8 +311,12 @@ void ShopWindow::addBuyItem(Item *item, int amount, int price) { if (!mBuyShopItems || !item) return; + bool emp = isShopEmpty(); mBuyShopItems->addItemNoDup(item->getId(), item->getColor(), amount, price); + if (emp && player_node) + player_node->updateStatus(); + updateButtonsAndLabels(); } @@ -315,8 +324,12 @@ void ShopWindow::addSellItem(Item *item, int amount, int price) { if (!mBuyShopItems || !item) return; + bool emp = isShopEmpty(); mSellShopItems->addItemNoDup(item->getId(), item->getColor(), amount, price); + if (emp && player_node) + player_node->updateStatus(); + updateButtonsAndLabels(); } diff --git a/src/gui/shopwindow.h b/src/gui/shopwindow.h index 53ed7690c..a8d131acb 100644 --- a/src/gui/shopwindow.h +++ b/src/gui/shopwindow.h @@ -109,7 +109,7 @@ class ShopWindow : public Window, public gcn::ActionListener, void setAcceptPlayer(std::string name) { mAcceptPlayer = name; } - const std::string &getAcceptPlayer() + const std::string &getAcceptPlayer() const { return mAcceptPlayer; } void sendMessage(const std::string &nick, std::string data, diff --git a/src/gui/skilldialog.h b/src/gui/skilldialog.h index dcb40927a..9032f82ef 100644 --- a/src/gui/skilldialog.h +++ b/src/gui/skilldialog.h @@ -77,7 +77,7 @@ class SkillDialog : public Window, public gcn::ActionListener SkillInfo* getSkill(int id); - bool hasSkills() + bool hasSkills() const { return !mSkills.empty(); } void widgetResized(const gcn::Event &event); diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp index 3988c819c..59ace1685 100644 --- a/src/gui/socialwindow.cpp +++ b/src/gui/socialwindow.cpp @@ -1143,7 +1143,7 @@ public: std::vector<std::string> *players = player_relations.getPlayersByRelation(PlayerRelation::FRIEND); - std::set<std::string> players2 = whoIsOnline->getOnlinePlayers(); + const std::set<std::string> &players2 = whoIsOnline->getOnlineNicks(); if (!players) return; @@ -1273,10 +1273,12 @@ SocialWindow::SocialWindow() : loadWindowState(); - mPlayers = new SocialPlayersTab("P"); + // TRANSLATORS: here P is title for visible players tab in social window + mPlayers = new SocialPlayersTab(_("P")); mTabs->addTab(mPlayers, mPlayers->mScroll); - mFriends = new SocialFriendsTab("F"); + // TRANSLATORS: here F is title for friends tab in social window + mFriends = new SocialFriendsTab(_("F")); mTabs->addTab(mFriends, mFriends->mScroll); mNavigation = new SocialNavigationTab(); diff --git a/src/gui/socialwindow.h b/src/gui/socialwindow.h index 1429866ee..9da78562b 100644 --- a/src/gui/socialwindow.h +++ b/src/gui/socialwindow.h @@ -101,13 +101,13 @@ public: void prevTab(); - Map* getMap() + Map* getMap() const { return mMap; } void setMap(Map *map) { mMap = map; mProcessedPortals = false; } - bool getProcessedPortals() + bool getProcessedPortals() const { return mProcessedPortals; } void setProcessedPortals(int n) diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp index 410ee08e2..86964383a 100644 --- a/src/gui/statuswindow.cpp +++ b/src/gui/statuswindow.cpp @@ -69,7 +69,7 @@ class AttrDisplay : public Container virtual std::string update(); - virtual Type getType() + virtual Type getType() const { return UNKNOWN; } std::string getValue() @@ -96,7 +96,7 @@ class DerDisplay : public AttrDisplay public: DerDisplay(int id, const std::string &name); - virtual Type getType() + virtual Type getType() const { return DERIVED; } }; @@ -107,7 +107,7 @@ class ChangeDisplay : public AttrDisplay, gcn::ActionListener std::string update(); - virtual Type getType() + virtual Type getType() const { return CHANGEABLE; } void setPointsNeeded(int needed); @@ -424,12 +424,12 @@ void StatusWindow::addAttribute(int id, const std::string &name, if (modifiable) { disp = new ChangeDisplay(id, name); - mAttrCont->add(disp); + mAttrCont->add1(disp); } else { disp = new DerDisplay(id, name); - mDAttrCont->add(disp); + mDAttrCont->add1(disp); } mAttrs[id] = disp; } @@ -522,9 +522,14 @@ void StatusWindow::updateProgressBar(ProgressBar *bar, int value, int max, / static_cast<float>(max); if (percent) - bar->setText(strprintf("%2.5f%%", static_cast<double>(100 * progress))); + { + bar->setText(strprintf("%2.5f%%", + static_cast<double>(100 * progress))); + } else + { bar->setText(toString(value) + "/" + toString(max)); + } bar->setProgress(progress); } diff --git a/src/gui/theme.h b/src/gui/theme.h index 3be6882a3..9cb8f6180 100644 --- a/src/gui/theme.h +++ b/src/gui/theme.h @@ -95,7 +95,7 @@ class Skin */ void updateAlpha(float minimumOpacityAllowed = 0.0f); - int getPadding() + int getPadding() const { return mPadding; } int instances; diff --git a/src/gui/tradewindow.h b/src/gui/tradewindow.h index b055c90ce..268d2f108 100644 --- a/src/gui/tradewindow.h +++ b/src/gui/tradewindow.h @@ -128,7 +128,7 @@ class TradeWindow : public Window, gcn::ActionListener, gcn::SelectionListener void initTrade(std::string nick); - std::string getAutoTradeNick() + std::string getAutoTradeNick() const { return mAutoAddToNick; } bool checkItem(Item *item); diff --git a/src/gui/updaterwindow.cpp b/src/gui/updaterwindow.cpp index 39dde65c3..28bd8467c 100644 --- a/src/gui/updaterwindow.cpp +++ b/src/gui/updaterwindow.cpp @@ -155,6 +155,12 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost, mLoadUpdates(applyUpdates), mUpdateType(updateType) { + setWindowName("UpdaterWindow"); + setResizable(true); + setDefaultSize(450, 400, ImageRect::CENTER); + setMinWidth(320); + setMinHeight(240); + mBrowserBox = new BrowserBox; mScrollArea = new ScrollArea(mBrowserBox); mLabel = new Label(_("Connecting...")); @@ -175,14 +181,12 @@ UpdaterWindow::UpdaterWindow(const std::string &updateHost, placer(3, 5, mCancelButton); placer(4, 5, mPlayButton); - reflowLayout(450, 400); - Layout &layout = getLayout(); layout.setRowHeight(0, Layout::AUTO_SET); addKeyListener(this); - center(); + loadWindowState(); setVisible(true); mCancelButton->requestFocus(); diff --git a/src/gui/userpalette.h b/src/gui/userpalette.h index cb0593fa7..6fba30abc 100644 --- a/src/gui/userpalette.h +++ b/src/gui/userpalette.h @@ -107,7 +107,7 @@ class UserPalette : public Palette, public gcn::ListModel * * @return the requested test color */ - inline const gcn::Color &getTestColor(int type) + inline const gcn::Color &getTestColor(int type) const { return mColors[type].testColor; } /** diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 1407415fd..7ff2c8850 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -497,16 +497,16 @@ void Viewport::mousePressed(gcn::MouseEvent &event) } } else if (player_node->withinAttackRange(mHoverBeing) || - keyboard.isKeyActive(keyboard.KEY_ATTACK)) + keyboard.isActionActive(keyboard.KEY_ATTACK)) { if (player_node != mHoverBeing) { player_node->attack(mHoverBeing, - !keyboard.isKeyActive(keyboard.KEY_TARGET)); + !keyboard.isActionActive(keyboard.KEY_TARGET)); return; } } - else if (!keyboard.isKeyActive(keyboard.KEY_ATTACK)) + else if (!keyboard.isActionActive(keyboard.KEY_ATTACK)) { if (player_node != mHoverBeing) { @@ -522,7 +522,7 @@ void Viewport::mousePressed(gcn::MouseEvent &event) player_node->pickUp(mHoverItem); } // Just walk around - else if (!keyboard.isKeyActive(keyboard.KEY_ATTACK)) + else if (!keyboard.isActionActive(keyboard.KEY_ATTACK)) { player_node->stopAttack(); player_node->cancelFollow(); @@ -875,3 +875,44 @@ bool Viewport::isPopupMenuVisible() { return mPopupMenu ? mPopupMenu->isVisible() : false; } + +void Viewport::moveCameraToActor(int actorId, int x, int y) +{ + if (!player_node) + return; + + Actor *actor = actorSpriteManager->findBeing(actorId); + if (!actor) + return; + Vector actorPos = actor->getPosition(); + Vector playerPos = player_node->getPosition(); + mCameraMode = 1; + mCameraRelativeX = actorPos.x - playerPos.x + x; + mCameraRelativeY = actorPos.y - playerPos.y + y; +} + +void Viewport::moveCameraToPosition(int x, int y) +{ + if (!player_node) + return; + + Vector playerPos = player_node->getPosition(); + mCameraMode = 1; + + mCameraRelativeX = x - playerPos.x; + mCameraRelativeY = y - playerPos.y; +} + +void Viewport::moveCameraRelative(int x, int y) +{ + mCameraMode = 1; + mCameraRelativeX += x; + mCameraRelativeY += y; +} + +void Viewport::returnCamera() +{ + mCameraMode = 0; + mCameraRelativeX = 0; + mCameraRelativeY = 0; +} diff --git a/src/gui/viewport.h b/src/gui/viewport.h index b25f51242..f3035b5df 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -218,13 +218,13 @@ class Viewport : public WindowContainer, public gcn::MouseListener, Map *getCurrentMap() const { return mMap; } - int getDebugPath() + int getDebugPath() const { return mShowDebugPath; } void setDebugPath(int n) { mShowDebugPath = n; } - int getCameraMode() + int getCameraMode() const { return mCameraMode; } /** @@ -237,19 +237,33 @@ class Viewport : public WindowContainer, public gcn::MouseListener, */ void cleanHoverItems(); - Map *getMap() + Map *getMap() const { return mMap; } void moveCamera(int dx, int dy); - int getCameraRelativeX() + int getCameraRelativeX() const { return mCameraRelativeX; } - int getCameraRelativeY() + int getCameraRelativeY() const { return mCameraRelativeY; } + void setCameraRelativeX(int n) + { mCameraRelativeX = n; } + + void setCameraRelativeY(int n) + { mCameraRelativeY = n; } + bool isPopupMenuVisible(); + void moveCameraToActor(int actorId, int x = 0, int y = 0); + + void moveCameraToPosition(int x, int y); + + void moveCameraRelative(int x, int y); + + void returnCamera(); + protected: friend class ActorSpriteManager; diff --git a/src/gui/whoisonline.cpp b/src/gui/whoisonline.cpp index a80fb4c89..205a1aae1 100644 --- a/src/gui/whoisonline.cpp +++ b/src/gui/whoisonline.cpp @@ -48,6 +48,7 @@ #include "gui/chatwindow.h" +#include "utils/dtor.h" #include "utils/gettext.h" #include "utils/stringutils.h" @@ -68,21 +69,10 @@ class NameFunctuator { public: - bool operator()(const std::string &left, - const std::string &right) const + bool operator()(const OnlinePlayer *left, + const OnlinePlayer *right) const { - for (std::string::const_iterator lit = left.begin(), - rit = right.begin(); - lit != left.end() && rit != right.end(); ++lit, ++rit) - { - if (tolower(*lit) < tolower(*rit)) - return true; - else if (tolower(*lit) > tolower(*rit)) - return false; - } - if (left.size() < right.size()) - return true; - return false; + return (compareStrI(left->getNick(), right->getNick()) < 0); } } nameCompare; @@ -149,6 +139,14 @@ WhoIsOnline::~WhoIsOnline() // Remove possibly leftover temporary download delete[] mCurlError; + + std::set<OnlinePlayer*>::iterator itd = mOnlinePlayers.begin(); + std::set<OnlinePlayer*>::iterator itd_end = mOnlinePlayers.end(); + + for (; itd != itd_end; ++ itd) + delete *itd; + mOnlinePlayers.clear(); + mOnlineNicks.clear(); } void WhoIsOnline::handleLink(const std::string& link, gcn::MouseEvent *event) @@ -186,10 +184,10 @@ void WhoIsOnline::handleLink(const std::string& link, gcn::MouseEvent *event) } } -void WhoIsOnline::updateWindow(std::vector<std::string> &friends, - std::vector<std::string> &neutral, - std::vector<std::string> &disregard, - std::vector<std::string> enemy, +void WhoIsOnline::updateWindow(std::vector<OnlinePlayer*> &friends, + std::vector<OnlinePlayer*> &neutral, + std::vector<OnlinePlayer*> &disregard, + std::vector<OnlinePlayer*> enemy, int numOnline) { //Set window caption @@ -202,7 +200,7 @@ void WhoIsOnline::updateWindow(std::vector<std::string> &friends, bool addedFromSection(false); for (int i = 0; i < static_cast<int>(friends.size()); i++) { - mBrowserBox->addRow(friends.at(i)); + mBrowserBox->addRow(friends.at(i)->getText()); addedFromSection = true; } if (addedFromSection == true) @@ -212,7 +210,7 @@ void WhoIsOnline::updateWindow(std::vector<std::string> &friends, } for (int i = 0; i < static_cast<int>(enemy.size()); i++) { - mBrowserBox->addRow(enemy.at(i)); + mBrowserBox->addRow(enemy.at(i)->getText()); addedFromSection = true; } if (addedFromSection == true) @@ -222,7 +220,7 @@ void WhoIsOnline::updateWindow(std::vector<std::string> &friends, } for (int i = 0; i < static_cast<int>(neutral.size()); i++) { - mBrowserBox->addRow(neutral.at(i)); + mBrowserBox->addRow(neutral.at(i)->getText()); addedFromSection = true; } if (addedFromSection == true && !disregard.empty()) @@ -232,7 +230,7 @@ void WhoIsOnline::updateWindow(std::vector<std::string> &friends, } for (int i = 0; i < static_cast<int>(disregard.size()); i++) { - mBrowserBox->addRow(disregard.at(i)); + mBrowserBox->addRow(disregard.at(i)->getText()); } if (mScrollArea->getVerticalMaxScroll() < @@ -243,43 +241,59 @@ void WhoIsOnline::updateWindow(std::vector<std::string> &friends, } } -void WhoIsOnline::loadList(std::vector<std::string> &list) +void WhoIsOnline::loadList(std::vector<OnlinePlayer*> &list) { mBrowserBox->clearRows(); int numOnline = list.size(); - std::vector<std::string> friends; - std::vector<std::string> neutral; - std::vector<std::string> disregard; - std::vector<std::string> enemy; + std::vector<OnlinePlayer*> friends; + std::vector<OnlinePlayer*> neutral; + std::vector<OnlinePlayer*> disregard; + std::vector<OnlinePlayer*> enemy; + + std::set<OnlinePlayer*>::iterator itd = mOnlinePlayers.begin(); + std::set<OnlinePlayer*>::iterator itd_end = mOnlinePlayers.end(); + for (; itd != itd_end; ++ itd) + delete *itd; mOnlinePlayers.clear(); + mOnlineNicks.clear(); + mShowLevel = config.getBoolValue("showlevel"); - std::vector<std::string>::const_iterator it = list.begin(); - std::vector<std::string>::const_iterator it_end = list.end(); + std::vector<OnlinePlayer*>::iterator it = list.begin(); + std::vector<OnlinePlayer*>::iterator it_end = list.end(); for (; it != it_end; ++ it) { - std::string nick = *it; - mOnlinePlayers.insert(nick); + OnlinePlayer *player = *it; + std::string nick = player->getNick(); + mOnlinePlayers.insert(player); + mOnlineNicks.insert(nick); + + if (!mShowLevel) + player->setLevel(0); switch (player_relations.getRelation(nick)) { case PlayerRelation::NEUTRAL: default: - neutral.push_back(prepareNick(nick, 0, "0")); + player->setText("0"); + neutral.push_back(player); break; case PlayerRelation::FRIEND: - friends.push_back(prepareNick(nick, 0, "2")); + player->setText("2"); + friends.push_back(player); break; case PlayerRelation::DISREGARDED: case PlayerRelation::BLACKLISTED: - disregard.push_back(prepareNick(nick, 0, "8")); + player->setText("8"); + disregard.push_back(player); break; case PlayerRelation::ENEMY2: - enemy.push_back(prepareNick(nick, 0, "1")); + player->setText("1"); + enemy.push_back(player); break; case PlayerRelation::IGNORED: @@ -290,10 +304,10 @@ void WhoIsOnline::loadList(std::vector<std::string> &list) } updateWindow(friends, neutral, disregard, enemy, numOnline); - if (!mOnlinePlayers.empty()) + if (!mOnlineNicks.empty()) { if (chatWindow) - chatWindow->updateOnline(mOnlinePlayers); + chatWindow->updateOnline(mOnlineNicks); if (socialWindow) socialWindow->updateActiveList(); } @@ -313,15 +327,23 @@ void WhoIsOnline::loadWebList() bool listStarted(false); std::string lineStr; int numOnline(0); - std::vector<std::string> friends; - std::vector<std::string> neutral; - std::vector<std::string> disregard; - std::vector<std::string> enemy; + std::vector<OnlinePlayer*> friends; + std::vector<OnlinePlayer*> neutral; + std::vector<OnlinePlayer*> disregard; + std::vector<OnlinePlayer*> enemy; // Tokenize and add each line separately char *line = strtok(mMemoryBuffer, "\n"); const std::string gmText = "(GM)"; + + std::set<OnlinePlayer*>::iterator itd = mOnlinePlayers.begin(); + std::set<OnlinePlayer*>::iterator itd_end = mOnlinePlayers.end(); + + for (; itd != itd_end; ++ itd) + delete *itd; + mOnlinePlayers.clear(); + mOnlineNicks.clear(); mShowLevel = config.getBoolValue("showlevel"); @@ -383,27 +405,38 @@ void WhoIsOnline::loadWebList() } } - mOnlinePlayers.insert(nick); + + if (!mShowLevel) + level = 0; + + OnlinePlayer *player = new OnlinePlayer(nick, 255, level, + GENDER_UNSPECIFIED, -1); + mOnlinePlayers.insert(player); + mOnlineNicks.insert(nick); numOnline++; switch (player_relations.getRelation(nick)) { case PlayerRelation::NEUTRAL: default: - neutral.push_back(prepareNick(nick, level, "0")); + player->setText("0"); + neutral.push_back(player); break; case PlayerRelation::FRIEND: - friends.push_back(prepareNick(nick, level, "2")); + player->setText("2"); + friends.push_back(player); break; case PlayerRelation::DISREGARDED: case PlayerRelation::BLACKLISTED: - disregard.push_back(prepareNick(nick, level, "8")); + player->setText("8"); + disregard.push_back(player); break; case PlayerRelation::ENEMY2: - enemy.push_back(prepareNick(nick, level, "1")); + player->setText("1"); + enemy.push_back(player); break; case PlayerRelation::IGNORED: @@ -431,6 +464,9 @@ void WhoIsOnline::loadWebList() size_t WhoIsOnline::memoryWrite(void *ptr, size_t size, size_t nmemb, FILE *stream) { + if (!stream) + return 0; + WhoIsOnline *wio = reinterpret_cast<WhoIsOnline *>(stream); size_t totalMem = size * nmemb; wio->mMemoryBuffer = static_cast<char*>(realloc(wio->mMemoryBuffer, @@ -472,8 +508,8 @@ int WhoIsOnline::downloadThread(void *ptr) curl_easy_setopt(curl, CURLOPT_WRITEDATA, ptr); curl_easy_setopt(curl, CURLOPT_USERAGENT, - strprintf(PACKAGE_EXTENDED_VERSION, branding - .getValue("appShort", "mana").c_str()).c_str()); + strprintf(PACKAGE_EXTENDED_VERSION, + branding.getStringValue("appName").c_str()).c_str()); curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, wio->mCurlError); curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); @@ -596,10 +632,10 @@ void WhoIsOnline::logic() mUpdateButton->setEnabled(true); mUpdateTimer = 0; updateSize(); - if (!mOnlinePlayers.empty()) + if (!mOnlineNicks.empty()) { if (chatWindow) - chatWindow->updateOnline(mOnlinePlayers); + chatWindow->updateOnline(mOnlineNicks); if (socialWindow) socialWindow->updateActiveList(); } @@ -681,3 +717,46 @@ void WhoIsOnline::optionChanged(const std::string &name) if (name == "updateOnlineList") mUpdateOnlineList = config.getBoolValue("updateOnlineList"); } + +void OnlinePlayer::setText(std::string color) +{ + mText = strprintf("@@%s|##%s%s ", mNick.c_str(), + color.c_str(), mNick.c_str()); + + if (mStatus != 255 && actorSpriteManager) + { + Being *being = actorSpriteManager->findBeingByName( + mNick, Being::PLAYER); + if (being) + being->setState(mStatus); + } + + if (mLevel > 0) + mText += strprintf("%d", mLevel); + + if (mGender == GENDER_FEMALE) + mText += "\u2640"; + else if (mGender == GENDER_MALE) + mText += "\u2642"; + + if (mStatus > 0 && mStatus != 255) + { + if (mStatus & Being::FLAG_SHOP) + mText += "$"; + if (mStatus & Being::FLAG_AWAY) + { + // TRANSLATORS: this away status writed in player nick + mText += _("A"); + } + if (mStatus & Being::FLAG_INACTIVE) + { + // TRANSLATORS: this inactive status writed in player nick + mText += _("I"); + } + } + + if (mVersion > 0) + mText += strprintf(" - %d", mVersion); + + mText += strprintf("@@"); +} diff --git a/src/gui/whoisonline.h b/src/gui/whoisonline.h index ade391d5a..dad51e857 100644 --- a/src/gui/whoisonline.h +++ b/src/gui/whoisonline.h @@ -42,6 +42,54 @@ class ScrollArea; struct SDL_Thread; +class OnlinePlayer +{ + public: + OnlinePlayer(std::string nick, unsigned char status, + char level, unsigned char gender, char version) : + mNick(nick), + mText(""), + mStatus(status), + mLevel(level), + mVersion(version), + mGender(gender) + { + } + + const std::string getNick() const + { return mNick; } + + unsigned char getStaus() const + { return mStatus; } + + char getVersion() const + { return mVersion; } + + char getLevel() const + { return mLevel; } + + const std::string getText() const + { return mText; } + + void setText(std::string str); + + void setLevel(char level) + { mLevel = level; } + + private: + std::string mNick; + + std::string mText; + + unsigned char mStatus; + + char mLevel; + + char mVersion; + + unsigned char mGender; +}; + /** * Update progress window GUI * @@ -52,7 +100,7 @@ class WhoIsOnline : public Window, public gcn::ActionListener, public ConfigListener { - public: +public: /** * Constructor. */ @@ -68,7 +116,7 @@ class WhoIsOnline : public Window, */ void loadWebList(); - void loadList(std::vector<std::string> &list); + void loadList(std::vector<OnlinePlayer*> &list); void handleLink(const std::string& link, gcn::MouseEvent *event); @@ -78,9 +126,12 @@ class WhoIsOnline : public Window, void widgetResized(const gcn::Event &event); - std::set<std::string> &getOnlinePlayers() + const std::set<OnlinePlayer*> &getOnlinePlayers() { return mOnlinePlayers; } + const std::set<std::string> &getOnlineNicks() + { return mOnlineNicks; } + void setAllowUpdate(bool n) { mAllowUpdate = n; } @@ -109,10 +160,10 @@ private: const std::string prepareNick(std::string nick, int level, std::string color) const; - void updateWindow(std::vector<std::string> &friends, - std::vector<std::string> &neutral, - std::vector<std::string> &disregard, - std::vector<std::string> enemy, + void updateWindow(std::vector<OnlinePlayer*> &friends, + std::vector<OnlinePlayer*> &neutral, + std::vector<OnlinePlayer*> &disregard, + std::vector<OnlinePlayer*> enemy, int numOnline); enum DownloadStatus @@ -143,7 +194,8 @@ private: BrowserBox *mBrowserBox; ScrollArea *mScrollArea; time_t mUpdateTimer; - std::set<std::string> mOnlinePlayers; + std::set<OnlinePlayer*> mOnlinePlayers; + std::set<std::string> mOnlineNicks; gcn::Button *mUpdateButton; bool mAllowUpdate; diff --git a/src/gui/widgets/browserbox.h b/src/gui/widgets/browserbox.h index ab3049c0b..d82ebd758 100644 --- a/src/gui/widgets/browserbox.h +++ b/src/gui/widgets/browserbox.h @@ -187,7 +187,7 @@ class BrowserBox : public gcn::Widget, TextRows &getRows() { return mTextRows; } - bool hasRows() + bool hasRows() const { return !mTextRows.empty(); } void setAlwaysUpdate(bool n) diff --git a/src/gui/widgets/button.h b/src/gui/widgets/button.h index aed46bb55..560e46377 100644 --- a/src/gui/widgets/button.h +++ b/src/gui/widgets/button.h @@ -70,16 +70,16 @@ class Button : public gcn::Button, public gcn::WidgetListener void setDescription(std::string text) { mDescription = text; } - std::string getDescription() + std::string getDescription() const { return mDescription; } - unsigned getClickCount() + unsigned getClickCount() const { return mClickCount; } void setTag(int tag) { mTag = tag; } - int getTag() + int getTag() const { return mTag; } void widgetResized(const gcn::Event &event); diff --git a/src/gui/widgets/channeltab.h b/src/gui/widgets/channeltab.h index 4b56d2e05..39702a696 100644 --- a/src/gui/widgets/channeltab.h +++ b/src/gui/widgets/channeltab.h @@ -34,7 +34,8 @@ class ChannelTab : public ChatTab { public: - Channel *getChannel() const { return mChannel; } + Channel *getChannel() const + { return mChannel; } void showHelp(); diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp index aea367482..6d5dfc9dd 100644 --- a/src/gui/widgets/chattab.cpp +++ b/src/gui/widgets/chattab.cpp @@ -224,9 +224,17 @@ void ChatTab::chatLog(std::string line, Own own, { struct tm *timeInfo; timeInfo = localtime(&t); - line = strprintf("%s[%02d:%02d] %s%s", lineColor.c_str(), - timeInfo->tm_hour, timeInfo->tm_min, tmp.nick.c_str(), - tmp.text.c_str()); + if (timeInfo) + { + line = strprintf("%s[%02d:%02d] %s%s", lineColor.c_str(), + timeInfo->tm_hour, timeInfo->tm_min, tmp.nick.c_str(), + tmp.text.c_str()); + } + else + { + line = strprintf("%s %s%s", lineColor.c_str(), + tmp.nick.c_str(), tmp.text.c_str()); + } } else { diff --git a/src/gui/widgets/chattab.h b/src/gui/widgets/chattab.h index ddf10bf5e..912305a63 100644 --- a/src/gui/widgets/chattab.h +++ b/src/gui/widgets/chattab.h @@ -137,24 +137,24 @@ class ChatTab : public Tab std::list<std::string> &getRows() { return mTextOutput->getRows(); } - bool hasRows() + bool hasRows() const { return mTextOutput->hasRows(); } void loadFromLogFile(std::string name); - bool getAllowHighlight() + bool getAllowHighlight() const { return mAllowHightlight; } void setAllowHighlight(bool n) { mAllowHightlight = n; } - bool getRemoveNames() + bool getRemoveNames() const { return mRemoveNames; } void setRemoveNames(bool n) { mRemoveNames = n; } - bool getNoAway() + bool getNoAway() const { return mNoAway; } void setNoAway(bool n) diff --git a/src/gui/widgets/desktop.cpp b/src/gui/widgets/desktop.cpp index beb232fb2..b40558c78 100644 --- a/src/gui/widgets/desktop.cpp +++ b/src/gui/widgets/desktop.cpp @@ -48,10 +48,14 @@ Desktop::Desktop() : std::string appName = branding.getValue("appName", std::string("")); if (appName.empty()) + { mVersionLabel = new Label(FULL_VERSION); + } else - mVersionLabel = new Label(strprintf("%s (Mana %s)", appName.c_str(), - FULL_VERSION)); + { + mVersionLabel = new Label(strprintf("%s (%s)", FULL_VERSION, + appName.c_str())); + } mVersionLabel->setBackgroundColor( Theme::getThemeColor(Theme::BACKGROUND, 128)); diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp index e8d7bb7e3..794357275 100644 --- a/src/gui/widgets/emoteshortcutcontainer.cpp +++ b/src/gui/widgets/emoteshortcutcontainer.cpp @@ -43,7 +43,7 @@ #include "debug.h" -static const int MAX_ITEMS = 44; +static const int MAX_ITEMS = 48; EmoteShortcutContainer::EmoteShortcutContainer(): ShortcutContainer(), diff --git a/src/gui/widgets/guildchattab.h b/src/gui/widgets/guildchattab.h index bebdaa1f3..be6f4d034 100644 --- a/src/gui/widgets/guildchattab.h +++ b/src/gui/widgets/guildchattab.h @@ -41,7 +41,8 @@ class GuildChatTab : public ChatTab void saveToLogFile(std::string &msg); - int getType() const { return ChatTab::TAB_GUILD; } + int getType() const + { return ChatTab::TAB_GUILD; } protected: void handleInput(const std::string &msg); diff --git a/src/gui/widgets/icon.h b/src/gui/widgets/icon.h index 6f05da3f7..98fee314a 100644 --- a/src/gui/widgets/icon.h +++ b/src/gui/widgets/icon.h @@ -48,7 +48,8 @@ class Icon : public gcn::Widget /** * Gets the current Image. */ - Image *getImage() const { return mImage; } + Image *getImage() const + { return mImage; } /** * Sets the image to display. diff --git a/src/gui/widgets/layout.h b/src/gui/widgets/layout.h index 02fed43b5..046d09b59 100644 --- a/src/gui/widgets/layout.h +++ b/src/gui/widgets/layout.h @@ -266,10 +266,10 @@ class LayoutCell void setType(int t) { mType = t; } - int getWidth() + int getWidth() const { return mExtent[0]; } - int getHeight() + int getHeight() const { return mExtent[1]; } void setWidth(int w) diff --git a/src/gui/widgets/popup.h b/src/gui/widgets/popup.h index 8ff21149a..5572abd03 100644 --- a/src/gui/widgets/popup.h +++ b/src/gui/widgets/popup.h @@ -94,28 +94,32 @@ class Popup : public Container, public gcn::MouseListener, */ void setMinWidth(int width); - int getMinWidth() const { return mMinWidth; } + int getMinWidth() const + { return mMinWidth; } /** * Sets the minimum height of the popup. */ void setMinHeight(int height); - int getMinHeight() const { return mMinHeight; } + int getMinHeight() const + { return mMinHeight; } /** * Sets the maximum width of the popup. */ void setMaxWidth(int width); - int getMaxWidth() const { return mMaxWidth; } + int getMaxWidth() const + { return mMaxWidth; } /** * Sets the minimum height of the popup. */ void setMaxHeight(int height); - int getMaxHeight() const { return mMaxHeight; } + int getMaxHeight() const + { return mMaxHeight; } /** * Gets the padding of the popup. The padding is the distance between @@ -124,9 +128,11 @@ class Popup : public Container, public gcn::MouseListener, * @return The padding of the popup. * @see setPadding */ - int getPadding() const { return mPadding; } + int getPadding() const + { return mPadding; } - void setPadding(int padding) { mPadding = padding; } + void setPadding(int padding) + { mPadding = padding; } /** * Sets the name of the popup. This is only useful for debug purposes. diff --git a/src/gui/widgets/progressbar.h b/src/gui/widgets/progressbar.h index 163310245..603df6157 100644 --- a/src/gui/widgets/progressbar.h +++ b/src/gui/widgets/progressbar.h @@ -73,7 +73,8 @@ class ProgressBar : public gcn::Widget, public gcn::WidgetListener /** * Returns the current progress. */ - float getProgress() const { return mProgress; } + float getProgress() const + { return mProgress; } /** * Change the ProgressPalette for this ProgressBar to follow or -1 to @@ -89,7 +90,8 @@ class ProgressBar : public gcn::Widget, public gcn::WidgetListener /** * Returns the color of the progress bar. */ - const gcn::Color &getColor() const { return mColor; } + const gcn::Color &getColor() const + { return mColor; } /** * Sets the text shown on the progress bar. diff --git a/src/gui/widgets/scrollarea.h b/src/gui/widgets/scrollarea.h index 86902b5c9..582033071 100644 --- a/src/gui/widgets/scrollarea.h +++ b/src/gui/widgets/scrollarea.h @@ -89,7 +89,8 @@ class ScrollArea : public gcn::ScrollArea, public gcn::WidgetListener /** * Returns whether the widget draws its background or not. */ - bool isOpaque() const { return mOpaque; } + bool isOpaque() const + { return mOpaque; } /** * Called when the mouse moves in the widget area. diff --git a/src/gui/widgets/setupitem.cpp b/src/gui/widgets/setupitem.cpp index 92ff625c2..059b05ba2 100644 --- a/src/gui/widgets/setupitem.cpp +++ b/src/gui/widgets/setupitem.cpp @@ -192,7 +192,7 @@ void SetupItemCheckBox::createControls() load(); mCheckBox = new CheckBox(mText, mValue != "0", mParent, mEventName); mWidget = mCheckBox; - mParent->getContainer()->add(mWidget); + mParent->getContainer()->add1(mWidget); mParent->addControl(this); mParent->addActionListener(this); mWidget->addActionListener(this); @@ -275,7 +275,7 @@ void SetupItemTextField::createControls() mHorizont->add(mTextField); mHorizont->add(mButton); - mParent->getContainer()->add(mHorizont, true, 4); + mParent->getContainer()->add2(mHorizont, true, 4); mParent->addControl(this); mParent->addControl(this, mEventName + "_EDIT"); mParent->addControl(this, mEventName + "_EDIT_OK"); @@ -398,7 +398,7 @@ void SetupItemIntTextField::createControls() mHorizont->add(mTextField); mHorizont->add(mButton); - mParent->getContainer()->add(mHorizont, true, 4); + mParent->getContainer()->add2(mHorizont, true, 4); mParent->addControl(this); mParent->addControl(this, mEventName + "_EDIT"); mParent->addControl(this, mEventName + "_EDIT_OK"); @@ -486,7 +486,7 @@ void SetupItemLabel::createControls() } mWidget = mLabel; - mParent->getContainer()->add(mWidget); + mParent->getContainer()->add1(mWidget); mParent->addControl(this); mParent->addActionListener(this); mWidget->addActionListener(this); @@ -568,7 +568,7 @@ void SetupItemDropDown::createControls() mHorizont->add(mLabel); mHorizont->add(mDropDown); - mParent->getContainer()->add(mHorizont, true, 4); + mParent->getContainer()->add2(mHorizont, true, 4); mParent->addControl(this); mParent->addActionListener(this); mWidget->addActionListener(this); diff --git a/src/gui/widgets/setupitem.h b/src/gui/widgets/setupitem.h index eb2680ede..71856d6e2 100644 --- a/src/gui/widgets/setupitem.h +++ b/src/gui/widgets/setupitem.h @@ -75,7 +75,7 @@ class SetupItem : public gcn::ActionListener void setWidget(gcn::Widget *widget) { mWidget = widget; } - gcn::Widget *getWidget() + gcn::Widget *getWidget() const { return mWidget; } Configuration *getConfig(); @@ -93,7 +93,7 @@ class SetupItem : public gcn::ActionListener virtual void externalUpdated(std::string eventName); // virtual int add(ContainerPlacer &place, int x, int y, int width); - bool isMainConfig() + bool isMainConfig() const { return mMainConfig; } protected: diff --git a/src/gui/widgets/setuptabscroll.h b/src/gui/widgets/setuptabscroll.h index 4ad1f464b..d471ecfbc 100644 --- a/src/gui/widgets/setuptabscroll.h +++ b/src/gui/widgets/setuptabscroll.h @@ -43,7 +43,7 @@ class SetupTabScroll : public SetupTab void addControl(SetupItem *widget, std::string event); - VertContainer *getContainer() + VertContainer *getContainer() const { return mContainer; } virtual void apply(); diff --git a/src/gui/widgets/shoplistbox.h b/src/gui/widgets/shoplistbox.h index 9b416d3a3..694fdb92e 100644 --- a/src/gui/widgets/shoplistbox.h +++ b/src/gui/widgets/shoplistbox.h @@ -56,7 +56,8 @@ class ShopListBox : public ListBox /** * Returns the height of a row. */ - unsigned int getRowHeight() const { return mRowHeight; } + unsigned int getRowHeight() const + { return mRowHeight; } /** * gives information about the current player's money diff --git a/src/gui/widgets/tab.h b/src/gui/widgets/tab.h index 40b46ede5..829689543 100644 --- a/src/gui/widgets/tab.h +++ b/src/gui/widgets/tab.h @@ -61,7 +61,7 @@ class Tab : public gcn::Tab, public gcn::WidgetListener */ void setFlash(int flash); - int getFlash() + int getFlash() const { return mFlash; } void widgetResized(const gcn::Event &event); @@ -70,7 +70,7 @@ class Tab : public gcn::Tab, public gcn::WidgetListener void setLabelFont(gcn::Font *font); - gcn::Label *getLabel() + gcn::Label *getLabel() const { return mLabel; } protected: diff --git a/src/gui/widgets/tabbedarea.h b/src/gui/widgets/tabbedarea.h index b202dfc9d..cceaf56b7 100644 --- a/src/gui/widgets/tabbedarea.h +++ b/src/gui/widgets/tabbedarea.h @@ -136,13 +136,13 @@ class TabbedArea : public gcn::TabbedArea, public gcn::WidgetListener void setRightMargin(int n) { mRightMargin = n; } - int getRightMargin() + int getRightMargin() const { return mRightMargin; } void setFollowDownScroll(bool n) { mFollowDownScroll = n; } - bool getFollowDownScroll() + bool getFollowDownScroll() const { return mFollowDownScroll; } void fixSize() diff --git a/src/gui/widgets/textbox.h b/src/gui/widgets/textbox.h index 6d2467b38..a052247c4 100644 --- a/src/gui/widgets/textbox.h +++ b/src/gui/widgets/textbox.h @@ -59,7 +59,8 @@ class TextBox : public gcn::TextBox */ inline void draw(gcn::Graphics *graphics) { - setForegroundColor(*mTextColor); + if (mTextColor) + setForegroundColor(*mTextColor); gcn::TextBox::draw(graphics); } diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index 03fdb5378..4dba2eb57 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -183,7 +183,7 @@ int TextField::getValue() const if (value < mMinimum) return mMinimum; - if (value > mMaximum) + if (value > (signed)mMaximum) return mMaximum; return value; @@ -195,29 +195,43 @@ void TextField::keyPressed(gcn::KeyEvent &keyEvent) if (val >= 32) { - int l; - if (val < 128) - l = 1; // 0xxxxxxx - else if (val < 0x800) - l = 2; // 110xxxxx 10xxxxxx - else if (val < 0x10000) - l = 3; // 1110xxxx 10xxxxxx 10xxxxxx - else - l = 4; // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - - char buf[4]; - for (int i = 0; i < l; ++i) + if (mNumeric) { - buf[i] = static_cast<char>(val >> (6 * (l - i - 1))); - if (i > 0) - buf[i] = static_cast<char>((buf[i] & 63) | 128); + if ((val >= '0' && val <= '9') || (val == '-' && !mCaretPosition)) + { + char buf[2]; + buf[0] = val; + buf[1] = 0; + mText.insert(mCaretPosition, std::string(buf)); + mCaretPosition += 1; + } } + else if (!mMaximum || mText.size() < mMaximum) + { + int l; + if (val < 128) + l = 1; // 0xxxxxxx + else if (val < 0x800) + l = 2; // 110xxxxx 10xxxxxx + else if (val < 0x10000) + l = 3; // 1110xxxx 10xxxxxx 10xxxxxx + else + l = 4; // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx + + char buf[4]; + for (int i = 0; i < l; ++i) + { + buf[i] = static_cast<char>(val >> (6 * (l - i - 1))); + if (i > 0) + buf[i] = static_cast<char>((buf[i] & 63) | 128); + } - if (l > 1) - buf[0] |= static_cast<char>(255 << (8 - l)); + if (l > 1) + buf[0] |= static_cast<char>(255 << (8 - l)); - mText.insert(mCaretPosition, std::string(buf, buf + l)); - mCaretPosition += l; + mText.insert(mCaretPosition, std::string(buf, buf + l)); + mCaretPosition += l; + } } /* In UTF-8, 10xxxxxx is only used for inner parts of characters. So skip diff --git a/src/gui/widgets/textfield.h b/src/gui/widgets/textfield.h index bc1123f19..fef606526 100644 --- a/src/gui/widgets/textfield.h +++ b/src/gui/widgets/textfield.h @@ -114,7 +114,7 @@ class TextField : public gcn::TextField static ImageRect skin; bool mNumeric; int mMinimum; - int mMaximum; + unsigned mMaximum; bool mLoseFocusOnTab; int mLastEventPaste; }; diff --git a/src/gui/widgets/vertcontainer.cpp b/src/gui/widgets/vertcontainer.cpp index 305343d1a..0eb59c8f9 100644 --- a/src/gui/widgets/vertcontainer.cpp +++ b/src/gui/widgets/vertcontainer.cpp @@ -35,12 +35,12 @@ VertContainer::VertContainer(int verticalItemSize, bool resizable, addWidgetListener(this); } -void VertContainer::add(gcn::Widget *widget, int spacing) +void VertContainer::add1(gcn::Widget *widget, int spacing) { - add(widget, mResizable, spacing); + add2(widget, mResizable, spacing); } -void VertContainer::add(gcn::Widget *widget, bool resizable, int spacing) +void VertContainer::add2(gcn::Widget *widget, bool resizable, int spacing) { if (!widget) return; @@ -70,6 +70,7 @@ void VertContainer::clear() mCount = 0; mNextY = 0; + mResizableWidgets.clear(); } void VertContainer::widgetResized(const gcn::Event &event A_UNUSED) diff --git a/src/gui/widgets/vertcontainer.h b/src/gui/widgets/vertcontainer.h index 6e1305a06..b4e43d31d 100644 --- a/src/gui/widgets/vertcontainer.h +++ b/src/gui/widgets/vertcontainer.h @@ -39,10 +39,10 @@ class VertContainer : public Container, public gcn::WidgetListener VertContainer(int verticalItemSize, bool resizable = true, int leftSpacing = 0); - virtual void add(gcn::Widget *widget, bool resizable, - int spacing = -1); + virtual void add2(gcn::Widget *widget, bool resizable, + int spacing = -1); - virtual void add(gcn::Widget *widget, int spacing = -1); + virtual void add1(gcn::Widget *widget, int spacing = -1); virtual void clear(); diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 3858b0d81..6e6918694 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -433,7 +433,7 @@ void Window::setVisible(bool visible, bool forceSticky) // Check if the window is off screen... if (visible) - checkIfIsOffScreen(); + ensureOnScreen(); if (isStickyButtonLock()) gcn::Window::setVisible(visible); @@ -713,7 +713,7 @@ void Window::loadWindowState() } // Check if the window is off screen... - checkIfIsOffScreen(); + ensureOnScreen(); if (viewport) { @@ -848,6 +848,22 @@ void Window::resetToDefaultSize() saveWindowState(); } +void Window::adjustPositionAfterResize(int oldScreenWidth, int oldScreenHeight) +{ + gcn::Rectangle dimension = getDimension(); + + // If window was aligned to the right or bottom, keep it there + const int rightMargin = oldScreenWidth - (getX() + getWidth()); + const int bottomMargin = oldScreenHeight - (getY() + getHeight()); + if (getX() > 0 && getX() > rightMargin) + dimension.x = mainGraphics->mWidth - rightMargin - getWidth(); + if (getY() > 0 && getY() > bottomMargin) + dimension.y = mainGraphics->mHeight - bottomMargin - getHeight(); + + setDimension(dimension); + ensureOnScreen(); +} + int Window::getResizeHandles(gcn::MouseEvent &event) { if ((mStickyButtonLock && mSticky) || event.getX() < 0 || event.getY() < 0) @@ -972,57 +988,27 @@ void Window::centerHorisontally() setLocationHorisontallyRelativeTo(getParent()); } -void Window::checkIfIsOffScreen(bool partially, bool entirely) +void Window::ensureOnScreen() { - // Move the window onto screen if it has become off screen - // For instance, because of resolution change... - - // First of all, don't deal when a window hasn't got - // any size initialized yet... + // Skip when a window hasn't got any size initialized yet if (getWidth() == 0 && getHeight() == 0) return; - // Made partially the default behaviour - if (!partially && !entirely) - partially = true; - - // Keep guichan window inside screen (supports resizing any side) - - gcn::Rectangle winDimension = getDimension(); - - if (winDimension.x < 0) - { - winDimension.width += winDimension.x; - winDimension.x = 0; - } - if (winDimension.y < 0) - { - winDimension.height += winDimension.y; - winDimension.y = 0; - } - - // Look if the window is partially off-screen limits... - if (partially) - { - if (winDimension.x + winDimension.width > mainGraphics->mWidth) - winDimension.x = mainGraphics->mWidth - winDimension.width; - - if (winDimension.y + winDimension.height > mainGraphics->mHeight) - winDimension.y = mainGraphics->mHeight - winDimension.height; + gcn::Rectangle dimension = getDimension(); - setDimension(winDimension); - return; - } + // Check the left and bottom screen boundaries + if (dimension.x + dimension.width > mainGraphics->mWidth) + dimension.x = mainGraphics->mWidth - dimension.width; + if (dimension.y + dimension.height > mainGraphics->mHeight) + dimension.y = mainGraphics->mHeight - dimension.height; - if (entirely) - { - if (winDimension.x > mainGraphics->mWidth) - winDimension.x = mainGraphics->mWidth - winDimension.width; + // But never allow the windows to disappear in to the right and top + if (dimension.x < 0) + dimension.x = 0; + if (dimension.y < 0) + dimension.y = 0; - if (winDimension.y > mainGraphics->mHeight) - winDimension.y = mainGraphics->mHeight - winDimension.height; - } - setDimension(winDimension); + setDimension(dimension); } gcn::Rectangle Window::getWindowArea() diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h index 65dbf196b..6fa47dedc 100644 --- a/src/gui/widgets/window.h +++ b/src/gui/widgets/window.h @@ -329,6 +329,13 @@ class Window : public gcn::Window, gcn::WidgetListener virtual void resetToDefaultSize(); /** + * Adjusts the window position after the application window has been + * resized. + */ + void adjustPositionAfterResize(int oldScreenWidth, + int oldScreenHeight); + + /** * Gets the layout handler for this window. */ Layout &getLayout(); @@ -406,11 +413,11 @@ class Window : public gcn::Window, gcn::WidgetListener }; /** - * Check if the window is off-screen and then move it to be visible - * again. This is internally used by loadWindowState - * and setVisible(true) members. + * Ensures the window is on the screen, moving it if necessary. This is + * used by loadWindowState and setVisible(true), and when the screen + * is resized. */ - void checkIfIsOffScreen(bool partially = true, bool entirely = true); + void ensureOnScreen(); /** * Determines if the mouse is in a resize area and returns appropriate diff --git a/src/gui/widgets/windowcontainer.cpp b/src/gui/widgets/windowcontainer.cpp index 43aaea8a4..9e698ffa6 100644 --- a/src/gui/widgets/windowcontainer.cpp +++ b/src/gui/widgets/windowcontainer.cpp @@ -22,6 +22,8 @@ #include "gui/widgets/windowcontainer.h" +#include "gui/widgets/window.h" + #include "utils/dtor.h" #include "debug.h" @@ -41,3 +43,13 @@ void WindowContainer::scheduleDelete(gcn::Widget *widget) if (widget) mDeathList.push_back(widget); } + +void WindowContainer::adjustAfterResize(int oldScreenWidth, + int oldScreenHeight) +{ + for (WidgetListIterator i = mWidgets.begin(); i != mWidgets.end(); ++i) + { + if (Window *window = dynamic_cast<Window*>(*i)) + window->adjustPositionAfterResize(oldScreenWidth, oldScreenHeight); + } +} diff --git a/src/gui/widgets/windowcontainer.h b/src/gui/widgets/windowcontainer.h index 00ef04c19..1cec11861 100644 --- a/src/gui/widgets/windowcontainer.h +++ b/src/gui/widgets/windowcontainer.h @@ -48,6 +48,12 @@ class WindowContainer : public Container */ void scheduleDelete(gcn::Widget *widget); + /** + * Ensures that all visible windows are on the screen after the screen + * has been resized. + */ + void adjustAfterResize(int oldScreenWidth, int oldScreenHeight); + private: /** * List of widgets that are scheduled to be deleted. diff --git a/src/gui/windowmenu.cpp b/src/gui/windowmenu.cpp index e954340f8..138090075 100644 --- a/src/gui/windowmenu.cpp +++ b/src/gui/windowmenu.cpp @@ -299,7 +299,7 @@ void WindowMenu::mouseMoved(gcn::MouseEvent &event) if (key != KeyboardConfig::KEY_NO_VALUE) { mTextPopup->show(x + getX(), y + getY(), btn->getDescription(), - "Key: " + keyboard.getKeyValueString(key)); + strprintf(_("Key: %s"), keyboard.getKeyValueString(key).c_str())); } else { diff --git a/src/guild.cpp b/src/guild.cpp index e569bed65..238155d32 100644 --- a/src/guild.cpp +++ b/src/guild.cpp @@ -166,6 +166,8 @@ void Guild::removeMember(GuildMember *member) itr_end = mMembers.end(); while (itr != itr_end) { + if (!*itr) + continue; if ((*itr)->mId == member->mId && (*itr)->mCharId == member->mCharId && (*itr)->getName() == member->getName()) @@ -175,7 +177,7 @@ void Guild::removeMember(GuildMember *member) delete m; return; } - ++itr; + ++ itr; } } @@ -255,6 +257,9 @@ void Guild::setRights(short rights) bool Guild::isMember(GuildMember *member) const { + if (!member) + return false; + if (member->mGuild && member->mGuild != this) return false; diff --git a/src/guild.h b/src/guild.h index e95677ec6..8715c2907 100644 --- a/src/guild.h +++ b/src/guild.h @@ -43,7 +43,7 @@ public: Guild *getGuild() const { return mGuild; } - int getPos() + int getPos() const { return mPos; } void setPos(int pos) diff --git a/src/guildmanager.h b/src/guildmanager.h index 368b2456c..b415d85e8 100644 --- a/src/guildmanager.h +++ b/src/guildmanager.h @@ -74,7 +74,7 @@ class GuildManager bool afterRemove(); - bool havePower() + bool havePower() const { return mHavePower; } private: diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index 0079ee2ee..ea04a0e89 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -267,6 +267,14 @@ static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = { KeyboardConfig::GRP_EMOTION}, {"keyEmoteShortcut44", SDLK_b, strprintf(N_("Emote Shortcut %d"), 44), KeyboardConfig::GRP_EMOTION}, + {"keyEmoteShortcut45", SDLK_n, strprintf(N_("Emote Shortcut %d"), 45), + KeyboardConfig::GRP_EMOTION}, + {"keyEmoteShortcut46", SDLK_m, strprintf(N_("Emote Shortcut %d"), 46), + KeyboardConfig::GRP_EMOTION}, + {"keyEmoteShortcut47", SDLK_COMMA, strprintf(N_("Emote Shortcut %d"), 47), + KeyboardConfig::GRP_EMOTION}, + {"keyEmoteShortcut48", SDLK_PERIOD, strprintf(N_("Emote Shortcut %d"), 48), + KeyboardConfig::GRP_EMOTION}, {"", 0, N_("Outfits Keys"), 0}, {"keyWearOutfit", SDLK_RCTRL, N_("Wear Outfit"), KeyboardConfig::GRP_DEFAULT}, @@ -360,7 +368,7 @@ void KeyboardConfig::init() mKey[i].value = KEY_NO_VALUE; mKey[i].grp = keyData[i].grp; } - for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_44; i ++) + for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_48; i ++) { mKey[i].caption = strprintf( _("Emote Shortcut %d"), i - KEY_EMOTE_1 + 1); @@ -460,7 +468,7 @@ int KeyboardConfig::getKeyIndex(int keyValue, int grp) const int KeyboardConfig::getKeyEmoteOffset(int keyValue) const { - for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_44; i++) + for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_48; i++) { if (keyValue == mKey[i].value) return 1 + i - KEY_EMOTE_1; @@ -468,7 +476,7 @@ int KeyboardConfig::getKeyEmoteOffset(int keyValue) const return 0; } -bool KeyboardConfig::isKeyActive(int index) const +bool KeyboardConfig::isActionActive(int index) const { if (!mActiveKeys) return false; diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h index 45c5ba65f..1610c1ecd 100644 --- a/src/keyboardconfig.h +++ b/src/keyboardconfig.h @@ -136,7 +136,7 @@ class KeyboardConfig /** * Checks if the key is active, by providing the key function index. */ - bool isKeyActive(int index) const; + bool isActionActive(int index) const; /** * Takes a snapshot of all the active keys. @@ -278,6 +278,10 @@ class KeyboardConfig KEY_EMOTE_42, KEY_EMOTE_43, KEY_EMOTE_44, + KEY_EMOTE_45, + KEY_EMOTE_46, + KEY_EMOTE_47, + KEY_EMOTE_48, KEY_SEPARATOR5, KEY_WEAR_OUTFIT, KEY_COPY_OUTFIT, diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 0da291711..27897a486 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -354,7 +354,8 @@ void LocalPlayer::logic() } } - if (mEnableAdvert && !mBlockAdvert && mAdvertTime < cur_time) + if (serverVersion < 4 && mEnableAdvert && !mBlockAdvert + && mAdvertTime < cur_time) { Uint8 smile = FLAG_SPECIAL; if (mTradebot && shopWindow && !shopWindow->isShopEmpty()) @@ -1782,7 +1783,7 @@ void LocalPlayer::moveToTarget(unsigned int dist) case 6: case 7: dist = mAttackRange; - if (dist == 1) + if (dist == 1 && serverVersion < 1) dist = 2; default: break; @@ -1874,6 +1875,9 @@ void LocalPlayer::changeMode(unsigned *var, unsigned limit, const char *conf, std::string (LocalPlayer::*func)(), unsigned def, bool save) { + if (!var) + return; + (*var) ++; if (*var >= limit) *var = def; @@ -3442,6 +3446,7 @@ void LocalPlayer::setAway(const std::string &message) if (!message.empty()) config.setValue("afkMessage", message); changeAwayMode(); + updateStatus(); } void LocalPlayer::setPseudoAway(const std::string &message) @@ -3716,7 +3721,8 @@ void LocalPlayer::attack2(Being *target, bool keep, bool dontChangeEquipment) changeEquipmentBeforeAttack(target); if ((!target || getAttackType() == 0 || getAttackType() == 3) - || (withinAttackRange(target, true, 1) + || (withinAttackRange(target, serverVersion < 1, + serverVersion < 1 ? 1 : 0) && getPathLength(target) <= getAttackRange2())) { attack(target, keep); @@ -4206,11 +4212,30 @@ const char *LocalPlayer::getVarItem(const char **arr, unsigned index, return arr[sz]; } +void LocalPlayer::updateStatus() +{ + if (serverVersion >= 4 && mEnableAdvert) + { + Uint8 status = 0; + if (mTradebot && shopWindow && !shopWindow->isShopEmpty()) + status += FLAG_SHOP; + + if (mAwayMode || mPseudoAwayMode) + status += FLAG_AWAY; + + if (mInactive) + status += FLAG_INACTIVE; + + Net::getPlayerHandler()->updateStatus(status); + } +} + void AwayListener::action(const gcn::ActionEvent &event) { if (event.getId() == "ok" && player_node && player_node->getAway()) { player_node->changeAwayMode(); + player_node->updateStatus(); if (outfitWindow) outfitWindow->unwearAwayOutfit(); if (miniStatusWindow) diff --git a/src/localplayer.h b/src/localplayer.h index ed181e3d0..a7ce3dd7f 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -139,7 +139,7 @@ class LocalPlayer : public Being, public ActorSpriteListener, void setGMLevel(int level); - int getGMLevel() + int getGMLevel() const { return mGMLevel; } void stopAttack(); @@ -217,7 +217,7 @@ class LocalPlayer : public Being, public ActorSpriteListener, bool isPathSetByMouse() const { return mPathSetByMouse; } - int getInvertDirection() + int getInvertDirection() const { return mInvertDirection; } void setInvertDirection(int n) @@ -225,16 +225,16 @@ class LocalPlayer : public Being, public ActorSpriteListener, void invertDirection(); - int getAttackWeaponType() + int getAttackWeaponType() const { return mAttackWeaponType; } - int getAttackType() + int getAttackType() const { return mAttackType; } - int getFollowMode() + int getFollowMode() const { return mFollowMode; } - int getImitationMode() + int getImitationMode() const { return mImitationMode; } void changeAttackWeaponType(); @@ -247,41 +247,41 @@ class LocalPlayer : public Being, public ActorSpriteListener, void changePickUpType(); - int getCrazyMoveType() - { return mCrazyMoveType ; } + int getCrazyMoveType() const + { return mCrazyMoveType; } - int getPickUpType() - { return mPickUpType ; } + int getPickUpType() const + { return mPickUpType; } - int getQuickDropCounter() - { return mQuickDropCounter ; } + int getQuickDropCounter() const + { return mQuickDropCounter; } void changeQuickDropCounter(); - int getMoveState() - { return mMoveState ; } + int getMoveState() const + { return mMoveState; } void setMoveState(int n) - { mMoveState = n ; } + { mMoveState = n; } void switchMagicAttack(); void switchPvpAttack(); - int getMagicAttackType() - { return mMagicAttackType ; } + int getMagicAttackType() const + { return mMagicAttackType; } - int getPvpAttackType() - { return mPvpAttackType ; } + int getPvpAttackType() const + { return mPvpAttackType; } - int getMoveToTargetType() - { return mMoveToTargetType ; } + int getMoveToTargetType() const + { return mMoveToTargetType; } - int getDisableGameModifiers() - { return mDisableGameModifiers ; } + int getDisableGameModifiers() const + { return mDisableGameModifiers; } - int getPingTime() - { return mPingTime ; } + int getPingTime() const + { return mPingTime; } void tryPingRequest(); @@ -329,16 +329,16 @@ class LocalPlayer : public Being, public ActorSpriteListener, void setPseudoAway(const std::string &message); - bool getAway() + bool getAway() const { return mAwayMode; } - bool getPseudoAway() + bool getPseudoAway() const { return mPseudoAwayMode; } void setHalfAway(bool n) { mInactive = n; } - bool getHalfAway() + bool getHalfAway() const { return mInactive; } void afkRespond(ChatTab *tab, const std::string &nick); @@ -369,7 +369,7 @@ class LocalPlayer : public Being, public ActorSpriteListener, void setRealPos(int x, int y); - bool isServerBuggy() + bool isServerBuggy() const { return mIsServerBuggy; } void fixPos(int maxDist = 1); @@ -413,7 +413,7 @@ class LocalPlayer : public Being, public ActorSpriteListener, void respawn(); - FloorItem *getPickUpTarget() + FloorItem *getPickUpTarget() const { return mPickUpTarget; } void unSetPickUpTarget() @@ -477,6 +477,8 @@ class LocalPlayer : public Being, public ActorSpriteListener, bool checAttackPermissions(Being *target); + void updateStatus(); + std::string getInvertDirectionString(); std::string getCrazyMoveTypeString(); diff --git a/src/main.h b/src/main.h index 541296d22..fbc672939 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.2.1.22" -#define CHECK_VERSION "01.02.01.22" +#define SMALL_VERSION "1.2.2.5" +#define CHECK_VERSION "01.02.02.05" #ifdef HAVE_CONFIG_H #include "../config.h" diff --git a/src/manaplus.rc b/src/manaplus.rc index b7720e2cc..b16ca40a7 100644 --- a/src/manaplus.rc +++ b/src/manaplus.rc @@ -3,6 +3,7 @@ #include "winver.h" A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "../data/icons/manaplus.ico" +evol ICON MOVEABLE PURE LOADONCALL DISCARDABLE "../data/evol/icons/evol-client.ico" 1 VERSIONINFO FILEVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD @@ -11,10 +12,10 @@ PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD { BLOCK "StringFileInfo" { BLOCK "040904E4" { - VALUE "CompanyName", "The Mana Development Team" + VALUE "CompanyName", "The ManaPlus Development Team" VALUE "FileVersion", PACKAGE_VERSION "4144" VALUE "FileDescription", "ManaPlus" - VALUE "LegalCopyright", "2004-2010 (C)" + VALUE "LegalCopyright", "2004-2012 (C)" VALUE "OriginalFilename", "manaplus.exe" VALUE "ProductName", "ManaPlus MMORPG Client" VALUE "ProductVersion", PACKAGE_VERSION "4144" diff --git a/src/map.cpp b/src/map.cpp index 211504504..488fb16e9 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -156,7 +156,7 @@ void MapLayer::optionChanged(const std::string &value) void MapLayer::setTile(int x, int y, Image *img) { - setTile(x + y * mWidth, img); + mTiles[x + y * mWidth] = img; } void MapLayer::draw(Graphics *graphics, int startX, int startY, @@ -1383,9 +1383,6 @@ Path Map::findPath(int startX, int startY, int destX, int destY, if (startX >= mWidth || startY >= mHeight) return path; - // Declare open list, a list with open tiles sorted on F cost - std::priority_queue<Location> openList; - // Return when destination not walkable if (!getWalk(destX, destY, walkmask)) return path; @@ -1397,6 +1394,9 @@ Path Map::findPath(int startX, int startY, int destX, int destY, startTile->Gcost = 0; + // Declare open list, a list with open tiles sorted on F cost + std::priority_queue<Location> openList; + // Add the start point to the open list openList.push(Location(startX, startY, startTile)); @@ -1796,6 +1796,9 @@ MapItem *Map::findPortalXY(int x, int y) for (it = mMapPortals.begin(), it_end = mMapPortals.end(); it != it_end; ++it) { + if (!*it) + continue; + MapItem *item = *it; if (item->mX == x && item->mY == y) return item; @@ -152,7 +152,8 @@ class MapLayer: public ConfigListener /** * Set tile image with x + y * width already known. */ - void setTile(int index, Image *img) { mTiles[index] = img; } + void setTile(int index, Image *img) + { mTiles[index] = img; } /** * Draws this layer to the given graphics context. The coordinates are @@ -191,7 +192,7 @@ class MapLayer: public ConfigListener const Actors *actors, int mDebugFlags, int yFix) const; - bool isFringeLayer() + bool isFringeLayer() const { return mIsFringeLayer; } void setSpecialLayer(SpecialLayer *val) @@ -200,10 +201,10 @@ class MapLayer: public ConfigListener void setTempLayer(SpecialLayer *val) { mTempLayer = val; } - int getWidth() + int getWidth() const { return mWidth; } - int getHeight() + int getHeight() const { return mHeight; } // void setTileInfo(int x, int y, int width, int cnt); @@ -355,12 +356,14 @@ class Map : public Properties, public ConfigListener /** * Returns the width of this map in tiles. */ - int getWidth() const { return mWidth; } + int getWidth() const + { return mWidth; } /** * Returns the height of this map in tiles. */ - int getHeight() const { return mHeight; } + int getHeight() const + { return mHeight; } /** * Returns the tile width of this map. @@ -375,6 +378,7 @@ class Map : public Properties, public ConfigListener { return mTileHeight; } const std::string getMusicFile() const; + const std::string getName() const; /** @@ -434,16 +438,16 @@ class Map : public Properties, public ConfigListener void saveExtraLayer(); - SpecialLayer *getTempLayer() + SpecialLayer *getTempLayer() const { return mTempLayer; } - SpecialLayer *getSpecialLayer() + SpecialLayer *getSpecialLayer() const { return mSpecialLayer; } void setHasWarps(bool n) { mHasWarps = n; } - bool getHasWarps() + bool getHasWarps() const { return mHasWarps; } std::string getUserMapDirectory() const; @@ -476,7 +480,7 @@ class Map : public Properties, public ConfigListener void setPvpMode(int mode); - ObjectsLayer* getObjectsLayer() + ObjectsLayer* getObjectsLayer() const { return mObjects; } std::string getObjectData(unsigned x, unsigned y, int type); @@ -488,7 +492,7 @@ class Map : public Properties, public ConfigListener void setActorsFix(int x, int y) { mActorFixX = x; mActorFixY = y; } - int getVersion() + int getVersion() const { return mVersion; } void setVersion(int n) @@ -498,7 +502,7 @@ class Map : public Properties, public ConfigListener void redrawMap(); - bool empty() + bool empty() const { return mLayers.empty(); } protected: diff --git a/src/mumblemanager.cpp b/src/mumblemanager.cpp index 766f4085e..100b600b4 100644 --- a/src/mumblemanager.cpp +++ b/src/mumblemanager.cpp @@ -1,5 +1,10 @@ /* - *Code taken from: http://mumble.sourceforge.net/Link + * Code taken from: http://mumble.sourceforge.net/Link + * + * All code listed below is in the public domain and can be used, shared or + * modified freely + * + * Copyright (C) 2011-2012 The ManaPlus Developers */ #include "mumblemanager.h" @@ -78,7 +83,6 @@ void MumbleManager::init() #if defined BSD4_4 return; #endif - if (mLinkedMem || !config.getBoolValue("enableMumble")) return; diff --git a/src/mumblemanager.h b/src/mumblemanager.h index f7617233f..480bacfab 100644 --- a/src/mumblemanager.h +++ b/src/mumblemanager.h @@ -1,5 +1,10 @@ /* - * Code taken from: http://mumble.sourceforge.net/Link + * Code taken from: http://mumble.sourceforge.net/Link + * + * All code listed below is in the public domain and can be used, shared or + * modified freely + * + * Copyright (C) 2011-2012 The ManaPlus Developers */ #ifndef MUMBLEMANAGER_H diff --git a/src/net/adminhandler.h b/src/net/adminhandler.h index f6d8606ce..2ac462834 100644 --- a/src/net/adminhandler.h +++ b/src/net/adminhandler.h @@ -42,15 +42,15 @@ class AdminHandler virtual void kick(int playerId) = 0; - virtual void kick(const std::string &name) = 0; + virtual void kickName(const std::string &name) = 0; virtual void ban(int playerId) = 0; - virtual void ban(const std::string &name) = 0; + virtual void banName(const std::string &name) = 0; virtual void unban(int playerId) = 0; - virtual void unban(const std::string &name) = 0; + virtual void unbanName(const std::string &name) = 0; virtual void mute(int playerId, int type, int limit) = 0; diff --git a/src/net/download.cpp b/src/net/download.cpp index 22af389f3..d20713dfa 100644 --- a/src/net/download.cpp +++ b/src/net/download.cpp @@ -239,7 +239,7 @@ int Download::downloadThread(void *ptr) curl_easy_setopt(d->mCurl, CURLOPT_USERAGENT, strprintf(PACKAGE_EXTENDED_VERSION, - branding.getStringValue("appShort").c_str()).c_str()); + branding.getStringValue("appName").c_str()).c_str()); curl_easy_setopt(d->mCurl, CURLOPT_ERRORBUFFER, d->mError); curl_easy_setopt(d->mCurl, CURLOPT_URL, d->mUrl.c_str()); curl_easy_setopt(d->mCurl, CURLOPT_NOPROGRESS, 0); diff --git a/src/net/ea/adminhandler.cpp b/src/net/ea/adminhandler.cpp index 556629458..f70be3cc8 100644 --- a/src/net/ea/adminhandler.cpp +++ b/src/net/ea/adminhandler.cpp @@ -32,7 +32,7 @@ namespace Ea { -void AdminHandler::kick(const std::string &name) +void AdminHandler::kickName(const std::string &name) { Net::getChatHandler()->talk("@kick " + name); } @@ -42,7 +42,7 @@ void AdminHandler::ban(int playerId A_UNUSED) // Not supported } -void AdminHandler::ban(const std::string &name) +void AdminHandler::banName(const std::string &name) { Net::getChatHandler()->talk("@ban " + name); } @@ -52,7 +52,7 @@ void AdminHandler::unban(int playerId A_UNUSED) // Not supported } -void AdminHandler::unban(const std::string &name) +void AdminHandler::unbanName(const std::string &name) { Net::getChatHandler()->talk("@unban " + name); } diff --git a/src/net/ea/adminhandler.h b/src/net/ea/adminhandler.h index 70c458514..5b5224174 100644 --- a/src/net/ea/adminhandler.h +++ b/src/net/ea/adminhandler.h @@ -35,15 +35,15 @@ class AdminHandler : public Net::AdminHandler virtual ~AdminHandler() { } - virtual void kick(const std::string &name); + virtual void kickName(const std::string &name); virtual void ban(int playerId); - virtual void ban(const std::string &name); + virtual void banName(const std::string &name); virtual void unban(int playerId); - virtual void unban(const std::string &name); + virtual void unbanName(const std::string &name); virtual void mute(int playerId, int type, int limit); diff --git a/src/net/ea/playerhandler.cpp b/src/net/ea/playerhandler.cpp index 6a841415f..76a7b0dbc 100644 --- a/src/net/ea/playerhandler.cpp +++ b/src/net/ea/playerhandler.cpp @@ -645,4 +645,5 @@ int PlayerHandler::getAttackLocation() const { return EA_ATK; } + } // namespace Ea diff --git a/src/net/inventoryhandler.h b/src/net/inventoryhandler.h index ec2f3db47..642d6f1c1 100644 --- a/src/net/inventoryhandler.h +++ b/src/net/inventoryhandler.h @@ -57,8 +57,8 @@ class InventoryHandler //void changeCart() = 0; - virtual void moveItem(int source, int slot, int amount, - int destination) = 0; + virtual void moveItem2(int source, int slot, int amount, + int destination) = 0; // TODO: fix/remove me virtual size_t getSize(int type) const = 0; diff --git a/src/net/manaserv/adminhandler.cpp b/src/net/manaserv/adminhandler.cpp index 609c9e4f1..f44da97ff 100644 --- a/src/net/manaserv/adminhandler.cpp +++ b/src/net/manaserv/adminhandler.cpp @@ -62,7 +62,7 @@ void AdminHandler::kick(int playerId A_UNUSED) // TODO } -void AdminHandler::kick(const std::string &name A_UNUSED) +void AdminHandler::kickName(const std::string &name A_UNUSED) { // TODO } @@ -72,7 +72,7 @@ void AdminHandler::ban(int playerId A_UNUSED) // TODO } -void AdminHandler::ban(const std::string &name A_UNUSED) +void AdminHandler::banName(const std::string &name A_UNUSED) { // TODO } @@ -82,7 +82,7 @@ void AdminHandler::unban(int playerId A_UNUSED) // TODO } -void AdminHandler::unban(const std::string &name A_UNUSED) +void AdminHandler::unbanName(const std::string &name A_UNUSED) { // TODO } diff --git a/src/net/manaserv/adminhandler.h b/src/net/manaserv/adminhandler.h index a4157b3b0..87c536c31 100644 --- a/src/net/manaserv/adminhandler.h +++ b/src/net/manaserv/adminhandler.h @@ -42,15 +42,15 @@ class AdminHandler : public Net::AdminHandler void kick(int playerId); - void kick(const std::string &name); + void kickName(const std::string &name); void ban(int playerId); - void ban(const std::string &name); + void banName(const std::string &name); void unban(int playerId); - void unban(const std::string &name); + void unbanName(const std::string &name); void mute(int playerId, int type, int limit); diff --git a/src/net/manaserv/attributes.cpp b/src/net/manaserv/attributes.cpp index 662032e29..c032b6bb8 100644 --- a/src/net/manaserv/attributes.cpp +++ b/src/net/manaserv/attributes.cpp @@ -73,16 +73,16 @@ namespace Attributes static unsigned int attributeMinimum = 0; static unsigned int attributeMaximum = 0; - unsigned int getCreationPoints() + unsigned int getCreationPoints() const { return creationPoints; } - unsigned int getAttributeMinimum() + unsigned int getAttributeMinimum() const { return attributeMinimum; } - unsigned int getAttributeMaximum() + unsigned int getAttributeMaximum() const { return attributeMaximum; } - std::vector<std::string>& getLabels() + std::vector<std::string>& getLabels() const { return attributeLabels; } /** diff --git a/src/net/manaserv/connection.h b/src/net/manaserv/connection.h index 4263ae21f..1d3454c75 100644 --- a/src/net/manaserv/connection.h +++ b/src/net/manaserv/connection.h @@ -63,7 +63,7 @@ namespace ManaServ */ void disconnect(); - State getState() + State getState() const { return mState; } /** diff --git a/src/net/manaserv/gamehandler.h b/src/net/manaserv/gamehandler.h index 443533bba..83e636e0e 100644 --- a/src/net/manaserv/gamehandler.h +++ b/src/net/manaserv/gamehandler.h @@ -52,14 +52,16 @@ class GameHandler : public MessageHandler, public Net::GameHandler void ping(int tick); - bool removeDeadBeings() const { return false; } + bool removeDeadBeings() const + { return false; } void clear(); void gameLoading(); /** The ManaServ protocol doesn't use the MP status bar. */ - bool canUseMagicBar() const { return false; } + bool canUseMagicBar() const + { return false; } void disconnect2(); }; diff --git a/src/net/manaserv/guildhandler.h b/src/net/manaserv/guildhandler.h index 893a7157b..47d595bfa 100644 --- a/src/net/manaserv/guildhandler.h +++ b/src/net/manaserv/guildhandler.h @@ -35,7 +35,7 @@ class GuildHandler : public Net::GuildHandler, public MessageHandler public: GuildHandler(); - bool isSupported() + bool isSupported() const { return true; } void handleMessage(Net::MessageIn &msg); diff --git a/src/net/manaserv/loginhandler.cpp b/src/net/manaserv/loginhandler.cpp index 8b8ac831f..f1c597c00 100644 --- a/src/net/manaserv/loginhandler.cpp +++ b/src/net/manaserv/loginhandler.cpp @@ -339,7 +339,7 @@ void LoginHandler::readServerInfo(Net::MessageIn &msg) return; // Set the update host when included in the message - const std::string updateHost = msg.readString(); + std::string updateHost = msg.readString(); if (!updateHost.empty()) { if (!checkPath(updateHost)) diff --git a/src/net/manaserv/playerhandler.cpp b/src/net/manaserv/playerhandler.cpp index 5ebf840bc..aa79d4d41 100644 --- a/src/net/manaserv/playerhandler.cpp +++ b/src/net/manaserv/playerhandler.cpp @@ -448,4 +448,9 @@ void PlayerHandler::requestOnlineList() } +void PlayerHandler::updateStatus(Uint8 status) +{ + +} + } // namespace ManaServ diff --git a/src/net/manaserv/playerhandler.h b/src/net/manaserv/playerhandler.h index 0255406a8..23d2f5e32 100644 --- a/src/net/manaserv/playerhandler.h +++ b/src/net/manaserv/playerhandler.h @@ -74,6 +74,8 @@ class PlayerHandler : public MessageHandler, public Net::PlayerHandler Vector getDefaultWalkSpeed() const; + void updateStatus(Uint8 status); + private: void handleMapChangeMessage(Net::MessageIn &msg); }; diff --git a/src/net/manaserv/specialhandler.cpp b/src/net/manaserv/specialhandler.cpp index 13c6f7613..c168afd7c 100644 --- a/src/net/manaserv/specialhandler.cpp +++ b/src/net/manaserv/specialhandler.cpp @@ -53,19 +53,19 @@ void SpecialHandler::use(int id) gameServerConnection->send(msg); } -void SpecialHandler::use(int id A_UNUSED, int level A_UNUSED, - int beingId A_UNUSED) +void SpecialHandler::useBeing(int id A_UNUSED, int level A_UNUSED, + int beingId A_UNUSED) { // TODO } -void SpecialHandler::use(int id A_UNUSED, int level A_UNUSED, int x A_UNUSED, - int y A_UNUSED) +void SpecialHandler::usePos(int id A_UNUSED, int level A_UNUSED, + int x A_UNUSED, int y A_UNUSED) { // TODO } -void SpecialHandler::use(int id A_UNUSED, const std::string &map A_UNUSED) +void SpecialHandler::useMap(int id A_UNUSED, const std::string &map A_UNUSED) { // TODO } diff --git a/src/net/manaserv/specialhandler.h b/src/net/manaserv/specialhandler.h index f6a20e4ac..2f1ce4d07 100644 --- a/src/net/manaserv/specialhandler.h +++ b/src/net/manaserv/specialhandler.h @@ -39,11 +39,11 @@ class SpecialHandler : public MessageHandler, public Net::SpecialHandler void use(int id); - void use(int id, int level, int beingId); + void useBeing(int id, int level, int beingId); - void use(int id, int level, int x, int y); + void usePos(int id, int level, int x, int y); - void use(int id, const std::string &map); + void useMap(int id, const std::string &map); }; } // namespace ManaServ diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp index 4fb61dc6a..0547ed337 100644 --- a/src/net/messagein.cpp +++ b/src/net/messagein.cpp @@ -241,7 +241,7 @@ std::string MessageIn::readRawString(int length) return str; } -char *MessageIn::readBytes(int length) +unsigned char *MessageIn::readBytes(int length) { // Get string length if (length < 0) @@ -255,13 +255,28 @@ char *MessageIn::readBytes(int length) return nullptr; } - char *buf = new char[length + 2]; + unsigned char *buf = new unsigned char[length + 2]; memcpy (buf, mData + mPos, length); buf[length] = 0; buf[length + 1] = 0; mPos += length; +#ifdef ENABLEDEBUGLOG + std::string str; + for (int f = 0; f < length; f ++) + str += strprintf ("%02x", (unsigned)buf[f]); + str += " "; + for (int f = 0; f < length; f ++) + { + if (buf[f]) + str += strprintf ("%c", buf[f]); + else + str += "_"; + } + logger->log("ReadBytes: " + str); +#endif + PacketCounters::incInBytes(length); return buf; } diff --git a/src/net/messagein.h b/src/net/messagein.h index 8dd43a1a0..1eb5bf232 100644 --- a/src/net/messagein.h +++ b/src/net/messagein.h @@ -95,7 +95,7 @@ class MessageIn virtual std::string readRawString(int length); - char *readBytes(int length); + unsigned char *readBytes(int length); virtual ~MessageIn() { } diff --git a/src/net/playerhandler.h b/src/net/playerhandler.h index f62acc0c9..6ae912102 100644 --- a/src/net/playerhandler.h +++ b/src/net/playerhandler.h @@ -73,6 +73,8 @@ class PlayerHandler virtual Vector getDefaultWalkSpeed() const = 0; virtual void requestOnlineList() = 0; + + virtual void updateStatus(Uint8 status) = 0; }; } // namespace Net diff --git a/src/net/serverinfo.h b/src/net/serverinfo.h index fb6a99a33..b4bb1a2d8 100644 --- a/src/net/serverinfo.h +++ b/src/net/serverinfo.h @@ -54,7 +54,7 @@ public: ServerInfo() { type = TMWATHENA; - port = 0; + port = 6901; save = false; version.first = 0; } diff --git a/src/net/specialhandler.h b/src/net/specialhandler.h index 7ed3673cf..f385f47f9 100644 --- a/src/net/specialhandler.h +++ b/src/net/specialhandler.h @@ -35,11 +35,11 @@ class SpecialHandler virtual void use(int id) = 0; - virtual void use(int id, int level, int beingId) = 0; + virtual void useBeing(int id, int level, int beingId) = 0; - virtual void use(int id, int level, int x, int y) = 0; + virtual void usePos(int id, int level, int x, int y) = 0; - virtual void use(int id, const std::string &map) = 0; + virtual void useMap(int id, const std::string &map) = 0; }; } diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index 627db1402..8d279fc32 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -590,7 +590,7 @@ void BeingHandler::processPlayerMoveUpdate(Net::MessageIn &msg, int msgType) if (gmstatus & 0x80) dstBeing->setGM(true); - if (msgType == 1) + if (msgType == 1 || msgType == 2) { int type = msg.readInt8(); switch (type) diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp index 717df1284..1bee91144 100644 --- a/src/net/tmwa/charserverhandler.cpp +++ b/src/net/tmwa/charserverhandler.cpp @@ -364,8 +364,11 @@ void CharServerHandler::processCharLogin(Net::MessageIn &msg) Net::Character *character = new Net::Character; readPlayerData(msg, character, version); mCharacters.push_back(character); - logger->log("CharServer: Player: %s (%d)", - character->dummy->getName().c_str(), character->slot); + if (character && character->dummy) + { + logger->log("CharServer: Player: %s (%d)", + character->dummy->getName().c_str(), character->slot); + } } Client::setState(STATE_CHAR_SELECT); diff --git a/src/net/tmwa/inventoryhandler.cpp b/src/net/tmwa/inventoryhandler.cpp index 7fa26f5ed..db670a17b 100644 --- a/src/net/tmwa/inventoryhandler.cpp +++ b/src/net/tmwa/inventoryhandler.cpp @@ -186,8 +186,8 @@ void InventoryHandler::closeStorage(int type A_UNUSED) MessageOut outMsg(CMSG_CLOSE_STORAGE); } -void InventoryHandler::moveItem(int source, int slot, int amount, - int destination) +void InventoryHandler::moveItem2(int source, int slot, int amount, + int destination) { if (source == Inventory::INVENTORY && destination == Inventory::STORAGE) { diff --git a/src/net/tmwa/inventoryhandler.h b/src/net/tmwa/inventoryhandler.h index d2ecc4b6d..c6e000b3a 100644 --- a/src/net/tmwa/inventoryhandler.h +++ b/src/net/tmwa/inventoryhandler.h @@ -53,7 +53,7 @@ class InventoryHandler : public MessageHandler, public Ea::InventoryHandler void closeStorage(int type); - void moveItem(int source, int slot, int amount, int destination); + void moveItem2(int source, int slot, int amount, int destination); }; } // namespace TmwAthena diff --git a/src/net/tmwa/network.cpp b/src/net/tmwa/network.cpp index addc737ee..31329eafb 100644 --- a/src/net/tmwa/network.cpp +++ b/src/net/tmwa/network.cpp @@ -83,7 +83,7 @@ short packet_lengths[] = -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10, // #0x0200 26, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 19, 10, 0, 0, 0, - 2, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, -1, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 122, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; diff --git a/src/net/tmwa/network.h b/src/net/tmwa/network.h index 17a4f7370..c0ec6ef3c 100644 --- a/src/net/tmwa/network.h +++ b/src/net/tmwa/network.h @@ -39,7 +39,7 @@ * Protocol version, reported to the eAthena char and mapserver who can adjust * the protocol accordingly. */ -#define CLIENT_PROTOCOL_VERSION 4 +#define CLIENT_PROTOCOL_VERSION 5 #define CLIENT_TMW_PROTOCOL_VERSION 1 namespace TmwAthena diff --git a/src/net/tmwa/npchandler.cpp b/src/net/tmwa/npchandler.cpp index 574f34d55..d86c64a96 100644 --- a/src/net/tmwa/npchandler.cpp +++ b/src/net/tmwa/npchandler.cpp @@ -25,6 +25,7 @@ #include "localplayer.h" #include "gui/npcdialog.h" +#include "gui/viewport.h" #include "net/messagein.h" #include "net/net.h" @@ -41,7 +42,8 @@ extern Net::NpcHandler *npcHandler; namespace TmwAthena { -NpcHandler::NpcHandler() +NpcHandler::NpcHandler() : + mRequestLang(false) { static const Uint16 _messages[] = { @@ -51,6 +53,7 @@ NpcHandler::NpcHandler() SMSG_NPC_CLOSE, SMSG_NPC_INT_INPUT, SMSG_NPC_STR_INPUT, + SMSG_NPC_COMMAND, 0 }; handledMessages = _messages; @@ -59,9 +62,12 @@ NpcHandler::NpcHandler() void NpcHandler::handleMessage(Net::MessageIn &msg) { - getNpc(msg, msg.getId() == SMSG_NPC_CHOICE + int npcId = getNpc(msg, msg.getId() == SMSG_NPC_CHOICE || msg.getId() == SMSG_NPC_MESSAGE); + if (msg.getId() != SMSG_NPC_STR_INPUT) + mRequestLang = false; + switch (msg.getId()) { case SMSG_NPC_CHOICE: @@ -85,7 +91,14 @@ void NpcHandler::handleMessage(Net::MessageIn &msg) break; case SMSG_NPC_STR_INPUT: - processNpcStrInput(msg); + if (mRequestLang) + processLangReuqest(msg, npcId); + else + processNpcStrInput(msg); + break; + + case SMSG_NPC_COMMAND: + processNpcCommand(msg, npcId); break; default: @@ -118,6 +131,8 @@ void NpcHandler::closeDialog(int npcId) { if ((*it).second.dialog) (*it).second.dialog->close(); + if ((*it).second.dialog == mDialog) + mDialog = nullptr; mNpcDialogs.erase(it); } } @@ -213,6 +228,7 @@ int NpcHandler::getNpc(Net::MessageIn &msg, bool haveLength) else { mDialog = new NpcDialog(npcId); + mDialog->saveCamera(); if (player_node) player_node->stopWalking(false); Wrapper wrap; @@ -222,9 +238,70 @@ int NpcHandler::getNpc(Net::MessageIn &msg, bool haveLength) } else { + if (mDialog && mDialog != diag->second.dialog) + mDialog->restoreCamera(); mDialog = diag->second.dialog; + if (mDialog) + mDialog->saveCamera(); } return npcId; } +void NpcHandler::processNpcCommand(Net::MessageIn &msg, int npcId) +{ + const int cmd = msg.readInt16(); + switch (cmd) + { + case 0: + mRequestLang = true; + break; + + case 1: + if (viewport) + viewport->moveCameraToActor(npcId); + break; + + case 2: + if (viewport) + { + const int id = msg.readInt32(); + const int x = msg.readInt16(); + const int y = msg.readInt16(); + if (!id) + viewport->moveCameraToPosition(x, y); + else + viewport->moveCameraToActor(id, x, y); + } + break; + + case 3: + if (viewport) + viewport->returnCamera(); + break; + + case 4: + if (viewport) + { + msg.readInt32(); // id + const int x = msg.readInt16(); + const int y = msg.readInt16(); + viewport->moveCameraRelative(x, y); + } + break; + case 5: + closeDialog(npcId); + break; + + default: + logger->log("unknown npc command: %d", cmd); + break; + } +} + +void NpcHandler::processLangReuqest(Net::MessageIn &msg A_UNUSED, int npcId) +{ + mRequestLang = false; + stringInput(npcId, getLangSimple()); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/npchandler.h b/src/net/tmwa/npchandler.h index 967829ddc..1cfcacb20 100644 --- a/src/net/tmwa/npchandler.h +++ b/src/net/tmwa/npchandler.h @@ -65,6 +65,13 @@ class NpcHandler : public MessageHandler, public Ea::NpcHandler void sellItem(int beingId, int itemId, int amount); int getNpc(Net::MessageIn &msg, bool haveLength); + + void processNpcCommand(Net::MessageIn &msg, int npcId); + + void processLangReuqest(Net::MessageIn &msg, int npcId); + + private: + bool mRequestLang; }; } // namespace TmwAthena diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index d5f0641eb..16e833ec9 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -22,6 +22,7 @@ #include "net/tmwa/playerhandler.h" +#include "configuration.h" #include "logger.h" #include "net/messagein.h" @@ -218,7 +219,7 @@ void PlayerHandler::processOnlineList(Net::MessageIn &msg) return; int size = msg.readInt16() - 4; - std::vector<std::string> arr; + std::vector<OnlinePlayer*> arr; if (!size) { @@ -227,14 +228,44 @@ void PlayerHandler::processOnlineList(Net::MessageIn &msg) return; } - const char *start = msg.readBytes(size); - const char *buf = start; + char *start = (char*)msg.readBytes(size); + if (!start) + return; + + char *buf = start; - while (buf - start + 1 < size && *(buf + 1)) + int addVal = 1; + if (serverVersion >= 4) + addVal = 3; + + while (buf - start + 1 < size && *(buf + addVal)) { -// char status = *buf; // now unused + unsigned char status = 255; + unsigned char ver = 0; + unsigned char level = 0; + if (serverVersion >= 4) + { + status = *buf; + buf ++; + level = *buf; + buf ++; + ver = *buf; + } buf ++; - arr.push_back(buf); + + int gender = GENDER_UNSPECIFIED; + if (serverVersion >= 4) + { + if (config.getBoolValue("showgender")) + { + if (status & Being::FLAG_GENDER) + gender = GENDER_MALE; + else + gender = GENDER_FEMALE; + } + } + arr.push_back(new OnlinePlayer((char*)buf, + status, level, gender, ver)); buf += strlen(buf) + 1; } @@ -243,4 +274,11 @@ void PlayerHandler::processOnlineList(Net::MessageIn &msg) delete [] start; } +void PlayerHandler::updateStatus(Uint8 status) +{ + MessageOut outMsg(CMSG_SET_STATUS); + outMsg.writeInt8(status); + outMsg.writeInt8(0); +} + } // namespace TmwAthena diff --git a/src/net/tmwa/playerhandler.h b/src/net/tmwa/playerhandler.h index 0fa524d51..14aa191f6 100644 --- a/src/net/tmwa/playerhandler.h +++ b/src/net/tmwa/playerhandler.h @@ -53,6 +53,7 @@ class PlayerHandler : public MessageHandler, public Ea::PlayerHandler void changeAction(Being::Action action); void processOnlineList(Net::MessageIn &msg); void requestOnlineList(); + void updateStatus(Uint8 status); void respawn(); }; diff --git a/src/net/tmwa/protocol.h b/src/net/tmwa/protocol.h index 0f124cc20..256f1dce4 100644 --- a/src/net/tmwa/protocol.h +++ b/src/net/tmwa/protocol.h @@ -335,5 +335,7 @@ enum #define SMSG_IGNORE_ALL_RESPONSE 0x00d2 #define CMSG_ONLINE_LIST 0x0210 #define SMSG_ONLINE_LIST 0x0211 +#define SMSG_NPC_COMMAND 0x0212 +#define CMSG_SET_STATUS 0x0213 #endif diff --git a/src/net/tmwa/specialhandler.cpp b/src/net/tmwa/specialhandler.cpp index 9fa7b6dfa..129f0b47e 100644 --- a/src/net/tmwa/specialhandler.cpp +++ b/src/net/tmwa/specialhandler.cpp @@ -69,7 +69,7 @@ void SpecialHandler::handleMessage(Net::MessageIn &msg) } } -void SpecialHandler::use(int id, int level, int beingId) +void SpecialHandler::useBeing(int id, int level, int beingId) { MessageOut outMsg(CMSG_SKILL_USE_BEING); outMsg.writeInt16(static_cast<Sint16>(level)); @@ -77,7 +77,7 @@ void SpecialHandler::use(int id, int level, int beingId) outMsg.writeInt16(static_cast<Sint16>(beingId)); } -void SpecialHandler::use(int id, int level, int x, int y) +void SpecialHandler::usePos(int id, int level, int x, int y) { MessageOut outMsg(CMSG_SKILL_USE_POSITION); outMsg.writeInt16(static_cast<Sint16>(level)); @@ -86,7 +86,7 @@ void SpecialHandler::use(int id, int level, int x, int y) outMsg.writeInt16(static_cast<Sint16>(y)); } -void SpecialHandler::use(int id, const std::string &map) +void SpecialHandler::useMap(int id, const std::string &map) { MessageOut outMsg(CMSG_SKILL_USE_MAP); outMsg.writeInt16(static_cast<Sint16>(id)); diff --git a/src/net/tmwa/specialhandler.h b/src/net/tmwa/specialhandler.h index f17ef4c44..216adddc6 100644 --- a/src/net/tmwa/specialhandler.h +++ b/src/net/tmwa/specialhandler.h @@ -40,11 +40,11 @@ class SpecialHandler : public MessageHandler, public Ea::SpecialHandler void handleMessage(Net::MessageIn &msg); - void use(int id, int level, int beingId); + void useBeing(int id, int level, int beingId); - void use(int id, int level, int x, int y); + void usePos(int id, int level, int x, int y); - void use(int id, const std::string &map); + void useMap(int id, const std::string &map); }; } // namespace TmwAthena diff --git a/src/opengl1graphics.cpp b/src/opengl1graphics.cpp index 6f712f698..34e9fcda3 100644 --- a/src/opengl1graphics.cpp +++ b/src/opengl1graphics.cpp @@ -61,8 +61,8 @@ void OpenGL1Graphics::setSync(bool sync) mSync = sync; } -bool OpenGL1Graphics::setVideoMode(int w, int h, int bpp, - bool fs, bool hwaccel) +bool OpenGL1Graphics::setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame) { logger->log("Setting video mode %dx%d %s", w, h, fs ? "fullscreen" : "windowed"); @@ -74,9 +74,25 @@ bool OpenGL1Graphics::setVideoMode(int w, int h, int bpp, mBpp = bpp; mFullscreen = fs; mHWAccel = hwaccel; + mEnableResize = resize; + mNoFrame = noFrame; if (fs) + { displayFlags |= SDL_FULLSCREEN; + } + else + { + // Resizing currently not supported on Windows, where it would require + // reuploading all textures. +#if !defined(_WIN32) + if (resize) + displayFlags |= SDL_RESIZABLE; +#endif + } + + if (noFrame) + displayFlags |= SDL_NOFRAME; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -472,6 +488,7 @@ void OpenGL1Graphics::_beginDraw() void OpenGL1Graphics::_endDraw() { + popClipArea(); } SDL_Surface* OpenGL1Graphics::getScreenshot() diff --git a/src/opengl1graphics.h b/src/opengl1graphics.h index 87458d8b9..76dc3ef00 100644 --- a/src/opengl1graphics.h +++ b/src/opengl1graphics.h @@ -45,10 +45,12 @@ class OpenGL1Graphics : public Graphics * the next call to setVideoMode(). Only implemented on MacOS for now. */ void setSync(bool sync); + bool getSync() const { return mSync; } - bool setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel); + bool setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame); bool drawImage(Image *image, int srcX, int srcY, diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp index b744a3caf..2c3d914b0 100644 --- a/src/openglgraphics.cpp +++ b/src/openglgraphics.cpp @@ -71,7 +71,8 @@ void OpenGLGraphics::setSync(bool sync) mSync = sync; } -bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) +bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame) { logger->log("Setting video mode %dx%d %s", w, h, fs ? "fullscreen" : "windowed"); @@ -83,9 +84,25 @@ bool OpenGLGraphics::setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel) mBpp = bpp; mFullscreen = fs; mHWAccel = hwaccel; + mEnableResize = resize; + mNoFrame = noFrame; if (fs) + { displayFlags |= SDL_FULLSCREEN; + } + else + { + // Resizing currently not supported on Windows, where it would require + // reuploading all textures. +#if !defined(_WIN32) + if (resize) + displayFlags |= SDL_RESIZABLE; +#endif + } + + if (noFrame) + displayFlags |= SDL_NOFRAME; SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); @@ -1017,6 +1034,7 @@ void OpenGLGraphics::_beginDraw() void OpenGLGraphics::_endDraw() { + popClipArea(); } SDL_Surface* OpenGLGraphics::getScreenshot() diff --git a/src/openglgraphics.h b/src/openglgraphics.h index 1047223ad..f3bdc4470 100644 --- a/src/openglgraphics.h +++ b/src/openglgraphics.h @@ -45,10 +45,12 @@ class OpenGLGraphics : public Graphics * the next call to setVideoMode(). Only implemented on MacOS for now. */ void setSync(bool sync); + bool getSync() const { return mSync; } - bool setVideoMode(int w, int h, int bpp, bool fs, bool hwaccel); + bool setVideoMode(int w, int h, int bpp, bool fs, + bool hwaccel, bool resize, bool noFrame); bool drawImage(Image *image, int srcX, int srcY, diff --git a/src/particle.h b/src/particle.h index a79181498..7485b118f 100644 --- a/src/particle.h +++ b/src/particle.h @@ -219,7 +219,7 @@ class Particle : public Actor /** * Gets the flag if the particle is supposed to be moved by its parent */ - bool doesFollow() + bool doesFollow() const { return mFollow; } /** diff --git a/src/resources/action.h b/src/resources/action.h index 1e3965363..3951cc02c 100644 --- a/src/resources/action.h +++ b/src/resources/action.h @@ -43,7 +43,7 @@ class Action Animation *getAnimation(int direction) const; - unsigned getNumber() + unsigned getNumber() const { return mNumber; } void setNumber(unsigned n) diff --git a/src/resources/colordb.cpp b/src/resources/colordb.cpp index 1ffe507b2..2ddf27ac3 100644 --- a/src/resources/colordb.cpp +++ b/src/resources/colordb.cpp @@ -30,7 +30,7 @@ namespace { - ColorDB::Colors mHairColors; + int mHairColorsSize = 0; bool mLoaded = false; std::string mFail = "#ffffff"; ColorDB::ColorLists mColorLists; @@ -44,10 +44,22 @@ void ColorDB::load() loadHair(); if (serverVersion >= 1) loadColorLists(); + + ColorListsIterator it = mColorLists.find("hair"); + if (it != mColorLists.end()) + mHairColorsSize = (*it).second.size(); + else + mHairColorsSize = 0; } void ColorDB::loadHair() { + std::map <int, ItemColor> colors; + ColorListsIterator it = mColorLists.find("hair"); + + if (it != mColorLists.end()) + colors = it->second; + XML::Document *doc = new XML::Document("hair.xml"); XmlNodePtr root = doc->rootNode(); bool hairXml = true; @@ -65,7 +77,7 @@ void ColorDB::loadHair() if (!root || !xmlNameEqual(root, "colors")) { logger->log1("ColorDB: Failed to find any color files."); - mHairColors[0] = mFail; + colors[0] = ItemColor(0, "", ""); mLoaded = true; delete doc; @@ -80,17 +92,17 @@ void ColorDB::loadHair() { int id = XML::getProperty(node, "id", 0); - if (mHairColors.find(id) != mHairColors.end()) + if (colors.find(id) != colors.end()) logger->log("ColorDB: Redefinition of dye ID %d", id); - mHairColors[id] = hairXml ? - XML::getProperty(node, "value", "#FFFFFF") : - XML::getProperty(node, "dye", "#FFFFFF"); + colors[id] = ItemColor(id, XML::getProperty(node, "name", ""), + XML::getProperty(node, hairXml ? "value" : "dye", "#FFFFFF")); } } delete doc; + mColorLists["hair"] = colors; mLoaded = true; } @@ -139,7 +151,6 @@ void ColorDB::unload() { logger->log1("Unloading color database..."); - mHairColors.clear(); mColorLists.clear(); mLoaded = false; } @@ -149,22 +160,54 @@ std::string &ColorDB::getHairColor(int id) if (!mLoaded) load(); - ColorIterator i = mHairColors.find(id); + ColorListsIterator it = mColorLists.find("hair"); + if (it == mColorLists.end()) + { + logger->log1("ColorDB: Error, hair colors list empty"); + return mFail; + } + + ColorIterator i = (*it).second.find(id); + + if (i == (*it).second.end()) + { + logger->log("ColorDB: Error, unknown dye ID# %d", id); + return mFail; + } + else + { + return i->second.color; + } +} + +std::string &ColorDB::getHairColorName(int id) +{ + if (!mLoaded) + load(); + + ColorListsIterator it = mColorLists.find("hair"); + if (it == mColorLists.end()) + { + logger->log1("ColorDB: Error, hair colors list empty"); + return mFail; + } + + ColorIterator i = (*it).second.find(id); - if (i == mHairColors.end()) + if (i == (*it).second.end()) { logger->log("ColorDB: Error, unknown dye ID# %d", id); return mFail; } else { - return i->second; + return i->second.name; } } int ColorDB::getHairSize() { - return static_cast<int>(mHairColors.size()); + return mHairColorsSize; } std::map <int, ColorDB::ItemColor> *ColorDB::getColorsList(std::string name) diff --git a/src/resources/colordb.h b/src/resources/colordb.h index 36907095e..ade4227f8 100644 --- a/src/resources/colordb.h +++ b/src/resources/colordb.h @@ -70,12 +70,14 @@ namespace ColorDB std::string &getHairColor(int id); + std::string &getHairColorName(int id); + int getHairSize(); std::map <int, ItemColor> *getColorsList(std::string name); // Color DB - typedef std::map<int, std::string> Colors; + typedef std::map<int, ItemColor> Colors; typedef Colors::iterator ColorIterator; typedef std::map <std::string, std::map <int, ItemColor> > ColorLists; typedef ColorLists::iterator ColorListsIterator; diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp index c6126a57b..07e192cd4 100644 --- a/src/resources/emotedb.cpp +++ b/src/resources/emotedb.cpp @@ -67,6 +67,10 @@ void EmoteDB::load() continue; int id = XML::getProperty(emoteNode, "id", -1); + // skip hight images + if (id > 19) + continue; + if (id == -1) { logger->log1("Emote Database: Emote with missing ID in " @@ -104,7 +108,6 @@ void EmoteDB::load() mLastEmote = id; } - XML::Document doc2("graphics/sprites/manaplus_emotes.xml"); rootNode = doc2.rootNode(); diff --git a/src/resources/image.cpp b/src/resources/image.cpp index d94967631..6f9042029 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -79,6 +79,8 @@ Image::Image(SDL_Surface *image, bool hasAlphaChannel0, Uint8 *alphaChannel): { logger->log( "Image::Image(SDL_Surface*): Couldn't load invalid Surface!"); + mBounds.w = 0; + mBounds.h = 0; } } @@ -119,10 +121,8 @@ Image::~Image() unload(); } -Resource *Image::load(void *buffer, unsigned bufferSize) +Resource *Image::load(SDL_RWops *rw) { - // Load the raw file data from the buffer in an RWops structure - SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize); SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); if (!tmpImage) @@ -137,9 +137,8 @@ Resource *Image::load(void *buffer, unsigned bufferSize) return image; } -Resource *Image::load(void *buffer, unsigned bufferSize, Dye const &dye) +Resource *Image::load(SDL_RWops *rw, Dye const &dye) { - SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize); SDL_Surface *tmpImage = IMG_Load_RW(rw, 1); if (!tmpImage) @@ -162,7 +161,7 @@ Resource *Image::load(void *buffer, unsigned bufferSize, Dye const &dye) SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE); SDL_FreeSurface(tmpImage); - Uint32 *pixels = static_cast< Uint32 * >(surf->pixels); + Uint32 *pixels = static_cast<Uint32 *>(surf->pixels); for (Uint32 *p_end = pixels + surf->w * surf->h; pixels != p_end; ++pixels) { const Uint32 p = *pixels; @@ -210,10 +209,11 @@ Image *Image::createTextSurface(SDL_Surface *tmpImage, float alpha) bool hasAlpha = false; bool converted = false; + const int sz = tmpImage->w * tmpImage->h; + // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[tmpImage->w * tmpImage->h]; + Uint8 *alphaChannel = new Uint8[sz]; - const int sz = tmpImage->w * tmpImage->h; const SDL_PixelFormat * const fmt = tmpImage->format; if (fmt->Amask) { @@ -466,7 +466,7 @@ Image* Image::SDLmerge(Image *image, int x, int y) SDL_LockSurface(surface); SDL_LockSurface(mSDLSurface); - const int x0 = (y * getWidth()) + x; + const int x0 = (y * mBounds.w) + x; const int maxX = std::min(image->mBounds.w, static_cast<Uint16>(mBounds.w - x)); const int maxY = std::min(image->mBounds.w, @@ -479,7 +479,7 @@ Image* Image::SDLmerge(Image *image, int x, int y) for (offset_y = ((y > 0) ? 0 : -y); offset_y < maxY; offset_y++) { // Computing offset on both images - current_offset = (offset_y * getWidth()) + x1; + current_offset = (offset_y * mBounds.w) + x1; surface_offset = offset_y * surface->w + offset_x; // Retrieving a pixel to merge @@ -546,7 +546,7 @@ Image* Image::SDLgetScaledImage(int width, int height) return nullptr; // No scaling when there is ... no different given size ... - if (width == getWidth() && height == getHeight()) + if (width == mBounds.w && height == mBounds.h) return nullptr; Image* scaledImage = nullptr; @@ -555,8 +555,8 @@ Image* Image::SDLgetScaledImage(int width, int height) if (mSDLSurface) { scaledSurface = zoomSurface(mSDLSurface, - static_cast<double>(width) / getWidth(), - static_cast<double>(height) / getHeight(), + static_cast<double>(width) / mBounds.w, + static_cast<double>(height) / mBounds.h, 1); // The load function takes care of the SDL<->OpenGL implementation @@ -626,22 +626,20 @@ Image *Image::_SDLload(SDL_Surface *tmpImage) bool hasAlpha = false; bool converted = false; - // The alpha channel to be filled with alpha values - Uint8 *alphaChannel = new Uint8[tmpImage->w * tmpImage->h]; - if (tmpImage->format->BitsPerPixel != 32) { tmpImage = convertTo32Bit(tmpImage); if (!tmpImage) - { - delete[] alphaChannel; return nullptr; - } converted = true; } const int sz = tmpImage->w * tmpImage->h; + + // The alpha channel to be filled with alpha values + Uint8 *alphaChannel = new Uint8[sz]; + // Figure out whether the image uses its alpha layer if (!tmpImage->format->palette) { @@ -663,19 +661,19 @@ Image *Image::_SDLload(SDL_Surface *tmpImage) else { if (SDL_ALPHA_OPAQUE != 255) + { hasAlpha = true; - memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); -// for (int i = 0; i < sz; ++ i) -// alphaChannel[i] = SDL_ALPHA_OPAQUE; + memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); + } } } else { if (SDL_ALPHA_OPAQUE != 255) + { hasAlpha = true; - memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); -// for (int i = 0; i < sz; ++ i) -// alphaChannel[i] = SDL_ALPHA_OPAQUE; + memset(alphaChannel, SDL_ALPHA_OPAQUE, sz); + } } SDL_Surface *image; @@ -705,7 +703,6 @@ Image *Image::_SDLload(SDL_Surface *tmpImage) if (converted) SDL_FreeSurface(tmpImage); -// SDL_SetColorKey(image, SDL_SRCCOLORKEY | SDL_RLEACCEL, 0); return new Image(image, hasAlpha, alphaChannel); } diff --git a/src/resources/image.h b/src/resources/image.h index a9f5722cd..68ab09e58 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -66,28 +66,25 @@ class Image : public Resource virtual ~Image(); /** - * Loads an image from a buffer in memory. + * Loads an image from an SDL_RWops structure. * - * @param buffer The memory buffer containing the image data. - * @param bufferSize The size of the memory buffer in bytes. + * @param rw The SDL_RWops to load the image from. * * @return <code>NULL</code> if an error occurred, a valid pointer * otherwise. */ - static Resource *load(void *buffer, unsigned bufferSize); + static Resource *load(SDL_RWops *rw); /** - * Loads an image from a buffer in memory and recolors it. + * Loads an image from an SDL_RWops structure and recolors it. * - * @param buffer The memory buffer containing the image data. - * @param bufferSize The size of the memory buffer in bytes. + * @param rw The SDL_RWops to load the image from. * @param dye The dye used to recolor the image. * * @return <code>NULL</code> if an error occurred, a valid pointer * otherwise. */ - static Resource *load(void *buffer, unsigned bufferSize, - Dye const &dye); + static Resource *load(SDL_RWops *rw, Dye const &dye); /** * Loads an image from an SDL surface. @@ -106,7 +103,7 @@ class Image : public Resource /** * Tells is the image is loaded */ - bool isLoaded() + bool isLoaded() const { return mLoaded; } /** @@ -220,16 +217,16 @@ class Image : public Resource static int mTextureType; #endif - bool isHasAlphaChannel() + bool isHasAlphaChannel() const { return mHasAlphaChannel; } - bool isAlphaVisible() + bool isAlphaVisible() const { return mIsAlphaVisible; } void setAlphaVisible(bool b) { mIsAlphaVisible = b; } - bool isAlphaCalculated() + bool isAlphaCalculated() const { return mIsAlphaCalculated; } void setAlphaCalculated(bool b) diff --git a/src/resources/imageset.h b/src/resources/imageset.h index 69ebebdc0..edfc4b123 100644 --- a/src/resources/imageset.h +++ b/src/resources/imageset.h @@ -63,13 +63,13 @@ class ImageSet : public Resource size_type size() const { return mImages.size(); } - int getOffsetX() + int getOffsetX() const { return mOffsetX; } void setOffsetX(int n) { mOffsetX = n; } - int getOffsetY() + int getOffsetY() const { return mOffsetY; } void setOffsetY(int n) diff --git a/src/resources/iteminfo.h b/src/resources/iteminfo.h index 8c5e2dd8f..5f789663f 100644 --- a/src/resources/iteminfo.h +++ b/src/resources/iteminfo.h @@ -148,7 +148,8 @@ class ItemInfo void setEffect(const std::string &effect) { mEffect = effect; } - const std::string &getEffect() const { return mEffect; } + const std::string &getEffect() const + { return mEffect; } void setType(ItemType type) { mType = type; } @@ -250,7 +251,7 @@ class ItemInfo void setColorsList(std::string name); - bool isHaveColors() + bool isHaveColors() const { return !mColorList.empty(); } const std::string replaceColors(std::string str, diff --git a/src/resources/music.cpp b/src/resources/music.cpp index 6e752ab60..b13812f18 100644 --- a/src/resources/music.cpp +++ b/src/resources/music.cpp @@ -26,30 +26,21 @@ #include "debug.h" -Music::Music(Mix_Chunk *music): - mChunk(music), - mChannel(-1) +Music::Music(Mix_Music *music) : + mMusic(music) { } Music::~Music() { - //Mix_FreeMusic(music); - Mix_FreeChunk(mChunk); + Mix_FreeMusic(mMusic); } -Resource *Music::load(void *buffer, unsigned bufferSize) +Resource *Music::load(SDL_RWops *rw) { - // Load the raw file data from the buffer in an RWops structure - SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize); - - // Use Mix_LoadMUS to load the raw music data - //Mix_Music* music = Mix_LoadMUS_RW(rw); Need to be implemeted - Mix_Chunk *tmpMusic = Mix_LoadWAV_RW(rw, 1); - - if (tmpMusic) + if (Mix_Music *music = Mix_LoadMUS_RW(rw)) { - return new Music(tmpMusic); + return new Music(music); } else { @@ -58,30 +49,10 @@ Resource *Music::load(void *buffer, unsigned bufferSize) } } -bool Music::play(int loops) -{ - /* - * Warning: loops should be always set to -1 (infinite) with current - * implementation to avoid halting the playback of other samples - */ - - /*if (Mix_PlayMusic(music, loops)) - return true;*/ - Mix_VolumeChunk(mChunk, 120); - mChannel = Mix_PlayChannel(-1, mChunk, loops); - - return mChannel != -1; -} - -void Music::stop() +bool Music::play(int loops, int fadeIn) { - /* - * Warning: very dungerous trick, it could try to stop channels occupied - * by samples rather than the current music file - */ - - //Mix_HaltMusic(); - - if (mChannel != -1) - Mix_HaltChannel(mChannel); + if (fadeIn > 0) + return Mix_FadeInMusic(mMusic, loops, fadeIn); + else + return Mix_PlayMusic(mMusic, loops); } diff --git a/src/resources/music.h b/src/resources/music.h index 428c02572..88cc752bc 100644 --- a/src/resources/music.h +++ b/src/resources/music.h @@ -41,38 +41,32 @@ class Music : public Resource /** * Loads a music from a buffer in memory. * - * @param buffer The memory buffer containing the music data. - * @param bufferSize The size of the memory buffer in bytes. + * @param rw The SDL_RWops to load the music data from. * * @return <code>NULL</code> if the an error occurred, a valid pointer * otherwise. */ - static Resource *load(void *buffer, unsigned bufferSize); + static Resource *load(SDL_RWops *rw); /** * Plays the music. * - * @param loops Number of times to repeat the playback. + * @param loops Number of times to repeat the playback (-1 means + * forever). + * @param fadeIn Duration in milliseconds to fade in the music. * * @return <code>true</code> if the playback started properly * <code>false</code> otherwise. */ - virtual bool play(int loops); - - /** - * Stops the music. - */ - virtual void stop(); + bool play(int loops = -1, int fadeIn = 0); protected: /** * Constructor. */ - Music(Mix_Chunk *music); + Music(Mix_Music *music); - //Mix_Music *music; - Mix_Chunk *mChunk; - int mChannel; + Mix_Music *mMusic; }; #endif diff --git a/src/resources/resource.h b/src/resources/resource.h index b8e06aaa7..c0ea7ca23 100644 --- a/src/resources/resource.h +++ b/src/resources/resource.h @@ -73,7 +73,7 @@ class Resource { return mRefCount; } #ifdef DEBUG_DUMP_LEAKS - bool getDumped() + bool getDumped() const { return mDumped; } void setDumped(bool n) diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 3376394bc..c26526b97 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -35,6 +35,7 @@ #include "resources/spritedef.h" #include "utils/mkdir.h" +#include "utils/physfsrwops.h" #include <physfs.h> #include <SDL_image.h> @@ -42,6 +43,7 @@ #include <fstream> #include <iostream> #include <sstream> +#include <zlib.h> #include <sys/stat.h> #include <sys/time.h> @@ -397,19 +399,16 @@ struct ResourceLoader ResourceManager *manager; std::string path; ResourceManager::loader fun; + static Resource *load(void *v) { if (!v) return nullptr; ResourceLoader *l = static_cast< ResourceLoader * >(v); - int fileSize; - if (!l->manager) + SDL_RWops *rw = PHYSFSRWOPS_openRead(l->path.c_str()); + if (!rw) return nullptr; - void *buffer = l->manager->loadFile(l->path, fileSize); - if (!buffer) - return nullptr; - Resource *res = l->fun(buffer, fileSize); - free(buffer); + Resource *res = l->fun(rw); return res; } }; @@ -451,16 +450,14 @@ struct DyedImageLoader d = new Dye(path.substr(p + 1)); path = path.substr(0, p); } - int fileSize; - void *buffer = l->manager->loadFile(path, fileSize); - if (!buffer) + SDL_RWops *rw = PHYSFSRWOPS_openRead(path.c_str()); + if (!rw) { delete d; return nullptr; } - Resource *res = d ? Image::load(buffer, fileSize, *d) - : Image::load(buffer, fileSize); - free(buffer); + Resource *res = d ? Image::load(rw, *d) + : Image::load(rw); delete d; return res; } @@ -695,18 +692,10 @@ void ResourceManager::saveTextFile(std::string path, std::string name, SDL_Surface *ResourceManager::loadSDLSurface(const std::string &filename) { - int fileSize; - void *buffer = loadFile(filename, fileSize); - SDL_Surface *tmp = nullptr; - - if (buffer) - { - SDL_RWops *rw = SDL_RWFromMem(buffer, fileSize); - tmp = IMG_Load_RW(rw, 1); - ::free(buffer); - } - - return tmp; + SDL_Surface *surface = nullptr; + if (SDL_RWops *rw = PHYSFSRWOPS_openRead(filename.c_str())) + surface = IMG_Load_RW(rw, 1); + return surface; } void ResourceManager::scheduleDelete(SDL_Surface* surface) diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index f0146b8b4..9df96d354 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -37,7 +37,9 @@ class Music; class Resource; class SoundEffect; class SpriteDef; + struct SDL_Surface; +struct SDL_RWops; /** * A class for loading and managing resources. @@ -48,7 +50,7 @@ class ResourceManager public: - typedef Resource *(*loader)(void *, unsigned); + typedef Resource *(*loader)(SDL_RWops *); typedef Resource *(*generator)(void *); ResourceManager(); @@ -252,17 +254,17 @@ class ResourceManager */ static void deleteInstance(); - int size() + int size() const { return mResources.size(); } typedef std::map<std::string, Resource*> Resources; typedef Resources::iterator ResourceIterator; #ifdef DEBUG_DUMP_LEAKS - Resources* getResources() + Resources* getResources() const { return &mResources; } - Resources* getOrphanedResources() + Resources* getOrphanedResources() const { return &mOrphanedResources; } #endif diff --git a/src/resources/soundeffect.cpp b/src/resources/soundeffect.cpp index eaa323bd6..6a3a980a7 100644 --- a/src/resources/soundeffect.cpp +++ b/src/resources/soundeffect.cpp @@ -31,14 +31,10 @@ SoundEffect::~SoundEffect() Mix_FreeChunk(mChunk); } -Resource *SoundEffect::load(void *buffer, unsigned bufferSize) +Resource *SoundEffect::load(SDL_RWops *rw) { - if (!buffer) + if (!rw) return nullptr; - - // Load the raw file data from the buffer in an RWops structure - SDL_RWops *rw = SDL_RWFromMem(buffer, bufferSize); - // Load the music data and free the RWops structure Mix_Chunk *tmpSoundEffect = Mix_LoadWAV_RW(rw, 1); diff --git a/src/resources/soundeffect.h b/src/resources/soundeffect.h index 91ca3bb59..b8c9e8735 100644 --- a/src/resources/soundeffect.h +++ b/src/resources/soundeffect.h @@ -41,13 +41,12 @@ class SoundEffect : public Resource /** * Loads a sample from a buffer in memory. * - * @param buffer The memory buffer containing the sample data. - * @param bufferSize The size of the memory buffer in bytes. + * @param rw The SDL_RWops to load the sample data from. * * @return <code>NULL</code> if the an error occurred, a valid pointer * otherwise. */ - static Resource *load(void *buffer, unsigned bufferSize); + static Resource *load(SDL_RWops *rw); /** * Plays the sample. @@ -65,7 +64,8 @@ class SoundEffect : public Resource /** * Constructor. */ - SoundEffect(Mix_Chunk *soundEffect): mChunk(soundEffect) + SoundEffect(Mix_Chunk *soundEffect) : + mChunk(soundEffect) { } Mix_Chunk *mChunk; diff --git a/src/sound.cpp b/src/sound.cpp index 123a66567..913b55656 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -27,6 +27,7 @@ #include "logger.h" #include "sound.h" +#include "resources/music.h" #include "resources/resourcemanager.h" #include "resources/soundeffect.h" @@ -158,10 +159,17 @@ void Sound::info() compiledVersion.major, compiledVersion.minor, compiledVersion.patch); - logger->log("Sound::info() SDL_mixer: %i.%i.%i (linked)", + if (linkedVersion) + { + logger->log("Sound::info() SDL_mixer: %i.%i.%i (linked)", linkedVersion->major, linkedVersion->minor, linkedVersion->patch); + } + else + { + logger->log1("Sound::info() SDL_mixer: unknown"); + } logger->log("Sound::info() Driver: %s", driver); logger->log("Sound::info() Format: %s", format); logger->log("Sound::info() Rate: %i", rate); @@ -184,84 +192,49 @@ void Sound::setSfxVolume(int volume) Mix_Volume(-1, mSfxVolume); } -static Mix_Music *loadMusic(const std::string &filename) +static Music *loadMusic(const std::string &fileName) { ResourceManager *resman = ResourceManager::getInstance(); - std::string path = resman->getPath( - paths.getStringValue("music") + filename); - - if (path.find(".zip/") != std::string::npos || - path.find(".zip\\") != std::string::npos) - { - // Music file is a virtual file inside a zip archive - we have to copy - // it to a temporary physical file so that SDL_mixer can stream it. - logger->log("Loading music \"%s\" from temporary file tempMusic.ogg", - path.c_str()); - bool success = resman->copyFile(paths.getStringValue("music") - + filename, "tempMusic.ogg"); - if (success) - path = resman->getPath("tempMusic.ogg"); - else - return nullptr; - } - else - { - logger->log("Loading music \"%s\"", path.c_str()); - } - - if (path.empty()) - return nullptr; - - Mix_Music *music = Mix_LoadMUS(path.c_str()); - - if (!music) - { - logger->log("Mix_LoadMUS() Error loading '%s': %s", path.c_str(), - Mix_GetError()); - } - - return music; + return resman->getMusic(paths.getStringValue("music") + fileName); } -void Sound::playMusic(const std::string &filename) +void Sound::playMusic(const std::string &fileName) { - mCurrentMusicFile = filename; + mCurrentMusicFile = fileName; if (!mInstalled || !mPlayMusic) return; haltMusic(); - if (!filename.empty() && (mMusic = loadMusic(filename))) - Mix_PlayMusic(mMusic, -1); // Loop forever + if (!fileName.empty()) + { + mMusic = loadMusic(fileName); + if (mMusic) + mMusic->play(); + } } void Sound::stopMusic() { - if (!mInstalled) - return; - - logger->log1("Sound::stopMusic()"); - - if (mMusic) - { - Mix_HaltMusic(); - Mix_FreeMusic(mMusic); - mMusic = nullptr; - } + haltMusic(); } -void Sound::fadeInMusic(const std::string &path, int ms) +void Sound::fadeInMusic(const std::string &fileName, int ms) { - mCurrentMusicFile = path; + mCurrentMusicFile = fileName; if (!mInstalled || !mPlayMusic) return; haltMusic(); - if ((mMusic = loadMusic(path.c_str()))) - Mix_FadeInMusic(mMusic, -1, ms); // Loop forever + if (!fileName.empty()) + { + mMusic = loadMusic(fileName); + if (mMusic) + mMusic->play(-1, ms); + } } void Sound::fadeOutMusic(int ms) @@ -285,9 +258,9 @@ void Sound::fadeOutMusic(int ms) } } -void Sound::fadeOutAndPlayMusic(const std::string &path, int ms) +void Sound::fadeOutAndPlayMusic(const std::string &fileName, int ms) { - mNextMusicPath = path; + mNextMusicFile = fileName; fadeOutMusic(ms); } @@ -297,15 +270,15 @@ void Sound::logic() { if (mMusic) { - Mix_FreeMusic(mMusic); + mMusic->decRef(); mMusic = nullptr; } sFadingOutEnded = false; - if (!mNextMusicPath.empty()) + if (!mNextMusicFile.empty()) { - playMusic(mNextMusicPath); - mNextMusicPath.clear(); + playMusic(mNextMusicFile); + mNextMusicFile.clear(); } } } @@ -383,8 +356,11 @@ void Sound::haltMusic() return; Mix_HaltMusic(); - Mix_FreeMusic(mMusic); - mMusic = nullptr; + if (mMusic) + { + mMusic->decRef(); + mMusic = nullptr; + } } void Sound::changeAudio() diff --git a/src/sound.h b/src/sound.h index 6ac361cac..7f9fb64a4 100644 --- a/src/sound.h +++ b/src/sound.h @@ -29,6 +29,8 @@ #include <string> +class Music; + /** Sound engine * * \ingroup CORE @@ -54,9 +56,9 @@ class Sound : public ConfigListener /** * Starts background music. * - * @param path The full path to the music file. + * @param fileName The name of the music file. */ - void playMusic(const std::string &path); + void playMusic(const std::string &fileName); /** * Stops currently running background music track. @@ -66,10 +68,10 @@ class Sound : public ConfigListener /** * Fades in background music. * - * @param path The full path to the music file. - * @param ms Duration of fade-in effect (ms) + * @param fileName The name of the music file. + * @param ms Duration of fade-in effect (ms) */ - void fadeInMusic(const std::string &path, int ms = 1000); + void fadeInMusic(const std::string &fileName, int ms = 1000); /** * Fades out currently running background music track. @@ -81,15 +83,16 @@ class Sound : public ConfigListener /** * Fades out a background music and play a new one. * - * @param path The full path to the fade in music file. - * @param ms Duration of fade-out effect (ms) + * @param fileName The name of the music file. + * @param ms Duration of fade-out effect (ms) */ - void fadeOutAndPlayMusic(const std::string &path, int ms = 1000); + void fadeOutAndPlayMusic(const std::string &fileName, int ms = 1000); int getMaxVolume() const { return MIX_MAX_VOLUME; } void setMusicVolume(int volume); + void setSfxVolume(int volume); /** @@ -112,7 +115,7 @@ class Sound : public ConfigListener void volumeRestore(); - std::string getCurrentMusicFile() + std::string getCurrentMusicFile() const { return mCurrentMusicFile; } /** @@ -133,7 +136,7 @@ class Sound : public ConfigListener * When calling fadeOutAndPlayMusic(), * the music file below will then be played */ - std::string mNextMusicPath; + std::string mNextMusicFile; bool mInstalled; @@ -141,7 +144,7 @@ class Sound : public ConfigListener int mMusicVolume; std::string mCurrentMusicFile; - Mix_Music *mMusic; + Music *mMusic; bool mPlayBattle; bool mPlayGui; bool mPlayMusic; diff --git a/src/textcommand.h b/src/textcommand.h index b1af7667d..27b44cc7a 100644 --- a/src/textcommand.h +++ b/src/textcommand.h @@ -155,7 +155,7 @@ class TextCommand bool isEmpty() const { return mCommand == "" && mSymbol == "" ; } - Image *getImage() + Image *getImage() const { return mImage; } private: diff --git a/src/utils/checkutils.cpp b/src/utils/checkutils.cpp new file mode 100644 index 000000000..64bb42d0c --- /dev/null +++ b/src/utils/checkutils.cpp @@ -0,0 +1,39 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 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/checkutils.h" + +#include <string.h> + +#include "logger.h" + +bool reportFalseReal(bool val, const char* file, unsigned line) +{ + if (!val) + logger->log("Debug: false value at %s:%u", file, line); + return val; +} + +bool reportTrueReal(bool val, const char* file, unsigned line) +{ + if (val) + logger->log("Debug: true value at %s:%u", file, line); + return val; +} diff --git a/src/utils/checkutils.h b/src/utils/checkutils.h new file mode 100644 index 000000000..6791ff7e0 --- /dev/null +++ b/src/utils/checkutils.h @@ -0,0 +1,30 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 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_CHECKUTILS_H +#define UTILS_CHECKUTILS_H + +#include <string> + +bool reportFalseReal(bool val, const char* file, unsigned line); + +bool reportTrueReal(bool val, const char* file, unsigned line); + +#endif // UTILS_CHECKUTILS_H diff --git a/src/utils/copynpaste.cpp b/src/utils/copynpaste.cpp index 3e9e09a5c..d918c8108 100644 --- a/src/utils/copynpaste.cpp +++ b/src/utils/copynpaste.cpp @@ -331,7 +331,7 @@ static char* getSelection2(Display *dpy, Window us, Atom selection, if (left < 1) { if (ret == Success) - XFree(data); + XFree(data); return nullptr; } diff --git a/src/utils/physfsrwops.cpp b/src/utils/physfsrwops.cpp new file mode 100644 index 000000000..1960f0dee --- /dev/null +++ b/src/utils/physfsrwops.cpp @@ -0,0 +1,186 @@ +/* + * This code provides a glue layer between PhysicsFS and Simple Directmedia + * Layer's (SDL) RWops i/o abstraction. + * + * License: this code is public domain. I make no warranty that it is useful, + * correct, harmless, or environmentally safe. + * + * This particular file may be used however you like, including copying it + * verbatim into a closed-source project, exploiting it commercially, and + * removing any trace of my name from the source (although I hope you won't + * do that). I welcome enhancements and corrections to this file, but I do + * not require you to send me patches if you make changes. This code has + * NO WARRANTY. + * + * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license. + * Please see LICENSE.txt in the root of the source tree. + * + * SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/ + * + * This file was written by Ryan C. Gordon. (icculus@icculus.org). + * + * Copyright (C) 2012 The ManaPlus Developers + */ + +#include <stdio.h> /* used for SEEK_SET, SEEK_CUR, SEEK_END ... */ +#include "utils/physfsrwops.h" + +#include "localconsts.h" + +static int physfsrwops_seek(SDL_RWops *rw, int offset, int whence) +{ + PHYSFS_file *handle = (PHYSFS_file *) rw->hidden.unknown.data1; + int pos = 0; + + if (whence == SEEK_SET) + { + pos = offset; + } /* if */ + else if (whence == SEEK_CUR) + { + PHYSFS_sint64 current = PHYSFS_tell(handle); + if (current == -1) + { + SDL_SetError("Can't find position in file: %s", + PHYSFS_getLastError()); + return -1; + } /* if */ + + pos = (int)current; + if (((PHYSFS_sint64)pos) != current) + { + SDL_SetError("Can't fit current file position in an int!"); + return -1; + } /* if */ + + if (offset == 0) /* this is a "tell" call. We're done. */ + return pos; + + pos += offset; + } /* else if */ + else if (whence == SEEK_END) + { + PHYSFS_sint64 len = PHYSFS_fileLength(handle); + if (len == -1) + { + SDL_SetError("Can't find end of file: %s", PHYSFS_getLastError()); + return -1; + } /* if */ + + pos = (int)len; + if (((PHYSFS_sint64)pos) != len) + { + SDL_SetError("Can't fit end-of-file position in an int!"); + return -1; + } /* if */ + + pos += offset; + } /* else if */ + else + { + SDL_SetError("Invalid 'whence' parameter."); + return -1; + } /* else */ + + if ( pos < 0 ) + { + SDL_SetError("Attempt to seek past start of file."); + return -1; + } /* if */ + + if (!PHYSFS_seek(handle, (PHYSFS_uint64) pos)) + { + SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); + return -1; + } /* if */ + + return pos; +} /* physfsrwops_seek */ + +static int physfsrwops_read(SDL_RWops *rw, void *ptr, int size, int maxnum) +{ + PHYSFS_file *handle = (PHYSFS_file*)rw->hidden.unknown.data1; + PHYSFS_sint64 rc = PHYSFS_read(handle, ptr, size, maxnum); + if (rc != maxnum) + { + if (!PHYSFS_eof(handle)) /* not EOF? Must be an error. */ + SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); + } /* if */ + + return (int)rc; +} /* physfsrwops_read */ + +static int physfsrwops_write(SDL_RWops *rw, const void *ptr, int size, int num) +{ + PHYSFS_file *handle = (PHYSFS_file*)rw->hidden.unknown.data1; + PHYSFS_sint64 rc = PHYSFS_write(handle, ptr, size, num); + if (rc != num) + SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); + + return (int) rc; +} /* physfsrwops_write */ + +static int physfsrwops_close(SDL_RWops *rw) +{ + PHYSFS_file *handle = (PHYSFS_file*)rw->hidden.unknown.data1; + if (!PHYSFS_close(handle)) + { + SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); + return -1; + } /* if */ + + SDL_FreeRW(rw); + return 0; +} /* physfsrwops_close */ + +static SDL_RWops *create_rwops(PHYSFS_file *handle) +{ + SDL_RWops *retval = nullptr; + + if (!handle) + { + SDL_SetError("PhysicsFS error: %s", PHYSFS_getLastError()); + } + else + { + retval = SDL_AllocRW(); + if (retval) + { + retval->seek = physfsrwops_seek; + retval->read = physfsrwops_read; + retval->write = physfsrwops_write; + retval->close = physfsrwops_close; + retval->hidden.unknown.data1 = handle; + } /* if */ + } /* else */ + + return retval; +} /* create_rwops */ + +SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle) +{ + SDL_RWops *retval = nullptr; + if (!handle) + SDL_SetError("NULL pointer passed to PHYSFSRWOPS_makeRWops()."); + else + retval = create_rwops(handle); + + return retval; +} /* PHYSFSRWOPS_makeRWops */ + +SDL_RWops *PHYSFSRWOPS_openRead(const char *fname) +{ + return create_rwops(PHYSFS_openRead(fname)); +} /* PHYSFSRWOPS_openRead */ + +SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname) +{ + return create_rwops(PHYSFS_openWrite(fname)); +} /* PHYSFSRWOPS_openWrite */ + +SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname) +{ + return create_rwops(PHYSFS_openAppend(fname)); +} /* PHYSFSRWOPS_openAppend */ + +/* end of physfsrwops.c ... */ diff --git a/src/utils/physfsrwops.h b/src/utils/physfsrwops.h new file mode 100644 index 000000000..efa004ac6 --- /dev/null +++ b/src/utils/physfsrwops.h @@ -0,0 +1,82 @@ +/* + * This code provides a glue layer between PhysicsFS and Simple Directmedia + * Layer's (SDL) RWops i/o abstraction. + * + * License: this code is public domain. I make no warranty that it is useful, + * correct, harmless, or environmentally safe. + * + * This particular file may be used however you like, including copying it + * verbatim into a closed-source project, exploiting it commercially, and + * removing any trace of my name from the source (although I hope you won't + * do that). I welcome enhancements and corrections to this file, but I do + * not require you to send me patches if you make changes. This code has + * NO WARRANTY. + * + * Unless otherwise stated, the rest of PhysicsFS falls under the zlib license. + * Please see LICENSE.txt in the root of the source tree. + * + * SDL falls under the LGPL license. You can get SDL at http://www.libsdl.org/ + * + * This file was written by Ryan C. Gordon. (icculus@icculus.org). + * + * Copyright (C) 2012 The ManaPlus Developers + */ + +#ifndef UTILS_PHYSFSRWOPS_H +#define UTILS_PHYSFSRWOPS_H + +#include <physfs.h> +#include <SDL.h> + +/** + * Open a platform-independent filename for reading, and make it accessible + * via an SDL_RWops structure. The file will be closed in PhysicsFS when the + * RWops is closed. PhysicsFS should be configured to your liking before + * opening files through this method. + * + * @param filename File to open in platform-independent notation. + * @return A valid SDL_RWops structure on success, NULL on error. Specifics + * of the error can be gleaned from PHYSFS_getLastError(). + */ +SDL_RWops *PHYSFSRWOPS_openRead(const char *fname); + +/** + * Open a platform-independent filename for writing, and make it accessible + * via an SDL_RWops structure. The file will be closed in PhysicsFS when the + * RWops is closed. PhysicsFS should be configured to your liking before + * opening files through this method. + * + * @param filename File to open in platform-independent notation. + * @return A valid SDL_RWops structure on success, NULL on error. Specifics + * of the error can be gleaned from PHYSFS_getLastError(). + */ +SDL_RWops *PHYSFSRWOPS_openWrite(const char *fname); + +/** + * Open a platform-independent filename for appending, and make it accessible + * via an SDL_RWops structure. The file will be closed in PhysicsFS when the + * RWops is closed. PhysicsFS should be configured to your liking before + * opening files through this method. + * + * @param filename File to open in platform-independent notation. + * @return A valid SDL_RWops structure on success, NULL on error. Specifics + * of the error can be gleaned from PHYSFS_getLastError(). + */ +SDL_RWops *PHYSFSRWOPS_openAppend(const char *fname); + +/** + * Make a SDL_RWops from an existing PhysicsFS file handle. You should + * dispose of any references to the handle after successful creation of + * the RWops. The actual PhysicsFS handle will be destroyed when the + * RWops is closed. + * + * @param handle a valid PhysicsFS file handle. + * @return A valid SDL_RWops structure on success, NULL on error. Specifics + * of the error can be gleaned from PHYSFS_getLastError(). + */ +SDL_RWops *PHYSFSRWOPS_makeRWops(PHYSFS_file *handle); + +#endif /* include-once blocker */ + +/* end of physfsrwops.h ... */ + diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index b855e3b04..08bcac9e6 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -509,6 +509,39 @@ std::vector<std::string> getLang() return langs; } +std::string getLangSimple() +{ + std::string lang = config.getValue("lang", "").c_str(); + if (lang.empty()) + { + char *lng = getenv("LANG"); + if (!lng) + return ""; + return lng; + } + return lang; +} + +std::string getLangShort() +{ + std::string lang = config.getValue("lang", "").c_str(); + if (lang.empty()) + { + char *lng = getenv("LANG"); + if (!lng) + return ""; + lang = lng; + } + + int dot = lang.find("."); + if (dot != (signed)std::string::npos) + lang = lang.substr(0, dot); + dot = lang.find("_"); + if (dot != (signed)std::string::npos) + return lang.substr(0, dot); + return lang; +} + std::string packList(std::list<std::string> &list) { std::list<std::string>::const_iterator i = list.begin(); @@ -541,6 +574,9 @@ std::string stringToHexPath(const std::string &str) void deleteCharLeft(std::string &str, unsigned *pos) { + if (!pos) + return; + while (*pos > 0) { (*pos)--; diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h index c6eb08a6c..0b22ef847 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -188,6 +188,10 @@ std::string combineDye2(std::string file, std::string dye); std::vector<std::string> getLang(); +std::string getLangSimple(); + +std::string getLangShort(); + std::string packList(std::list<std::string> &list); std::list<std::string> unpackList(const std::string &str); |