Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/modules/pickup/PickupManager.cc @ 11704

Last change on this file since 11704 was 11704, checked in by landauf, 6 years ago

[HUD_HS16] fixed wrong dependency between overlays and pickup module: pickup should NOT depend on overlays; instead overlays should use pickup.

also reverted all changes from HUD_HS16 in PickupManager for several reasons:

  • calling HUDPickupSystem is not necessary anymore due to the fixed dependencies
  • adding a console command is not necessary because there is already a full GUI for this purpose (press F4)
  • limiting the number of pickups to 10 is a bad idea because PickupManager manages pickups for ALL players in the game
  • Property svn:eol-style set to native
File size: 21.0 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 PickupManager.cc
31    @brief Implementation of the PickupManager class.
32*/
33
34#include "PickupManager.h"
35
36#include "core/CoreIncludes.h"
37#include "core/LuaState.h"
38#include "core/GUIManager.h"
39#include "core/class/Identifier.h"
40#include "core/singleton/ScopedSingletonIncludes.h"
41#include "network/Host.h"
42#include "network/NetworkFunctionIncludes.h"
43
44#include "infos/PlayerInfo.h"
45#include "interfaces/PickupCarrier.h"
46#include "worldentities/pawns/Pawn.h"
47
48#include "CollectiblePickup.h"
49#include "PickupRepresentation.h"
50
51namespace orxonox
52{
53    ManageScopedSingleton(PickupManager, ScopeID::ROOT, false);
54
55    // Initialization of the name of the PickupInventory GUI.
56    /*static*/ const std::string PickupManager::guiName_s = "PickupInventory";
57
58    // Register static network functions that are used to communicate changes to pickups over the network, such that the PickupInventory can display the information about the pickups properly.
59    registerStaticNetworkFunction(PickupManager::pickupChangedUsedNetwork);
60    registerStaticNetworkFunction(PickupManager::pickupChangedPickedUpNetwork);
61    registerStaticNetworkFunction(PickupManager::dropPickupNetworked);
62    registerStaticNetworkFunction(PickupManager::usePickupNetworked);
63
64    RegisterAbstractClass(PickupManager).inheritsFrom<PickupListener>();
65
66    /**
67    @brief
68        Constructor. Registers the PickupManager and creates the default PickupRepresentation.
69    */
70    PickupManager::PickupManager() : guiLoaded_(false), pickupHighestIndex_(0), defaultRepresentation_(nullptr)
71    {
72        RegisterObject(PickupManager);
73
74        this->defaultRepresentation_ = new PickupRepresentation();
75
76        orxout(internal_info, context::pickups) << "PickupManager created." << endl;
77    }
78
79    /**
80    @brief
81        Destructor.
82        Destroys the default PickupRepresentation and does some cleanup.
83    */
84    PickupManager::~PickupManager()
85    {
86        // Destroying the default representation.
87        if(this->defaultRepresentation_ != nullptr)
88            this->defaultRepresentation_->destroy();
89
90        this->representations_.clear();
91
92        // Destroying all the PickupInventoryContainers that are still there.
93        for(const auto& mapEntry : this->pickupInventoryContainers_)
94            delete mapEntry.second;
95        this->pickupInventoryContainers_.clear();
96
97        // Destroying all the WeakPointers that are still there.
98        this->pickups_.clear();
99        this->indexes_.clear();
100
101        orxout(internal_info, context::pickups) << "PickupManager destroyed." << endl;
102    }
103
104    /**
105    @brief
106        Registers a PickupRepresentation.
107    @param name
108        The representation's name.
109    @param representation
110        A pointer to the PickupRepresentation.
111    @return
112        Returns true if successful and false if not.
113    */
114    bool PickupManager::registerRepresentation(const std::string& name, PickupRepresentation* representation)
115    {
116        assert(representation);
117
118        // If the list is not empty and Pickupable already has a Representation registered.
119        if(!this->representations_.empty() && this->representations_.find(name) != this->representations_.end())
120            return false;
121
122        this->representations_[name] = representation;
123
124        orxout(verbose, context::pickups) << "PickupRepresentation &" << representation << " registered with the PickupManager." << endl;
125        return true;
126    }
127
128    /**
129    @brief
130        Unegisters a PickupRepresentation.
131    @param name
132        The representation's name.
133    @return
134        Returns true if successful and false if not.
135    */
136    bool PickupManager::unregisterRepresentation(const std::string& name)
137    {
138        std::map<std::string, PickupRepresentation*>::iterator it = this->representations_.find(name);
139        if(it == this->representations_.end()) // If the Pickupable is not registered in the first place.
140            return false;
141
142        this->representations_.erase(it);
143
144        orxout(verbose, context::pickups) << "PickupRepresentation &" << name << " unregistered with the PickupManager." << endl;
145        return true;
146    }
147
148    /**
149    @brief
150        Get the PickupRepresentation with the given name.
151    @param name
152        The name of the PickupRepresentation.
153    @return
154        Returns a pointer to the PickupRepresentation.
155    */
156    PickupRepresentation* PickupManager::getRepresentation(const std::string& name)
157    {
158        std::map<std::string, PickupRepresentation*>::iterator it = this->representations_.find(name);
159        if(it == this->representations_.end()) // If there is no PickupRepresentation associated with the input name.
160        {
161            orxout(verbose, context::pickups) << "PickupManager::getRepresentation() returned default representation." << endl;
162            return this->defaultRepresentation_;
163        }
164
165        return it->second;
166    }
167
168    /**
169    @brief
170        Is called by the PickupListener to notify the PickupManager, that the input Pickupable has transited to the input used state.
171    @param pickup
172        The Pickupable whose used status changed.
173    @param used
174        The used status the Pickupable changed to.
175    */
176    void PickupManager::pickupChangedUsed(Pickupable* pickup, bool used)
177    {
178        assert(pickup);
179
180        if(!GameMode::isMaster()) // If this is neither standalone nor the server.
181            return;
182
183        CollectiblePickup* collectible = orxonox_cast<CollectiblePickup*>(pickup);
184        // If the Pickupable is part of a PickupCollection it isn't displayed in the PickupInventory, just the PickupCollection is.
185        if(collectible != nullptr && collectible->isInCollection())
186            return;
187
188        // Getting clientId of the host this change of the pickup's used status concerns.
189        PickupCarrier* carrier = pickup->getCarrier();
190        while(carrier->getCarrierParent() != nullptr)
191            carrier = carrier->getCarrierParent();
192        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
193        if(pawn == nullptr)
194            return;
195        PlayerInfo* info = pawn->getPlayer();
196        if(info == nullptr)
197            return;
198        unsigned int clientId = info->getClientID();
199
200        // Get the number identifying the pickup.
201        std::map<Pickupable*, uint32_t>::iterator it = this->indexes_.find(pickup);
202        assert(it != this->indexes_.end());
203        uint32_t index = it->second;
204
205        // If we're either in standalone mode or this is the host whom the change of the pickup's status concerns.
206        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
207        {
208            PickupManager::pickupChangedUsedNetwork(index, used, pickup->isUsable(), pickup->isUnusable());
209        }
210        // If the concerned host is somewhere in the network, we call pickupChangedUsedNetwork() on its PickupManager.
211        else
212        {
213            callStaticNetworkFunction(&PickupManager::pickupChangedUsedNetwork, clientId, index, used, pickup->isUsable(), pickup->isUnusable());
214        }
215    }
216
217    /**
218    @brief
219        Helper method to react to the change in the used status of a Pickupable.
220        Static method that is used by the server to inform the client it concerns about the status change.
221        The parameters that are given are used to update the information (i.e. the PickupInventoryContainer) the concerning PickupManager has about the Pickupable that changed.
222    @param pickup
223        A number identifying the Pickupable that changed its used status.
224    @param inUse
225        The used status the Pickupable changed to. (i.e. whether the Pickupable is in use or not).
226    @param usable
227        Whether the Pickupable's used status can be changed used in the PickupInventory.
228    @param unusable
229        Whether the Pickupable's used status can be changed to unused in the PickupInventory.
230    */
231    /*static*/ void PickupManager::pickupChangedUsedNetwork(uint32_t pickup, bool inUse, bool usable, bool unusable)
232    {
233        PickupManager& manager = PickupManager::getInstance(); // Get the PickupManager singleton on this host.
234        // If the input Pickupable (i.e its identifier) is not present in the list the PickupManager has.
235        if(manager.pickupInventoryContainers_.find(pickup) == manager.pickupInventoryContainers_.end())
236        {
237            orxout(internal_error, context::pickups) << "Pickupable &(" << pickup << ") was not registered with PickupManager for the PickupInventory, when it changed used." << endl;
238            return;
239        }
240
241        // Update the Pickupable's container with the information transferred.
242        manager.pickupInventoryContainers_[pickup]->inUse = inUse;
243        manager.pickupInventoryContainers_[pickup]->usable = usable;
244        manager.pickupInventoryContainers_[pickup]->unusable = unusable;
245
246        manager.updateGUI(); // Tell the PickupInventory that something has changed.
247    }
248
249    /**
250    @brief
251        Is called by the PickupListener to notify the PickupManager, that the input Pickupable has transited to the input pickedUp state.
252    @param pickup
253        The Pickupable whose pickedUp status changed.
254    @param pickedUp
255        The pickedUp status the Pickupable changed to.
256    */
257    void PickupManager::pickupChangedPickedUp(Pickupable* pickup, bool pickedUp)
258    {
259        assert(pickup);
260
261        if(!GameMode::isMaster()) // If this is neither standalone nor the server.
262            return;
263
264        CollectiblePickup* collectible = orxonox_cast<CollectiblePickup*>(pickup);
265        // If the Pickupable is part of a PickupCollection it isn't displayed in the PickupInventory, just the PickupCollection is.
266        if(collectible != nullptr && collectible->isInCollection())
267            return;
268
269        // Getting clientId of the host this change of the pickup's pickedUp status concerns.
270        PickupCarrier* carrier = pickup->getCarrier();
271        while(carrier->getCarrierParent() != nullptr)
272            carrier = carrier->getCarrierParent();
273        Pawn* pawn = orxonox_cast<Pawn*>(carrier);
274        if(pawn == nullptr)
275            return;
276        PlayerInfo* info = pawn->getFormerPlayer();
277        if(info == nullptr)
278            return;
279        unsigned int clientId = info->getClientID();
280
281        uint32_t index = 0;
282        if(pickedUp) // If the Pickupable has changed to picked up, it is added to the required lists.
283        {
284            index = this->getPickupIndex(); // Get a new identifier (index) for the Pickupable.
285            // Add the Pickupable to the indexes_ and pickups_ lists.
286            this->indexes_[pickup] = index;
287            this->pickups_[index] = pickup;
288        }
289        else // If it was dropped, it is removed from the required lists.
290        {
291            // Get the indentifier (index) that identifies the input Pickupable.
292            std::map<Pickupable*, uint32_t>::iterator it = this->indexes_.find(pickup);
293            index = it->second;
294
295            // Remove the Pickupable from the indexes_ and pickups_ list.
296            this->indexes_.erase(it);
297            this->pickups_.erase(index);
298        }
299
300        // If we're either in standalone mode or this is the host whom the change of the pickup's status concerns.
301        if(GameMode::isStandalone() || Host::getPlayerID() == clientId)
302        {
303            // If there is no PickupRepresentation registered the default representation is used.
304            if(this->representations_.find(pickup->getRepresentationName()) == this->representations_.end())
305                PickupManager::pickupChangedPickedUpNetwork(index, pickup->isUsable(), this->defaultRepresentation_->getObjectID(), pickup->getRepresentationName(), pickedUp);
306            else
307                PickupManager::pickupChangedPickedUpNetwork(index, pickup->isUsable(), this->representations_[pickup->getRepresentationName()]->getObjectID(), pickup->getRepresentationName(), pickedUp);
308        }
309        // If the concerned host is somewhere in the network, we call pickupChangedPickedUpNetwork() on its PickupManager.
310        else
311        {
312            // If there is no PickupRepresentation registered the default representation is used.
313            if(this->representations_.find(pickup->getRepresentationName()) == this->representations_.end())
314            {
315                callStaticNetworkFunction(&PickupManager::pickupChangedPickedUpNetwork, clientId, index, pickup->isUsable(), this->defaultRepresentation_->getObjectID(), pickedUp);
316            }
317            else
318            {
319                callStaticNetworkFunction(&PickupManager::pickupChangedPickedUpNetwork, clientId, index, pickup->isUsable(), this->representations_[pickup->getRepresentationName()]->getObjectID(), pickedUp);
320            }
321        }
322
323    }
324
325    /**
326    @brief
327        Helper method to react to the change in the pickedUp status of a Pickupable.
328        Static method that is used by the server to inform the client it concerns about the status change.
329        The parameters that are given are used to update the information (i.e. the PickupInventoryContainer) the concerning PickupManager has about the Pickupable that changed.
330    @param pickup
331        A number identifying the Pickupable that changed its pickedUp status.
332    @param usable
333        Whether the Pickupable's used status can be changed to used in the PickupInventory.
334    @param representationObjectId
335        The objectId identifying (over the network) the PickupRepresentation that represents this Pickupable.
336    @param representationName
337        The name of the associated PickupRepresentation
338    @param pickedUp
339        The pickedUp status the Pickupable changed to.
340    */
341    /*static*/ void PickupManager::pickupChangedPickedUpNetwork(uint32_t pickup, bool usable, uint32_t representationObjectId, const std::string& representationName, bool pickedUp)
342    {
343        PickupManager& manager = PickupManager::getInstance(); // Get the PickupManager singleton on this host.
344        // If the Pickupable has been picked up, we create a new PickupInventoryContainer for it.
345        if(pickedUp)
346        {
347            // Create a new PickupInventoryContainer for the Pickupable and set all the necessary information.
348            PickupInventoryContainer* container = new PickupInventoryContainer;
349            container->pickup = pickup;
350            container->inUse = false;
351            container->pickedUp = pickedUp;
352            container->usable = usable;
353            container->unusable = false;
354            container->representationObjectId = representationObjectId;
355            container->representationName = representationName;
356            // Insert the container into the pickupInventoryContainers_ list.
357            manager.pickupInventoryContainers_.insert(std::pair<uint32_t, PickupInventoryContainer*>(pickup, container));
358
359            manager.updateGUI(); // Tell the PickupInventory that something has changed.
360        }
361        // If the Pickupable has been dropped, we remove it from the pickupInventoryContainers_ list.
362        else
363        {
364            std::map<uint32_t, PickupInventoryContainer*>::iterator it = manager.pickupInventoryContainers_.find(pickup);
365            if(it != manager.pickupInventoryContainers_.end())
366                delete it->second;
367            manager.pickupInventoryContainers_.erase(pickup);
368
369            manager.updateGUI(); // Tell the PickupInventory that something has changed.
370        }
371    }
372
373    /**
374    @brief
375        Get the number of pickups currently picked up by the player.
376        This method is used in lua to populate the PickupInventory. The intended usage is to call this method to reset the iterator of the list of PickupInventoryContainers and then use popPickup() to get the individual PickupInventoryContainers.
377    @return
378        Returns the number of the players picked up Pickupables.
379    */
380    int PickupManager::getNumPickups(void)
381    {
382        this->pickupsIterator_ = this->pickupInventoryContainers_.begin(); // Reset iterator.
383
384        return this->pickupInventoryContainers_.size();
385    }
386
387    /**
388    @brief
389        Drop the input Pickupable.
390        This method checks whether the input Pickupable still exists and drops it, if so.
391    @param pickup
392        The identifier of the Pickupable to be dropped.
393    */
394    void PickupManager::dropPickup(uint32_t pickup)
395    {
396        // If we're either server or standalone and the list of pickups is not empty, we find and drop the input pickup.
397        if(GameMode::isMaster())
398        {
399            if(this->pickups_.empty())
400                return;
401            Pickupable* pickupable = this->pickups_.find(pickup)->second;
402            if(pickupable != nullptr)
403                pickupable->drop();
404        }
405        // If we're neither server nor standalone we drop the pickup by calling dropPickupNetworked() of the PickupManager on the server.
406        else
407        {
408            callStaticNetworkFunction(&PickupManager::dropPickupNetworked, 0, pickup);
409        }
410    }
411
412    /**
413    @brief
414        Helper method to drop the input pickup on the server.
415        Static method that is used by clients to instruct the server to drop the input pickup.
416    @param pickup
417        The identifier of the Pickupable to be dropped.
418    */
419    /*static*/ void PickupManager::dropPickupNetworked(uint32_t pickup)
420    {
421        if(GameMode::isServer()) // Obviously we only want to do this on the server.
422        {
423            PickupManager& manager = PickupManager::getInstance();
424            manager.dropPickup(pickup);
425        }
426    }
427
428    /**
429    @brief
430        Use (or unuse) the input Pickupable.
431        This method checks whether the input Pickupable still exists and uses (or unuses) it, if so,
432    @param pickup
433        The identifier of the Pickupable to be used (or unused).
434    @param use
435        If true the input Pickupable is used, if false it is unused.
436    */
437    void PickupManager::usePickup(uint32_t pickup, bool use)
438    {
439        // If we're either server or standalone and the list of pickups is not empty, we find and change the used status of the input pickup.
440        if(GameMode::isMaster())
441        {
442            if(this->pickups_.empty())
443                return;
444            Pickupable* pickupable = this->pickups_.find(pickup)->second;
445            if(pickupable != nullptr)
446                pickupable->setUsed(use);
447        }
448        // If we're neither server nor standalone we change the used status of the pickup by calling usePickupNetworked() of the PickupManager on the server.
449        else
450        {
451            callStaticNetworkFunction(&PickupManager::usePickupNetworked, 0, pickup, use);
452        }
453    }
454
455    /**
456    @brief
457        Helper method to use (or unuse) the input Pickupable on the server.
458        Static method that is used by clients to instruct the server to use (or unuse) the input pickup.
459    @param pickup
460        The identifier of the Pickupable to be used (or unused).
461    @param use
462        If true the input Pickupable is used, if false it is unused.
463    */
464    /*static*/ void PickupManager::usePickupNetworked(uint32_t pickup, bool use)
465    {
466        if(GameMode::isServer())
467        {
468            PickupManager& manager = PickupManager::getInstance();
469            manager.usePickup(pickup, use);
470        }
471    }
472
473    /**
474    @brief
475        Updates the PickupInventory GUI.
476        Also loads the PickupInventory GUI if is hasn't been done already.
477    */
478    inline void PickupManager::updateGUI(void)
479    {
480        // We only need to update (and load) the GUI if this host shows graphics.
481        if(GameMode::showsGraphics())
482        {
483            if(!this->guiLoaded_) // If the GUI hasn't been loaded, yet, we load it.
484            {
485                GUIManager::getInstance().loadGUI(PickupManager::guiName_s);
486                this->guiLoaded_ = true;
487            }
488
489            // Update the GUI.
490            GUIManager::getInstance().getLuaState()->doString(PickupManager::guiName_s + ".update()");
491        }
492    }
493
494    /**
495    @brief
496        Get a new index for a Pickupable.
497        This will work as long as the number of Pickupables that are picked up is sufficiently small and as long as they don't exist forever.
498    @return
499        Returns the new index.
500    */
501    uint32_t PickupManager::getPickupIndex(void)
502    {
503        if(this->pickupHighestIndex_ == uint32_t(~0x0)-1) // If we've reached the highest possible number, we wrap around.
504            this->pickupHighestIndex_ = 0;
505        return this->pickupHighestIndex_++;
506    }
507
508}
Note: See TracBrowser for help on using the repository browser.