From a6f6dc9c2db87ed852cac1f8a3047f9b1d3efac0 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Sun, 27 Apr 2014 16:24:12 +0300
Subject: Add StatListener.

---
 src/CMakeLists.txt                   |  2 +
 src/Makefile.am                      |  2 +
 src/being/localplayer.cpp            | 82 +++++++++++++--------------------
 src/being/localplayer.h              | 14 +++---
 src/being/playerinfo.cpp             | 13 ++----
 src/gui/windows/chatwindow.cpp       | 45 ++++++------------
 src/gui/windows/chatwindow.h         | 18 ++++----
 src/gui/windows/ministatuswindow.cpp | 13 ++----
 src/gui/windows/ministatuswindow.h   | 13 +++---
 src/gui/windows/statuswindow.cpp     | 88 +++++++++++++++++-------------------
 src/gui/windows/statuswindow.h       | 13 +++---
 src/listeners/statlistener.cpp       | 38 ++++++++++++++++
 src/listeners/statlistener.h         | 42 +++++++++++++++++
 13 files changed, 210 insertions(+), 173 deletions(-)
 create mode 100644 src/listeners/statlistener.cpp
 create mode 100644 src/listeners/statlistener.h

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2e94548ef..bb6596f00 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -815,6 +815,8 @@ SET(SRCS
     gui/rect.h
     events/selectionevent.h
     listeners/selectionlistener.h
+    listeners/statlistener.cpp
+    listeners/statlistener.h
     utils/sdlpixel.h
     gui/widgets/widget.h
     listeners/widgetlistener.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 409847682..8ae44549a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -171,6 +171,8 @@ manaplus_SOURCES += events/actionevent.h \
 	      gui/rect.h \
 	      events/selectionevent.h \
 	      listeners/selectionlistener.h \
+	      listeners/statlistener.cpp \
+	      listeners/statlistener.h \
 	      utils/sdlpixel.h \
 	      gui/widgets/widget.h \
 	      listeners/widgetlistener.h \
diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp
index ad26a15c2..08dce56ad 100644
--- a/src/being/localplayer.cpp
+++ b/src/being/localplayer.cpp
@@ -97,6 +97,7 @@ extern SkillDialog *skillDialog;
 LocalPlayer::LocalPlayer(const int id, const int subtype) :
     Being(id, PLAYER, subtype, nullptr),
     AttributeListener(),
+    StatListener(),
     mGMLevel(0),
     mInvertDirection(0),
     mCrazyMoveType(config.getIntValue("crazyMoveType")),
@@ -176,8 +177,6 @@ LocalPlayer::LocalPlayer(const int id, const int subtype) :
 {
     logger->log1("LocalPlayer::LocalPlayer");
 
-    listen(CHANNEL_ATTRIBUTES);
-
     mAttackRange = 0;
     mLevel = 1;
     mAdvanced = true;
@@ -1025,59 +1024,42 @@ void LocalPlayer::optionChanged(const std::string &value)
         mShowServerPos = config.getBoolValue("showserverpos");
 }
 
-void LocalPlayer::processEvent(const Channels channel,
-                               const DepricatedEvent &event)
+void LocalPlayer::statChanged(const int id,
+                              const int oldVal1,
+                              const int oldVal2)
 {
-    if (channel == CHANNEL_ATTRIBUTES)
+    if (!mShowJobExp || id != Net::getPlayerHandler()->getJobLocation())
+        return;
+
+    const std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
+    if (oldVal1 > exp.first || !oldVal2)
+        return;
+
+    const int change = exp.first - oldVal1;
+    if (change != 0 && mMessages.size() < 20)
     {
-        if (event.getName() == EVENT_UPDATESTAT)
+        if (!mMessages.empty())
         {
-            if (!mShowJobExp)
-                return;
-
-            const int id = event.getInt("id");
-            if (id == Net::getPlayerHandler()->getJobLocation())
+            MessagePair pair = mMessages.back();
+            // TRANSLATORS: this is normal experience
+            if (pair.first.find(strprintf(" %s", _("xp")))
+                == pair.first.size() - strlen(_("xp")) - 1)
             {
-                const std::pair<int, int> exp
-                    = PlayerInfo::getStatExperience(id);
-                if (event.getInt("oldValue1") > exp.first
-                    || !event.getInt("oldValue2"))
-                {
-                    return;
-                }
-
-                const int change = exp.first - event.getInt("oldValue1");
-                if (change != 0 && mMessages.size() < 20)
-                {
-                    if (!mMessages.empty())
-                    {
-                        MessagePair pair = mMessages.back();
-                        // TRANSLATORS: this is normal experience
-                        if (pair.first.find(strprintf(" %s",
-                            _("xp"))) == pair.first.size()
-                            - strlen(_("xp")) - 1)
-                        {
-                            mMessages.pop_back();
-                            // TRANSLATORS: this is job experience
-                            pair.first.append(strprintf(", %d %s",
-                                change, _("job")));
-                            mMessages.push_back(pair);
-                        }
-                        else
-                        {
-                            // TRANSLATORS: this is job experience
-                            addMessageToQueue(strprintf("%d %s",
-                                change, _("job")));
-                        }
-                    }
-                    else
-                    {
-                        // TRANSLATORS: this is job experience
-                        addMessageToQueue(strprintf(
-                            "%d %s", change, _("job")));
-                    }
-                }
+                mMessages.pop_back();
+                // TRANSLATORS: this is job experience
+                pair.first.append(strprintf(", %d %s", change, _("job")));
+                mMessages.push_back(pair);
             }
+            else
+            {
+                // TRANSLATORS: this is job experience
+                addMessageToQueue(strprintf("%d %s", change, _("job")));
+            }
+        }
+        else
+        {
+            // TRANSLATORS: this is job experience
+            addMessageToQueue(strprintf("%d %s", change, _("job")));
         }
     }
 }
diff --git a/src/being/localplayer.h b/src/being/localplayer.h
index ecf118799..5e8e0e8fe 100644
--- a/src/being/localplayer.h
+++ b/src/being/localplayer.h
@@ -23,8 +23,6 @@
 #ifndef BEING_LOCALPLAYER_H
 #define BEING_LOCALPLAYER_H
 
-#include "listeners/depricatedlistener.h"
-
 #include "being/being.h"
 
 #include "gui/userpalette.h"
@@ -32,6 +30,7 @@
 #include "listeners/actionlistener.h"
 #include "listeners/actorspritelistener.h"
 #include "listeners/attributelistener.h"
+#include "listeners/statlistener.h"
 
 #include <vector>
 
@@ -67,8 +66,8 @@ enum
  */
 class LocalPlayer final : public Being,
                           public ActorSpriteListener,
-                          public DepricatedListener,
-                          public AttributeListener
+                          public AttributeListener,
+                          public StatListener
 {
     public:
         /**
@@ -379,9 +378,6 @@ class LocalPlayer final : public Being,
          */
         void optionChanged(const std::string &value) override final;
 
-        void processEvent(const Channels channel,
-                          const DepricatedEvent &event) override final;
-
         /**
          * set a following player.
          */
@@ -515,6 +511,10 @@ class LocalPlayer final : public Being,
                               const int oldVal,
                               const int newVal) override final;
 
+        void statChanged(const int id,
+                         const int oldVal1,
+                         const int oldVal2) override final;
+
     protected:
         void updateCoords() override final;
 
diff --git a/src/being/playerinfo.cpp b/src/being/playerinfo.cpp
index 09604e971..ed52df6c0 100644
--- a/src/being/playerinfo.cpp
+++ b/src/being/playerinfo.cpp
@@ -39,6 +39,8 @@
 
 #include "utils/delete2.h"
 
+#include "listeners/statlistener.h"
+
 #include "debug.h"
 
 namespace PlayerInfo
@@ -64,16 +66,7 @@ void triggerAttr(const int id, const int old)
 
 void triggerStat(const int id, const int old1, const int old2)
 {
-    const StatMap::const_iterator it = mData.mStats.find(id);
-    if (it == mData.mStats.end())
-        return;
-
-    DepricatedEvent event(EVENT_UPDATESTAT);
-    event.setInt("id", id);
-    const Stat &stat = it->second;
-    event.setInt("oldValue1", old1);
-    event.setInt("oldValue2", old2);
-    DepricatedEvent::trigger(CHANNEL_ATTRIBUTES, event);
+    StatListener::distributeEvent(id, old1, old2);
 }
 
 // --- Attributes -------------------------------------------------------------
diff --git a/src/gui/windows/chatwindow.cpp b/src/gui/windows/chatwindow.cpp
index dbda471c4..5b1eba199 100644
--- a/src/gui/windows/chatwindow.cpp
+++ b/src/gui/windows/chatwindow.cpp
@@ -185,8 +185,6 @@ ChatWindow::ChatWindow():
 {
     mChatTabs->postInit();
 
-    listen(CHANNEL_ATTRIBUTES);
-
     setWindowName("Chat");
 
     if (setupWindow)
@@ -957,38 +955,25 @@ void ChatWindow::keyPressed(KeyEvent &event)
 
 #undef ifKey
 
-void ChatWindow::processEvent(const Channels channel,
-                              const DepricatedEvent &event)
+void ChatWindow::statChanged(const int id,
+                             const int oldVal1,
+                             const int oldVal2)
 {
-    if (channel == CHANNEL_ATTRIBUTES)
-    {
-        if (!mShowBattleEvents)
-            return;
+    if (!mShowBattleEvents || !config.getBoolValue("showJobExp"))
+        return;
 
-        if (event.getName() == EVENT_UPDATESTAT)
-        {
-            if (!config.getBoolValue("showJobExp"))
-                return;
+    if (id != Net::getPlayerHandler()->getJobLocation())
+        return;
 
-            const int id = event.getInt("id");
-            if (id == Net::getPlayerHandler()->getJobLocation())
-            {
-                const std::pair<int, int> exp
-                    = PlayerInfo::getStatExperience(id);
-                if (event.getInt("oldValue1") > exp.first
-                    || !event.getInt("oldValue2"))
-                {
-                    return;
-                }
+    const std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
+    if (oldVal1 > exp.first || !oldVal2)
+        return;
 
-                const int change = exp.first - event.getInt("oldValue1");
-                if (change != 0)
-                {
-                    battleChatLog(std::string("+").append(
-                        toString(change)).append(" job"));
-                }
-            }
-        }
+    const int change = exp.first - oldVal1;
+    if (change != 0)
+    {
+        battleChatLog(std::string("+").append(toString(
+            change)).append(" job"));
     }
 }
 
diff --git a/src/gui/windows/chatwindow.h b/src/gui/windows/chatwindow.h
index d345b5abc..3999d6b8a 100644
--- a/src/gui/windows/chatwindow.h
+++ b/src/gui/windows/chatwindow.h
@@ -23,14 +23,13 @@
 #ifndef GUI_WINDOWS_CHATWINDOW_H
 #define GUI_WINDOWS_CHATWINDOW_H
 
-#include "listeners/attributelistener.h"
-#include "listeners/configlistener.h"
-#include "listeners/depricatedlistener.h"
-
 #include "gui/widgets/window.h"
 
 #include "listeners/actionlistener.h"
+#include "listeners/attributelistener.h"
+#include "listeners/configlistener.h"
 #include "listeners/keylistener.h"
+#include "listeners/statlistener.h"
 
 #include <list>
 #include <map>
@@ -85,9 +84,9 @@ struct CHATLOG final
 class ChatWindow final : public Window,
                          public ActionListener,
                          public KeyListener,
-                         public DepricatedListener,
                          public ConfigListener,
-                         public AttributeListener
+                         public AttributeListener,
+                         public StatListener
 {
     public:
         /**
@@ -194,9 +193,6 @@ class ChatWindow final : public Window,
          */
         void mousePressed(MouseEvent &event) override final;
 
-        void processEvent(const Channels channel,
-                          const DepricatedEvent &event) override final;
-
         /**
          * Scrolls the chat window
          *
@@ -299,6 +295,10 @@ class ChatWindow final : public Window,
                               const int oldVal,
                               const int newVal) override final;
 
+        void statChanged(const int id,
+                         const int oldVal1,
+                         const int oldVal2) override final;
+
         static void localPetSay(const std::string &nick,
                                 const std::string &text);
 
diff --git a/src/gui/windows/ministatuswindow.cpp b/src/gui/windows/ministatuswindow.cpp
index 6fb330bbf..2320ac08a 100644
--- a/src/gui/windows/ministatuswindow.cpp
+++ b/src/gui/windows/ministatuswindow.cpp
@@ -112,8 +112,6 @@ MiniStatusWindow::MiniStatusWindow() :
     mTextPopup->postInit();
     mStatusPopup->postInit();
 
-    listen(CHANNEL_ATTRIBUTES);
-
     StatusWindow::updateHPBar(mHpBar);
 
     if (Net::getGameHandler()->canUseMagicBar() && statusWindow)
@@ -251,14 +249,13 @@ void MiniStatusWindow::drawIcons(Graphics *const graphics)
     }
 }
 
-void MiniStatusWindow::processEvent(const Channels channel A_UNUSED,
-                                    const DepricatedEvent &event)
+void MiniStatusWindow::statChanged(const int id,
+                                   const int oldVal1 A_UNUSED,
+                                   const int oldVal2 A_UNUSED)
 {
-    if (event.getName() == EVENT_UPDATESTAT)
-    {
+    if (statusWindow)
         statusWindow->updateMPBar(mMpBar);
-        StatusWindow::updateJobBar(mJobBar);
-    }
+    StatusWindow::updateJobBar(mJobBar);
 }
 
 void MiniStatusWindow::attributeChanged(const int id,
diff --git a/src/gui/windows/ministatuswindow.h b/src/gui/windows/ministatuswindow.h
index bab117c19..171e1fe2f 100644
--- a/src/gui/windows/ministatuswindow.h
+++ b/src/gui/windows/ministatuswindow.h
@@ -26,7 +26,7 @@
 #include "inventory.h"
 
 #include "listeners/attributelistener.h"
-#include "listeners/depricatedlistener.h"
+#include "listeners/statlistener.h"
 
 #include "gui/widgets/window.h"
 
@@ -45,8 +45,8 @@ class TextPopup;
  */
 class MiniStatusWindow final : public Window,
                                public InventoryListener,
-                               public DepricatedListener,
-                               public AttributeListener
+                               public AttributeListener,
+                               public StatListener
 {
     public:
         MiniStatusWindow();
@@ -64,9 +64,6 @@ class MiniStatusWindow final : public Window,
 
         void drawIcons(Graphics *const graphics);
 
-        void processEvent(const Channels channel,
-                          const DepricatedEvent &event) override final;
-
         void updateStatus();
 
         void logic() override final;
@@ -96,6 +93,10 @@ class MiniStatusWindow final : public Window,
                               const int oldVal,
                               const int newVal) override final;
 
+        void statChanged(const int id,
+                         const int oldVal1,
+                         const int oldVal2) override final;
+
 #ifdef USE_PROFILER
         void logicChildren();
 #endif
diff --git a/src/gui/windows/statuswindow.cpp b/src/gui/windows/statuswindow.cpp
index 5897ae64b..53abb7fdf 100644
--- a/src/gui/windows/statuswindow.cpp
+++ b/src/gui/windows/statuswindow.cpp
@@ -145,6 +145,7 @@ StatusWindow::StatusWindow() :
         "?", false, nullptr, "status.xml"),
     ActionListener(),
     AttributeListener(),
+    StatListener(),
     // TRANSLATORS: status window label
     mLvlLabel(new Label(this, strprintf(_("Level: %d"), 0))),
     // TRANSLATORS: status window label
@@ -170,8 +171,6 @@ StatusWindow::StatusWindow() :
     mCopyButton(new Button(this, _("Copy to chat"), "copy", this)),
     mAttrs()
 {
-    listen(CHANNEL_ATTRIBUTES);
-
     setWindowName("Status");
     if (setupWindow)
         setupWindow->registerWindowForReset(this);
@@ -335,68 +334,63 @@ StatusWindow::StatusWindow() :
     mLvlLabel->adjustSize();
 }
 
-void StatusWindow::processEvent(const Channels channel A_UNUSED,
-                                const DepricatedEvent &event)
+void StatusWindow::statChanged(const int id,
+                               const int oldVal1,
+                               const int oldVal2 A_UNUSED)
 {
     static bool blocked = false;
     if (blocked)
         return;
 
-    const DepricatedEvents &eventName = event.getName();
-    if (eventName == EVENT_UPDATESTAT)
+    if (id == Net::getPlayerHandler()->getJobLocation())
     {
-        const int id = event.getInt("id");
-        if (id == Net::getPlayerHandler()->getJobLocation())
+        if (mJobLvlLabel)
         {
-            if (mJobLvlLabel)
-            {
-                int lvl = PlayerInfo::getStatBase(id);
-                const int oldExp = event.getInt("oldValue1");
-                const std::pair<int, int> exp
-                    = PlayerInfo::getStatExperience(id);
+            int lvl = PlayerInfo::getStatBase(id);
+            const int oldExp = oldVal1;
+            const std::pair<int, int> exp = PlayerInfo::getStatExperience(id);
 
-                if (!lvl)
+            if (!lvl)
+            {
+                // possible server broken and don't send job level,
+                // then we fixing it :)
+                if (exp.second < 20000)
                 {
-                    // possible server broken and don't send job level,
-                    // then we fixing it :)
-                    if (exp.second < 20000)
-                    {
-                        lvl = 0;
-                    }
-                    else
-                    {
-                        lvl = (exp.second - 20000) / 150;
-                        blocked = true;
-                        PlayerInfo::setStatBase(id, lvl);
-                        blocked = false;
-                    }
+                    lvl = 0;
                 }
-
-                if (exp.first < oldExp && exp.second >= 20000)
-                {   // possible job level up. but server broken and don't send
-                    // new job exp limit, we fixing it
-                    lvl ++;
+                else
+                {
+                    lvl = (exp.second - 20000) / 150;
                     blocked = true;
-                    PlayerInfo::setStatExperience(
-                        id, exp.first, 20000 + lvl * 150);
                     PlayerInfo::setStatBase(id, lvl);
                     blocked = false;
                 }
+            }
 
-                // TRANSLATORS: status window label
-                mJobLvlLabel->setCaption(strprintf(_("Job: %d"), lvl));
-                mJobLvlLabel->adjustSize();
-
-                updateProgressBar(mJobBar, id, false);
+            if (exp.first < oldExp && exp.second >= 20000)
+            {   // possible job level up. but server broken and don't send
+                // new job exp limit, we fixing it
+                lvl ++;
+                blocked = true;
+                PlayerInfo::setStatExperience(
+                    id, exp.first, 20000 + lvl * 150);
+                PlayerInfo::setStatBase(id, lvl);
+                blocked = false;
             }
+
+            // TRANSLATORS: status window label
+            mJobLvlLabel->setCaption(strprintf(_("Job: %d"), lvl));
+            mJobLvlLabel->adjustSize();
+
+            updateProgressBar(mJobBar, id, false);
         }
-        else
-        {
-            updateMPBar(mMpBar, true);
-            const Attrs::const_iterator it = mAttrs.find(id);
-            if (it != mAttrs.end() && it->second)
-                it->second->update();
-        }
+    }
+    else
+    {
+        updateMPBar(mMpBar, true);
+        const Attrs::const_iterator it = mAttrs.find(id);
+        if (it != mAttrs.end() && it->second)
+            it->second->update();
     }
 }
 
diff --git a/src/gui/windows/statuswindow.h b/src/gui/windows/statuswindow.h
index 11aa2ad05..797e7647f 100644
--- a/src/gui/windows/statuswindow.h
+++ b/src/gui/windows/statuswindow.h
@@ -27,7 +27,7 @@
 
 #include "listeners/actionlistener.h"
 #include "listeners/attributelistener.h"
-#include "listeners/depricatedlistener.h"
+#include "listeners/statlistener.h"
 
 #include <map>
 
@@ -45,8 +45,8 @@ class VertContainer;
  */
 class StatusWindow final : public Window,
                            public ActionListener,
-                           public DepricatedListener,
-                           public AttributeListener
+                           public AttributeListener,
+                           public StatListener
 {
     public:
         /**
@@ -56,9 +56,6 @@ class StatusWindow final : public Window,
 
         A_DELETE_COPY(StatusWindow)
 
-        void processEvent(const Channels channel,
-                          const DepricatedEvent &event) override;
-
         void setPointsNeeded(const int id, const int needed);
 
         void addAttribute(const int id, const std::string &restrict name,
@@ -92,6 +89,10 @@ class StatusWindow final : public Window,
                               const int oldVal,
                               const int newVal) override final;
 
+        void statChanged(const int id,
+                         const int oldVal1,
+                         const int oldVal2) override final;
+
     private:
         static std::string translateLetter(const char *const letters);
         static std::string translateLetter2(std::string letters);
diff --git a/src/listeners/statlistener.cpp b/src/listeners/statlistener.cpp
new file mode 100644
index 000000000..420eb90db
--- /dev/null
+++ b/src/listeners/statlistener.cpp
@@ -0,0 +1,38 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2014  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 "listeners/statlistener.h"
+
+#include "debug.h"
+
+defineListener(StatListener)
+
+void StatListener::distributeEvent(const int id,
+                                   const int oldVal1,
+                                   const int oldVal2)
+{
+    FOR_EACH (std::vector<StatListener*>::iterator,
+              it, mListeners)
+    {
+        StatListener *const listener = *it;
+        if (listener)
+            listener->statChanged(id, oldVal1, oldVal2);
+    }
+}
diff --git a/src/listeners/statlistener.h b/src/listeners/statlistener.h
new file mode 100644
index 000000000..157dd9346
--- /dev/null
+++ b/src/listeners/statlistener.h
@@ -0,0 +1,42 @@
+/*
+ *  The ManaPlus Client
+ *  Copyright (C) 2014  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 LISTENERS_STATLISTENER_H
+#define LISTENERS_STATLISTENER_H
+
+#include "listeners/baselistener.hpp"
+
+#include "localconsts.h"
+
+class StatListener
+{
+    public:
+        virtual void statChanged(const int id,
+                                 const int oldVal1,
+                                 const int oldVal2) = 0;
+
+        static void distributeEvent(const int id,
+                                    const int oldVal1,
+                                    const int oldVal2);
+
+    defineListenerHeader(StatListener)
+};
+
+#endif  // LISTENERS_STATLISTENER_H
-- 
cgit v1.2.3-70-g09d2