Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/SuperOrxoBros_HS18/SuperOrxoBros_HS18/src/modules/pickup/PickupManager.cc @ 12175

Last change on this file since 12175 was 12175, checked in by siramesh, 5 years ago

Super Orxo Bros (Sidharth Ramesh, Nisa Balta, Jeff Ren)

File size: 20.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            PickupManager::pickupChangedPickedUpNetwork(index, pickup->isUsable(), pickup->getRepresentationName(), pickedUp, pawn->getObjectID());
304        }
305        // If the concerned host is somewhere in the network, we call pickupChangedPickedUpNetwork() on its PickupManager.
306        else
307        {
308            callStaticNetworkFunction(&PickupManager::pickupChangedPickedUpNetwork, clientId, index, pickup->isUsable(), pickedUp, pawn->getObjectID());
309        }
310
311    }
312
313    /**
314    @brief
315        Helper method to react to the change in the pickedUp status of a Pickupable.
316        Static method that is used by the server to inform the client it concerns about the status change.
317        The parameters that are given are used to update the information (i.e. the PickupInventoryContainer) the concerning PickupManager has about the Pickupable that changed.
318    @param pickup
319        A number identifying the Pickupable that changed its pickedUp status.
320    @param usable
321        Whether the Pickupable's used status can be changed to used in the PickupInventory.
322    @param representationName
323        The name of the associated PickupRepresentation
324    @param pickedUp
325        The pickedUp status the Pickupable changed to.
326    @param carrierPawnId
327        The objectId identifier (over the network) the Pawn that carries this Pickupable
328    */
329    /*static*/ void PickupManager::pickupChangedPickedUpNetwork(uint32_t pickup, bool usable, const std::string& representationName, bool pickedUp, uint32_t carrierPawnId)
330    {
331        PickupManager& manager = PickupManager::getInstance(); // Get the PickupManager singleton on this host.
332        // If the Pickupable has been picked up, we create a new PickupInventoryContainer for it.
333        if(pickedUp)
334        {
335            // Create a new PickupInventoryContainer for the Pickupable and set all the necessary information.
336            PickupInventoryContainer* container = new PickupInventoryContainer;
337            container->pickup = pickup;
338            container->inUse = false;
339            container->pickedUp = pickedUp;
340            container->usable = usable;
341            container->unusable = false;
342            container->representationName = representationName;
343            container->carrierPawnId = carrierPawnId;
344            // Insert the container into the pickupInventoryContainers_ list.
345            manager.pickupInventoryContainers_.insert(std::pair<uint32_t, PickupInventoryContainer*>(pickup, container));
346
347            manager.updateGUI(); // Tell the PickupInventory that something has changed.
348        }
349        // If the Pickupable has been dropped, we remove it from the pickupInventoryContainers_ list.
350        else
351        {
352            std::map<uint32_t, PickupInventoryContainer*>::iterator it = manager.pickupInventoryContainers_.find(pickup);
353            if(it != manager.pickupInventoryContainers_.end())
354                delete it->second;
355            manager.pickupInventoryContainers_.erase(pickup);
356
357            manager.updateGUI(); // Tell the PickupInventory that something has changed.
358        }
359    }
360
361    /**
362    @brief
363        Get the number of pickups currently picked up by the player.
364        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.
365    @return
366        Returns the number of the players picked up Pickupables.
367    */
368    int PickupManager::getNumPickups(void)
369    {
370        this->pickupsIterator_ = this->pickupInventoryContainers_.begin(); // Reset iterator.
371
372        return this->pickupInventoryContainers_.size();
373    }
374
375    /**
376    @brief
377        Drop the input Pickupable.
378        This method checks whether the input Pickupable still exists and drops it, if so.
379    @param pickup
380        The identifier of the Pickupable to be dropped.
381    */
382    void PickupManager::dropPickup(uint32_t pickup)
383    {
384        // If we're either server or standalone and the list of pickups is not empty, we find and drop the input pickup.
385        if(GameMode::isMaster())
386        {
387            if(this->pickups_.empty())
388                return;
389            Pickupable* pickupable = this->pickups_.find(pickup)->second;
390            if(pickupable != nullptr)
391                pickupable->drop();
392        }
393        // If we're neither server nor standalone we drop the pickup by calling dropPickupNetworked() of the PickupManager on the server.
394        else
395        {
396            callStaticNetworkFunction(&PickupManager::dropPickupNetworked, 0, pickup);
397        }
398    }
399
400    /**
401    @brief
402        Helper method to drop the input pickup on the server.
403        Static method that is used by clients to instruct the server to drop the input pickup.
404    @param pickup
405        The identifier of the Pickupable to be dropped.
406    */
407    /*static*/ void PickupManager::dropPickupNetworked(uint32_t pickup)
408    {
409        if(GameMode::isServer()) // Obviously we only want to do this on the server.
410        {
411            PickupManager& manager = PickupManager::getInstance();
412            manager.dropPickup(pickup);
413        }
414    }
415
416    /**
417    @brief
418        Use (or unuse) the input Pickupable.
419        This method checks whether the input Pickupable still exists and uses (or unuses) it, if so,
420    @param pickup
421        The identifier of the Pickupable to be used (or unused).
422    @param use
423        If true the input Pickupable is used, if false it is unused.
424    */
425    void PickupManager::usePickup(uint32_t pickup, bool use)
426    {
427        // 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.
428        if(GameMode::isMaster())
429        {
430            if(this->pickups_.empty())
431                return;
432            Pickupable* pickupable = this->pickups_.find(pickup)->second;
433            if(pickupable != nullptr)
434                pickupable->setUsed(use);
435        }
436        // If we're neither server nor standalone we change the used status of the pickup by calling usePickupNetworked() of the PickupManager on the server.
437        else
438        {
439            callStaticNetworkFunction(&PickupManager::usePickupNetworked, 0, pickup, use);
440        }
441    }
442
443    /**
444    @brief
445        Helper method to use (or unuse) the input Pickupable on the server.
446        Static method that is used by clients to instruct the server to use (or unuse) the input pickup.
447    @param pickup
448        The identifier of the Pickupable to be used (or unused).
449    @param use
450        If true the input Pickupable is used, if false it is unused.
451    */
452    /*static*/ void PickupManager::usePickupNetworked(uint32_t pickup, bool use)
453    {
454        if(GameMode::isServer())
455        {
456            PickupManager& manager = PickupManager::getInstance();
457            manager.usePickup(pickup, use);
458        }
459    }
460
461    /**
462    @brief
463        Updates the PickupInventory GUI.
464        Also loads the PickupInventory GUI if is hasn't been done already.
465    */
466    inline void PickupManager::updateGUI(void)
467    {
468        // We only need to update (and load) the GUI if this host shows graphics.
469        if(GameMode::showsGraphics())
470        {
471            if(!this->guiLoaded_) // If the GUI hasn't been loaded, yet, we load it.
472            {
473                GUIManager::getInstance().loadGUI(PickupManager::guiName_s);
474                this->guiLoaded_ = true;
475            }
476
477            // Update the GUI.
478            GUIManager::getInstance().getLuaState()->doString(PickupManager::guiName_s + ".update()");
479        }
480    }
481
482    /**
483    @brief
484        Get a new index for a Pickupable.
485        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.
486    @return
487        Returns the new index.
488    */
489    uint32_t PickupManager::getPickupIndex(void)
490    {
491        if(this->pickupHighestIndex_ == uint32_t(~0x0)-1) // If we've reached the highest possible number, we wrap around.
492            this->pickupHighestIndex_ = 0;
493        return this->pickupHighestIndex_++;
494    }
495
496}
Note: See TracBrowser for help on using the repository browser.