summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS2
-rwxr-xr-xconfigure.ac3
-rw-r--r--data/graphics/CMakeLists.txt3
-rw-r--r--data/graphics/Makefile.am8
-rw-r--r--data/graphics/images/CMakeLists.txt1
-rw-r--r--data/graphics/images/Makefile.am3
-rw-r--r--data/graphics/sprites/CMakeLists.txt6
-rw-r--r--data/graphics/sprites/Makefile.am9
-rw-r--r--data/graphics/sprites/error.png (renamed from data/graphics/images/error.png)bin314 -> 314 bytes
-rw-r--r--data/graphics/sprites/error.xml10
-rw-r--r--packaging/windows/setup.nsi4
-rw-r--r--po/POTFILES.in39
-rw-r--r--src/actorsprite.cpp10
-rw-r--r--src/actorsprite.h2
-rw-r--r--src/client.cpp26
-rw-r--r--src/gui/login.cpp3
-rw-r--r--src/gui/minimap.cpp4
-rw-r--r--src/gui/serverdialog.cpp18
-rw-r--r--src/gui/setup_players.cpp16
-rw-r--r--src/gui/setup_video.cpp1
-rw-r--r--src/gui/skilldialog.cpp6
-rw-r--r--src/gui/socialwindow.cpp19
-rw-r--r--src/gui/statuswindow.cpp7
-rw-r--r--src/gui/theme.cpp1
-rw-r--r--src/gui/truetypefont.cpp12
-rw-r--r--src/map.cpp7
-rw-r--r--src/map.h2
-rw-r--r--src/net/download.cpp4
-rw-r--r--src/net/manaserv/charhandler.cpp21
-rw-r--r--src/net/manaserv/generalhandler.cpp8
-rw-r--r--src/net/manaserv/stats.cpp11
-rw-r--r--src/net/manaserv/stats.h5
-rw-r--r--src/net/tmwa/charserverhandler.cpp10
-rw-r--r--src/net/tmwa/loginhandler.cpp13
-rw-r--r--src/net/tmwa/loginhandler.h1
-rw-r--r--src/playerrelations.cpp11
-rw-r--r--src/resources/colordb.cpp2
-rw-r--r--src/resources/emotedb.cpp2
-rw-r--r--src/resources/itemdb.cpp2
-rw-r--r--src/resources/monsterdb.cpp2
-rw-r--r--src/resources/npcdb.cpp2
-rw-r--r--src/statuseffect.cpp10
-rw-r--r--src/statuseffect.h1
-rw-r--r--src/utils/stringutils.cpp11
-rw-r--r--src/utils/stringutils.h2
-rw-r--r--tools/dyecmd/CMakeLists.txt28
-rw-r--r--tools/dyecmd/src/CMakeLists.txt59
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/dye.cpp96
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/dye.h19
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/dyecmd.cpp132
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/imagewriter.cpp24
-rwxr-xr-x[-rw-r--r--]tools/dyecmd/src/imagewriter.h0
52 files changed, 468 insertions, 230 deletions
diff --git a/NEWS b/NEWS
index bb4e21bc..d9e09656 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-1.0.0 (31 March 2010)
+1.0.0 (...)
- The Mana World client is now called the Mana client
- Added support for branding the client differently via command line parameter
- Added support for ManaServ and eAthena (TMW version) from the same binary
diff --git a/configure.ac b/configure.ac
index b1ceceec..058fc0a6 100755
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
AC_PREREQ(2.59)
-AC_INIT([Mana], [1.0.0-beta], [dev@manasource.org], [mana])
+AC_INIT([Mana], [1.0.0-beta2], [dev@manasource.org], [mana])
AM_INIT_AUTOMAKE([1.9])
AC_CONFIG_HEADERS([config.h:config.h.in])
AC_LANG_CPLUSPLUS
@@ -141,6 +141,7 @@ data/fonts/Makefile
data/graphics/Makefile
data/graphics/gui/Makefile
data/graphics/images/Makefile
+data/graphics/sprites/Makefile
data/help/Makefile
data/icons/Makefile
docs/Makefile
diff --git a/data/graphics/CMakeLists.txt b/data/graphics/CMakeLists.txt
index d7e78c30..a46ccfd0 100644
--- a/data/graphics/CMakeLists.txt
+++ b/data/graphics/CMakeLists.txt
@@ -1,5 +1,6 @@
ADD_SUBDIRECTORY(gui)
ADD_SUBDIRECTORY(images)
+ADD_SUBDIRECTORY(sprites)
SET (FILES
target-cursor-in-range-l.png
@@ -8,4 +9,4 @@ SET (FILES
target-cursor-normal-l.png
target-cursor-normal-m.png
target-cursor-normal-s.png
- ) \ No newline at end of file
+ )
diff --git a/data/graphics/Makefile.am b/data/graphics/Makefile.am
index 6a4d65d8..d2f93f58 100644
--- a/data/graphics/Makefile.am
+++ b/data/graphics/Makefile.am
@@ -9,8 +9,8 @@ graphics_DATA = \
target-cursor-normal-m.png \
target-cursor-normal-s.png
-SUBDIRS = gui images
-
-EXTRA_DIST = \
- $(graphics_DATA) \
+EXTRA_DIST = \
+ $(graphics_DATA) \
CMakeLists.txt
+
+SUBDIRS = gui images sprites
diff --git a/data/graphics/images/CMakeLists.txt b/data/graphics/images/CMakeLists.txt
index 5181b4e1..6694f254 100644
--- a/data/graphics/images/CMakeLists.txt
+++ b/data/graphics/images/CMakeLists.txt
@@ -1,5 +1,4 @@
SET(FILES
- error.png
login_wallpaper.png
)
diff --git a/data/graphics/images/Makefile.am b/data/graphics/images/Makefile.am
index 0bc2a5cd..20ea859f 100644
--- a/data/graphics/images/Makefile.am
+++ b/data/graphics/images/Makefile.am
@@ -1,9 +1,8 @@
imagesdir = $(pkgdatadir)/data/graphics/images
images_DATA = \
- error.png \
login_wallpaper.png
EXTRA_DIST = \
- $(images_DATA) \
+ $(images_DATA) \
CMakeLists.txt
diff --git a/data/graphics/sprites/CMakeLists.txt b/data/graphics/sprites/CMakeLists.txt
new file mode 100644
index 00000000..1d98772d
--- /dev/null
+++ b/data/graphics/sprites/CMakeLists.txt
@@ -0,0 +1,6 @@
+SET(FILES
+ error.png
+ error.xml
+ )
+
+INSTALL(FILES ${FILES} DESTINATION ${DATA_DIR}/graphics/sprits)
diff --git a/data/graphics/sprites/Makefile.am b/data/graphics/sprites/Makefile.am
new file mode 100644
index 00000000..249ca5cd
--- /dev/null
+++ b/data/graphics/sprites/Makefile.am
@@ -0,0 +1,9 @@
+spritesdir = $(pkgdatadir)/data/graphics/sprites
+
+sprites_DATA = \
+ error.png \
+ error.xml
+
+EXTRA_DIST = \
+ $(sprites_DATA) \
+ CMakeLists.txt
diff --git a/data/graphics/images/error.png b/data/graphics/sprites/error.png
index 6fd7c1a8..6fd7c1a8 100644
--- a/data/graphics/images/error.png
+++ b/data/graphics/sprites/error.png
Binary files differ
diff --git a/data/graphics/sprites/error.xml b/data/graphics/sprites/error.xml
new file mode 100644
index 00000000..3504bd01
--- /dev/null
+++ b/data/graphics/sprites/error.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<sprite>
+ <imageset name="base" src="graphics/sprites/error.png" width="29" height="9" />
+
+ <action name="default" imageset="base">
+ <animation direction="default">
+ <frame index="0" />
+ </animation>
+ </action>
+</sprite> \ No newline at end of file
diff --git a/packaging/windows/setup.nsi b/packaging/windows/setup.nsi
index d768821e..1b5dc97c 100644
--- a/packaging/windows/setup.nsi
+++ b/packaging/windows/setup.nsi
@@ -189,6 +189,7 @@ Section "Core files (required)" SecCore
CreateDirectory "$INSTDIR\data\icons"
CreateDirectory "$INSTDIR\data\graphics\gui"
CreateDirectory "$INSTDIR\data\graphics\images"
+ CreateDirectory "$INSTDIR\data\graphics\sprites"
CreateDirectory "$INSTDIR\docs"
SetOverwrite ifnewer
@@ -209,6 +210,9 @@ Section "Core files (required)" SecCore
File "${SRCDIR}\data\graphics\gui\*.xml"
SetOutPath "$INSTDIR\data\graphics\images"
File /x minimap_*.png ${SRCDIR}\data\graphics\images\*.png
+ SetOutPath "$INSTDIR\data\graphics\sprites"
+ File "${SRCDIR}\data\graphics\sprites\*.png"
+ File "${SRCDIR}\data\graphics\sprites\*.xml"
SetOutPath "$INSTDIR\data\help"
File "${SRCDIR}\data\help\*.txt"
SetOutPath "$INSTDIR\data\icons\"
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 738dd8a3..e2fbe68b 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -23,11 +23,11 @@ src/gui/itemamount.cpp
src/gui/itempopup.cpp
src/gui/login.cpp
src/gui/minimap.cpp
+src/gui/ministatus.cpp
src/gui/npcdialog.cpp
src/gui/npcpostdialog.cpp
src/gui/okdialog.cpp
src/gui/outfitwindow.cpp
-src/gui/palette.cpp
src/gui/popupmenu.cpp
src/gui/quitdialog.cpp
src/gui/recorder.cpp
@@ -48,11 +48,11 @@ src/gui/skilldialog.cpp
src/gui/socialwindow.cpp
src/gui/specialswindow.cpp
src/gui/statuswindow.cpp
-src/gui/storagewindow.cpp
src/gui/textdialog.cpp
src/gui/trade.cpp
src/gui/unregisterdialog.cpp
src/gui/updatewindow.cpp
+src/gui/userpalette.cpp
src/gui/widgets/channeltab.cpp
src/gui/widgets/chattab.cpp
src/gui/widgets/whispertab.cpp
@@ -62,33 +62,34 @@ src/keyboardconfig.cpp
src/localplayer.cpp
src/log.h
src/main.cpp
-src/net/ea/adminhandler.cpp
-src/net/ea/buysellhandler.cpp
-src/net/ea/charserverhandler.cpp
-src/net/ea/chathandler.cpp
-src/net/ea/gamehandler.cpp
-src/net/ea/generalhandler.cpp
-src/net/ea/gui/guildtab.cpp
-src/net/ea/guildhandler.cpp
-src/net/ea/gui/partytab.cpp
-src/net/ea/inventoryhandler.cpp
-src/net/ea/loginhandler.cpp
-src/net/ea/network.cpp
-src/net/ea/partyhandler.cpp
-src/net/ea/playerhandler.cpp
-src/net/ea/specialhandler.cpp
-src/net/ea/tradehandler.cpp
src/net/manaserv/beinghandler.cpp
src/net/manaserv/charhandler.cpp
src/net/manaserv/chathandler.cpp
-src/net/manaserv/generalhandler.cpp
src/net/manaserv/guildhandler.cpp
src/net/manaserv/loginhandler.cpp
src/net/manaserv/partyhandler.cpp
src/net/manaserv/playerhandler.cpp
+src/net/manaserv/stats.cpp
src/net/manaserv/tradehandler.cpp
+src/net/tmwa/adminhandler.cpp
+src/net/tmwa/buysellhandler.cpp
+src/net/tmwa/charserverhandler.cpp
+src/net/tmwa/chathandler.cpp
+src/net/tmwa/gamehandler.cpp
+src/net/tmwa/generalhandler.cpp
+src/net/tmwa/gui/guildtab.cpp
+src/net/tmwa/guildhandler.cpp
+src/net/tmwa/gui/partytab.cpp
+src/net/tmwa/inventoryhandler.cpp
+src/net/tmwa/loginhandler.cpp
+src/net/tmwa/network.cpp
+src/net/tmwa/partyhandler.cpp
+src/net/tmwa/playerhandler.cpp
+src/net/tmwa/specialhandler.cpp
+src/net/tmwa/tradehandler.cpp
src/playerrelations.cpp
src/resources/itemdb.cpp
src/resources/monsterdb.cpp
+src/resources/monsterinfo.cpp
src/utils/gettext.h
src/utils/stringutils.h
diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp
index a7821699..1104d810 100644
--- a/src/actorsprite.cpp
+++ b/src/actorsprite.cpp
@@ -43,6 +43,7 @@
ImageSet *ActorSprite::targetCursorImages[2][NUM_TC];
SimpleAnimation *ActorSprite::targetCursor[2][NUM_TC];
+bool ActorSprite::loaded = false;
ActorSprite::ActorSprite(int id):
mId(id),
@@ -345,12 +346,21 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display,
void ActorSprite::load()
{
+ if (loaded)
+ unload();
+
initTargetCursor();
+
+ loaded = true;
}
void ActorSprite::unload()
{
+ if (!loaded)
+ return;
+
cleanupTargetCursors();
+ loaded = false;
}
static const char *cursorType(int type)
diff --git a/src/actorsprite.h b/src/actorsprite.h
index 6c5885e6..e218ef74 100644
--- a/src/actorsprite.h
+++ b/src/actorsprite.h
@@ -223,6 +223,8 @@ private:
/** Animated target cursors. */
static SimpleAnimation *targetCursor[NUM_TCT][NUM_TC];
+ static bool loaded;
+
/** Target cursor being used */
SimpleAnimation *mUsedTargetCursor;
};
diff --git a/src/client.cpp b/src/client.cpp
index 323d5b49..35292d22 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -433,6 +433,14 @@ Client::~Client()
SDL_RemoveTimer(mLogicCounterId);
SDL_RemoveTimer(mSecondsCounterId);
+ // Unload XML databases
+ ColorDB::unload();
+ EmoteDB::unload();
+ ItemDB::unload();
+ MonsterDB::unload();
+ NPCDB::unload();
+ StatusEffect::unload();
+
// Before config.write() since it writes the shortcuts to the config
delete itemShortcut;
delete emoteShortcut;
@@ -586,19 +594,6 @@ int Client::exec()
{
delete game;
game = 0;
-
- if (mState != STATE_CHANGE_MAP)
- {
- // Unload XML databases
- ColorDB::unload();
- EmoteDB::unload();
- ItemDB::unload();
- MonsterDB::unload();
- NPCDB::unload();
- StatusEffect::unload();
-
- ActorSprite::unload();
- }
}
mOldState = mState;
@@ -973,6 +968,7 @@ int Client::exec()
case STATE_ERROR:
logger->log("State: ERROR");
+ logger->log("Error: %s\n", errorMessage.c_str());
mCurrentDialog = new OkDialog(_("Error"), errorMessage);
mCurrentDialog->addActionListener(&errorListener);
mCurrentDialog = NULL; // OkDialog deletes itself
@@ -1159,6 +1155,10 @@ void Client::initUpdatesDir()
mUpdateHost = config.getValue("updatehost", "");
}
+ // Don't go out of range int he next check
+ if (mUpdateHost.length() < 2)
+ return;
+
// Remove any trailing slash at the end of the update host
if (!mUpdateHost.empty() && mUpdateHost.at(mUpdateHost.size() - 1) == '/')
mUpdateHost.resize(mUpdateHost.size() - 1);
diff --git a/src/gui/login.cpp b/src/gui/login.cpp
index bfad5c32..b243fd04 100644
--- a/src/gui/login.cpp
+++ b/src/gui/login.cpp
@@ -91,7 +91,8 @@ LoginDialog::LoginDialog(LoginData *loginData):
mPassField->requestFocus();
mLoginButton->setEnabled(canSubmit());
- mRegisterButton->setEnabled(Net::getLoginHandler()->isRegistrationEnabled());
+ mRegisterButton->setEnabled(Net::getLoginHandler()
+ ->isRegistrationEnabled());
}
LoginDialog::~LoginDialog()
diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp
index e973fa54..1d01f48c 100644
--- a/src/gui/minimap.cpp
+++ b/src/gui/minimap.cpp
@@ -97,15 +97,13 @@ void Minimap::setMap(Map *map)
if (map)
{
std::string tempname =
- "graphics/minimaps/"+(*map->getFilename())+".png";
+ "graphics/minimaps/" + map->getFilename() + ".png";
ResourceManager *resman = ResourceManager::getInstance();
minimapName = map->getProperty("minimap");
if (minimapName.empty() && resman->exists(tempname))
- {
minimapName = tempname;
- }
mMapImage = resman->getImage(minimapName);
}
diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp
index 25725a80..ad8ab3c8 100644
--- a/src/gui/serverdialog.cpp
+++ b/src/gui/serverdialog.cpp
@@ -26,6 +26,7 @@
#include "configuration.h"
#include "gui.h"
#include "log.h"
+#include "main.h"
#include "gui/okdialog.h"
#include "gui/sdlinput.h"
@@ -527,6 +528,15 @@ void ServerDialog::loadServers()
std::string type = XML::getProperty(serverNode, "type", "unknown");
server.type = ServerInfo::parseType(type);
+
+ // Ignore unknown server types
+ if (server.type == ServerInfo::UNKNOWN)
+ {
+ logger->log("Ignoring server entry with unknown type: %s",
+ type.c_str());
+ continue;
+ }
+
server.name = XML::getProperty(serverNode, "name", std::string());
std::string version = XML::getProperty(serverNode, "minimumVersion",
@@ -538,15 +548,11 @@ void ServerDialog::loadServers()
// For display in the list
if (meetsMinimumVersion)
version.clear();
+ else if (version.empty())
+ version = _("requires a newer version");
else
version = strprintf(_("requires v%s"), version.c_str());
- if (server.type == ServerInfo::UNKNOWN)
- {
- logger->log("Unknown server type: %s", type.c_str());
- continue;
- }
-
for_each_xml_child_node(subNode, serverNode)
{
if (xmlStrEqual(subNode->name, BAD_CAST "connection"))
diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp
index 15cc787a..f7a39240 100644
--- a/src/gui/setup_players.cpp
+++ b/src/gui/setup_players.cpp
@@ -35,6 +35,7 @@
#include "gui/widgets/scrollarea.h"
#include "gui/widgets/table.h"
+#include "utils/dtor.h"
#include "utils/gettext.h"
#include <string>
@@ -88,7 +89,8 @@ class PlayerTableModel : public TableModel
{
public:
PlayerTableModel() :
- mPlayers(NULL)
+ mPlayers(NULL),
+ mListModel(new PlayerRelationListModel)
{
playerRelationsUpdated();
}
@@ -96,6 +98,7 @@ public:
virtual ~PlayerTableModel()
{
freeWidgets();
+ delete mListModel;
if (mPlayers)
delete mPlayers;
}
@@ -139,9 +142,8 @@ public:
std::string name = (*player_names)[r];
gcn::Widget *widget = new Label(name);
mWidgets.push_back(widget);
- gcn::ListModel *playerRelation = new PlayerRelationListModel;
- gcn::DropDown *choicebox = new DropDown(playerRelation);
+ gcn::DropDown *choicebox = new DropDown(mListModel);
choicebox->setSelected(player_relations.getRelation(name));
mWidgets.push_back(choicebox);
}
@@ -170,12 +172,7 @@ public:
delete mPlayers;
mPlayers = NULL;
- for (std::vector<gcn::Widget *>::const_iterator it = mWidgets.begin();
- it != mWidgets.end(); it++)
- {
- delete *it;
- }
-
+ delete_all(mWidgets);
mWidgets.clear();
}
@@ -187,6 +184,7 @@ public:
protected:
std::vector<std::string> *mPlayers;
std::vector<gcn::Widget *> mWidgets;
+ PlayerRelationListModel *mListModel;
};
/**
diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp
index ebe53261..81ce8107 100644
--- a/src/gui/setup_video.cpp
+++ b/src/gui/setup_video.cpp
@@ -380,6 +380,7 @@ Setup_Video::Setup_Video():
Setup_Video::~Setup_Video()
{
delete mModeListModel;
+ delete mModeList;
delete mFontSizeListModel;
}
diff --git a/src/gui/skilldialog.cpp b/src/gui/skilldialog.cpp
index 1a265589..683a6d43 100644
--- a/src/gui/skilldialog.cpp
+++ b/src/gui/skilldialog.cpp
@@ -185,6 +185,12 @@ public:
setCaption(name);
}
+ ~SkillTab()
+ {
+ delete mListBox;
+ mListBox = 0;
+ }
+
SkillInfo *getSelectedInfo()
{
return mListBox->getSelectedInfo();
diff --git a/src/gui/socialwindow.cpp b/src/gui/socialwindow.cpp
index 2043da52..25447f30 100644
--- a/src/gui/socialwindow.cpp
+++ b/src/gui/socialwindow.cpp
@@ -61,7 +61,7 @@ protected:
mConfirmDialog(NULL)
{}
- ~SocialTab()
+ virtual ~SocialTab()
{
// Cleanup dialogs
if (mInviteDialog)
@@ -106,6 +106,14 @@ public:
mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
}
+ ~GuildTab()
+ {
+ delete mList;
+ mList = 0;
+ delete mScroll;
+ mScroll = 0;
+ }
+
void action(const gcn::ActionEvent &event)
{
if (event.getId() == "do invite")
@@ -179,6 +187,14 @@ public:
mScroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
}
+ ~PartyTab()
+ {
+ delete mList;
+ mList = 0;
+ delete mScroll;
+ mScroll = 0;
+ }
+
void action(const gcn::ActionEvent &event)
{
if (event.getId() == "do invite")
@@ -350,6 +366,7 @@ SocialWindow::~SocialWindow()
mPartyInviter = "";
}
+ delete mCreatePopup;
}
bool SocialWindow::addTab(Guild *guild)
diff --git a/src/gui/statuswindow.cpp b/src/gui/statuswindow.cpp
index ad9c0ed7..c8ebdc98 100644
--- a/src/gui/statuswindow.cpp
+++ b/src/gui/statuswindow.cpp
@@ -51,6 +51,8 @@ class AttrDisplay : public Container
DERIVED, CHANGEABLE, UNKNOWN
};
+ ~AttrDisplay();
+
virtual std::string update();
virtual Type getType() { return UNKNOWN; }
@@ -404,6 +406,11 @@ AttrDisplay::AttrDisplay(int id, const std::string &name):
mLayout = new LayoutHelper(this);
}
+AttrDisplay::~AttrDisplay()
+{
+ delete mLayout;
+}
+
std::string AttrDisplay::update()
{
int base = player_node->getAttributeBase(mId);
diff --git a/src/gui/theme.cpp b/src/gui/theme.cpp
index 1406a0d0..e46616e0 100644
--- a/src/gui/theme.cpp
+++ b/src/gui/theme.cpp
@@ -228,6 +228,7 @@ Skin *Theme::readSkin(const std::string &filename)
Image *dBorders = Theme::getImageFromTheme(skinSetImage);
ImageRect border;
+ memset(&border, 0, sizeof(ImageRect));
// iterate <widget>'s
for_each_xml_child_node(widgetNode, rootNode)
diff --git a/src/gui/truetypefont.cpp b/src/gui/truetypefont.cpp
index 3bf1febe..e2ae5b93 100644
--- a/src/gui/truetypefont.cpp
+++ b/src/gui/truetypefont.cpp
@@ -26,9 +26,11 @@
#include "resources/image.h"
+#include "utils/stringutils.h"
+
#include <guichan/exception.hpp>
-#define CACHE_SIZE 256
+const unsigned int CACHE_SIZE = 256;
class TextChunk
{
@@ -55,8 +57,10 @@ class TextChunk
sdlCol.r = color.r;
sdlCol.g = color.g;
+ const char* str = getSafeUtf8String(text);
SDL_Surface *surface = TTF_RenderUTF8_Blended(
- font, text.c_str(), sdlCol);
+ font, str, sdlCol);
+ delete[] str;
if (!surface)
{
@@ -175,7 +179,9 @@ int TrueTypeFont::getWidth(const std::string &text) const
}
int w, h;
- TTF_SizeUTF8(mFont, text.c_str(), &w, &h);
+ const char* str = getSafeUtf8String(text);
+ TTF_SizeUTF8(mFont, str, &w, &h);
+ delete[] str;
return w;
}
diff --git a/src/map.cpp b/src/map.cpp
index 7b62746b..33bbccb1 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -580,16 +580,13 @@ const std::string Map::getName() const
return getProperty("mapname");
}
-const std::string *Map::getFilename() const
+const std::string Map::getFilename() const
{
std::string fileName = getProperty("_filename");
int lastSlash = fileName.rfind("/") + 1;
int lastDot = fileName.rfind(".");
- std::string *sub = new std::string(
- fileName.substr(lastSlash, lastDot - lastSlash));
-
- return sub;
+ return fileName.substr(lastSlash, lastDot - lastSlash);
}
Position Map::checkNodeOffsets(int radius, unsigned char walkMask,
diff --git a/src/map.h b/src/map.h
index 19d42b02..86a5d3ee 100644
--- a/src/map.h
+++ b/src/map.h
@@ -266,7 +266,7 @@ class Map : public Properties
/**
* Gives the map id based on filepath (ex: 009-1)
*/
- const std::string *getFilename() const;
+ const std::string getFilename() const;
/**
* Check the current position against surrounding blocking tiles, and
diff --git a/src/net/download.cpp b/src/net/download.cpp
index 2b96a6b9..a2cd4910 100644
--- a/src/net/download.cpp
+++ b/src/net/download.cpp
@@ -122,7 +122,7 @@ void Download::setWriteFunction(WriteFunction write)
bool Download::start()
{
- logger->log("Starting download: %s\n", mUrl.c_str());
+ logger->log("Starting download: %s", mUrl.c_str());
mThread = SDL_CreateThread(downloadThread, this);
@@ -140,7 +140,7 @@ bool Download::start()
void Download::cancel()
{
- logger->log("Canceling download: %s\n", mUrl.c_str());
+ logger->log("Canceling download: %s", mUrl.c_str());
mOptions.cancel = true;
if (mThread && SDL_GetThreadID(mThread) != 0)
diff --git a/src/net/manaserv/charhandler.cpp b/src/net/manaserv/charhandler.cpp
index 721780d2..e2c67f35 100644
--- a/src/net/manaserv/charhandler.cpp
+++ b/src/net/manaserv/charhandler.cpp
@@ -37,6 +37,7 @@
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
#include "net/manaserv/protocol.h"
+#include "net/manaserv/stats.h"
#include "resources/colordb.h"
@@ -258,15 +259,7 @@ void CharHandler::setCharCreateDialog(CharCreateDialog *window)
if (!mCharCreateDialog)
return;
- std::vector<std::string> attributes;
- attributes.push_back(_("Strength:"));
- attributes.push_back(_("Agility:"));
- attributes.push_back(_("Dexterity:"));
- attributes.push_back(_("Vitality:"));
- attributes.push_back(_("Intelligence:"));
- attributes.push_back(_("Willpower:"));
-
- mCharCreateDialog->setAttributes(attributes, 60, 1, 20);
+ mCharCreateDialog->setAttributes(Stats::getLabelVector(), 60, 1, 20);
}
void CharHandler::requestCharacters()
@@ -304,12 +297,10 @@ void CharHandler::newCharacter(const std::string &name,
msg.writeInt8(hairstyle);
msg.writeInt8(hairColor);
msg.writeInt8(gender);
- msg.writeInt16(stats[0]);
- msg.writeInt16(stats[1]);
- msg.writeInt16(stats[2]);
- msg.writeInt16(stats[3]);
- msg.writeInt16(stats[4]);
- msg.writeInt16(stats[5]);
+
+ std::vector<int>::const_iterator it, it_end;
+ for (it = stats.begin(), it_end = stats.end(); it != it_end; it++)
+ msg.writeInt16((*it));
accountServerConnection->send(msg);
}
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
index 09f68c1e..0d3073f1 100644
--- a/src/net/manaserv/generalhandler.cpp
+++ b/src/net/manaserv/generalhandler.cpp
@@ -108,9 +108,6 @@ void GeneralHandler::load()
registerHandler(mPartyHandler.get());
registerHandler(mPlayerHandler.get());
registerHandler(mTradeHandler.get());
-
- Stats::load();
- Stats::informItemDB();
}
void GeneralHandler::reload()
@@ -194,6 +191,11 @@ void GeneralHandler::stateChanged(State oldState, State newState)
GameHandler *game = static_cast<GameHandler*>(Net::getGameHandler());
game->gameLoading();
}
+ else if (newState == STATE_LOAD_DATA)
+ {
+ Stats::load();
+ Stats::informItemDB();
+ }
}
} // namespace ManaServ
diff --git a/src/net/manaserv/stats.cpp b/src/net/manaserv/stats.cpp
index b79b1fd9..f109a232 100644
--- a/src/net/manaserv/stats.cpp
+++ b/src/net/manaserv/stats.cpp
@@ -198,5 +198,16 @@ namespace Stats {
it->second.modifiable,
it->second.description);
}
+
+ std::vector<std::string> getLabelVector()
+ {
+ std::vector<std::string> attributes;
+ StatMap::const_iterator it, it_end;
+ for (it = stats.begin(), it_end = stats.end(); it != it_end; it++)
+ if (it->second.modifiable)
+ attributes.push_back(it->second.name + ":");
+
+ return attributes;
+ }
} // namespace Stats
} // namespace ManaServ
diff --git a/src/net/manaserv/stats.h b/src/net/manaserv/stats.h
index c4afbd79..63349095 100644
--- a/src/net/manaserv/stats.h
+++ b/src/net/manaserv/stats.h
@@ -21,6 +21,9 @@
#ifndef NET_MANASERV_STATS_H
#define NET_MANASERV_STATS_H
+#include <string>
+#include <vector>
+
namespace ManaServ {
namespace Stats {
void load();
@@ -30,6 +33,8 @@ namespace Stats {
void informItemDB();
void informStatusWindow();
+
+ std::vector<std::string> getLabelVector();
} // namespace Stats
} // namespace ManaServ
diff --git a/src/net/tmwa/charserverhandler.cpp b/src/net/tmwa/charserverhandler.cpp
index 843e5c9f..8f15691c 100644
--- a/src/net/tmwa/charserverhandler.cpp
+++ b/src/net/tmwa/charserverhandler.cpp
@@ -70,9 +70,6 @@ CharServerHandler::CharServerHandler()
void CharServerHandler::handleMessage(Net::MessageIn &msg)
{
- logger->log("CharServerHandler: Packet ID: %x, Length: %d",
- msg.getId(), msg.getLength());
-
switch (msg.getId())
{
case SMSG_CHAR_LOGIN:
@@ -102,16 +99,17 @@ void CharServerHandler::handleMessage(Net::MessageIn &msg)
switch (msg.readInt8())
{
case 0:
- errorMessage = _("Access denied.");
+ errorMessage = _("Access denied. Most likely, there are "
+ "too many players on this server.");
break;
case 1:
errorMessage = _("Cannot use this ID.");
break;
default:
- errorMessage = _("Unknown failure to select character.");
+ errorMessage = _("Unknown char-server failure.");
break;
}
- unlockCharSelectDialog();
+ Client::setState(STATE_ERROR);
break;
case SMSG_CHAR_CREATE_SUCCEEDED:
diff --git a/src/net/tmwa/loginhandler.cpp b/src/net/tmwa/loginhandler.cpp
index 7d973ba3..e58acb4d 100644
--- a/src/net/tmwa/loginhandler.cpp
+++ b/src/net/tmwa/loginhandler.cpp
@@ -42,6 +42,7 @@ namespace TmwAthena {
extern ServerInfo charServer;
LoginHandler::LoginHandler():
+ mVersionResponse(false),
mRegistrationEnabled(true)
{
static const Uint16 _messages[] = {
@@ -187,6 +188,7 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
case SMSG_SERVER_VERSION_RESPONSE:
{
// TODO: verify these!
+
msg.readInt8(); // -1
msg.readInt8(); // T
msg.readInt8(); // M
@@ -194,13 +196,10 @@ void LoginHandler::handleMessage(Net::MessageIn &msg)
unsigned int options = msg.readInt32();
- if (options & 1)
- {
- // Registeration not allowed
- mRegistrationEnabled = false;
- }
+ mRegistrationEnabled = (options & 1);
- //state = STATE_LOGIN;
+ // Leave this last
+ mVersionResponse = true;
}
break;
}
@@ -214,7 +213,7 @@ void LoginHandler::connect()
bool LoginHandler::isConnected()
{
- return mNetwork->isConnected();
+ return mVersionResponse && mNetwork->isConnected();
}
void LoginHandler::disconnect()
diff --git a/src/net/tmwa/loginhandler.h b/src/net/tmwa/loginhandler.h
index 455c75f1..8f6ea321 100644
--- a/src/net/tmwa/loginhandler.h
+++ b/src/net/tmwa/loginhandler.h
@@ -83,6 +83,7 @@ class LoginHandler : public MessageHandler, public Net::LoginHandler
void sendLoginRegister(const std::string &username,
const std::string &password);
+ bool mVersionResponse;
bool mRegistrationEnabled;
std::string mUpdateHost;
Worlds mWorlds;
diff --git a/src/playerrelations.cpp b/src/playerrelations.cpp
index 77d3fddd..f5d3d01b 100644
--- a/src/playerrelations.cpp
+++ b/src/playerrelations.cpp
@@ -90,13 +90,20 @@ PlayerRelation::PlayerRelation(Relation relation)
PlayerRelationsManager::PlayerRelationsManager() :
mPersistIgnores(false),
mDefaultPermissions(PlayerRelation::DEFAULT),
- mIgnoreStrategy(NULL)
+ mIgnoreStrategy(0)
{
}
PlayerRelationsManager::~PlayerRelationsManager()
{
delete_all(mIgnoreStrategies);
+
+ for (std::map<std::string,
+ PlayerRelation *>::const_iterator it = mRelations.begin();
+ it != mRelations.end(); it++)
+ {
+ delete it->second;
+ }
}
void PlayerRelationsManager::clear()
@@ -104,7 +111,9 @@ void PlayerRelationsManager::clear()
std::vector<std::string> *names = getPlayers();
for (std::vector<std::string>::const_iterator
it = names->begin(); it != names->end(); it++)
+ {
removePlayer(*it);
+ }
delete names;
}
diff --git a/src/resources/colordb.cpp b/src/resources/colordb.cpp
index 0041cee4..c35a5660 100644
--- a/src/resources/colordb.cpp
+++ b/src/resources/colordb.cpp
@@ -36,7 +36,7 @@ namespace
void ColorDB::load()
{
if (mLoaded)
- return;
+ unload();
XML::Document *doc = new XML::Document("hair.xml");
xmlNodePtr root = doc->rootNode();
diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp
index 117c0bab..fddab500 100644
--- a/src/resources/emotedb.cpp
+++ b/src/resources/emotedb.cpp
@@ -36,7 +36,7 @@ namespace
void EmoteDB::load()
{
if (mLoaded)
- return;
+ unload();
mLastEmote = 0;
diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp
index 57df6143..205268e5 100644
--- a/src/resources/itemdb.cpp
+++ b/src/resources/itemdb.cpp
@@ -109,7 +109,7 @@ static std::string normalized(const std::string &name)
void ItemDB::load()
{
if (mLoaded)
- return;
+ unload();
logger->log("Initializing item database...");
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index da89302d..0732bb19 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.cpp
@@ -42,7 +42,7 @@ namespace
void MonsterDB::load()
{
if (mLoaded)
- return;
+ unload();
logger->log("Initializing monster database...");
diff --git a/src/resources/npcdb.cpp b/src/resources/npcdb.cpp
index 03581e13..4f0ee10d 100644
--- a/src/resources/npcdb.cpp
+++ b/src/resources/npcdb.cpp
@@ -37,7 +37,7 @@ namespace
void NPCDB::load()
{
if (mLoaded)
- return;
+ unload();
logger->log("Initializing NPC database...");
diff --git a/src/statuseffect.cpp b/src/statuseffect.cpp
index 49619f8a..6ab0b8fa 100644
--- a/src/statuseffect.cpp
+++ b/src/statuseffect.cpp
@@ -32,6 +32,8 @@
#define STATUS_EFFECTS_FILE "status-effects.xml"
+bool StatusEffect::mLoaded = false;
+
StatusEffect::StatusEffect() :
mPersistentParticleEffect(false)
{}
@@ -113,6 +115,9 @@ StatusEffect *StatusEffect::getStunEffect(int index, bool enabling)
void StatusEffect::load()
{
+ if (mLoaded)
+ unload();
+
XML::Document doc(STATUS_EFFECTS_FILE);
xmlNodePtr rootNode = doc.rootNode();
@@ -175,8 +180,13 @@ void unloadMap(std::map<int, StatusEffect *> map)
void StatusEffect::unload()
{
+ if (!mLoaded)
+ return;
+
unloadMap(statusEffects[0]);
unloadMap(statusEffects[1]);
unloadMap(stunEffects[0]);
unloadMap(stunEffects[1]);
+
+ mLoaded = false;
}
diff --git a/src/statuseffect.h b/src/statuseffect.h
index 0fed5748..fc0e7336 100644
--- a/src/statuseffect.h
+++ b/src/statuseffect.h
@@ -98,6 +98,7 @@ public:
static void unload();
private:
+ static bool mLoaded;
std::string mMessage;
std::string mSFXEffect;
diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp
index 01bf0d3c..9fe3de14 100644
--- a/src/utils/stringutils.cpp
+++ b/src/utils/stringutils.cpp
@@ -21,10 +21,13 @@
#include "utils/stringutils.h"
+#include <string.h>
#include <algorithm>
#include <cstdarg>
#include <cstdio>
+const int UTF8_MAX_SIZE = 10;
+
std::string &trim(std::string &str)
{
std::string::size_type pos = str.find_last_not_of(' ');
@@ -164,3 +167,11 @@ const std::string findSameSubstring(const std::string &str1, const std::string &
}
return str1.substr(0, minLength);
}
+
+const char* getSafeUtf8String(std::string text)
+{
+ char* buf = new char[text.size() + UTF8_MAX_SIZE];
+ memcpy(buf, text.c_str(), text.size());
+ memset(buf + text.size(), 0, UTF8_MAX_SIZE);
+ return buf;
+} \ No newline at end of file
diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h
index 5e4718c0..ec82e240 100644
--- a/src/utils/stringutils.h
+++ b/src/utils/stringutils.h
@@ -123,4 +123,6 @@ bool isWordSeparator(char chr);
const std::string findSameSubstring(const std::string &str1, const std::string &str2);
+const char* getSafeUtf8String(std::string text);
+
#endif // UTILS_STRINGUTILS_H
diff --git a/tools/dyecmd/CMakeLists.txt b/tools/dyecmd/CMakeLists.txt
new file mode 100644
index 00000000..48566648
--- /dev/null
+++ b/tools/dyecmd/CMakeLists.txt
@@ -0,0 +1,28 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+PROJECT(MANA_DYECOMMAND)
+
+IF (NOT VERSION)
+ SET(VERSION 1.0.0)
+ENDIF()
+
+STRING(REPLACE "." " " _VERSION ${VERSION})
+SEPARATE_ARGUMENTS(_VERSION)
+LIST(LENGTH _VERSION _LEN)
+IF(NOT (_LEN EQUAL 4 OR _LEN EQUAL 3))
+ MESSAGE(FATAL_ERROR "Version needs to be in the form MAJOR.MINOR.RELEASE[.BUILD]")
+ENDIF()
+
+LIST(GET _VERSION 0 VER_MAJOR)
+LIST(GET _VERSION 1 VER_MINOR)
+LIST(GET _VERSION 2 VER_RELEASE)
+IF(_LEN EQUAL 4)
+ LIST(GET _VERSION 3 VER_BUILD)
+ELSE()
+ SET(VER_BUILD 0)
+ENDIF()
+
+# where to look for cmake modules
+SET(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMake/Modules)
+
+ADD_SUBDIRECTORY(src)
diff --git a/tools/dyecmd/src/CMakeLists.txt b/tools/dyecmd/src/CMakeLists.txt
new file mode 100644
index 00000000..f8e717b7
--- /dev/null
+++ b/tools/dyecmd/src/CMakeLists.txt
@@ -0,0 +1,59 @@
+FIND_PACKAGE(SDL REQUIRED)
+FIND_PACKAGE(SDL_image REQUIRED)
+FIND_PACKAGE(PNG REQUIRED)
+
+IF (CMAKE_COMPILER_IS_GNUCXX)
+ # Help getting compilation warnings
+ SET(CMAKE_CXX_FLAGS "-Wall")
+ IF (WIN32)
+ # This includes enough debug information to get something useful
+ # from Dr. Mingw while keeping binary size down. Almost useless
+ # with gdb, though.
+ SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -ggdb0 -gstabs2")
+ ENDIF()
+ENDIF()
+
+SET(FLAGS "-DPACKAGE_VERSION=\\\"${VERSION}\\\"")
+SET(FLAGS "${FLAGS} -DPKG_DATADIR=\\\"${PKG_DATADIR}/\\\"")
+SET(FLAGS "${FLAGS} -DLOCALEDIR=\\\"${LOCALEDIR}/\\\"")
+
+IF (CMAKE_BUILD_TYPE)
+ STRING(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER)
+ IF((CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) OR
+ (CMAKE_BUILD_TYPE_TOLOWER MATCHES relwithdebinfo))
+ SET(FLAGS "${FLAGS} -DDEBUG")
+ ENDIF()
+ENDIF()
+
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${SDL_INCLUDE_DIR}
+ ${SDLIMAGE_INCLUDE_DIR}
+ ${PNG_INCLUDE_DIR}
+ )
+
+# Fix some stuff that gets not hidden by mainline modules
+MARK_AS_ADVANCED(SDLIMAGE_INCLUDE_DIR)
+MARK_AS_ADVANCED(SDLIMAGE_LIBRARY)
+MARK_AS_ADVANCED(SDLMAIN_LIBRARY)
+MARK_AS_ADVANCED(SDL_INCLUDE_DIR)
+MARK_AS_ADVANCED(SDL_LIBRARY)
+
+SET(SRCS
+ dye.cpp
+ dye.h
+ dyecmd.cpp
+ imagewriter.cpp
+ imagewriter.h
+ )
+
+SET (PROGRAMS dyecmd)
+
+ADD_EXECUTABLE(dyecmd WIN32 ${SRCS})
+
+TARGET_LINK_LIBRARIES(dyecmd
+ ${SDL_LIBRARY}
+ ${SDLIMAGE_LIBRARY}
+ ${PNG_LIBRARIES})
+
+SET_TARGET_PROPERTIES(dyecmd PROPERTIES COMPILE_FLAGS "${FLAGS}")
diff --git a/tools/dyecmd/src/dye.cpp b/tools/dyecmd/src/dye.cpp
index 76b759cc..77da2ebb 100644..100755
--- a/tools/dyecmd/src/dye.cpp
+++ b/tools/dyecmd/src/dye.cpp
@@ -21,16 +21,20 @@
#include <algorithm>
#include <sstream>
+#include <iostream>
#include "dye.h"
Palette::Palette(const std::string &description)
{
+ mLoaded = false;
int size = description.length();
if (size == 0) return;
if (description[0] != '#')
{
- throw;
+ std::cout << "Missing # in the palette description "
+ << "in the third parameter." << std::endl;
+ return;
}
int pos = 1;
@@ -42,25 +46,41 @@ Palette::Palette(const std::string &description)
{
char c = description[pos + i];
int n;
- if ('0' <= c && c <= '9') n = c - '0';
- else if ('A' <= c && c <= 'F') n = c - 'A' + 10;
- else if ('a' <= c && c <= 'f') n = c - 'a' + 10;
+ if ('0' <= c && c <= '9')
+ n = c - '0';
+ else if ('A' <= c && c <= 'F')
+ n = c - 'A' + 10;
+ else if ('a' <= c && c <= 'f')
+ n = c - 'a' + 10;
else
- throw;
+ {
+ std::cout << "invalid Hexadecimal description: "
+ << description << std::endl;
+ return;
+ }
v = (v << 4) | n;
}
Color c = { { v >> 16, v >> 8, v } };
mColors.push_back(c);
pos += 6;
- if (pos == size) return;
- if (description[pos] != ',') break;
+ if (pos == size)
+ {
+ mLoaded = true;
+ return;
+ }
+ if (description[pos] != ',')
+ break;
+
++pos;
}
+
+ mLoaded = true;
}
void Palette::getColor(int intensity, int color[3]) const
{
+ // Return implicit black
if (intensity == 0)
{
color[0] = 0;
@@ -107,6 +127,7 @@ void Palette::getColor(int intensity, int color[3]) const
Dye::Dye(const std::string &description)
{
+ mLoaded = false;
for (int i = 0; i < 7; ++i)
mPalettes[i] = 0;
@@ -121,7 +142,9 @@ Dye::Dye(const std::string &description)
next_pos = length;
if (next_pos <= pos + 3 || description[pos + 1] != ':')
{
- throw;
+ std::cout << "Dyeing: Missing ':' in channel description."
+ << std::endl;
+ return;
}
int i = 0;
switch (description[pos])
@@ -134,12 +157,21 @@ Dye::Dye(const std::string &description)
case 'C': i = 5; break;
case 'W': i = 6; break;
default:
- throw;
+ std::cout << "Dyeing: Invalid channel. Not in [R,G,Y,B,M,C,W]"
+ << std::endl;
+ return;
}
- mPalettes[i] = new Palette(description.substr(pos + 2, next_pos - pos - 2));
+ mPalettes[i] = new Palette(
+ description.substr(pos + 2, next_pos - pos - 2));
+
+ if (!mPalettes[i]->loaded())
+ return;
+
++next_pos;
}
while (next_pos < length);
+
+ mLoaded = true;
}
Dye::~Dye()
@@ -168,47 +200,3 @@ void Dye::update(int color[3]) const
if (mPalettes[i - 1])
mPalettes[i - 1]->getColor(cmax, color);
}
-
-void Dye::instantiate(std::string &target, const std::string &palettes)
-{
- std::string::size_type next_pos = target.find('|');
- if (next_pos == std::string::npos || palettes.empty()) return;
- ++next_pos;
-
- std::ostringstream s;
- s << target.substr(0, next_pos);
- std::string::size_type last_pos = target.length(), pal_pos = 0;
- do
- {
- std::string::size_type pos = next_pos;
- next_pos = target.find(';', pos);
- if (next_pos == std::string::npos) next_pos = last_pos;
- if (next_pos == pos + 1 && pal_pos != std::string::npos)
- {
- std::string::size_type pal_next_pos = palettes.find(';', pal_pos);
- s << target[pos] << ':';
- if (pal_next_pos == std::string::npos)
- {
- s << palettes.substr(pal_pos);
- s << target.substr(next_pos);
- pal_pos = std::string::npos;
- break;
- }
- s << palettes.substr(pal_pos, pal_next_pos - pal_pos);
- pal_pos = pal_next_pos + 1;
- }
- else if (next_pos > pos + 2)
- {
- s << target.substr(pos, next_pos - pos);
- }
- else
- {
- throw;
- }
- s << target[next_pos];
- ++next_pos;
- }
- while (next_pos < last_pos);
-
- target = s.str();
-}
diff --git a/tools/dyecmd/src/dye.h b/tools/dyecmd/src/dye.h
index 5a8fe1b5..922f3370 100644..100755
--- a/tools/dyecmd/src/dye.h
+++ b/tools/dyecmd/src/dye.h
@@ -45,11 +45,19 @@ class Palette
*/
void getColor(int intensity, int color[3]) const;
+ /**
+ * Tells if the palette was successfully loaded.
+ */
+ bool loaded() const
+ { return mLoaded; }
+
private:
struct Color { unsigned char value[3]; };
std::vector< Color > mColors;
+
+ bool mLoaded;
};
/**
@@ -73,15 +81,15 @@ class Dye
~Dye();
/**
- * Modifies a pixel color.
+ * Tells if the dye description was successfully loaded.
*/
- void update(int color[3]) const;
+ bool loaded() const
+ { return mLoaded; }
/**
- * Fills the blank in a dye placeholder with some palette names.
+ * Modifies a pixel color.
*/
- static void instantiate(std::string &target,
- const std::string &palettes);
+ void update(int color[3]) const;
private:
@@ -91,6 +99,7 @@ class Dye
* Red, Green, Yellow, Blue, Magenta, White (or rather gray).
*/
Palette *mPalettes[7];
+ bool mLoaded;
};
#endif
diff --git a/tools/dyecmd/src/dyecmd.cpp b/tools/dyecmd/src/dyecmd.cpp
index ebecf9f1..5e06e500 100644..100755
--- a/tools/dyecmd/src/dyecmd.cpp
+++ b/tools/dyecmd/src/dyecmd.cpp
@@ -23,19 +23,20 @@
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
-
-
#include "dye.h"
#include "imagewriter.h"
using namespace std;
// return values
-#define RETURN_OK 1
-#define INVALID_PARAMETER_LIST 100
-#define INVALID_INPUT_IMAGE 101
-#define INVALID_OUTPUT_IMAGE 102
-#define INVALID_DYE_PARAMETER 105
+enum ReturnValues
+{
+ RETURN_OK = 0,
+ INVALID_PARAMETER_LIST = 100,
+ INVALID_INPUT_IMAGE = 101,
+ INVALID_OUTPUT_IMAGE = 102,
+ INVALID_DYE_PARAMETER = 105
+};
SDL_Surface* recolor(SDL_Surface* tmpImage, Dye* dye)
{
@@ -51,71 +52,104 @@ SDL_Surface* recolor(SDL_Surface* tmpImage, Dye* dye)
rgba.alpha = 255;
SDL_Surface *surf = SDL_ConvertSurface(tmpImage, &rgba, SDL_SWSURFACE);
- //SDL_FreeSurface(tmpImage);
+ //SDL_FreeSurface(tmpImage); <-- We'll free the surface later.
Uint32 *pixels = static_cast< Uint32 * >(surf->pixels);
for (Uint32 *p_end = pixels + surf->w * surf->h; pixels != p_end; ++pixels)
{
- int alpha = *pixels & 255;
+ int alpha = (*pixels >> rgba.Ashift) & 255;
if (!alpha) continue;
int v[3];
- v[0] = (*pixels >> 24) & 255;
- v[1] = (*pixels >> 16) & 255;
- v[2] = (*pixels >> 8 ) & 255;
+
+ v[0] = (*pixels >> rgba.Rshift) & 255;
+ v[1] = (*pixels >> rgba.Gshift) & 255;
+ v[2] = (*pixels >> rgba.Bshift) & 255;
dye->update(v);
+
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
*pixels = (v[0] << 24) | (v[1] << 16) | (v[2] << 8) | alpha;
+#else
+ *pixels = v[0] | (v[1] << 8) | (v[2] << 16) | (alpha << 24);
+#endif
}
return surf;
}
+void printHelp()
+{
+ cout << endl
+ << "This tool is used to dye item graphics used by the Mana client "
+ << "according to the specification described here: "
+ << endl << "http://doc.manasource.org/image_dyeing_system"
+ << endl << endl <<
+ "The tool expects 3 parameters:" << endl
+ << "dyecmd <source_image> <target_image> <dye_string>" << endl
+ << "e.g.:" << endl
+ << "dyecmd \"armor-legs-shorts.png\" "
+ <<"\"armor-legs-shorts2.png\" \"W:#222255,6666ff\"" << std::endl;
+}
+
int main(int argc, char* argv[])
{
Dye* dye = NULL;
- SDL_Surface* source = NULL;
+ SDL_Surface* source = NULL, *target = NULL;
+ ReturnValues returnValue = RETURN_OK;
- // not enough or to many parameters
- if (argc != 4)
+ if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
{
- cout << INVALID_PARAMETER_LIST << " - INVALID_PARAMETER_LIST";
- exit(INVALID_PARAMETER_LIST);
+ printHelp();
}
-
- try
+ // not enough or to many parameters
+ else if (argc != 4)
{
- dye = new Dye(argv[3]);
+ cout << INVALID_PARAMETER_LIST << " - INVALID_PARAMETER_LIST";
+ printHelp();
+ returnValue = INVALID_PARAMETER_LIST;
}
- catch (exception &e)
+ else
{
- cout << INVALID_DYE_PARAMETER << " - INVALID_DYE_PARAMETER";
- exit(INVALID_DYE_PARAMETER);
- }
+ // Start dyeing process.
+ string inputFile = argv[1];
+ string outputFile = argv[2];
+ string dyeDescription = argv[3];
- try
- {
- source = IMG_Load(argv[1]);
- if (!source)
+ dye = new Dye(dyeDescription);
+ if (!dye->loaded())
{
- throw;
+ cout << INVALID_DYE_PARAMETER << " - INVALID_DYE_PARAMETER";
+ printHelp();
+ returnValue = INVALID_DYE_PARAMETER;
}
- }
- catch (exception &e)
- {
- cout << INVALID_INPUT_IMAGE << " - INVALID_INPUT_IMAGE";
- exit(INVALID_INPUT_IMAGE);
- }
-
- SDL_Surface* target = recolor(source, dye);
-
- if (!ImageWriter::writePNG(target, argv[2]))
- {
- cout << INVALID_OUTPUT_IMAGE << " - INVALID_OUTPUT_IMAGE";
- exit(INVALID_OUTPUT_IMAGE);
- }
-
- SDL_FreeSurface(source);
- SDL_FreeSurface(target);
- delete dye;
-
- return 0;
+ else
+ {
+ source = IMG_Load(inputFile.c_str());
+ if (!source)
+ {
+ cout << INVALID_INPUT_IMAGE << " - INVALID_INPUT_IMAGE";
+ printHelp();
+ returnValue = INVALID_INPUT_IMAGE;
+ }
+ else
+ {
+ target = recolor(source, dye);
+
+ if (!ImageWriter::writePNG(target, outputFile))
+ {
+ cout << INVALID_OUTPUT_IMAGE << " - INVALID_OUTPUT_IMAGE";
+ printHelp();
+ returnValue = INVALID_OUTPUT_IMAGE;
+ }
+ } // Valid source image file
+ } // Valid dye parameter
+ } // Parameters ok
+
+ if (source)
+ SDL_FreeSurface(source);
+ if (target)
+ SDL_FreeSurface(target);
+ if (dye)
+ delete dye;
+
+ return returnValue;
}
diff --git a/tools/dyecmd/src/imagewriter.cpp b/tools/dyecmd/src/imagewriter.cpp
index 669b3567..d237abbf 100644..100755
--- a/tools/dyecmd/src/imagewriter.cpp
+++ b/tools/dyecmd/src/imagewriter.cpp
@@ -22,6 +22,7 @@
#include "imagewriter.h"
#include <png.h>
+#include <iostream>
#include <string>
#include <SDL/SDL.h>
@@ -32,8 +33,8 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
FILE *fp = fopen(filename.c_str(), "wb");
if (!fp)
{
- // todo
- // logger->log("could not open file %s for writing", filename.c_str());
+ std::cout << "PNG writer: Could not open file for writing: "
+ << filename << std::endl;
return false;
}
@@ -49,8 +50,8 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
if (!png_ptr)
{
- // todo
- // logger->log("Had trouble creating png_structp");
+ std::cout << "PNG writer: Had trouble creating png_structp"
+ << std::endl;
return false;
}
@@ -58,16 +59,15 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
if (!info_ptr)
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- // todo
- // logger->log("Could not create png_info");
+ std::cout << "PNG writer: Could not create png_info" << std::endl;
return false;
}
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- // todo
- // logger->log("problem writing to %s", filename.c_str());
+ std::cout << "PNG writer: problem writing to : "
+ << filename << std::endl;
return false;
}
@@ -86,8 +86,9 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
row_pointers = new png_bytep[surface->h];
if (!row_pointers)
{
- // todo
- // logger->log("Had trouble converting surface to row pointers");
+ std::cout
+ << "PNG writer: Had trouble converting surface to row pointers"
+ << std::endl;
return false;
}
@@ -105,9 +106,8 @@ bool ImageWriter::writePNG(SDL_Surface *surface,
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
- if (SDL_MUSTLOCK(surface)) {
+ if (SDL_MUSTLOCK(surface))
SDL_UnlockSurface(surface);
- }
return true;
}
diff --git a/tools/dyecmd/src/imagewriter.h b/tools/dyecmd/src/imagewriter.h
index a8bcdf57..a8bcdf57 100644..100755
--- a/tools/dyecmd/src/imagewriter.h
+++ b/tools/dyecmd/src/imagewriter.h