the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
1#include "stdafx.h"
2#include "com.mojang.nbt.h"
3#include "net.minecraft.world.entity.player.h"
4#include "net.minecraft.world.item.h"
5#include "net.minecraft.world.level.tile.h"
6#include "net.minecraft.stats.h"
7#include "Material.h"
8#include "Inventory.h"
9
10const int Inventory::POP_TIME_DURATION = 5;
11const int Inventory::MAX_INVENTORY_STACK_SIZE = 64;
12
13const int Inventory::INVENTORY_SIZE = 4 * 9;
14const int Inventory::SELECTION_SIZE = 9;
15
16// 4J Stu - The Pllayer is managed by shared_ptrs elsewhere, but it owns us so we don't want to also
17// keep a shared_ptr of it. If we pass it on we should use shared_from_this() though
18Inventory::Inventory(Player *player)
19{
20 items = ItemInstanceArray( INVENTORY_SIZE );
21 armor = ItemInstanceArray( 4 );
22
23 selected = 0;
24
25 carried = nullptr;
26
27 changed = false;
28
29 this->player = player;
30}
31
32Inventory::~Inventory()
33{
34 delete [] items.data;
35 delete [] armor.data;
36}
37
38shared_ptr<ItemInstance> Inventory::getSelected()
39{
40 // sanity checking to prevent exploits
41 if (selected < SELECTION_SIZE && selected >= 0)
42 {
43 return items[selected];
44 }
45 return nullptr;
46}
47
48// 4J-PB - Added for the in-game tooltips
49bool Inventory::IsHeldItem()
50{
51 // sanity checking to prevent exploits
52 if (selected < SELECTION_SIZE && selected >= 0)
53 {
54 if(items[selected])
55 {
56 return true;
57 }
58 }
59 return false;
60}
61
62int Inventory::getSelectionSize()
63{
64 return SELECTION_SIZE;
65}
66
67
68int Inventory::getSlot(int tileId)
69{
70 for (unsigned int i = 0; i < items.length; i++)
71 {
72 if (items[i] != NULL && items[i]->id == tileId) return i;
73 }
74 return -1;
75}
76
77int Inventory::getSlot(int tileId, int data)
78{
79 for (int i = 0; i < items.length; i++)
80 {
81 if (items[i] != NULL && items[i]->id == tileId && items[i]->getAuxValue() == data) return i;
82 }
83 return -1;
84}
85
86int Inventory::getSlotWithRemainingSpace(shared_ptr<ItemInstance> item)
87{
88 for (unsigned int i = 0; i < items.length; i++)
89 {
90 if (items[i] != NULL && items[i]->id == item->id && items[i]->isStackable()
91 && items[i]->count < items[i]->getMaxStackSize() && items[i]->count < getMaxStackSize()
92 && (!items[i]->isStackedByData() || items[i]->getAuxValue() == item->getAuxValue())
93 && ItemInstance::tagMatches(items[i], item))
94 {
95 return i;
96 }
97 }
98 return -1;
99}
100
101int Inventory::getFreeSlot()
102{
103 for (unsigned int i = 0; i < items.length; i++)
104 {
105 if (items[i] == NULL) return i;
106 }
107 return -1;
108}
109
110
111void Inventory::grabTexture(int id, int data, bool checkData, bool mayReplace)
112{
113 int slot = -1;
114 heldItem = getSelected();
115 if (checkData)
116 {
117 slot = getSlot(id, data);
118 }
119 else
120 {
121 slot = getSlot(id);
122 }
123 if (slot >= 0 && slot < 9)
124 {
125 selected = slot;
126 return;
127 }
128
129 if (mayReplace)
130 {
131 if (id > 0)
132 {
133 int firstEmpty = getFreeSlot();
134 if (firstEmpty >= 0 && firstEmpty < 9)
135 {
136 selected = firstEmpty;
137 }
138
139 replaceSlot(Item::items[id], data);
140 }
141 }
142}
143
144void Inventory::swapPaint(int wheel)
145{
146 if (wheel > 0) wheel = 1;
147 if (wheel < 0) wheel = -1;
148
149 selected -= wheel;
150
151 while (selected < 0)
152 selected += 9;
153 while (selected >= 9)
154 selected -= 9;
155}
156
157int Inventory::clearInventory(int id, int data)
158{
159 int count = 0;
160 for (int i = 0; i < items.length; i++)
161 {
162 shared_ptr<ItemInstance> item = items[i];
163 if (item == NULL) continue;
164 if (id > -1 && item->id != id) continue;
165 if (data > -1 && item->getAuxValue() != data) continue;
166
167 count += item->count;
168 items[i] = nullptr;
169 }
170 for (int i = 0; i < armor.length; i++)
171 {
172 shared_ptr<ItemInstance> item = armor[i];
173 if (item == NULL) continue;
174 if (id > -1 && item->id != id) continue;
175 if (data > -1 && item->getAuxValue() != data) continue;
176
177 count += item->count;
178 armor[i] = nullptr;
179 }
180
181 if (carried != NULL)
182 {
183 if (id > -1 && carried->id != id) return count;
184 if (data > -1 && carried->getAuxValue() != data) return count;
185
186 count += carried->count;
187 setCarried(nullptr);
188 }
189
190 return count;
191}
192
193void Inventory::replaceSlot(Item *item, int data)
194{
195 if (item != NULL)
196 {
197 // It's too easy to accidentally pick block and lose enchanted items.
198 if (heldItem != NULL && heldItem->isEnchantable() && getSlot(heldItem->id, heldItem->getDamageValue()) == selected)
199 {
200 return;
201 }
202
203 int oldSlot = getSlot(item->id, data);
204 if (oldSlot >= 0)
205 {
206 int oldSlotCount = items[oldSlot]->count;
207 items[oldSlot] = items[selected];
208 items[selected] = shared_ptr<ItemInstance>( new ItemInstance(Item::items[item->id], oldSlotCount, data) );
209 }
210 else
211 {
212 items[selected] = shared_ptr<ItemInstance>(new ItemInstance(Item::items[item->id], 1, data));
213 }
214 }
215}
216
217
218int Inventory::addResource(shared_ptr<ItemInstance> itemInstance)
219{
220
221 int type = itemInstance->id;
222 int count = itemInstance->count;
223
224 // 4J Stu - Brought forward from 1.2
225 if (itemInstance->getMaxStackSize() == 1)
226 {
227 int slot = getFreeSlot();
228 if (slot < 0) return count;
229 if (items[slot] == NULL)
230 {
231 items[slot] = ItemInstance::clone(itemInstance);
232 player->handleCollectItem(itemInstance);
233 }
234 return 0;
235 }
236
237 int slot = getSlotWithRemainingSpace(itemInstance);
238 if (slot < 0) slot = getFreeSlot();
239 if (slot < 0) return count;
240 if (items[slot] == NULL)
241 {
242 items[slot] = shared_ptr<ItemInstance>( new ItemInstance(type, 0, itemInstance->getAuxValue()) );
243 // 4J Stu - Brought forward from 1.2
244 if (itemInstance->hasTag())
245 {
246 items[slot]->setTag((CompoundTag *) itemInstance->getTag()->copy());
247 player->handleCollectItem(itemInstance);
248 }
249 }
250
251 int toAdd = count;
252 if (toAdd > items[slot]->getMaxStackSize() - items[slot]->count)
253 {
254 toAdd = items[slot]->getMaxStackSize() - items[slot]->count;
255 }
256 if (toAdd > getMaxStackSize() - items[slot]->count)
257 {
258 toAdd = getMaxStackSize() - items[slot]->count;
259 }
260
261 if (toAdd == 0) return count;
262
263 count -= toAdd;
264 items[slot]->count += toAdd;
265 items[slot]->popTime = POP_TIME_DURATION;
266
267 return count;
268}
269
270
271void Inventory::tick()
272{
273 for (unsigned int i = 0; i < items.length; i++)
274 {
275 if (items[i] != NULL)
276 {
277 items[i]->inventoryTick(player->level, player->shared_from_this(), i, selected == i);
278 }
279 }
280}
281
282bool Inventory::removeResource(int type)
283{
284 int slot = getSlot(type);
285 if (slot < 0) return false;
286 if (--items[slot]->count <= 0) items[slot] = nullptr;
287
288 return true;
289}
290
291bool Inventory::removeResource(int type,int iAuxVal)
292{
293 int slot = getSlot(type,iAuxVal);
294 if (slot < 0) return false;
295 if (--items[slot]->count <= 0) items[slot] = nullptr;
296
297 return true;
298}
299
300void Inventory::removeResources(shared_ptr<ItemInstance> item)
301{
302 if(item == NULL) return;
303
304 int countToRemove = item->count;
305 for (unsigned int i = 0; i < items.length; i++)
306 {
307 if (items[i] != NULL && items[i]->sameItemWithTags(item))
308 {
309 int slotCount = items[i]->count;
310 items[i]->count -= countToRemove;
311 if(slotCount < countToRemove)
312 {
313 countToRemove -= slotCount;
314 }
315 else
316 {
317 countToRemove = 0;
318 }
319 if(items[i]->count <= 0) items[i] = nullptr;
320 }
321 }
322}
323
324shared_ptr<ItemInstance> Inventory::getResourceItem(int type)
325{
326 int slot = getSlot(type);
327 if (slot < 0) return nullptr;
328 return getItem( slot );
329}
330
331shared_ptr<ItemInstance> Inventory::getResourceItem(int type,int iAuxVal)
332{
333 int slot = getSlot(type,iAuxVal);
334 if (slot < 0) return nullptr;
335 return getItem( slot );
336}
337
338bool Inventory::hasResource(int type)
339{
340 int slot = getSlot(type);
341 if (slot < 0) return false;
342
343 return true;
344}
345
346void Inventory::swapSlots(int from, int to)
347{
348 shared_ptr<ItemInstance> tmp = items[to];
349 items[to] = items[from];
350 items[from] = tmp;
351}
352
353bool Inventory::add(shared_ptr<ItemInstance> item)
354{
355 if (item == NULL) return false;
356 if (item->count == 0) return false;
357
358 if (!item->isDamaged())
359 {
360 int lastSize;
361 int count = item->count;
362 do
363 {
364 lastSize = item->count;
365 item->count = addResource(item);
366 } while (item->count > 0 && item->count < lastSize);
367 if (item->count == lastSize && player->abilities.instabuild)
368 {
369 // silently destroy the item when having a full inventory
370 item->count = 0;
371 return true;
372 }
373 if( item->count < lastSize )
374 {
375 player->awardStat(
376 GenericStats::itemsCollected(item->id, item->getAuxValue()),
377 GenericStats::param_itemsCollected(item->id, item->getAuxValue(), count)
378 );
379 return true;
380 }
381 else
382 return false;
383 }
384
385 int slot = getFreeSlot();
386 if (slot >= 0)
387 {
388 player->handleCollectItem(item);
389
390 player->awardStat(
391 GenericStats::itemsCollected(item->id, item->getAuxValue()),
392 GenericStats::param_itemsCollected(item->id, item->getAuxValue(), item->GetCount()));
393
394 items[slot] = ItemInstance::clone(item);
395 items[slot]->popTime = POP_TIME_DURATION;
396 item->count = 0;
397 return true;
398 }
399 else if (player->abilities.instabuild)
400 {
401 // silently destroy the item when having a full inventory
402 item->count = 0;
403 return true;
404 }
405 return false;
406}
407
408shared_ptr<ItemInstance> Inventory::removeItem(unsigned int slot, int count)
409{
410
411 ItemInstanceArray pile = items;
412 if (slot >= items.length)
413 {
414 pile = armor;
415 slot -= items.length;
416 }
417
418 if (pile[slot] != NULL)
419 {
420 if (pile[slot]->count <= count)
421 {
422 shared_ptr<ItemInstance> item = pile[slot];
423 pile[slot] = nullptr;
424 return item;
425 }
426 else
427 {
428 shared_ptr<ItemInstance> i = pile[slot]->remove(count);
429 if (pile[slot]->count == 0) pile[slot] = nullptr;
430 return i;
431 }
432 }
433 return nullptr;
434}
435
436shared_ptr<ItemInstance> Inventory::removeItemNoUpdate(int slot)
437{
438 ItemInstanceArray pile = items;
439 if (slot >= items.length)
440 {
441 pile = armor;
442 slot -= items.length;
443 }
444
445 if (pile[slot] != NULL)
446 {
447 shared_ptr<ItemInstance> item = pile[slot];
448 pile[slot] = nullptr;
449 return item;
450 }
451 return nullptr;
452}
453
454void Inventory::setItem(unsigned int slot, shared_ptr<ItemInstance> item)
455{
456#ifdef _DEBUG
457 if(item!=NULL)
458 {
459 wstring itemstring=item->toString();
460 app.DebugPrintf("Inventory::setItem - slot = %d,\t item = %d ",slot,item->id);
461 //OutputDebugStringW(itemstring.c_str());
462 app.DebugPrintf("\n");
463 }
464#else
465 if(item!=NULL)
466 {
467 app.DebugPrintf("Inventory::setItem - slot = %d,\t item = %d, aux = %d\n",slot,item->id,item->getAuxValue());
468 }
469#endif
470 // 4J Stu - Changed this a little from Java to be less funn
471 if( slot >= items.length )
472 {
473 armor[slot - items.length] = item;
474 }
475 else
476 {
477 items[slot] = item;
478 }
479 player->handleCollectItem(item);
480 /*
481 ItemInstanceArray& pile = items;
482 if (slot >= pile.length)
483 {
484 slot -= pile.length;
485 pile = armor;
486 }
487
488 pile[slot] = item;
489 */
490}
491
492float Inventory::getDestroySpeed(Tile *tile)
493{
494 float speed = 1.0f;
495 if (items[selected] != NULL) speed *= items[selected]->getDestroySpeed(tile);
496 return speed;
497}
498
499ListTag<CompoundTag> *Inventory::save(ListTag<CompoundTag> *listTag)
500{
501 for (unsigned int i = 0; i < items.length; i++)
502 {
503 if (items[i] != NULL)
504 {
505 CompoundTag *tag = new CompoundTag();
506 tag->putByte(L"Slot", (byte) i);
507 items[i]->save(tag);
508 listTag->add(tag);
509 }
510 }
511 for (unsigned int i = 0; i < armor.length; i++)
512 {
513 if (armor[i] != NULL)
514 {
515 CompoundTag *tag = new CompoundTag();
516 tag->putByte(L"Slot", (byte) (i + 100));
517 armor[i]->save(tag);
518 listTag->add(tag);
519 }
520 }
521 return listTag;
522}
523
524void Inventory::load(ListTag<CompoundTag> *inventoryList)
525{
526 if( items.data != NULL)
527 {
528 delete[] items.data;
529 items.data = NULL;
530 }
531 if( armor.data != NULL)
532 {
533 delete[] armor.data;
534 armor.data = NULL;
535
536 }
537 items = ItemInstanceArray( INVENTORY_SIZE );
538 armor = ItemInstanceArray( 4 );
539 for (int i = 0; i < inventoryList->size(); i++)
540 {
541 CompoundTag *tag = inventoryList->get(i);
542 unsigned int slot = tag->getByte(L"Slot") & 0xff;
543 shared_ptr<ItemInstance> item = shared_ptr<ItemInstance>( ItemInstance::fromTag(tag) );
544 if (item != NULL)
545 {
546 if (slot >= 0 && slot < items.length) items[slot] = item;
547 if (slot >= 100 && slot < armor.length + 100) armor[slot - 100] = item;
548 }
549 }
550}
551
552unsigned int Inventory::getContainerSize()
553{
554 return items.length + 4;
555}
556
557shared_ptr<ItemInstance> Inventory::getItem(unsigned int slot)
558{
559 // 4J Stu - Changed this a little from the Java so it's less funny
560 if( slot >= items.length )
561 {
562 return armor[ slot - items.length ];
563 }
564 else
565 {
566 return items[ slot ];
567 }
568 /*
569 ItemInstanceArray pile = items;
570 if (slot >= pile.length)
571 {
572 slot -= pile.length;
573 pile = armor;
574 }
575
576 return pile[slot];
577 */
578}
579
580wstring Inventory::getName()
581{
582 return app.GetString(IDS_INVENTORY);
583}
584
585wstring Inventory::getCustomName()
586{
587 return L"";
588}
589
590bool Inventory::hasCustomName()
591{
592 return false;
593}
594
595int Inventory::getMaxStackSize() const
596{
597 return MAX_INVENTORY_STACK_SIZE;
598}
599
600bool Inventory::canDestroy(Tile *tile)
601{
602 if (tile->material->isAlwaysDestroyable()) return true;
603
604 shared_ptr<ItemInstance> item = getItem(selected);
605 if (item != NULL) return item->canDestroySpecial(tile);
606 return false;
607}
608
609shared_ptr<ItemInstance> Inventory::getArmor(int layer)
610{
611 return armor[layer];
612}
613
614int Inventory::getArmorValue()
615{
616 int val = 0;
617 for (unsigned int i = 0; i < armor.length; i++)
618 {
619 if (armor[i] != NULL && dynamic_cast<ArmorItem *>( armor[i]->getItem() ) != NULL )
620 {
621 int baseProtection = dynamic_cast<ArmorItem *>(armor[i]->getItem())->defense;
622
623 val += baseProtection;
624 }
625 }
626 return val;
627}
628
629void Inventory::hurtArmor(float dmg)
630{
631 dmg = dmg / 4;
632 if (dmg < 1)
633 {
634 dmg = 1;
635 }
636 for (unsigned int i = 0; i < armor.length; i++)
637 {
638 if (armor[i] != NULL && dynamic_cast<ArmorItem *>( armor[i]->getItem() ) != NULL )
639 {
640 armor[i]->hurtAndBreak( (int) dmg, dynamic_pointer_cast<LivingEntity>( player->shared_from_this() ) );
641 if (armor[i]->count == 0)
642 {
643 armor[i] = nullptr;
644 }
645 }
646 }
647}
648
649void Inventory::dropAll()
650{
651 for (unsigned int i = 0; i < items.length; i++)
652 {
653 if (items[i] != NULL)
654 {
655 player->drop(items[i], true);
656 items[i] = nullptr;
657 }
658 }
659 for (unsigned int i = 0; i < armor.length; i++)
660 {
661 if (armor[i] != NULL)
662 {
663 player->drop(armor[i], true);
664 armor[i] = nullptr;
665 }
666 }
667}
668
669void Inventory::setChanged()
670{
671 changed = true;
672}
673
674bool Inventory::isSame(shared_ptr<Inventory> copy)
675{
676 for (unsigned int i = 0; i < items.length; i++)
677 {
678 if (!isSame( copy->items[i], items[i])) return false;
679 }
680 for (unsigned int i = 0; i < armor.length; i++)
681 {
682 if (!isSame( copy->armor[i], armor[i])) return false;
683 }
684 return true;
685}
686
687
688bool Inventory::isSame(shared_ptr<ItemInstance> a, shared_ptr<ItemInstance> b)
689{
690 if (a == NULL && b == NULL) return true;
691 if (a == NULL || b == NULL) return false;
692
693 return a->id == b->id && a->count == b->count && a->getAuxValue() == b->getAuxValue();
694}
695
696
697shared_ptr<Inventory> Inventory::copy()
698{
699 shared_ptr<Inventory> copy = shared_ptr<Inventory>( new Inventory(NULL) );
700 for (unsigned int i = 0; i < items.length; i++)
701 {
702 copy->items[i] = items[i] != NULL ? items[i]->copy() : nullptr;
703 }
704 for (unsigned int i = 0; i < armor.length; i++)
705 {
706 copy->armor[i] = armor[i] != NULL ? armor[i]->copy() : nullptr;
707 }
708 return copy;
709}
710
711void Inventory::setCarried(shared_ptr<ItemInstance> carried)
712{
713 this->carried = carried;
714 player->handleCollectItem(carried);
715}
716
717shared_ptr<ItemInstance> Inventory::getCarried()
718{
719 return carried;
720}
721
722bool Inventory::stillValid(shared_ptr<Player> player)
723{
724 if (this->player->removed) return false;
725 if (player->distanceToSqr(this->player->shared_from_this()) > 8 * 8) return false;
726 return true;
727}
728
729bool Inventory::contains(shared_ptr<ItemInstance> itemInstance)
730{
731 for (unsigned int i = 0; i < armor.length; i++)
732 {
733 if (armor[i] != NULL && armor[i]->sameItem(itemInstance)) return true;
734 }
735 for (unsigned int i = 0; i < items.length; i++)
736 {
737 if (items[i] != NULL && items[i]->sameItem(itemInstance)) return true;
738 }
739 return false;
740}
741
742void Inventory::startOpen()
743{
744 // TODO Auto-generated method stub
745}
746
747void Inventory::stopOpen()
748{
749 // TODO Auto-generated method stub
750}
751
752bool Inventory::canPlaceItem(int slot, shared_ptr<ItemInstance> item)
753{
754 return true;
755}
756
757void Inventory::replaceWith(shared_ptr<Inventory> other)
758{
759 for (int i = 0; i < items.length; i++)
760 {
761 items[i] = ItemInstance::clone(other->items[i]);
762 }
763 for (int i = 0; i < armor.length; i++)
764 {
765 armor[i] = ItemInstance::clone(other->armor[i]);
766 }
767
768 selected = other->selected;
769}
770
771int Inventory::countMatches(shared_ptr<ItemInstance> itemInstance)
772{
773 if(itemInstance == NULL) return 0;
774 int count = 0;
775 //for (unsigned int i = 0; i < armor.length; i++)
776 //{
777 // if (armor[i] != NULL && armor[i]->sameItem(itemInstance)) count += items[i]->count;
778 //}
779 for (unsigned int i = 0; i < items.length; i++)
780 {
781 if (items[i] != NULL && items[i]->sameItemWithTags(itemInstance)) count += items[i]->count;
782 }
783 return count;
784}