Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/unity_build/src/modules/notifications/NotificationManager.cc @ 8740

Last change on this file since 8740 was 8688, checked in by rgrieder, 14 years ago

Removed the need to declare the tolua interface explicitly (DeclareToluaInterface).
This is now automatically done in the ToluaBindLibrary.cc files.
That also removes the need for tolua bind header files.

  • Property svn:eol-style set to native
File size: 16.3 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Damian 'Mozork' Frick
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file NotificationManager.cc
31    @brief Implementation of the NotificationManager class.
32*/
33
34#include "NotificationManager.h"
35
36#include "core/command/ConsoleCommand.h"
37#include "core/CoreIncludes.h"
38#include "core/GUIManager.h"
39#include "core/LuaState.h"
40#include "network/Host.h"
41#include "network/NetworkFunction.h"
42#include "util/ScopedSingletonManager.h"
43
44#include "interfaces/NotificationListener.h"
45
46#include "Notification.h"
47#include "NotificationQueue.h"
48
49namespace orxonox
50{
51
52    const std::string NotificationManager::ALL("all");
53    const std::string NotificationManager::NONE("none");
54
55    ManageScopedSingleton(NotificationManager, ScopeID::Root, false);
56
57    // Setting console command to enter the edit mode.
58    SetConsoleCommand("enterEditMode", &NotificationManager::enterEditMode);
59
60    registerStaticNetworkFunction(NotificationManager::sendNotification);
61
62    /**
63    @brief
64        Constructor. Registers the Object.
65    */
66    NotificationManager::NotificationManager()
67    {
68        RegisterRootObject(NotificationManager);
69
70        this->highestIndex_ = 0;
71
72        ModifyConsoleCommand("enterEditMode").setObject(this);
73
74        COUT(3) << "NotificatioManager created." << std::endl;
75    }
76
77    /**
78    @brief
79        Destructor.
80    */
81    NotificationManager::~NotificationManager()
82    {
83        ModifyConsoleCommand("enterEditMode").setObject(NULL);
84
85        // Destroys all Notifications.
86        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it!= this->allNotificationsList_.end(); it++)
87            it->second->destroy();
88        this->allNotificationsList_.clear();
89
90        COUT(3) << "NotificationManager destroyed." << std::endl;
91    }
92
93    /**
94    @brief
95        Is called before the object is destroyed.
96    */
97    void NotificationManager::preDestroy(void)
98    {
99        // Destroys all NotificationQueues that have been registered with the NotificationManager.
100        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.begin();
101        while(it != this->queues_.end())
102        {
103            it->second->destroy(true);
104            it = this->queues_.begin();
105        }
106
107        this->queues_.clear();
108    }
109
110    /**
111    @brief
112        Sends a Notification with the specified message to the specified client from the specified sender.
113    @param message
114        The message that should be sent.
115    @param clientId
116        The id of the client the notification should be sent to.
117    @param sender
118        The sender that sent the notification.
119    @param isLocal
120        If this is set to true (false is default), then the Notification is sent to the client where this function is executed, meaning the Notification is sent locally.
121    */
122    /*static*/ void NotificationManager::sendNotification(const std::string& message, unsigned int clientId, const std::string& sender, bool isLocal)
123    {
124        // If we're in standalone mode or we're already no the right client we create and send the Notification.
125        if(GameMode::isStandalone() || isLocal || Host::getPlayerID() == clientId)
126        {
127            Notification* notification = new Notification(message, sender);
128            if(NotificationManager::getInstance().registerNotification(notification))
129                COUT(3) << "Notification \"" << notification->getMessage() << "\" sent." << std::endl;
130        }
131        // If we're on the server (and the server is not the intended recipient of the Notification) we send it over the network.
132        else if(GameMode::isServer())
133        {
134            callStaticNetworkFunction(NotificationManager::sendNotification, clientId, message, clientId, sender);
135        }
136    }
137
138    /**
139    @brief
140        Registers a Notification within the NotificationManager and makes sure that the Notification is sent to all the NotificationListeners associated with its sender.
141    @param notification
142        The Notification to be registered.
143    @return
144        Returns true if successful.
145    */
146    bool NotificationManager::registerNotification(Notification* notification)
147    {
148        assert(notification);
149
150        std::time_t time = std::time(0); // Get current time.
151
152        // Add the Notification to the list that holds all Notifications.
153        this->allNotificationsList_.insert(std::pair<std::time_t, Notification*>(time, notification));
154
155        if(notification->getSender() == NotificationManager::NONE) // If the sender has no specific name, then the Notification is only added to the list of all Notifications.
156            return true;
157
158        bool all = false;
159        if(notification->getSender() == NotificationManager::ALL) // If all are the sender, then the Notifications is added to every NotificationListener.
160            all = true;
161
162        // Insert the Notification in all NotificationListeners that have its sender as target.
163        for(std::map<NotificationListener*, unsigned int>::iterator it = this->listenerList_.begin(); it != this->listenerList_.end(); it++) // Iterate through all NotificationListeners.
164        {
165            const std::set<std::string>& set = it->first->getTargetsSet();
166            bool bAll = set.find(NotificationManager::ALL) != set.end();
167            // If either the Notification has as sender 'all', the NotificationListener displays all Notifications or the NotificationListener has the sender of the Notification as target.
168            if(all || bAll || set.find(notification->getSender()) != set.end())
169            {
170                if(!bAll)
171                    this->notificationLists_[it->second]->insert(std::pair<std::time_t, Notification*>(time, notification)); // Insert the Notification in the notifications list of the current NotificationListener.
172                it->first->update(notification, time); // Update the NotificationListener.
173            }
174        }
175
176        COUT(4) << "Notification (&" << notification << ") registered with the NotificationManager." << std::endl;
177
178        return true;
179    }
180
181    /**
182    @brief
183        Unregisters a Notification within the NotificationManager for a given NotificationListener.
184    @param notification
185        A pointer to the Notification to be unregistered.
186    @param listener
187        A pointer to the NotificationListener the Notification is unregistered for.
188    */
189    void NotificationManager::unregisterNotification(Notification* notification, NotificationListener* listener)
190    {
191        assert(notification);
192        assert(listener);
193
194        // Remove the Notification from the list of Notifications of the input NotificationListener.
195        this->removeNotification(notification, *(this->notificationLists_.find(this->listenerList_.find(listener)->second)->second));
196
197        COUT(4) << "Notification (&" << notification << ") unregistered with the NotificationManager from listener (&" << listener << ")" << std::endl;
198    }
199
200    /**
201    @brief
202        Helper method that removes an input Notification form an input map.
203    @param notification
204        A pointer to the Notification to be removed.
205    @param map
206        The map the Notification should be removed from.
207    @return
208        Returns true if successful.
209    */
210    bool NotificationManager::removeNotification(Notification* notification, std::multimap<std::time_t, Notification*>& map)
211    {
212        // Iterates through all items in the map until the Notification is found.
213        //TODO: Do more efficiently?
214        for(std::multimap<std::time_t, Notification*>::iterator it = map.begin(); it != map.end(); it++)
215        {
216            if(it->second == notification)
217            {
218                map.erase(it);
219                return true;
220            }
221        }
222        return false;
223    }
224
225    /**
226    @brief
227        Registers a NotificationListener within the NotificationManager.
228    @param listener
229        The NotificationListener to be registered.
230    @return
231        Returns true if successful.  Fales if the NotificationListener is already registered.
232    */
233    bool NotificationManager::registerListener(NotificationListener* listener)
234    {
235        assert(listener);
236
237        // If the NotificationListener is already registered.
238        if(this->listenerList_.find(listener) != this->listenerList_.end())
239            return false;
240
241        this->highestIndex_ += 1;
242        unsigned int index = this->highestIndex_; // An identifier that identifies each registered NotificationListener uniquely.
243
244        this->listenerList_[listener] = index; // Add the NotificationListener to the list of NotificationListeners.
245
246        const std::set<std::string>& set = listener->getTargetsSet();
247
248        // If all senders are the target of the NotificationListener, then the list of Notifications for that specific NotificationListener is the same as the list of all Notifications.
249        bool bAll = set.find(NotificationManager::ALL) != set.end();
250        std::multimap<std::time_t, Notification*>* map = NULL;
251        if(bAll)
252            this->notificationLists_[index] = &this->allNotificationsList_;
253        // Else a new list (resp. multimap) is created and added to the list of Notification lists for NotificationListeners.
254        else
255        {
256            this->notificationLists_[index] = new std::multimap<std::time_t, Notification*>;
257            map = this->notificationLists_[index];
258        }
259
260        // Iterate through all Notifications to determine whether any of them should belong to the newly registered NotificationListener.
261        for(std::multimap<std::time_t, Notification*>::iterator it = this->allNotificationsList_.begin(); it != this->allNotificationsList_.end(); it++)
262        {
263            if(!bAll && set.find(it->second->getSender()) != set.end()) // Checks whether the listener has the sender of the current Notification as target.
264                map->insert(std::pair<std::time_t, Notification*>(it->first, it->second));
265        }
266
267        listener->update(); // Update the listener.
268
269        COUT(4) << "NotificationListener registered with the NotificationManager." << std::endl;
270
271        return true;
272    }
273
274    /**
275    @brief
276        Unregisters a NotificationListener within the NotificationManager.
277    @param listener
278        The NotificationListener to be unregistered.
279    */
280    void NotificationManager::unregisterListener(NotificationListener* listener)
281    {
282        assert(listener);
283
284        unsigned int identifier = this->listenerList_.find(listener)->second;
285        std::multimap<std::time_t, Notification*>* map = this->notificationLists_.find(identifier)->second;
286
287        // If the map is not the map of all Notifications, make sure all Notifications are unregistered.
288        std::multimap<std::time_t, Notification*>::iterator it = map->begin();
289        if(map != &this->allNotificationsList_)
290        {
291            while(it != map->end())
292            {
293                this->unregisterNotification(it->second, listener);
294                it = map->begin();
295            }
296            delete map;
297        }
298
299        COUT(4) << "NotificationListener '" << identifier << "' unregistered with the NotificationManager." << std::endl;
300
301        // Remove the NotificationListener from the list of NotificationListeners.
302        this->listenerList_.erase(listener);
303        // Remove the Notifications list that was associated with the input NotificationListener.
304        this->notificationLists_.erase(identifier);
305    }
306
307    /**
308    @brief
309        Fetches the Notifications for a specific NotificationListener in a specified timeframe and stores them in the input map.
310    @param listener
311        The NotificationListener the Notifications are fetched for.
312    @param map
313        A pointer to a multimap, in which the notifications are stored. The map needs to have been allocated.
314    @param timeFrameStart
315        The start time of the timeframe.
316    @param timeFrameEnd
317        The end time of the timeframe.
318    @return
319        Returns true if successful.
320    */
321    void NotificationManager::getNotifications(NotificationListener* listener, std::multimap<std::time_t,Notification*>* map, const std::time_t & timeFrameStart, const std::time_t & timeFrameEnd)
322    {
323        assert(listener);
324        assert(map);
325
326        std::multimap<std::time_t, Notification*>* notifications = this->notificationLists_[this->listenerList_[listener]]; // All the Notifications for the input NotificationListener.
327
328        std::multimap<std::time_t,Notification*>::iterator it, itLowest, itHighest;
329        // Iterators pointing to the bounds specified by the specified start and end times of the time frame.
330        itLowest = notifications->lower_bound(timeFrameStart);
331        itHighest = notifications->upper_bound(timeFrameEnd);
332
333        for(it = itLowest; it != itHighest; it++) // Iterate through the Notifications from the start of the time frame to the end of it.
334            map->insert(std::pair<std::time_t, Notification*>(it->first, it->second)); // Add the found Notifications to the map.
335    }
336
337    /**
338    @brief
339        Enters the edit mode of the NotificationLayer.
340    */
341    void NotificationManager::enterEditMode(void)
342    {
343        if(GameMode::showsGraphics())
344        {
345            GUIManager::getInstance().hideGUI("NotificationLayer");
346            GUIManager::getInstance().showGUI("NotificationLayer", false, false);
347            GUIManager::getInstance().getLuaState()->doString("NotificationLayer.enterEditMode()");
348        }
349    }
350
351    /**
352    @brief
353        Registers a NotificationQueue.
354        This makes sure that the NotificationQueue can be attained through lua by name. It also makes sure that the NotificationQueue is destroyed upon destruction of the NotificationManager.
355    @param queue
356        A pointer to the NotificationQueue to be registered.
357    @return
358        Returns true if successful. If e.g. the a NotificationQueue with that name already exists this returns false.
359    */
360    bool NotificationManager::registerQueue(NotificationQueue* queue)
361    {
362        COUT(4) << "NotificationQueue '" << queue->getName() << "' registered with the NotificationManager." << std::endl;
363        return this->queues_.insert(std::pair<const std::string, NotificationQueue*>(queue->getName(), queue)).second;
364    }
365
366    /**
367    @brief
368        Unregisters a NotificationQueue.
369    @param queue
370        A pointer to the NotificationQueue to be unregistered.
371    */
372    void NotificationManager::unregisterQueue(NotificationQueue* queue)
373    {
374        COUT(4) << "NotificationQueue '" << queue->getName() << "' unregistered with the NotificationManager." << std::endl;
375        this->queues_.erase(queue->getName());
376    }
377
378    /**
379    @brief
380        Loads all the NotificationQueues that should exist.
381    */
382    void NotificationManager::loadQueues(void)
383    {
384        new NotificationQueue("all");
385    }
386
387    /**
388    @brief
389        Creates a new NotificationQueue.
390        This is used in lua.
391    @param name
392        The name of the new NotificationQueue.
393    */
394    void NotificationManager::createQueue(const std::string& name)
395    {
396        new NotificationQueue(name);
397    }
398
399    /**
400    @brief
401        Get the NotificationQueue with the input name.
402    @param name
403        The name of the NotificationQueue.
404    @return
405        Returns a pointer to the NotificationQueue with the input name. Returns NULL if no NotificationQueue with such a name exists.
406    */
407    NotificationQueue* NotificationManager::getQueue(const std::string & name)
408    {
409        std::map<const std::string, NotificationQueue*>::iterator it = this->queues_.find(name);
410        // Returns NULL if no such NotificationQueue exists.
411        if(it == this->queues_.end())
412            return NULL;
413
414        return (*it).second;
415    }
416
417}
Note: See TracBrowser for help on using the repository browser.