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.h"
4#include "net.minecraft.world.entity.player.h"
5#include "net.minecraft.world.item.h"
6#include "net.minecraft.world.item.crafting.h"
7#include "net.minecraft.world.level.h"
8#include "net.minecraft.world.level.tile.h"
9#include "Material.h"
10#include "FurnaceTileEntity.h"
11
12int furnaceSlotsForUp [] = { FurnaceTileEntity::SLOT_INPUT };
13int furnaceSlotsForDown [] = { FurnaceTileEntity::SLOT_RESULT, FurnaceTileEntity::SLOT_FUEL };
14int furnaceSlotsForSides [] = { FurnaceTileEntity::SLOT_FUEL };
15
16const intArray FurnaceTileEntity::SLOTS_FOR_UP = intArray(furnaceSlotsForUp, 1);
17const intArray FurnaceTileEntity::SLOTS_FOR_DOWN = intArray(furnaceSlotsForDown, 2);
18const intArray FurnaceTileEntity::SLOTS_FOR_SIDES = intArray(furnaceSlotsForSides, 1);
19
20const int FurnaceTileEntity::BURN_INTERVAL = 10 * 20;
21
22// 4J Stu - Need a ctor to initialise member variables
23FurnaceTileEntity::FurnaceTileEntity() : TileEntity()
24{
25 items = ItemInstanceArray(3);
26
27 litTime = 0;
28 litDuration = 0;
29 tickCount = 0;
30 m_charcoalUsed = false;
31 name = L"";
32}
33
34FurnaceTileEntity::~FurnaceTileEntity()
35{
36 delete[] items.data;
37}
38
39
40unsigned int FurnaceTileEntity::getContainerSize()
41{
42 return items.length;
43}
44
45
46shared_ptr<ItemInstance> FurnaceTileEntity::getItem(unsigned int slot)
47{
48 return items[slot];
49}
50
51
52shared_ptr<ItemInstance> FurnaceTileEntity::removeItem(unsigned int slot, int count)
53{
54 m_charcoalUsed = false;
55
56 if (items[slot] != NULL)
57 {
58 if (items[slot]->count <= count)
59 {
60 shared_ptr<ItemInstance> item = items[slot];
61 items[slot] = nullptr;
62 // 4J Stu - Fix for duplication glitch
63 if(item->count <= 0) return nullptr;
64 return item;
65 }
66 else
67 {
68 shared_ptr<ItemInstance> i = items[slot]->remove(count);
69 if (items[slot]->count == 0) items[slot] = nullptr;
70 // 4J Stu - Fix for duplication glitch
71 if(i->count <= 0) return nullptr;
72 return i;
73 }
74 }
75 return nullptr;
76}
77
78shared_ptr<ItemInstance> FurnaceTileEntity::removeItemNoUpdate(int slot)
79{
80 m_charcoalUsed = false;
81
82 if (items[slot] != NULL)
83 {
84 shared_ptr<ItemInstance> item = items[slot];
85 items[slot] = nullptr;
86 return item;
87 }
88 return nullptr;
89}
90
91
92void FurnaceTileEntity::setItem(unsigned int slot, shared_ptr<ItemInstance> item)
93{
94 items[slot] = item;
95 if (item != NULL && item->count > getMaxStackSize()) item->count = getMaxStackSize();
96}
97
98
99wstring FurnaceTileEntity::getName()
100{
101 return hasCustomName() ? name : app.GetString(IDS_TILE_FURNACE);
102}
103
104wstring FurnaceTileEntity::getCustomName()
105{
106 return hasCustomName() ? name : L"";
107}
108
109bool FurnaceTileEntity::hasCustomName()
110{
111 return !name.empty();
112}
113
114void FurnaceTileEntity::setCustomName(const wstring &name)
115{
116 this->name = name;
117}
118
119void FurnaceTileEntity::load(CompoundTag *base)
120{
121 TileEntity::load(base);
122 ListTag<CompoundTag> *inventoryList = (ListTag<CompoundTag> *) base->getList(L"Items");
123 delete[] items.data;
124 items = ItemInstanceArray(getContainerSize());
125 for (int i = 0; i < inventoryList->size(); i++)
126 {
127 CompoundTag *tag = inventoryList->get(i);
128 unsigned int slot = tag->getByte(L"Slot");
129 if (slot >= 0 && slot < items.length) items[slot] = ItemInstance::fromTag(tag);
130 }
131
132 litTime = base->getShort(L"BurnTime");
133 tickCount = base->getShort(L"CookTime");
134 litDuration = getBurnDuration(items[SLOT_FUEL]);
135 if (base->contains(L"CustomName")) name = base->getString(L"CustomName");
136 m_charcoalUsed = base->getBoolean(L"CharcoalUsed");
137}
138
139
140void FurnaceTileEntity::save(CompoundTag *base)
141{
142 TileEntity::save(base);
143 base->putShort(L"BurnTime", (short) (litTime));
144 base->putShort(L"CookTime", (short) (tickCount));
145 ListTag<CompoundTag> *listTag = new ListTag<CompoundTag>();
146
147 for (unsigned int i = 0; i < items.length; i++)
148 {
149 if (items[i] != NULL)
150 {
151 CompoundTag *tag = new CompoundTag();
152 tag->putByte(L"Slot", (byte) i);
153 items[i]->save(tag);
154 listTag->add(tag);
155 }
156 }
157 base->put(L"Items", listTag);
158 if (hasCustomName()) base->putString(L"CustomName", name);
159 base->putBoolean(L"CharcoalUsed", m_charcoalUsed);
160}
161
162
163int FurnaceTileEntity::getMaxStackSize() const
164{
165 return Container::LARGE_MAX_STACK_SIZE;
166}
167
168
169int FurnaceTileEntity::getBurnProgress(int max)
170{
171 return tickCount * max / BURN_INTERVAL;
172}
173
174
175int FurnaceTileEntity::getLitProgress(int max)
176{
177 if (litDuration == 0) litDuration = BURN_INTERVAL;
178 return litTime * max / litDuration;
179}
180
181
182bool FurnaceTileEntity::isLit()
183{
184 return litTime > 0;
185}
186
187
188void FurnaceTileEntity::tick()
189{
190 bool wasLit = litTime > 0;
191 bool changed = false;
192 if (litTime > 0)
193 {
194 litTime--;
195 }
196
197 if ( level != NULL && !level->isClientSide)
198 {
199 if (litTime == 0 && canBurn())
200 {
201 litDuration = litTime = getBurnDuration(items[SLOT_FUEL]);
202 if (litTime > 0)
203 {
204 changed = true;
205 if (items[SLOT_FUEL] != NULL)
206 {
207 // 4J Added: Keep track of whether charcoal was used in production of current stack.
208 if ( items[SLOT_FUEL]->getItem()->id == Item::coal_Id
209 && items[SLOT_FUEL]->getAuxValue() == CoalItem::CHAR_COAL)
210 {
211 m_charcoalUsed = true;
212 }
213
214 items[SLOT_FUEL]->count--;
215 if (items[SLOT_FUEL]->count == 0)
216 {
217 Item *remaining = items[SLOT_FUEL]->getItem()->getCraftingRemainingItem();
218 items[SLOT_FUEL] = remaining != NULL ? shared_ptr<ItemInstance>(new ItemInstance(remaining)) : nullptr;
219 }
220 }
221 }
222 }
223
224 if (isLit() && canBurn())
225 {
226 tickCount++;
227 if (tickCount == BURN_INTERVAL)
228 {
229 tickCount = 0;
230 burn();
231 changed = true;
232 }
233 }
234 else
235 {
236 tickCount = 0;
237 }
238
239 if (wasLit != litTime > 0)
240 {
241 changed = true;
242 FurnaceTile::setLit(litTime > 0, level, x, y, z);
243 }
244 }
245
246 if (changed) setChanged();
247}
248
249
250bool FurnaceTileEntity::canBurn()
251{
252 if (items[SLOT_INPUT] == NULL) return false;
253 const ItemInstance *burnResult = FurnaceRecipes::getInstance()->getResult(items[SLOT_INPUT]->getItem()->id);
254 if (burnResult == NULL) return false;
255 if (items[SLOT_RESULT] == NULL) return true;
256 if (!items[SLOT_RESULT]->sameItem_not_shared(burnResult)) return false;
257 if (items[SLOT_RESULT]->count < getMaxStackSize() && items[SLOT_RESULT]->count < items[SLOT_RESULT]->getMaxStackSize()) return true;
258 if (items[SLOT_RESULT]->count < burnResult->getMaxStackSize()) return true;
259 return false;
260}
261
262
263void FurnaceTileEntity::burn()
264{
265 if (!canBurn()) return;
266
267 const ItemInstance *result = FurnaceRecipes::getInstance()->getResult(items[SLOT_INPUT]->getItem()->id);
268 if (items[SLOT_RESULT] == NULL) items[SLOT_RESULT] = result->copy();
269 else if (items[SLOT_RESULT]->id == result->id) items[SLOT_RESULT]->count++;
270
271 items[SLOT_INPUT]->count--;
272 if (items[SLOT_INPUT]->count <= 0) items[SLOT_INPUT] = nullptr;
273}
274
275
276int FurnaceTileEntity::getBurnDuration(shared_ptr<ItemInstance> itemInstance)
277{
278 if (itemInstance == NULL) return 0;
279 int id = itemInstance->getItem()->id;
280
281 Item *item = itemInstance->getItem();
282
283 if (id < 256 && Tile::tiles[id] != NULL)
284 {
285 Tile *tile = Tile::tiles[id];
286
287 if (tile == Tile::woodSlabHalf)
288 {
289 return BURN_INTERVAL * 3 / 4;
290 }
291
292 if (tile->material == Material::wood)
293 {
294 return BURN_INTERVAL * 3 / 2;
295 }
296
297 if (tile == Tile::coalBlock)
298 {
299 return BURN_INTERVAL * 8 * 10;
300 }
301 }
302
303 if (dynamic_cast<DiggerItem *>(item) && ((DiggerItem *) item)->getTier() == Item::Tier::WOOD)
304 {
305 return BURN_INTERVAL;
306 }
307 else if (dynamic_cast<WeaponItem *>(item) && ((WeaponItem *) item)->getTier() == Item::Tier::WOOD)
308 {
309 return BURN_INTERVAL;
310 }
311 else if (dynamic_cast<HoeItem *>(item) && ((HoeItem *) item)->getTier() == Item::Tier::WOOD)
312 {
313 return BURN_INTERVAL;
314 }
315
316 if (id == Item::stick->id)
317 {
318 return BURN_INTERVAL / 2;
319 }
320
321 if (id == Item::coal->id) return BURN_INTERVAL * 8;
322
323 if (id == Item::bucket_lava->id) return BURN_INTERVAL * 100;
324
325 if (id == Tile::sapling_Id) return BURN_INTERVAL / 2;
326
327 if (id == Item::blazeRod_Id) return BURN_INTERVAL * 12;
328
329 return 0;
330}
331
332bool FurnaceTileEntity::isFuel(shared_ptr<ItemInstance> item)
333{
334 return getBurnDuration(item) > 0;
335}
336
337bool FurnaceTileEntity::stillValid(shared_ptr<Player> player)
338{
339 if (level->getTileEntity(x, y, z) != shared_from_this() ) return false;
340 if (player->distanceToSqr(x + 0.5, y + 0.5, z + 0.5) > 8 * 8) return false;
341 return true;
342}
343
344void FurnaceTileEntity::setChanged()
345{
346 return TileEntity::setChanged();
347}
348
349void FurnaceTileEntity::startOpen()
350{
351}
352
353void FurnaceTileEntity::stopOpen()
354{
355}
356
357bool FurnaceTileEntity::canPlaceItem(int slot, shared_ptr<ItemInstance> item)
358{
359 if (slot == SLOT_RESULT) return false;
360 if (slot == SLOT_FUEL) return isFuel(item);
361 return true;
362}
363
364intArray FurnaceTileEntity::getSlotsForFace(int face)
365{
366 if (face == Facing::DOWN)
367 {
368 return SLOTS_FOR_DOWN;
369 }
370 else if (face == Facing::UP)
371 {
372 return SLOTS_FOR_UP;
373 }
374 else
375 {
376 return SLOTS_FOR_SIDES;
377 }
378}
379
380bool FurnaceTileEntity::canPlaceItemThroughFace(int slot, shared_ptr<ItemInstance> item, int face)
381{
382 return canPlaceItem(slot, item);
383
384}
385
386bool FurnaceTileEntity::canTakeItemThroughFace(int slot, shared_ptr<ItemInstance> item, int face)
387{
388 if (face == Facing::DOWN && slot == SLOT_FUEL)
389 {
390 if (item->id != Item::bucket_empty_Id) return false;
391 }
392
393 return true;
394}
395
396// 4J Added
397shared_ptr<TileEntity> FurnaceTileEntity::clone()
398{
399 shared_ptr<FurnaceTileEntity> result = shared_ptr<FurnaceTileEntity>( new FurnaceTileEntity() );
400 TileEntity::clone(result);
401
402 result->litTime = litTime;
403 result->tickCount = tickCount;
404 result->litDuration = litDuration;
405
406 for (unsigned int i = 0; i < items.length; i++)
407 {
408 if (items[i] != NULL)
409 {
410 result->items[i] = ItemInstance::clone(items[i]);
411 }
412 }
413 return result;
414}