1 /*
2  *  Copyright (C) 2011-2016  OpenDungeons Team
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef TRAPMANAGER_H
19 #define TRAPMANAGER_H
20 
21 #include <vector>
22 #include <istream>
23 #include <cstdint>
24 
25 class ClientNotification;
26 class GameMap;
27 class InputCommand;
28 class InputManager;
29 class ODPacket;
30 class Player;
31 class Seat;
32 class Tile;
33 class Trap;
34 
35 enum class TrapType;
36 
37 //! \brief Factory class to register a new trap
38 class TrapFactory
39 {
40 public:
~TrapFactory()41     virtual ~TrapFactory()
42     {}
43 
44     virtual TrapType getTrapType() const = 0;
45     virtual const std::string& getName() const = 0;
46     virtual const std::string& getNameReadable() const = 0;
47     virtual int getCostPerTile() const = 0;
48     virtual const std::string& getMeshName() const = 0;
49 
50     virtual void checkBuildTrap(GameMap* gameMap, const InputManager& inputManager, InputCommand& inputCommand) const = 0;
51     virtual bool buildTrap(GameMap* gameMap, Player* player, ODPacket& packet) const = 0;
52     virtual void checkBuildTrapEditor(GameMap* gameMap, const InputManager& inputManager, InputCommand& inputCommand) const = 0;
53     virtual bool buildTrapEditor(GameMap* gameMap, ODPacket& packet) const = 0;
54     virtual Trap* getTrapFromStream(GameMap* gameMap, std::istream& is) const = 0;
55     virtual bool buildTrapOnTiles(GameMap* gameMap, Player* player, const std::vector<Tile*>& tiles) const = 0;
56 
57     std::string formatBuildTrap(TrapType type, uint32_t price) const;
58 
59     //! \brief Computes the trap cost by checking the buildable tiles according to the given inputManager
60     //! and updates the inputCommand with (price/buildable tiles)
61     //! Note that traps that use checkBuildTrapDefault should also use buildTrapDefault and vice-versa
62     //! to make sure everything works if the data sent/received are changed
63     void checkBuildTrapDefault(GameMap* gameMap, TrapType type, const InputManager& inputManager, InputCommand& inputCommand) const;
64     bool getTrapTilesDefault(std::vector<Tile*>& tiles, GameMap* gameMap, Player* player, ODPacket& packet) const;
65     bool buildTrapDefault(GameMap* gameMap, Trap* trap, Seat* seat, const std::vector<Tile*>& tiles) const;
66     void checkBuildTrapDefaultEditor(GameMap* gameMap, TrapType type, const InputManager& inputManager, InputCommand& inputCommand) const;
67     bool buildTrapDefaultEditor(GameMap* gameMap, Trap* trap, ODPacket& packet) const;
68 };
69 
70 class TrapManager
71 {
72 friend class TrapRegister;
73 
74 public:
75     static Trap* load(GameMap* gameMap, std::istream& is);
76     //! \brief Handles the Trap deletion
77     static void dispose(const Trap* trap);
78     static void write(const Trap& trap, std::ostream& os);
79 
80     //! \brief Called on client side. It should check if the trap can be built according to the given inputManager
81     //! for the given player. It should update the InputCommand to make sure it displays the correct
82     //! information (price, selection icon, ...).
83     //! An ODPacket should be sent to the server if the trap is validated with relevant data. On server side, buildTrap
84     //! will be called with the data from the client and it build the trap if it is validated.
85     static void checkBuildTrap(GameMap* gameMap, TrapType type, const InputManager& inputManager, InputCommand& inputCommand);
86 
87     //! \brief Called on server side. Builds the trap according to the information in the packet
88     //! returns true if the trap was correctly built and false otherwise
89     static bool buildTrap(GameMap* gameMap, TrapType type, Player* player, ODPacket& packet);
90 
91     //! \brief Same as previous functions but for EditorMode
92     static void checkBuildTrapEditor(GameMap* gameMap, TrapType type, const InputManager& inputManager, InputCommand& inputCommand);
93     static bool buildTrapEditor(GameMap* gameMap, TrapType type, ODPacket& packet);
94     static bool buildTrapOnTiles(GameMap* gameMap, TrapType type, Player* player, const std::vector<Tile*>& tiles);
95 
96 
97     /*! \brief Exports the headers needed to recreate the Trap. It allows to extend Traps as much as wanted.
98      * The content of the Trap will be exported by exportToStream.
99      */
100     static Trap* getTrapFromStream(GameMap* gameMap, std::istream &is);
101 
102     //! \brief Gets the trap identification name
103     static const std::string& getTrapNameFromTrapType(TrapType type);
104 
105     //! \brief Gets the trap readable name
106     static const std::string& getTrapReadableName(TrapType type);
107 
108     static TrapType getTrapTypeFromTrapName(const std::string& name);
109 
110     //! \brief Called on client side. It should check if there are trap tiles to sell according
111     //! to the given inputManager for the given player. It should update the InputCommand to make
112     //! sure it displays the correct information (returned price, selection icon, ...).
113     //! An ODPacket should be sent to the server if the action is validated with relevant data. On server side,
114     //! sellTrapTiles will be called with the data from the client and it should sell the tiles if it is validated.
115     static void checkSellTrapTiles(GameMap* gameMap, const InputManager& inputManager, InputCommand& inputCommand);
116 
117     //! \brief Called on server side. Sells trap tiles according to the information in the packet
118     static void sellTrapTiles(GameMap* gameMap, Seat* seatSell, ODPacket& packet);
119 
120     //! \brief Same as above functions but for Editor mode
121     static void checkSellTrapTilesEditor(GameMap* gameMap, const InputManager& inputManager, InputCommand& inputCommand);
122     static void sellTrapTilesEditor(GameMap* gameMap, ODPacket& packet);
123 
124     static std::string formatSellTrap(int price);
125 
126     static int costPerTile(TrapType type);
127 
128     static const std::string& getMeshFromTrapType(TrapType trapType);
129 
130     /*! \brief Creates a ClientNotification to ask for creating a trap. It fills the packet with the needed data
131      * for the TrapManager to retrieve the spell (mainly the TrapType) so that the traps only have to handle their
132      * specific data.
133      */
134     static ClientNotification* createTrapClientNotification(TrapType type);
135     static ClientNotification* createTrapClientNotificationEditor(TrapType type);
136 
137     static int32_t getNeededWorkshopPointsPerTrap(TrapType trapType);
138 
139 private:
140     static void registerFactory(const TrapFactory* factory);
141     static void unregisterFactory(const TrapFactory* factory);
142 };
143 
144 class TrapRegister
145 {
146 public:
TrapRegister(const TrapFactory * factoryToRegister)147     TrapRegister(const TrapFactory* factoryToRegister) :
148         mTrapFactory(factoryToRegister)
149     {
150         TrapManager::registerFactory(mTrapFactory);
151     }
~TrapRegister()152     ~TrapRegister()
153     {
154         TrapManager::unregisterFactory(mTrapFactory);
155         delete mTrapFactory;
156     }
157 
getTrapFactory()158     inline const TrapFactory* getTrapFactory() const
159     { return mTrapFactory; }
160 
161 private:
162     const TrapFactory* mTrapFactory;
163 };
164 
165 #endif // TRAPMANAGER_H
166