From bf9bccc30a186e338f96c230a4f63cc924c77bd8 Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Tue, 14 Jun 2011 23:23:30 +0300 Subject: Add ability to add comments to any players. --- src/being.cpp | 41 ++++++++++++++++++++++++++++- src/being.h | 15 +++++++++++ src/client.cpp | 17 ++++++++++++ src/client.h | 5 ++++ src/gui/beingpopup.cpp | 26 ++++++++++++++++++ src/gui/beingpopup.h | 1 + src/gui/popupmenu.cpp | 55 ++++++++++++++++++++++++++++++++++++++- src/gui/popupmenu.h | 19 ++++++++++++++ src/resources/resourcemanager.cpp | 51 ++++++++++++++++++++++++++++++++++++ src/resources/resourcemanager.h | 17 +++++++++++- src/utils/stringutils.cpp | 13 ++++++++- src/utils/stringutils.h | 4 ++- 12 files changed, 259 insertions(+), 5 deletions(-) diff --git a/src/being.cpp b/src/being.cpp index d45bbcf74..508f56aef 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -216,7 +216,9 @@ Being::Being(int id, Type type, Uint16 subtype, Map *map): mMinHit(0), mMaxHit(0), mCriticalHit(0), - mPvpRank(0) + mPvpRank(0), + mComment(""), + mGotComment(false) { mSpriteRemap = new int[20]; mSpriteHide = new int[20]; @@ -236,6 +238,8 @@ Being::Being(int id, Type type, Uint16 subtype, Map *map): if (getType() == PLAYER) mShowName = config.getBoolValue("visiblenames"); + else + mGotComment = true; config.addListener("visiblenames", this); @@ -2251,6 +2255,41 @@ void Being::clearCache() beingInfoCache.clear(); } +void Being::updateComment() +{ + if (mGotComment || mName.empty()) + return; + + mGotComment = true; + mComment = loadComment(mName); +} + +std::string Being::loadComment(const std::string &name) +{ + std::string str = Client::getUsersDirectory() + + stringToHexPath(name) + "/comment.txt"; + std::vector lines; + + ResourceManager *resman = ResourceManager::getInstance(); + if (resman->existsLocal(str)) + { + lines = resman->loadTextFileLocal(str); + if (lines.size() >= 2) + return lines[1]; + } + return ""; +} + +void Being::saveComment(const std::string &name, + const std::string &comment) +{ + std::string dir = Client::getUsersDirectory() + + stringToHexPath(name); + std::string fileName = dir + "/comment.txt"; + ResourceManager *resman = ResourceManager::getInstance(); + resman->saveTextFile(dir, "comment.txt", name + "\n" + comment); +} + BeingEquipBackend::BeingEquipBackend(Being *being): mBeing(being) { diff --git a/src/being.h b/src/being.h index 652b8a889..ddcef1930 100644 --- a/src/being.h +++ b/src/being.h @@ -725,8 +725,21 @@ class Being : public ActorSprite, public ConfigListener std::string getGenderSignWithSpace() const; + void updateComment(); + + std::string getComment() + { return mComment; } + + void setComment(std::string n) + { mComment = n; } + static void clearCache(); + static std::string loadComment(const std::string &name); + + static void saveComment(const std::string &name, + const std::string &comment); + protected: /** * Sets the new path for this being. @@ -858,6 +871,8 @@ class Being : public ActorSprite, public ConfigListener unsigned int mPvpRank; int *mSpriteRemap; int *mSpriteHide; + std::string mComment; + bool mGotComment; }; extern std::list beingInfoCache; diff --git a/src/client.cpp b/src/client.cpp index 5e1fca53b..f20c674d9 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -235,6 +235,7 @@ Client *Client::mInstance = 0; Client::Client(const Options &options): mOptions(options), mServerConfigDir(""), + mUsersDir(""), mRootDir(""), mCurrentDialog(0), mQuitDialog(0), @@ -1458,6 +1459,7 @@ void Client::initServerConfig(std::string serverName) } initPacketLimiter(); initTradeFilter(); + initUsersDir(); player_relations.init(); // Initialize the item and emote shortcuts. @@ -1844,6 +1846,16 @@ void Client::initTradeFilter() } } +void Client::initUsersDir() +{ + mUsersDir = Client::getServerConfigDirectory() + "/users/"; + if (mkdir_r(mUsersDir.c_str())) + { + logger->error(strprintf(_("%s doesn't exist and can't be created! " + "Exiting."), mUsersDir.c_str())); + } +} + void Client::initPacketLimiter() { //here i setting packet limits. but current server is broken, @@ -2049,6 +2061,11 @@ const std::string Client::getServerConfigDirectory() return instance()->mServerConfigDir; } +const std::string Client::getUsersDirectory() +{ + return instance()->mUsersDir; +} + void Client::setGuiAlpha(float n) { instance()->mGuiAlpha = n; diff --git a/src/client.h b/src/client.h index f03a213db..dc94bdd93 100644 --- a/src/client.h +++ b/src/client.h @@ -224,6 +224,8 @@ public: static const std::string getServerConfigDirectory(); + static const std::string getUsersDirectory(); + static bool getIsMinimized() { return instance()->mIsMinimized; } @@ -262,6 +264,8 @@ public: void initTradeFilter(); + void initUsersDir(); + void initPacketLimiter(); void writePacketLimits(std::string packetLimitsName); @@ -298,6 +302,7 @@ private: std::string mUpdatesDir; std::string mScreenshotDir; std::string mServerConfigDir; + std::string mUsersDir; std::string mRootDir; std::string mServerName; diff --git a/src/gui/beingpopup.cpp b/src/gui/beingpopup.cpp index 1b32d2b7b..2ba79d1a1 100644 --- a/src/gui/beingpopup.cpp +++ b/src/gui/beingpopup.cpp @@ -59,10 +59,14 @@ BeingPopup::BeingPopup(): mBeingRank = new Label("A"); mBeingRank->setPosition(getPadding(), 3 * fontHeight); + mBeingComment = new Label("A"); + mBeingComment->setPosition(getPadding(), 4 * fontHeight); + add(mBeingName); add(mBeingParty); add(mBeingGuild); add(mBeingRank); + add(mBeingComment); } BeingPopup::~BeingPopup() @@ -80,6 +84,9 @@ void BeingPopup::show(int x, int y, Being *b) Label *label1 = mBeingParty; Label *label2 = mBeingGuild; Label *label3 = mBeingRank; + Label *label4 = mBeingComment; + + b->updateComment(); mBeingName->setCaption(b->getName() + b->getGenderSignWithSpace()); if (gui) @@ -94,6 +101,7 @@ void BeingPopup::show(int x, int y, Being *b) label1->setCaption(""); label2->setCaption(""); label3->setCaption(""); + label4->setCaption(""); if (!(b->getPartyName().empty())) { @@ -103,6 +111,7 @@ void BeingPopup::show(int x, int y, Being *b) } else { + label4 = label3; label3 = label2; label2 = label1; label1 = 0; @@ -116,6 +125,7 @@ void BeingPopup::show(int x, int y, Being *b) } else { + label4 = label3; label3 = label2; label2 = 0; } @@ -127,9 +137,21 @@ void BeingPopup::show(int x, int y, Being *b) } else { + label4 = label3; label3 = 0; } + if (!b->getComment().empty()) + { + label4->setCaption(strprintf(_("Comment: %s"), + b->getComment().c_str())); + label4->adjustSize(); + } + else + { + label4 = 0; + } + int minWidth = mBeingName->getWidth(); if (label1 && label1->getWidth() > minWidth) minWidth = label1->getWidth(); @@ -137,6 +159,8 @@ void BeingPopup::show(int x, int y, Being *b) minWidth = label2->getWidth(); if (label3 && label3->getWidth() > minWidth) minWidth = label3->getWidth(); + if (label4 && label4->getWidth() > minWidth) + minWidth = label4->getWidth(); int height = getFont()->getHeight(); if (label1) @@ -145,6 +169,8 @@ void BeingPopup::show(int x, int y, Being *b) height += getFont()->getHeight(); if (label3) height += getFont()->getHeight(); + if (label4) + height += getFont()->getHeight(); setContentSize(minWidth + 10, height + 10); diff --git a/src/gui/beingpopup.h b/src/gui/beingpopup.h index ea4ece110..2aeb6c20c 100644 --- a/src/gui/beingpopup.h +++ b/src/gui/beingpopup.h @@ -55,6 +55,7 @@ class BeingPopup : public Popup Label *mBeingParty; Label *mBeingGuild; Label *mBeingRank; + Label *mBeingComment; }; #endif // BEINGPOPUP_H diff --git a/src/gui/popupmenu.cpp b/src/gui/popupmenu.cpp index aaf47f36a..0c5e7a365 100644 --- a/src/gui/popupmenu.cpp +++ b/src/gui/popupmenu.cpp @@ -103,6 +103,8 @@ PopupMenu::PopupMenu(): mBrowserBox->setLinkHandler(this); mRenameListener.setMapItem(0); mRenameListener.setDialog(0); + mPlayerListener.setNick(""); + mPlayerListener.setDialog(0); add(mBrowserBox); } @@ -240,6 +242,8 @@ void PopupMenu::showPopup(int x, int y, Being *being) mBrowserBox->addRow(strprintf("@@items|%s@@", _("Show Items"))); mBrowserBox->addRow(strprintf("@@undress|%s@@", _("Undress"))); + mBrowserBox->addRow(strprintf( + "@@addcomment|%s@@", _("Add comment"))); if (player_relations.getDefault() & PlayerRelation::TRADE) { @@ -391,7 +395,7 @@ void PopupMenu::showPlayerPopup(int x, int y, std::string nick) mBrowserBox->addRow("##3---"); mBrowserBox->addRow(strprintf("@@follow|%s@@", _("Follow"))); mBrowserBox->addRow(strprintf("@@imitation|%s@@", _("Imitation"))); - + mBrowserBox->addRow(strprintf("@@addcomment|%s@@", _("Add comment"))); if (player_node->isInParty() && player_node->getParty()) { @@ -642,6 +646,8 @@ void PopupMenu::showChatPopup(int x, int y, ChatTab *tab) mBrowserBox->addRow(strprintf("@@move|%s@@", _("Move"))); mBrowserBox->addRow(strprintf("@@items|%s@@", _("Show Items"))); mBrowserBox->addRow(strprintf("@@undress|%s@@", _("Undress"))); + mBrowserBox->addRow(strprintf( + "@@addcomment|%s@@", _("Add comment"))); if (player_relations.getDefault() & PlayerRelation::TRADE) { @@ -690,6 +696,12 @@ void PopupMenu::showChatPopup(int x, int y, ChatTab *tab) } } } + else + { + mBrowserBox->addRow(strprintf( + "@@addcomment|%s@@", _("Add comment"))); + mBrowserBox->addRow("##3---"); + } } mBrowserBox->addRow(strprintf("@@cancel|%s@@", _("Cancel"))); @@ -1170,6 +1182,27 @@ void PopupMenu::handleLink(const std::string &link, { Net::getBeingHandler()->undress(being); } + else if (link == "addcomment" && !mNick.empty()) + { + // TRANSLATORS: number of chars in string should be near original + TextDialog *dialog = new TextDialog(_("Player comment "), + // TRANSLATORS: number of chars in string should be near original + _("Comment: ")); + mPlayerListener.setDialog(dialog); + mPlayerListener.setNick(mNick); + + if (being) + { + being->updateComment(); + dialog->setText(being->getComment()); + } + else + { + dialog->setText(Being::loadComment(mNick)); + } + dialog->setActionEventId("ok"); + dialog->addActionListener(&mPlayerListener); + } else if (link == "guild-kick" && !mNick.empty()) { if (player_node) @@ -1923,3 +1956,23 @@ void RenameListener::action(const gcn::ActionEvent &event) } mDialog = 0; } + +PlayerListener::PlayerListener() : + mNick(""), + mDialog(0) +{ +} + +void PlayerListener::action(const gcn::ActionEvent &event) +{ + if (event.getId() == "ok" && !mNick.empty() && mDialog) + { + std::string comment = mDialog->getText(); + Being* being = actorSpriteManager->findBeingByName( + mNick, Being::PLAYER); + if (being) + being->setComment(comment); + Being::saveComment(mNick, comment); + } + mDialog = 0; +} diff --git a/src/gui/popupmenu.h b/src/gui/popupmenu.h index 976e3e5d2..50d86ff37 100644 --- a/src/gui/popupmenu.h +++ b/src/gui/popupmenu.h @@ -65,6 +65,24 @@ class RenameListener : public gcn::ActionListener TextDialog *mDialog; }; +class PlayerListener : public gcn::ActionListener +{ + public: + PlayerListener(); + + void action(const gcn::ActionEvent &event); + + void setNick(std::string name) + { mNick = name; } + + void setDialog(TextDialog *dialog) + { mDialog = dialog; } + + private: + std::string mNick; + TextDialog *mDialog; +}; + /** * Window showing popup menu. */ @@ -149,6 +167,7 @@ class PopupMenu : public Popup, public LinkHandler TextCommand *mSpell; Window *mWindow; RenameListener mRenameListener; + PlayerListener mPlayerListener; TextDialog *mDialog; Button *mButton; std::string mNick; diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index aea598935..96902cb4c 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -34,11 +34,16 @@ #include "resources/soundeffect.h" #include "resources/spritedef.h" +#include "utils/mkdir.h" + #include #include #include +#include +#include #include +#include #include #include "debug.h" @@ -299,6 +304,17 @@ bool ResourceManager::exists(const std::string &path) return PHYSFS_exists(path.c_str()); } +bool ResourceManager::existsLocal(const std::string &path) +{ + bool flg(false); + std::fstream file; + file.open(path.c_str(), std::ios::in); + if (file.is_open()) + flg = true; + file.close(); + return flg; +} + bool ResourceManager::isDirectory(const std::string &path) { return PHYSFS_isDirectory(path.c_str()); @@ -644,6 +660,41 @@ std::vector ResourceManager::loadTextFile( return lines; } +std::vector ResourceManager::loadTextFileLocal( + const std::string &fileName) +{ + std::ifstream file; + char line[501]; + std::vector lines; + + file.open(fileName.c_str(), std::ios::in); + + if (!file.is_open()) + { + logger->log("Couldn't load text file: %s", fileName.c_str()); + return lines; + } + + while (file.getline(line, 500)) + lines.push_back(line); + + return lines; +} + +void ResourceManager::saveTextFile(std::string path, std::string name, + std::string text) +{ + if (!mkdir_r(path.c_str())) + { + std::ofstream file; + std::string fileName = path + "/" + name; + + file.open(fileName.c_str(), std::ios::out); + file << text << std::endl; + file.close(); + } +} + SDL_Surface *ResourceManager::loadSDLSurface(const std::string &filename) { int fileSize; diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index 71cbdce62..0b73a796e 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -103,9 +103,15 @@ class ResourceManager /** * Checks whether the given file or directory exists in the search path + * (PhysFS) */ bool exists(const std::string &path); + /** + * Checks whether the given file or directory exists + */ + bool existsLocal(const std::string &path); + /** * Checks whether the given path is a directory. */ @@ -209,10 +215,19 @@ class ResourceManager void *loadFile(const std::string &fileName, int &fileSize); /** - * Retrieves the contents of a text file. + * Retrieves the contents of a text file (PhysFS). */ std::vector loadTextFile(const std::string &fileName); + /** + * Retrieves the contents of a text file. + */ + std::vector loadTextFileLocal(const std::string + &fileName); + + void saveTextFile(std::string path, std::string name, + std::string text); + /** * Loads the given filename as an SDL surface. The returned surface is * expected to be freed by the caller using SDL_FreeSurface. diff --git a/src/utils/stringutils.cpp b/src/utils/stringutils.cpp index 5e45b6168..dffec3f0c 100644 --- a/src/utils/stringutils.cpp +++ b/src/utils/stringutils.cpp @@ -474,7 +474,18 @@ std::string packList(std::list &list) return str; } -std::list unpackList(const std::string str) +std::list unpackList(const std::string &str) { return splitToStringList(str, '|'); } + +std::string stringToHexPath(const std::string &str) +{ + if (str.empty()) + return ""; + + std::string hex = strprintf("%%%2x/", (int)str[0]); + for (unsigned f = 1; f < str.size(); f ++) + hex += strprintf("%%%2x", (int)str[f]); + return hex; +} diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h index 9d22f8ba8..796df92c5 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -182,6 +182,8 @@ std::vector getLang(); std::string packList(std::list &list); -std::list unpackList(const std::string str); +std::list unpackList(const std::string &str); + +std::string stringToHexPath(const std::string &str); #endif // UTILS_STRINGUTILS_H -- cgit v1.2.3-60-g2f50