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_CONTAINER_H_5590165FD8A2451B98D71F13CD3ED8DC
21#define FS_CONTAINER_H_5590165FD8A2451B98D71F13CD3ED8DC
22
23#include <queue>
24
25#include "cylinder.h"
26#include "item.h"
27
28class Container;
29class DepotChest;
30class DepotLocker;
31
32class ContainerIterator
33{
34 public:
35 bool hasNext() const {
36 return !over.empty();
37 }
38
39 void advance();
40 Item* operator*();
41
42 private:
43 std::list<const Container*> over;
44 ItemDeque::const_iterator cur;
45
46 friend class Container;
47};
48
49class Container : public Item, public Cylinder
50{
51 public:
52 explicit Container(uint16_t type);
53 Container(uint16_t type, uint16_t size, bool unlocked = true, bool pagination = false);
54 explicit Container(Tile* tile);
55 ~Container();
56
57 // non-copyable
58 Container(const Container&) = delete;
59 Container& operator=(const Container&) = delete;
60
61 Item* clone() const override final;
62
63 Container* getContainer() override final {
64 return this;
65 }
66 const Container* getContainer() const override final {
67 return this;
68 }
69
70 virtual DepotLocker* getDepotLocker() {
71 return nullptr;
72 }
73 virtual const DepotLocker* getDepotLocker() const {
74 return nullptr;
75 }
76
77 Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream) override;
78 bool unserializeItemNode(OTB::Loader& loader, const OTB::Node& node, PropStream& propStream) override;
79 std::string getContentDescription() const;
80
81 size_t size() const {
82 return itemlist.size();
83 }
84 bool empty() const {
85 return itemlist.empty();
86 }
87 uint32_t capacity() const {
88 return maxSize;
89 }
90
91 ContainerIterator iterator() const;
92
93 const ItemDeque& getItemList() const {
94 return itemlist;
95 }
96
97 ItemDeque::const_reverse_iterator getReversedItems() const {
98 return itemlist.rbegin();
99 }
100 ItemDeque::const_reverse_iterator getReversedEnd() const {
101 return itemlist.rend();
102 }
103
104 std::string getName(bool addArticle = false) const;
105
106 bool hasParent() const;
107 void addItem(Item* item);
108 Item* getItemByIndex(size_t index) const;
109 bool isHoldingItem(const Item* item) const;
110
111 uint32_t getItemHoldingCount() const;
112 uint32_t getWeight() const override final;
113
114 bool isUnlocked() const {
115 return unlocked;
116 }
117 bool hasPagination() const {
118 return pagination;
119 }
120
121 //cylinder implementations
122 virtual ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count,
123 uint32_t flags, Creature* actor = nullptr) const override;
124 ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, uint32_t& maxQueryCount,
125 uint32_t flags) const override final;
126 ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const override final;
127 Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem,
128 uint32_t& flags) override final;
129
130 void addThing(Thing* thing) override final;
131 void addThing(int32_t index, Thing* thing) override final;
132 void addItemBack(Item* item);
133
134 void updateThing(Thing* thing, uint16_t itemId, uint32_t count) override final;
135 void replaceThing(uint32_t index, Thing* thing) override final;
136
137 void removeThing(Thing* thing, uint32_t count) override final;
138
139 int32_t getThingIndex(const Thing* thing) const override final;
140 size_t getFirstIndex() const override final;
141 size_t getLastIndex() const override final;
142 uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const override final;
143 std::map<uint32_t, uint32_t>& getAllItemTypeCount(std::map<uint32_t, uint32_t>& countMap) const override final;
144 Thing* getThing(size_t index) const override final;
145
146 void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) override;
147 void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) override;
148
149 void internalAddThing(Thing* thing) override final;
150 void internalAddThing(uint32_t index, Thing* thing) override final;
151 void startDecaying() override final;
152
153 protected:
154 ItemDeque itemlist;
155
156 private:
157 std::ostringstream& getContentDescription(std::ostringstream& os) const;
158
159 uint32_t maxSize;
160 uint32_t totalWeight = 0;
161 uint32_t serializationCount = 0;
162
163 bool unlocked;
164 bool pagination;
165
166 void onAddContainerItem(Item* item);
167 void onUpdateContainerItem(uint32_t index, Item* oldItem, Item* newItem);
168 void onRemoveContainerItem(uint32_t index, Item* item);
169
170 Container* getParentContainer();
171 void updateItemWeight(int32_t diff);
172
173 friend class ContainerIterator;
174 friend class IOMapSerialize;
175};
176
177#endif
178