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 "net.minecraft.h"
3#include "net.minecraft.world.entity.h"
4#include "net.minecraft.world.entity.item.h"
5#include "net.minecraft.world.entity.player.h"
6#include "net.minecraft.world.level.h"
7#include "net.minecraft.world.level.tile.h"
8#include "net.minecraft.world.level.tile.entity.h"
9#include "net.minecraft.world.phys.h"
10#include "net.minecraft.world.h"
11#include "HopperTileEntity.h"
12
13HopperTileEntity::HopperTileEntity()
14{
15 items = ItemInstanceArray(5);
16 name = L"";
17 cooldownTime = -1;
18}
19
20HopperTileEntity::~HopperTileEntity()
21{
22 delete [] items.data;
23}
24
25void HopperTileEntity::load(CompoundTag *base)
26{
27 TileEntity::load(base);
28
29 ListTag<CompoundTag> *inventoryList = (ListTag<CompoundTag> *) base->getList(L"Items");
30 delete[] items.data;
31 items = ItemInstanceArray(getContainerSize());
32 if (base->contains(L"CustomName")) name = base->getString(L"CustomName");
33 cooldownTime = base->getInt(L"TransferCooldown");
34 for (int i = 0; i < inventoryList->size(); i++)
35 {
36 CompoundTag *tag = inventoryList->get(i);
37 int slot = tag->getByte(L"Slot");
38 if (slot >= 0 && slot < items.length) items[slot] = ItemInstance::fromTag(tag);
39 }
40}
41
42void HopperTileEntity::save(CompoundTag *base)
43{
44 TileEntity::save(base);
45 ListTag<CompoundTag> *listTag = new ListTag<CompoundTag>();
46
47 for (int i = 0; i < items.length; i++)
48 {
49 if (items[i] != NULL)
50 {
51 CompoundTag *tag = new CompoundTag();
52 tag->putByte(L"Slot", (byte) i);
53 items[i]->save(tag);
54 listTag->add(tag);
55 }
56 }
57 base->put(L"Items", listTag);
58 base->putInt(L"TransferCooldown", cooldownTime);
59 if (hasCustomName()) base->putString(L"CustomName", name);
60}
61
62void HopperTileEntity::setChanged()
63{
64 TileEntity::setChanged();
65}
66
67unsigned int HopperTileEntity::getContainerSize()
68{
69 return items.length;
70}
71
72shared_ptr<ItemInstance> HopperTileEntity::getItem(unsigned int slot)
73{
74 return items[slot];
75}
76
77shared_ptr<ItemInstance> HopperTileEntity::removeItem(unsigned int slot, int count)
78{
79 if (items[slot] != NULL)
80 {
81 if (items[slot]->count <= count)
82 {
83 shared_ptr<ItemInstance> item = items[slot];
84 items[slot] = nullptr;
85 return item;
86 }
87 else
88 {
89 shared_ptr<ItemInstance> i = items[slot]->remove(count);
90 if (items[slot]->count == 0) items[slot] = nullptr;
91 return i;
92 }
93 }
94 return nullptr;
95}
96
97shared_ptr<ItemInstance> HopperTileEntity::removeItemNoUpdate(int slot)
98{
99 if (items[slot] != NULL)
100 {
101 shared_ptr<ItemInstance> item = items[slot];
102 items[slot] = nullptr;
103 return item;
104 }
105 return nullptr;
106}
107
108void HopperTileEntity::setItem(unsigned int slot, shared_ptr<ItemInstance> item)
109{
110 items[slot] = item;
111 if (item != NULL && item->count > getMaxStackSize()) item->count = getMaxStackSize();
112}
113
114wstring HopperTileEntity::getName()
115{
116 return hasCustomName() ? name : app.GetString(IDS_CONTAINER_HOPPER);
117}
118
119wstring HopperTileEntity::getCustomName()
120{
121 return hasCustomName() ? name : L"";
122}
123
124bool HopperTileEntity::hasCustomName()
125{
126 return !name.empty();
127}
128
129void HopperTileEntity::setCustomName(const wstring &name)
130{
131 this->name = name;
132}
133
134int HopperTileEntity::getMaxStackSize() const
135{
136 return Container::LARGE_MAX_STACK_SIZE;
137}
138
139bool HopperTileEntity::stillValid(shared_ptr<Player> player)
140{
141 if (level->getTileEntity(x, y, z) != shared_from_this()) return false;
142 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false;
143 return true;
144}
145
146void HopperTileEntity::startOpen()
147{
148}
149
150void HopperTileEntity::stopOpen()
151{
152}
153
154bool HopperTileEntity::canPlaceItem(int slot, shared_ptr<ItemInstance> item)
155{
156 return true;
157}
158
159void HopperTileEntity::tick()
160{
161 if (level == NULL || level->isClientSide) return;
162
163 cooldownTime--;
164
165 if (!isOnCooldown())
166 {
167 setCooldown(0);
168 tryMoveItems();
169 }
170}
171
172bool HopperTileEntity::tryMoveItems()
173{
174 if (level == NULL || level->isClientSide) return false;
175
176 if (!isOnCooldown() && HopperTile::isTurnedOn(getData()))
177 {
178 bool changed = ejectItems();
179 changed = suckInItems(this) || changed;
180
181 if (changed)
182 {
183 setCooldown(MOVE_ITEM_SPEED);
184 setChanged();
185 return true;
186 }
187 }
188
189 return false;
190}
191
192bool HopperTileEntity::ejectItems()
193{
194 shared_ptr<Container> container = getAttachedContainer();
195 if (container == NULL)
196 {
197 return false;
198 }
199
200 for (int slot = 0; slot < getContainerSize(); slot++)
201 {
202 if (getItem(slot) == NULL) continue;
203
204 shared_ptr<ItemInstance> original = getItem(slot)->copy();
205 shared_ptr<ItemInstance> result = addItem(container.get(), removeItem(slot, 1), Facing::OPPOSITE_FACING[HopperTile::getAttachedFace(getData())]);
206
207 if (result == NULL || result->count == 0)
208 {
209 container->setChanged();
210 return true;
211 }
212 else
213 {
214 setItem(slot, original);
215 }
216 }
217
218 return false;
219}
220
221bool HopperTileEntity::suckInItems(Hopper *hopper)
222{
223 shared_ptr<Container> container = getSourceContainer(hopper);
224
225 if (container != NULL)
226 {
227 int face = Facing::DOWN;
228
229 shared_ptr<WorldlyContainer> worldly = dynamic_pointer_cast<WorldlyContainer>(container);
230 if ( (worldly != NULL) && (face > -1) )
231 {
232 intArray slots = worldly->getSlotsForFace(face);
233
234 for (int i = 0; i < slots.length; i++)
235 {
236 if (tryTakeInItemFromSlot(hopper, container.get(), slots[i], face)) return true;
237 }
238 }
239 else
240 {
241 int size = container->getContainerSize();
242 for (int i = 0; i < size; i++)
243 {
244 if (tryTakeInItemFromSlot(hopper, container.get(), i, face)) return true;
245 }
246 }
247 }
248 else
249 {
250 shared_ptr<ItemEntity> above = getItemAt(hopper->getLevel(), hopper->getLevelX(), hopper->getLevelY() + 1, hopper->getLevelZ());
251
252 if (above != NULL)
253 {
254 return addItem(hopper, above);
255 }
256 }
257
258 return false;
259}
260
261bool HopperTileEntity::tryTakeInItemFromSlot(Hopper *hopper, Container *container, int slot, int face)
262{
263 shared_ptr<ItemInstance> item = container->getItem(slot);
264
265 if (item != NULL && canTakeItemFromContainer(container, item, slot, face))
266 {
267 shared_ptr<ItemInstance> original = item->copy();
268 shared_ptr<ItemInstance> result = addItem(hopper, container->removeItem(slot, 1), -1);
269
270 if (result == NULL || result->count == 0)
271 {
272 container->setChanged();
273 return true;
274 }
275 else
276 {
277 container->setItem(slot, original);
278 }
279 }
280
281 return false;
282}
283
284bool HopperTileEntity::addItem(Container *container, shared_ptr<ItemEntity> item)
285{
286 bool changed = false;
287 if (item == NULL) return false;
288
289 shared_ptr<ItemInstance> copy = item->getItem()->copy();
290 shared_ptr<ItemInstance> result = addItem(container, copy, -1);
291
292 if (result == NULL || result->count == 0)
293 {
294 changed = true;
295
296 item->remove();
297 }
298 else
299 {
300 item->setItem(result);
301 }
302
303 return changed;
304}
305
306shared_ptr<ItemInstance> HopperTileEntity::addItem(Container *container, shared_ptr<ItemInstance> item, int face)
307{
308 if (dynamic_cast<WorldlyContainer *>( container ) != NULL && face > -1)
309 {
310 WorldlyContainer *worldly = (WorldlyContainer *) container;
311 intArray slots = worldly->getSlotsForFace(face);
312
313 for (int i = 0; i < slots.length && item != NULL && item->count > 0; i++)
314 {
315 item = tryMoveInItem(container, item, slots[i], face);
316 }
317 }
318 else
319 {
320 int size = container->getContainerSize();
321 for (int i = 0; i < size && item != NULL && item->count > 0; i++)
322 {
323 item = tryMoveInItem(container, item, i, face);
324 }
325 }
326
327 if (item != NULL && item->count == 0)
328 {
329 item = nullptr;
330 }
331
332 return item;
333}
334
335bool HopperTileEntity::canPlaceItemInContainer(Container *container, shared_ptr<ItemInstance> item, int slot, int face)
336{
337 if (!container->canPlaceItem(slot, item)) return false;
338 if ( dynamic_cast<WorldlyContainer *>( container ) != NULL && !dynamic_cast<WorldlyContainer *>( container )->canPlaceItemThroughFace(slot, item, face)) return false;
339 return true;
340}
341
342bool HopperTileEntity::canTakeItemFromContainer(Container *container, shared_ptr<ItemInstance> item, int slot, int face)
343{
344 if (dynamic_cast<WorldlyContainer *>( container ) != NULL && !dynamic_cast<WorldlyContainer *>( container )->canTakeItemThroughFace(slot, item, face)) return false;
345 return true;
346}
347
348shared_ptr<ItemInstance> HopperTileEntity::tryMoveInItem(Container *container, shared_ptr<ItemInstance> item, int slot, int face)
349{
350 shared_ptr<ItemInstance> current = container->getItem(slot);
351
352 if (canPlaceItemInContainer(container, item, slot, face))
353 {
354 bool success = false;
355 if (current == NULL)
356 {
357 container->setItem(slot, item);
358 item = nullptr;
359 success = true;
360 }
361 else if (canMergeItems(current, item))
362 {
363 int space = item->getMaxStackSize() - current->count;
364 int count = min(item->count, space);
365
366 item->count -= count;
367 current->count += count;
368 success = count > 0;
369 }
370 if (success)
371 {
372 HopperTileEntity *hopper = dynamic_cast<HopperTileEntity *>(container);
373 if (hopper != NULL)
374 {
375 hopper->setCooldown(MOVE_ITEM_SPEED);
376 container->setChanged();
377 }
378 container->setChanged();
379 }
380 }
381 return item;
382}
383
384shared_ptr<Container> HopperTileEntity::getAttachedContainer()
385{
386 int face = HopperTile::getAttachedFace(getData());
387 return getContainerAt(getLevel(), x + Facing::STEP_X[face], y + Facing::STEP_Y[face], z + Facing::STEP_Z[face]);
388}
389
390shared_ptr<Container> HopperTileEntity::getSourceContainer(Hopper *hopper)
391{
392 return getContainerAt(hopper->getLevel(), hopper->getLevelX(), hopper->getLevelY() + 1, hopper->getLevelZ());
393}
394
395shared_ptr<ItemEntity> HopperTileEntity::getItemAt(Level *level, double xt, double yt, double zt)
396{
397 vector<shared_ptr<Entity> > *entities = level->getEntitiesOfClass(typeid(ItemEntity), AABB::newTemp(xt, yt, zt, xt + 1, yt + 1, zt + 1), EntitySelector::ENTITY_STILL_ALIVE);
398
399 if (entities->size() > 0)
400 {
401 shared_ptr<ItemEntity> out = dynamic_pointer_cast<ItemEntity>( entities->at(0) );
402 delete entities;
403 return out;
404 }
405 else
406 {
407 delete entities;
408 return nullptr;
409 }
410}
411
412shared_ptr<Container> HopperTileEntity::getContainerAt(Level *level, double x, double y, double z)
413{
414 shared_ptr<Container> result = nullptr;
415
416 int xt = Mth::floor(x);
417 int yt = Mth::floor(y);
418 int zt = Mth::floor(z);
419
420 shared_ptr<TileEntity> entity = level->getTileEntity(xt, yt, zt);
421
422 result = dynamic_pointer_cast<Container>(entity);
423 if (result != NULL)
424 {
425 if ( dynamic_pointer_cast<ChestTileEntity>(result) != NULL )
426 {
427 int id = level->getTile(xt, yt, zt);
428 Tile *tile = Tile::tiles[id];
429
430 if ( dynamic_cast<ChestTile *>( tile ) != NULL )
431 {
432 result = ((ChestTile *) tile)->getContainer(level, xt, yt, zt);
433 }
434 }
435 }
436
437 if (result == NULL)
438 {
439 vector<shared_ptr<Entity> > *entities = level->getEntities(nullptr, AABB::newTemp(x, y, z, x + 1, y + 1, z + 1), EntitySelector::CONTAINER_ENTITY_SELECTOR);
440
441 if ( (entities != NULL) && (entities->size() > 0) )
442 {
443 result = dynamic_pointer_cast<Container>( entities->at( level->random->nextInt(entities->size()) ) );
444 }
445 }
446
447 return result;
448}
449
450bool HopperTileEntity::canMergeItems(shared_ptr<ItemInstance> a, shared_ptr<ItemInstance> b)
451{
452 if (a->id != b->id) return false;
453 if (a->getAuxValue() != b->getAuxValue()) return false;
454 if (a->count > a->getMaxStackSize()) return false;
455 if (!ItemInstance::tagMatches(a, b)) return false;
456 return true;
457}
458
459Level *HopperTileEntity::getLevel()
460{
461 return TileEntity::getLevel();
462}
463
464double HopperTileEntity::getLevelX()
465{
466 return x;
467}
468
469double HopperTileEntity::getLevelY()
470{
471 return y;
472}
473
474double HopperTileEntity::getLevelZ()
475{
476 return z;
477}
478
479void HopperTileEntity::setCooldown(int time)
480{
481 cooldownTime = time;
482}
483
484bool HopperTileEntity::isOnCooldown()
485{
486 return cooldownTime > 0;
487}
488
489// 4J Added
490shared_ptr<TileEntity> HopperTileEntity::clone()
491{
492 shared_ptr<HopperTileEntity> result = shared_ptr<HopperTileEntity>( new HopperTileEntity() );
493 TileEntity::clone(result);
494
495 result->name = name;
496 result->cooldownTime = cooldownTime;
497 for (unsigned int i = 0; i < items.length; i++)
498 {
499 if (items[i] != NULL)
500 {
501 result->items[i] = ItemInstance::clone(items[i]);
502 }
503 }
504 return result;
505}