Make inventory GUI do sane things when server-side inventory acts unusually
[oweals/minetest.git] / src / inventorymanager.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser 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 INVENTORYMANAGER_HEADER
21 #define INVENTORYMANAGER_HEADER
22
23 #include "inventory.h"
24 #include <iostream>
25 #include <string>
26 class ServerActiveObject;
27
28 struct InventoryLocation
29 {
30         enum Type{
31                 UNDEFINED,
32                 CURRENT_PLAYER,
33                 PLAYER,
34                 NODEMETA,
35         DETACHED,
36         } type;
37
38         std::string name; // PLAYER, DETACHED
39         v3s16 p; // NODEMETA
40
41         InventoryLocation()
42         {
43                 setUndefined();
44         }
45         void setUndefined()
46         {
47                 type = UNDEFINED;
48         }
49         void setCurrentPlayer()
50         {
51                 type = CURRENT_PLAYER;
52         }
53         void setPlayer(const std::string &name_)
54         {
55                 type = PLAYER;
56                 name = name_;
57         }
58         void setNodeMeta(v3s16 p_)
59         {
60                 type = NODEMETA;
61                 p = p_;
62         }
63         void setDetached(const std::string &name_)
64         {
65                 type = DETACHED;
66                 name = name_;
67         }
68
69         bool operator==(const InventoryLocation &other) const
70         {
71                 if(type != other.type)
72                         return false;
73                 switch(type){
74                 case UNDEFINED:
75                         return false;
76                 case CURRENT_PLAYER:
77                         return true;
78                 case PLAYER:
79                         return (name == other.name);
80                 case NODEMETA:
81                         return (p == other.p);
82                 case DETACHED:
83                         return (name == other.name);
84                 }
85                 return false;
86         }
87         bool operator!=(const InventoryLocation &other) const
88         {
89                 return !(*this == other);
90         }
91
92         void applyCurrentPlayer(const std::string &name_)
93         {
94                 if(type == CURRENT_PLAYER)
95                         setPlayer(name_);
96         }
97
98         std::string dump() const;
99         void serialize(std::ostream &os) const;
100         void deSerialize(std::istream &is);
101         void deSerialize(std::string s);
102 };
103
104 struct InventoryAction;
105
106 class InventoryManager
107 {
108 public:
109         InventoryManager(){}
110         virtual ~InventoryManager(){}
111         
112         // Get an inventory (server and client)
113         virtual Inventory* getInventory(const InventoryLocation &loc){return NULL;}
114     // Set modified (will be saved and sent over network; only on server)
115         virtual void setInventoryModified(const InventoryLocation &loc){}
116     // Send inventory action to server (only on client)
117         virtual void inventoryAction(InventoryAction *a){}
118 };
119
120 #define IACTION_MOVE 0
121 #define IACTION_DROP 1
122 #define IACTION_CRAFT 2
123
124 struct InventoryAction
125 {
126         static InventoryAction * deSerialize(std::istream &is);
127         
128         virtual u16 getType() const = 0;
129         virtual void serialize(std::ostream &os) const = 0;
130         virtual void apply(InventoryManager *mgr, ServerActiveObject *player,
131                         IGameDef *gamedef) = 0;
132         virtual void clientApply(InventoryManager *mgr, IGameDef *gamedef) = 0;
133         virtual ~InventoryAction() {};
134 };
135
136 struct IMoveAction : public InventoryAction
137 {
138         // count=0 means "everything"
139         u16 count;
140         InventoryLocation from_inv;
141         std::string from_list;
142         s16 from_i;
143         InventoryLocation to_inv;
144         std::string to_list;
145         s16 to_i;
146         
147         IMoveAction()
148         {
149                 count = 0;
150                 from_i = -1;
151                 to_i = -1;
152         }
153         
154         IMoveAction(std::istream &is);
155
156         u16 getType() const
157         {
158                 return IACTION_MOVE;
159         }
160
161         void serialize(std::ostream &os) const
162         {
163                 os<<"Move ";
164                 os<<count<<" ";
165                 os<<from_inv.dump()<<" ";
166                 os<<from_list<<" ";
167                 os<<from_i<<" ";
168                 os<<to_inv.dump()<<" ";
169                 os<<to_list<<" ";
170                 os<<to_i;
171         }
172
173         void apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef);
174
175         void clientApply(InventoryManager *mgr, IGameDef *gamedef);
176 };
177
178 struct IDropAction : public InventoryAction
179 {
180         // count=0 means "everything"
181         u16 count;
182         InventoryLocation from_inv;
183         std::string from_list;
184         s16 from_i;
185         
186         IDropAction()
187         {
188                 count = 0;
189                 from_i = -1;
190         }
191         
192         IDropAction(std::istream &is);
193
194         u16 getType() const
195         {
196                 return IACTION_DROP;
197         }
198
199         void serialize(std::ostream &os) const
200         {
201                 os<<"Drop ";
202                 os<<count<<" ";
203                 os<<from_inv.dump()<<" ";
204                 os<<from_list<<" ";
205                 os<<from_i;
206         }
207
208         void apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef);
209
210         void clientApply(InventoryManager *mgr, IGameDef *gamedef);
211 };
212
213 struct ICraftAction : public InventoryAction
214 {
215         // count=0 means "everything"
216         u16 count;
217         InventoryLocation craft_inv;
218         
219         ICraftAction()
220         {
221                 count = 0;
222         }
223         
224         ICraftAction(std::istream &is);
225
226         u16 getType() const
227         {
228                 return IACTION_CRAFT;
229         }
230
231         void serialize(std::ostream &os) const
232         {
233                 os<<"Craft ";
234                 os<<count<<" ";
235                 os<<craft_inv.dump()<<" ";
236         }
237
238         void apply(InventoryManager *mgr, ServerActiveObject *player, IGameDef *gamedef);
239
240         void clientApply(InventoryManager *mgr, IGameDef *gamedef);
241 };
242
243 // Crafting helper
244 bool getCraftingResult(Inventory *inv, ItemStack& result,
245                 bool decrementInput, IGameDef *gamedef);
246
247 #endif
248