1/**
2 * The Forgotten Server - a free and open-source MMORPG server emulator
3 * Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#ifndef FS_CYLINDER_H_54BBCEB2A5B7415DAD837E4D58115150
21#define FS_CYLINDER_H_54BBCEB2A5B7415DAD837E4D58115150
22
23#include "enums.h"
24#include "thing.h"
25
26class Item;
27class Creature;
28
29static constexpr int32_t INDEX_WHEREEVER = -1;
30
31enum cylinderflags_t {
32 FLAG_NOLIMIT = 1 << 0, // Bypass limits like capacity/container limits,
33 // blocking items/creatures etc.
34 FLAG_IGNOREBLOCKITEM = 1 << 1, // Bypass movable blocking item checks
35 FLAG_IGNOREBLOCKCREATURE = 1 << 2, // Bypass creature checks
36 FLAG_CHILDISOWNER =
37 1 << 3, // Used by containers to query capacity of the carrier (player)
38 FLAG_PATHFINDING =
39 1 << 4, // An additional check is done for floor changing/teleport items
40 FLAG_IGNOREFIELDDAMAGE = 1 << 5, // Bypass field damage checks
41 FLAG_IGNORENOTMOVEABLE = 1 << 6, // Bypass check for mobility
42 FLAG_IGNOREAUTOSTACK =
43 1 << 7, // queryDestination will not try to stack items together
44};
45
46enum cylinderlink_t {
47 LINK_OWNER,
48 LINK_PARENT,
49 LINK_TOPPARENT,
50 LINK_NEAR,
51};
52
53class Cylinder : virtual public Thing {
54public:
55 /**
56 * Query if the cylinder can add an object
57 * \param index points to the destination index (inventory slot/container
58 * position) -1 is a internal value and means add to a empty position, with no
59 * destItem
60 * \param thing the object to move/add
61 * \param count is the amount that we want to move/add
62 * \param flags if FLAG_CHILDISOWNER if set the query is from a child-cylinder
63 * (check cap etc.) if FLAG_NOLIMIT is set blocking items/container limits is
64 * ignored
65 * \param actor the creature trying to add the thing
66 * \returns ReturnValue holds the return value
67 */
68 virtual ReturnValue queryAdd(int32_t index, const Thing &thing,
69 uint32_t count, uint32_t flags,
70 Creature *actor = nullptr) const = 0;
71
72 /**
73 * Query the cylinder how much it can accept
74 * \param index points to the destination index (inventory slot/container
75 * position) -1 is a internal value and means add to a empty position, with no
76 * destItem
77 * \param thing the object to move/add
78 * \param count is the amount that we want to move/add
79 * \param maxQueryCount is the max amount that the cylinder can accept
80 * \param flags optional flags to modify the default behaviour
81 * \returns ReturnValue holds the return value
82 */
83 virtual ReturnValue queryMaxCount(int32_t index, const Thing &thing,
84 uint32_t count, uint32_t &maxQueryCount,
85 uint32_t flags) const = 0;
86
87 /**
88 * Query if the cylinder can remove an object
89 * \param thing the object to move/remove
90 * \param count is the amount that we want to remove
91 * \param flags optional flags to modify the default behaviour
92 * \returns ReturnValue holds the return value
93 */
94 virtual ReturnValue queryRemove(const Thing &thing, uint32_t count,
95 uint32_t flags) const = 0;
96
97 /**
98 * Query the destination cylinder
99 * \param index points to the destination index (inventory slot/container
100 * position), -1 is a internal value and means add to a empty position, with
101 * no destItem this method can change the index to point to the new cylinder
102 * index
103 * \param destItem is the destination object
104 * \param flags optional flags to modify the default behaviour
105 * this method can modify the flags
106 * \returns Cylinder returns the destination cylinder
107 */
108 virtual Cylinder *queryDestination(int32_t &index, const Thing &thing,
109 Item **destItem, uint32_t &flags) = 0;
110
111 /**
112 * Add the object to the cylinder
113 * \param thing is the object to add
114 */
115 virtual void addThing(Thing *thing) = 0;
116
117 /**
118 * Add the object to the cylinder
119 * \param index points to the destination index (inventory slot/container
120 * position)
121 * \param thing is the object to add
122 */
123 virtual void addThing(int32_t index, Thing *thing) = 0;
124
125 /**
126 * Update the item count or type for an object
127 * \param thing is the object to update
128 * \param itemId is the new item id
129 * \param count is the new count value
130 */
131 virtual void updateThing(Thing *thing, uint16_t itemId, uint32_t count) = 0;
132
133 /**
134 * Replace an object with a new
135 * \param index is the position to change (inventory slot/container position)
136 * \param thing is the object to update
137 */
138 virtual void replaceThing(uint32_t index, Thing *thing) = 0;
139
140 /**
141 * Remove an object
142 * \param thing is the object to delete
143 * \param count is the new count value
144 */
145 virtual void removeThing(Thing *thing, uint32_t count) = 0;
146
147 /**
148 * Is sent after an operation (move/add) to update internal values
149 * \param thing is the object that has been added
150 * \param index is the objects new index value
151 * \param link holds the relation the object has to the cylinder
152 */
153 virtual void postAddNotification(Thing *thing, const Cylinder *oldParent,
154 int32_t index,
155 cylinderlink_t link = LINK_OWNER) = 0;
156
157 /**
158 * Is sent after an operation (move/remove) to update internal values
159 * \param thing is the object that has been removed
160 * \param index is the previous index of the removed object
161 * \param link holds the relation the object has to the cylinder
162 */
163 virtual void postRemoveNotification(Thing *thing, const Cylinder *newParent,
164 int32_t index,
165 cylinderlink_t link = LINK_OWNER) = 0;
166
167 /**
168 * Gets the index of an object
169 * \param thing the object to get the index value from
170 * \returns the index of the object, returns -1 if not found
171 */
172 virtual int32_t getThingIndex(const Thing *thing) const;
173
174 /**
175 * Returns the first index
176 * \returns the first index, if not implemented 0 is returned
177 */
178 virtual size_t getFirstIndex() const;
179
180 /**
181 * Returns the last index
182 * \returns the last index, if not implemented 0 is returned
183 */
184 virtual size_t getLastIndex() const;
185
186 /**
187 * Gets the object based on index
188 * \returns the object, returns nullptr if not found
189 */
190 virtual Thing *getThing(size_t index) const;
191
192 /**
193 * Get the amount of items of a certain type
194 * \param itemId is the item type to the get the count of
195 * \param subType is the extra type an item can have such as
196 * charges/fluidtype, -1 means not used
197 * \returns the amount of items of the asked item type
198 */
199 virtual uint32_t getItemTypeCount(uint16_t itemId,
200 int32_t subType = -1) const;
201
202 /**
203 * Get the amount of items of a all types
204 * \param countMap a map to put the itemID:count mapping in
205 * \returns a map mapping item id to count (same as first argument)
206 */
207 virtual std::map<uint32_t, uint32_t> &
208 getAllItemTypeCount(std::map<uint32_t, uint32_t> &countMap) const;
209
210 /**
211 * Adds an object to the cylinder without sending to the client(s)
212 * \param thing is the object to add
213 */
214 virtual void internalAddThing(Thing *thing);
215
216 /**
217 * Adds an object to the cylinder without sending to the client(s)
218 * \param thing is the object to add
219 * \param index points to the destination index (inventory slot/container
220 * position)
221 */
222 virtual void internalAddThing(uint32_t index, Thing *thing);
223
224 virtual void startDecaying();
225};
226
227class VirtualCylinder final : public Cylinder {
228public:
229 static VirtualCylinder *virtualCylinder;
230
231 virtual ReturnValue queryAdd(int32_t, const Thing &, uint32_t, uint32_t,
232 Creature * = nullptr) const override {
233 return RETURNVALUE_NOTPOSSIBLE;
234 }
235 virtual ReturnValue queryMaxCount(int32_t, const Thing &, uint32_t,
236 uint32_t &, uint32_t) const override {
237 return RETURNVALUE_NOTPOSSIBLE;
238 }
239 virtual ReturnValue queryRemove(const Thing &, uint32_t,
240 uint32_t) const override {
241 return RETURNVALUE_NOTPOSSIBLE;
242 }
243 virtual Cylinder *queryDestination(int32_t &, const Thing &, Item **,
244 uint32_t &) override {
245 return nullptr;
246 }
247
248 virtual void addThing(Thing *) override {}
249 virtual void addThing(int32_t, Thing *) override {}
250 virtual void updateThing(Thing *, uint16_t, uint32_t) override {}
251 virtual void replaceThing(uint32_t, Thing *) override {}
252 virtual void removeThing(Thing *, uint32_t) override {}
253
254 virtual void postAddNotification(Thing *, const Cylinder *, int32_t,
255 cylinderlink_t = LINK_OWNER) override {}
256 virtual void postRemoveNotification(Thing *, const Cylinder *, int32_t,
257 cylinderlink_t = LINK_OWNER) override {}
258
259 bool isPushable() const override { return false; }
260 int32_t getThrowRange() const override { return 1; }
261 std::string getDescription(int32_t) const override { return {}; }
262 bool isRemoved() const override { return false; }
263};
264
265#endif
266