freg  0.3
Free-Roaming Elementary Game
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Inventory.cpp
Go to the documentation of this file.
1  /* freg, Free-Roaming Elementary Game with open and interactive world
2  * Copyright (C) 2012-2014 Alexander 'mmaulwurff' Kromm
3  * mmaulwurff@gmail.com
4  *
5  * This file is part of FREG.
6  *
7  * FREG is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * FREG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with FREG. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "Block.h"
21 #include "World.h"
22 #include "Inventory.h"
23 #include "CraftManager.h"
24 #include "BlockManager.h"
25 
26 int Inventory::Start() const { return 0; }
27 int Inventory::Size() const { return size; }
28 int Inventory::Number(const int i) const { return inventory[i].size(); }
29 bool Inventory::Access() const { return true; }
30 
31 bool Inventory::Drop(const int src, int dest, int num,
32  Inventory * const inv_to)
33 {
34  dest = qMax(inv_to->Start(), dest);
35  bool ok_flag = false;
36  while ( num-- ) {
37  if ( src < Size()
38  && dest < inv_to->Size()
39  && not inventory[src].isEmpty()
40  && inv_to->Get(inventory[src].top(), dest) )
41  {
42  ok_flag = true;
43  Pull(src);
44  }
45  }
46  return ok_flag;
47 }
48 
49 bool Inventory::GetAll(Inventory * const from) {
50  bool flag = false;
51  for (int i=0; i<from->Size(); ++i) {
52  if ( from->Drop(i, 0, from->Number(i), this) ) {
53  flag = true;
54  }
55  }
56  return flag;
57 }
58 
59 void Inventory::Pull(const int num) {
60  if ( not inventory[num].isEmpty() ) {
61  inventory[num].pop();
62  }
63 }
64 
65 void Inventory::SaveAttributes(QDataStream & out) const {
66  for (int i=0; i<Size(); ++i) {
67  out << quint8(Number(i));
68  if ( not inventory[i].isEmpty() ) {
69  Block * const to_save = inventory[i].top();
70  for (int j=0; j<Number(i); ++j) {
71  to_save->SaveToFile(out);
72  to_save->RestoreDurabilityAfterSave();
73  }
74  }
75  }
76 }
77 
78 bool Inventory::Get(Block * const block, const int start) {
79  if ( block == nullptr ) return true;
80  if ( block->Wearable() == WEARABLE_VESSEL ) {
81  for (int i=0; i<Size(); ++i) {
82  if ( Number(i)==1 && ShowBlock(i) ) {
83  Inventory * const inner = ShowBlock(i)->HasInventory();
84  if ( inner && inner->Get(block) ) {
85  return true;
86  }
87  }
88  }
89  } else {
90  for (int i=start; i<Size(); ++i) {
91  if ( GetExact(block, i) ) {
92  ReceiveSignal(QObject::tr("You have %1 at slot '%2'.").
93  arg(block->FullName()).
94  arg(char(i + 'a')));
95  return true;
96  }
97  }
98  }
99  ReceiveSignal(QObject::tr("No room."));
100  return false;
101 }
102 
103 bool Inventory::GetExact(Block * const block, const int num) {
104  if ( block == nullptr) return true;
105  if ( inventory[num].isEmpty() ||
106  (*block == *inventory[num].top() && Number(num)<MAX_STACK_SIZE) )
107  {
108  inventory[num].push(block);
109  return true;
110  } else {
111  return false;
112  }
113 }
114 
115 void Inventory::MoveInside(const int from, const int num_to, const int num) {
116  for (int i=0; i<num; ++i) {
117  if ( GetExact(ShowBlock(from), num_to) ) {
118  Pull(from);
119  }
120  }
121 }
122 
123 bool Inventory::InscribeInv(const int num, const QString str) {
124  const int number = Number(num);
125  if ( number == 0 ) {
126  return false;
127  }
128  const int sub = inventory[num].top()->Sub();
129  if ( inventory[num].top() == block_manager.Normal(sub) ) {
130  for (int i=0; i<number; ++i) {
131  inventory[num].replace(i, block_manager.Normal(sub));
132  }
133  }
134  for (int i=0; i<number; ++i) {
135  if ( not inventory[num].at(i)->Inscribe(str) ) {
136  ReceiveSignal(QObject::tr("Cannot inscribe %1.").
137  arg(InvFullName(num)));
138  return false;
139  }
140  }
141  ReceiveSignal(QObject::tr("Inscribed %1.").arg(InvFullName(num)));
142  return true;
143 }
144 
145 QString Inventory::InvFullName(const int num) const {
146  return QString("%1%2").
147  arg( inventory[num].isEmpty() ?
148  QObject::tr("-empty-") :
149  inventory[num].top()->FullName() ).
150  arg( Number(num) <= 1 ?
151  "" : QString(" (x%1)").arg(Number(num)));
152 }
153 
154 int Inventory::GetInvWeight(const int i) const {
155  return inventory[i].isEmpty() ?
156  0 : inventory[i].top()->Weight()*Number(i);
157 }
158 
159 int Inventory::GetInvSub(const int i) const {
160  return inventory[i].isEmpty() ?
161  AIR : inventory[i].top()->Sub();
162 }
163 
164 int Inventory::GetInvKind(const int i) const {
165  return inventory[i].isEmpty() ?
166  BLOCK : int(inventory[i].top()->Kind());
167 }
168 
169 int Inventory::Weight() const {
170  int sum = 0;
171  for (int i=0; i<Size(); ++i) {
172  sum += GetInvWeight(i);
173  }
174  return sum / MAX_STACK_SIZE;
175 }
176 
177 Block * Inventory::ShowBlockInSlot(const int slot, const int index) const {
178  return ( slot >= Size() || index >= Number(slot) ) ?
179  nullptr : inventory[slot].at(index);
180 }
181 
182 Block * Inventory::ShowBlock(const int slot) const {
183  return ( slot >= Size() || inventory[slot].isEmpty() ) ?
184  nullptr : inventory[slot].top();
185 }
186 
187 bool Inventory::IsEmpty() const {
188  for (int i=Start(); i<Size(); ++i) {
189  if ( not inventory[i].isEmpty() ) {
190  return false;
191  }
192  }
193  return true;
194 }
195 
196 void Inventory::Push(const int x, const int y, const int z,
197  const int push_direction)
198 {
199  int x_targ, y_targ, z_targ;
200  world->Focus(x, y, z, &x_targ, &y_targ, &z_targ,
201  World::Anti(Block::MakeDirFromDamage(push_direction)));
202  Inventory * const inv =
203  world->GetBlock(x_targ, y_targ, z_targ)->HasInventory();
204  if ( inv != nullptr ) {
205  inv->GetAll(this);
206  }
207 }
208 
209 bool Inventory::MiniCraft(const int num) {
210  if ( Number(num) == 0 ) {
211  ReceiveSignal(QObject::tr("Nothing at slot '%1'.").
212  arg(char(num + 'a')));
213  return false;
214  } // else:
215  CraftItem * crafted =
216  new CraftItem({Number(num), GetInvKind(num), GetInvSub(num)});
217  if ( craft_manager->MiniCraft(&crafted) ) {
218  while ( not inventory[num].isEmpty() ) {
220  Pull(num);
221  }
222  for (int i=0; i<crafted->num; ++i) {
223  GetExact(BlockManager::NewBlock(crafted->kind, crafted->sub), num);
224  }
225  ReceiveSignal(QObject::tr("Craft successful."));
226  delete crafted;
227  return true;
228  } else {
229  ReceiveSignal(QObject::tr("You don't know how to craft this."));
230  return false;
231  }
232 }
233 
235  for (int i=Start(); i<Size()-1; ++i) {
236  if ( Number(i) != MAX_STACK_SIZE ) {
237  for (int j=i; j<Size(); ++j) {
238  MoveInside(j, i, Number(j));
239  }
240  }
241  }
242 }
243 
244 Inventory::Inventory(const int sz) :
245  size(sz),
246  inventory(new QStack<Block *>[sz])
247 {}
248 
249 Inventory::Inventory(QDataStream & str, const int sz) :
250  Inventory(sz)
251 {
252  for (int i=0; i<Size(); ++i) {
253  quint8 num;
254  str >> num;
255  while ( num-- ) {
256  quint8 kind, sub;
257  inventory[i].push(BlockManager::KindSubFromFile(str, &kind, &sub) ?
258  block_manager.Normal(sub) :
259  BlockManager::BlockFromFile(str, kind, sub));
260  }
261  }
262 }
263 
265  const int size = Size();
266  for (int i=0; i<size; ++i) {
267  while ( not inventory[i].isEmpty() ) {
269  }
270  }
271  delete [] inventory;
272 }
273 
274 // Define pure virtual functions to simplify debugging
275 void Inventory::ReceiveSignal(QString) { Q_UNREACHABLE(); }
276 
277 QString Inventory::FullName() const {
278  Q_UNREACHABLE();
279  return QString();
280 }
281 
283  Q_UNREACHABLE();
284  return nullptr;
285 }
virtual QString FullName() const
Definition: Block.cpp:88
bool InscribeInv(int num, QString str)
Returns true on success.
Definition: Inventory.cpp:123
bool MiniCraft(CraftItem **) const
bool IsEmpty() const
Definition: Inventory.cpp:187
void DeleteBlock(Block *) const
Does not actually delete normal blocks.
BlockManager block_manager
int Number(int i) const
Definition: Inventory.cpp:28
World * world
Definition: World.cpp:32
void MoveInside(int num_from, int num_to, int num)
Definition: Inventory.cpp:115
void RestoreDurabilityAfterSave()
Importart! Use it if block won't be deleted after SaveToFile.
Definition: Block.cpp:328
void Shake()
Stacks items in inventory if possible.
Definition: Inventory.cpp:234
const quint8 size
Definition: Inventory.h:91
Block * Normal(int sub) const
Use this to receive a pointer to normal block.
virtual bool Access() const
Definition: Inventory.cpp:29
virtual bool Drop(int src, int dest, int num, Inventory *to)
Returns true on success.
Definition: Inventory.cpp:31
static dirs Anti(dirs dir)
Definition: World.cpp:191
virtual bool Get(Block *block, int start=0)
Returns true on success.
Definition: Inventory.cpp:78
0
Definition: header.h:115
int GetInvSub(int i) const
Returns AIR if slot number i is empty.
Definition: Inventory.cpp:159
virtual Inventory * HasInventory()
Definition: Block.cpp:224
int GetInvKind(int i) const
Returns BLOCK if slot number i is empty.
Definition: Inventory.cpp:164
int GetInvWeight(int i) const
Definition: Inventory.cpp:154
Block * ShowBlock(int slot) const
Definition: Inventory.cpp:182
const int kind
Definition: CraftManager.h:32
virtual int Start() const
Definition: Inventory.cpp:26
int Size() const
Definition: Inventory.cpp:27
virtual bool GetAll(Inventory *from)
Returns true on success.
Definition: Inventory.cpp:49
virtual void ReceiveSignal(QString)=0
Definition: Inventory.cpp:275
static dirs MakeDirFromDamage(int damage_kind)
Definition: Block.cpp:83
Block * GetBlock(int x, int y, int z) const
Definition: World.cpp:204
virtual ~Inventory()
Definition: Inventory.cpp:264
Provides declaration for class Inventory for freg.
const int sub
Definition: CraftManager.h:33
Block * ShowBlockInSlot(int slot, int index) const
Don't move block shown by this function.
Definition: Inventory.cpp:177
QStack< Block * > *const inventory
Definition: Inventory.h:92
Inventory(Inventory &inv)=delete
virtual Inventory * HasInventory()=0
Definition: Inventory.cpp:282
virtual wearable Wearable() const
Definition: Block.cpp:212
virtual bool GetExact(Block *block, int num)
Returns true if block found its place.
Definition: Inventory.cpp:103
19
Definition: header.h:179
static Block * NewBlock(int kind, int sub)
Use this to receive a pointer to new not-normal block.
virtual int Weight() const
Definition: Inventory.cpp:169
void Push(int x, int y, int z, int push_direction)
Definition: Inventory.cpp:196
void Pull(int num)
Removes block from inventory. Does not delete block.
Definition: Inventory.cpp:59
Provides block ability to contain other blocks inside.
Definition: Inventory.h:33
virtual QString FullName() const =0
Definition: Inventory.cpp:277
const int num
Definition: CraftManager.h:31
void SaveToFile(QDataStream &out)
Definition: Block.cpp:309
const int MAX_STACK_SIZE
Definition: Inventory.h:29
bool Focus(int x, int y, int z, int *x_targ, int *y_targ, int *z_targ, dirs dir) const
False on error, true if focus is received to _targ successfully.
Definition: World.cpp:491
const CraftManager * craft_manager
static Block * BlockFromFile(QDataStream &, int kind, int sub)
Use this to load block from file.
Block without special physics and attributes.
Definition: Block.h:89
virtual QString InvFullName(int num) const
Definition: Inventory.cpp:145
virtual void SaveAttributes(QDataStream &out) const
Definition: Inventory.cpp:65
Provides definition for class Block.
bool MiniCraft(int num)
Returns true on success (something has been crafted).
Definition: Inventory.cpp:209
static bool KindSubFromFile(QDataStream &, quint8 *kind, quint8 *sub)
Returns true if block is normal.