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.world.entity.item.h"
3#include "net.minecraft.world.entity.player.h"
4#include "net.minecraft.world.entity.projectile.h"
5#include "net.minecraft.world.item.h"
6#include "net.minecraft.world.inventory.h"
7#include "net.minecraft.world.level.h"
8#include "net.minecraft.world.level.tile.h"
9#include "net.minecraft.world.level.tile.entity.h"
10#include "net.minecraft.world.h"
11#include "DispenserTile.h"
12#include "net.minecraft.h"
13#include "Mob.h"
14
15BehaviorRegistry DispenserTile::REGISTRY = BehaviorRegistry(new DefaultDispenseItemBehavior());
16
17DispenserTile::DispenserTile(int id) : BaseEntityTile(id, Material::stone)
18{
19 random = new Random();
20
21 iconTop = NULL;
22 iconFront = NULL;
23 iconFrontVertical = NULL;
24}
25
26int DispenserTile::getTickDelay(Level *level)
27{
28 return 4;
29}
30
31void DispenserTile::onPlace(Level *level, int x, int y, int z)
32{
33 BaseEntityTile::onPlace(level, x, y, z);
34 recalcLockDir(level, x, y, z);
35}
36
37void DispenserTile::recalcLockDir(Level *level, int x, int y, int z)
38{
39 if (level->isClientSide)
40 {
41 return;
42 }
43
44 int n = level->getTile(x, y, z - 1); // face = 2
45 int s = level->getTile(x, y, z + 1); // face = 3
46 int w = level->getTile(x - 1, y, z); // face = 4
47 int e = level->getTile(x + 1, y, z); // face = 5
48
49 int lockDir = 3;
50 if (Tile::solid[n] && !Tile::solid[s]) lockDir = 3;
51 if (Tile::solid[s] && !Tile::solid[n]) lockDir = 2;
52 if (Tile::solid[w] && !Tile::solid[e]) lockDir = 5;
53 if (Tile::solid[e] && !Tile::solid[w]) lockDir = 4;
54 level->setData(x, y, z, lockDir, Tile::UPDATE_CLIENTS);
55}
56
57Icon *DispenserTile::getTexture(int face, int data)
58{
59 int dir = data & FACING_MASK;
60
61 if (face == dir)
62 {
63 if (dir == Facing::UP || dir == Facing::DOWN)
64 {
65 return iconFrontVertical;
66 }
67 else
68 {
69 return iconFront;
70 }
71 }
72
73 if (dir == Facing::UP || dir == Facing::DOWN)
74 {
75 return iconTop;
76 }
77 else if (face == Facing::UP || face == Facing::DOWN)
78 {
79 return iconTop;
80 }
81
82 return icon;
83}
84
85void DispenserTile::registerIcons(IconRegister *iconRegister)
86{
87 icon = iconRegister->registerIcon(L"furnace_side");
88 iconTop = iconRegister->registerIcon(L"furnace_top");
89 iconFront = iconRegister->registerIcon(L"dispenser_front");
90 iconFrontVertical = iconRegister->registerIcon(L"dispenser_front_vertical");
91}
92
93// 4J-PB - Adding a TestUse for tooltip display
94bool DispenserTile::TestUse()
95{
96 return true;
97}
98
99bool DispenserTile::use(Level *level, int x, int y, int z, shared_ptr<Player> player, int clickedFace, float clickX, float clickY, float clickZ, bool soundOnly/*=false*/) // 4J added soundOnly param
100{
101 if( soundOnly) return false;
102
103 if (level->isClientSide)
104 {
105 return true;
106 }
107
108 shared_ptr<DispenserTileEntity> trap = dynamic_pointer_cast<DispenserTileEntity>( level->getTileEntity(x, y, z) );
109 player->openTrap(trap);
110
111 return true;
112}
113
114void DispenserTile::dispenseFrom(Level *level, int x, int y, int z)
115{
116 BlockSourceImpl source(level, x, y, z);
117 shared_ptr<DispenserTileEntity> trap = dynamic_pointer_cast<DispenserTileEntity>( source.getEntity() );
118 if (trap == NULL) return;
119
120 int slot = trap->getRandomSlot();
121 if (slot < 0)
122 {
123 level->levelEvent(LevelEvent::SOUND_CLICK_FAIL, x, y, z, 0);
124 }
125 else
126 {
127 shared_ptr<ItemInstance> item = trap->getItem(slot);
128 DispenseItemBehavior *behavior = getDispenseMethod(item);
129
130 if (behavior != DispenseItemBehavior::NOOP)
131 {
132 shared_ptr<ItemInstance> leftOver = behavior->dispense(&source, item);
133
134 trap->setItem(slot, leftOver->count == 0 ? nullptr : leftOver);
135 }
136 }
137}
138
139DispenseItemBehavior *DispenserTile::getDispenseMethod(shared_ptr<ItemInstance> item)
140{
141 return REGISTRY.get(item->getItem());
142}
143
144void DispenserTile::neighborChanged(Level *level, int x, int y, int z, int type)
145{
146 bool signal = level->hasNeighborSignal(x, y, z) || level->hasNeighborSignal(x, y + 1, z);
147 int data = level->getData(x, y, z);
148 bool isTriggered = (data & TRIGGER_BIT) != 0;
149
150 if (signal && !isTriggered)
151 {
152 level->addToTickNextTick(x, y, z, id, getTickDelay(level));
153 level->setData(x, y, z, data | TRIGGER_BIT, UPDATE_NONE);
154 }
155 else if (!signal && isTriggered)
156 {
157 level->setData(x, y, z, data & ~TRIGGER_BIT, UPDATE_NONE);
158 }
159}
160
161void DispenserTile::tick(Level *level, int x, int y, int z, Random *random)
162{
163 if (!level->isClientSide) // && (level.hasNeighborSignal(x, y, z) || level.hasNeighborSignal(x, y + 1, z)))
164 {
165 dispenseFrom(level, x, y, z);
166 }
167}
168
169shared_ptr<TileEntity> DispenserTile::newTileEntity(Level *level)
170{
171 return shared_ptr<DispenserTileEntity>( new DispenserTileEntity() );
172}
173
174void DispenserTile::setPlacedBy(Level *level, int x, int y, int z, shared_ptr<LivingEntity> by, shared_ptr<ItemInstance> itemInstance)
175{
176 int dir = PistonBaseTile::getNewFacing(level, x, y, z, by);
177
178 level->setData(x, y, z, dir, Tile::UPDATE_CLIENTS);
179
180 if (itemInstance->hasCustomHoverName())
181 {
182 dynamic_pointer_cast<DispenserTileEntity>( level->getTileEntity(x, y, z))->setCustomName(itemInstance->getHoverName());
183 }
184}
185
186void DispenserTile::onRemove(Level *level, int x, int y, int z, int id, int data)
187{
188 shared_ptr<Container> container = dynamic_pointer_cast<DispenserTileEntity>( level->getTileEntity(x, y, z) );
189 if (container != NULL )
190 {
191 for (unsigned int i = 0; i < container->getContainerSize(); i++)
192 {
193 shared_ptr<ItemInstance> item = container->getItem(i);
194 if (item != NULL)
195 {
196 float xo = random->nextFloat() * 0.8f + 0.1f;
197 float yo = random->nextFloat() * 0.8f + 0.1f;
198 float zo = random->nextFloat() * 0.8f + 0.1f;
199
200 while (item->count > 0)
201 {
202 int count = random->nextInt(21) + 10;
203 if (count > item->count) count = item->count;
204 item->count -= count;
205
206 shared_ptr<ItemInstance> newItem = shared_ptr<ItemInstance>( new ItemInstance(item->id, count, item->getAuxValue()) );
207 newItem->set4JData( item->get4JData() );
208 shared_ptr<ItemEntity> itemEntity = shared_ptr<ItemEntity>( new ItemEntity(level, x + xo, y + yo, z + zo, newItem ) );
209 float pow = 0.05f;
210 itemEntity->xd = (float) random->nextGaussian() * pow;
211 itemEntity->yd = (float) random->nextGaussian() * pow + 0.2f;
212 itemEntity->zd = (float) random->nextGaussian() * pow;
213 if (item->hasTag())
214 {
215 itemEntity->getItem()->setTag((CompoundTag *) item->getTag()->copy());
216 }
217 level->addEntity(itemEntity);
218 }
219
220 // 4J Stu - Fix for duplication glitch
221 container->setItem(i,nullptr);
222 }
223 }
224 level->updateNeighbourForOutputSignal(x, y, z, id);
225 }
226 BaseEntityTile::onRemove(level, x, y, z, id, data);
227}
228
229Position *DispenserTile::getDispensePosition(BlockSource *source)
230{
231 FacingEnum *facing = getFacing(source->getData());
232
233 double originX = source->getX() + 0.7 * facing->getStepX();
234 double originY = source->getY() + 0.7 * facing->getStepY();
235 double originZ = source->getZ() + 0.7 * facing->getStepZ();
236
237 return new PositionImpl(originX, originY, originZ);
238}
239
240FacingEnum *DispenserTile::getFacing(int data)
241{
242 return FacingEnum::fromData(data & FACING_MASK);
243}
244
245bool DispenserTile::hasAnalogOutputSignal()
246{
247 return true;
248}
249
250int DispenserTile::getAnalogOutputSignal(Level *level, int x, int y, int z, int dir)
251{
252 return AbstractContainerMenu::getRedstoneSignalFromContainer(dynamic_pointer_cast<Container>( level->getTileEntity(x, y, z)) );
253}