Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/HUD_HS16/src/modules/pickup/PickupManager.cc @ 11305

Last change on this file since 11305 was 11305, checked in by patricwi, 7 years ago

linker error

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