-
Notifications
You must be signed in to change notification settings - Fork 10
/
BlockShulkerBox.java
504 lines (443 loc) · 18.7 KB
/
BlockShulkerBox.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
package com.progwml6.ironshulkerbox.common.blocks;
import com.progwml6.ironshulkerbox.common.core.IronShulkerBoxBlocks;
import com.progwml6.ironshulkerbox.common.tileentity.TileEntityIronShulkerBox;
import com.progwml6.ironshulkerbox.common.util.BlockNames;
import net.minecraft.block.Block;
import net.minecraft.block.BlockDirectional;
import net.minecraft.block.material.EnumPushReaction;
import net.minecraft.block.state.BlockFaceShape;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.Enchantments;
import net.minecraft.init.Items;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer;
import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.INameable;
import net.minecraft.util.Mirror;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.fml.network.NetworkHooks;
import javax.annotation.Nullable;
import java.util.List;
public abstract class BlockShulkerBox extends Block
{
public static final EnumProperty<EnumFacing> FACING = BlockDirectional.FACING;
protected final EnumDyeColor color;
private final IronShulkerBoxType type;
public BlockShulkerBox(EnumDyeColor colorIn, Block.Properties properties, IronShulkerBoxType typeIn)
{
super(properties);
this.color = colorIn;
this.type = typeIn;
this.setDefaultState((IBlockState) (this.stateContainer.getBaseState()).with(FACING, EnumFacing.UP));
this.setRegistryName(new ResourceLocation(BlockNames.getNameWithColor(typeIn.itemName, colorIn)));
}
/**
* @deprecated call via {@link IBlockState#causesSuffocation()} whenever possible. Implementing/overriding is fine.
*/
@Override
public boolean causesSuffocation(IBlockState state)
{
return true;
}
/**
* @deprecated call via {@link IBlockState#isFullCube()} whenever possible. Implementing/overriding is fine.
*/
@Override
public boolean isFullCube(IBlockState state)
{
return false;
}
/**
* @deprecated call via {@link IBlockState#hasCustomBreakingProgress()} whenever possible. Implementing/overriding is
* fine.
*/
@Override
@OnlyIn(Dist.CLIENT)
public boolean hasCustomBreakingProgress(IBlockState state)
{
return true;
}
/**
* The type of render function called. MODEL for mixed tesr and static model, MODELBLOCK_ANIMATED for TESR-only,
* LIQUID for vanilla liquids, INVISIBLE to skip all rendering
* @deprecated call via {@link IBlockState#getRenderType()} whenever possible. Implementing/overriding is fine.
*/
@Override
public EnumBlockRenderType getRenderType(IBlockState state)
{
return EnumBlockRenderType.ENTITYBLOCK_ANIMATED;
}
@Override
public boolean onBlockActivated(IBlockState state, World worldIn, BlockPos pos, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ)
{
if (worldIn.isRemote)
{
return true;
}
else if (player.isSpectator())
{
return true;
}
else
{
TileEntity tileentity = worldIn.getTileEntity(pos);
if (tileentity instanceof TileEntityIronShulkerBox)
{
EnumFacing enumFacing = state.get(FACING);
boolean flag;
if (((TileEntityIronShulkerBox) tileentity).getAnimationStatus() == TileEntityIronShulkerBox.AnimationStatus.CLOSED)
{
AxisAlignedBB axisalignedbb = VoxelShapes.fullCube().getBoundingBox().expand((double) (0.5F * (float) enumFacing.getXOffset()), (double) (0.5F * (float) enumFacing.getYOffset()), (double) (0.5F * (float) enumFacing.getZOffset())).contract((double) enumFacing.getXOffset(), (double) enumFacing.getYOffset(), (double) enumFacing.getZOffset());
flag = worldIn.isCollisionBoxesEmpty(null, axisalignedbb.offset(pos.offset(enumFacing)));
}
else
{
flag = true;
}
if (flag)
{
player.addStat(StatList.OPEN_SHULKER_BOX);
if (player instanceof EntityPlayerMP && !(player instanceof FakePlayer))
{
EntityPlayerMP entityPlayerMP = (EntityPlayerMP) player;
NetworkHooks.openGui(entityPlayerMP, (IInteractionObject) tileentity, buf -> buf.writeBlockPos(tileentity.getPos()));
}
}
return true;
}
else
{
return false;
}
}
}
@Override
public IBlockState getStateForPlacement(BlockItemUseContext context)
{
return this.getDefaultState().with(FACING, context.getFace());
}
@Override
protected void fillStateContainer(StateContainer.Builder<Block, IBlockState> builder)
{
builder.add(FACING);
}
/**
* Called before the Block is set to air in the world. Called regardless of if the player's tool can actually collect
* this block
*/
@Override
public void onBlockHarvested(World worldIn, BlockPos pos, IBlockState state, EntityPlayer player)
{
if (worldIn.getTileEntity(pos) instanceof TileEntityIronShulkerBox)
{
TileEntityIronShulkerBox shulkerBox = (TileEntityIronShulkerBox) worldIn.getTileEntity(pos);
shulkerBox.setDestroyedByCreativePlayer(player.abilities.isCreativeMode);
shulkerBox.fillWithLoot(player);
}
super.onBlockHarvested(worldIn, pos, state, player);
}
@Override
public void dropBlockAsItemWithChance(IBlockState state, World worldIn, BlockPos pos, float chancePerItem, int fortune)
{
}
/**
* Called by ItemBlocks after a block is set in the world, to allow post-place logic
*/
@Override
public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack)
{
if (stack.hasDisplayName())
{
TileEntity tileentity = worldIn.getTileEntity(pos);
if (tileentity instanceof TileEntityIronShulkerBox)
{
((TileEntityIronShulkerBox) tileentity).setCustomName(stack.getDisplayName());
}
}
}
@Override
public void onReplaced(IBlockState state, World worldIn, BlockPos pos, IBlockState newState, boolean isMoving)
{
if (state.getBlock() != newState.getBlock())
{
TileEntity tileentity = worldIn.getTileEntity(pos);
if (tileentity instanceof TileEntityIronShulkerBox)
{
TileEntityIronShulkerBox shulkerBox = (TileEntityIronShulkerBox) tileentity;
if (!shulkerBox.isCleared() && shulkerBox.shouldDrop())
{
ItemStack itemstack = new ItemStack(this);
itemstack.getOrCreateTag().put("BlockEntityTag", ((TileEntityIronShulkerBox) tileentity).saveToNbt(new NBTTagCompound()));
if (shulkerBox.hasCustomName())
{
itemstack.setDisplayName(shulkerBox.getCustomName());
shulkerBox.setCustomName((ITextComponent) null);
}
spawnAsEntity(worldIn, pos, itemstack);
}
worldIn.updateComparatorOutputLevel(pos, state.getBlock());
}
super.onReplaced(state, worldIn, pos, newState, isMoving);
worldIn.removeTileEntity(pos);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void addInformation(ItemStack stack, @Nullable IBlockReader worldIn, List<ITextComponent> tooltip, ITooltipFlag flagIn)
{
super.addInformation(stack, worldIn, tooltip, flagIn);
NBTTagCompound nbttagcompound = stack.getChildTag("BlockEntityTag");
if (nbttagcompound != null)
{
if (nbttagcompound.contains("LootTable", 8))
{
tooltip.add(new TextComponentString("???????"));
}
if (nbttagcompound.contains("Items", 9))
{
NonNullList<ItemStack> nonnulllist = NonNullList.<ItemStack>withSize(27, ItemStack.EMPTY);
ItemStackHelper.loadAllItems(nbttagcompound, nonnulllist);
int i = 0;
int j = 0;
for (ItemStack itemstack : nonnulllist)
{
if (!itemstack.isEmpty())
{
++j;
if (i <= 4)
{
++i;
ITextComponent itextcomponent = itemstack.getDisplayName().shallowCopy();
itextcomponent.appendText(" x").appendText(String.valueOf(itemstack.getCount()));
tooltip.add(itextcomponent);
}
}
}
if (j - i > 0)
{
tooltip.add((new TextComponentTranslation("container.shulkerBox.more", new Object[] { j - i })).applyTextStyle(TextFormatting.ITALIC));
}
}
}
}
/**
* @deprecated call via {@link IBlockState#getPushReaction()} whenever possible. Implementing/overriding is fine.
*/
@Override
public EnumPushReaction getPushReaction(IBlockState state)
{
return EnumPushReaction.DESTROY;
}
@Override
public VoxelShape getShape(IBlockState state, IBlockReader worldIn, BlockPos pos)
{
TileEntity tileentity = worldIn.getTileEntity(pos);
return tileentity instanceof TileEntityIronShulkerBox ? VoxelShapes.create(((TileEntityIronShulkerBox) tileentity).getBoundingBox(state)) : VoxelShapes.fullCube();
}
@Override
public boolean isSolid(IBlockState state)
{
return false;
}
/**
* @deprecated call via {@link IBlockState#hasComparatorInputOverride()} whenever possible. Implementing/overriding
* is fine.
*/
@Override
public boolean hasComparatorInputOverride(IBlockState state)
{
return true;
}
/**
* @deprecated call via {@link IBlockState#getComparatorInputOverride(World, BlockPos)} whenever possible.
* Implementing/overriding is fine.
*/
@Override
public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos)
{
return Container.calcRedstoneFromInventory((IInventory) worldIn.getTileEntity(pos));
}
@Override
public ItemStack getItem(IBlockReader worldIn, BlockPos pos, IBlockState state)
{
ItemStack itemstack = super.getItem(worldIn, pos, state);
TileEntityIronShulkerBox shulkerBox = (TileEntityIronShulkerBox) worldIn.getTileEntity(pos);
NBTTagCompound nbttagcompound = shulkerBox.saveToNbt(new NBTTagCompound());
if (!nbttagcompound.isEmpty())
{
itemstack.setTagInfo("BlockEntityTag", nbttagcompound);
}
return itemstack;
}
/**
* Returns the blockstate with the given rotation from the passed blockstate. If inapplicable, returns the passed
* blockstate.
* @deprecated call via {@link IBlockState#rotate(Rotation)} whenever possible. Implementing/overriding is
* fine.
*/
@Override
public IBlockState rotate(IBlockState state, Rotation rot)
{
return (IBlockState) state.with(FACING, rot.rotate((EnumFacing) state.get(FACING)));
}
/**
* Returns the blockstate with the given mirror of the passed blockstate. If inapplicable, returns the passed
* blockstate.
* @deprecated call via {@link IBlockState#mirror(Mirror)} whenever possible. Implementing/overriding is fine.
*/
@Override
public IBlockState mirror(IBlockState state, Mirror mirrorIn)
{
return state.rotate(mirrorIn.toRotation((EnumFacing) state.get(FACING)));
}
/**
* Get the geometry of the queried face at the given position and state. This is used to decide whether things like
* buttons are allowed to be placed on the face, or how glass panes connect to the face, among other things.
* <p>
* Common values are {@code SOLID}, which is the default, and {@code UNDEFINED}, which represents something that does
* not fit the other descriptions and will generally cause other things not to connect to the face.
*
* @return an approximation of the form of the given face
* @deprecated call via {@link IBlockState#getBlockFaceShape(IBlockReader, BlockPos, EnumFacing)} whenever possible.
* Implementing/overriding is fine.
*/
@Override
public BlockFaceShape getBlockFaceShape(IBlockReader worldIn, IBlockState state, BlockPos pos, EnumFacing face)
{
EnumFacing enumfacing = (EnumFacing) state.get(FACING);
TileEntityIronShulkerBox.AnimationStatus animationstatus = ((TileEntityIronShulkerBox) worldIn.getTileEntity(pos)).getAnimationStatus();
return animationstatus != TileEntityIronShulkerBox.AnimationStatus.CLOSED && (animationstatus != TileEntityIronShulkerBox.AnimationStatus.OPENED || enumfacing != face.getOpposite() && enumfacing != face) ? BlockFaceShape.UNDEFINED : BlockFaceShape.SOLID;
}
@Override
public boolean hasTileEntity(IBlockState state)
{
return true;
}
public static IronShulkerBoxType getTypeFromItem(Item itemIn)
{
return getTypeFromBlock(Block.getBlockFromItem(itemIn));
}
public static IronShulkerBoxType getTypeFromBlock(Block blockIn)
{
return blockIn instanceof BlockShulkerBox ? ((BlockShulkerBox) blockIn).getType() : null;
}
public IronShulkerBoxType getType()
{
return this.type;
}
public static EnumDyeColor getColorFromItem(Item itemIn)
{
return getColorFromBlock(Block.getBlockFromItem(itemIn));
}
public static EnumDyeColor getColorFromBlock(Block blockIn)
{
return blockIn instanceof BlockShulkerBox ? ((BlockShulkerBox) blockIn).getColor() : null;
}
public static Block getBlockByColor(EnumDyeColor colorIn, IronShulkerBoxType typeIn)
{
switch (typeIn)
{
case IRON:
return IronShulkerBoxBlocks.ironShulkerBoxes.get(colorIn.getId());
case GOLD:
return IronShulkerBoxBlocks.goldShulkerBoxes.get(colorIn.getId());
case DIAMOND:
return IronShulkerBoxBlocks.diamondShulkerBoxes.get(colorIn.getId());
case COPPER:
return IronShulkerBoxBlocks.copperShulkerBoxes.get(colorIn.getId());
case SILVER:
return IronShulkerBoxBlocks.silverShulkerBoxes.get(colorIn.getId());
case CRYSTAL:
return IronShulkerBoxBlocks.crystalShulkerBoxes.get(colorIn.getId());
case OBSIDIAN:
return IronShulkerBoxBlocks.obsidianShulkerBoxes.get(colorIn.getId());
default:
return IronShulkerBoxBlocks.redIronShulkerBoxBlock;
}
}
public static ItemStack getColoredItemStack(EnumDyeColor colorIn, IronShulkerBoxType typeIn)
{
return new ItemStack(getBlockByColor(colorIn, typeIn));
}
public EnumDyeColor getColor()
{
return this.color;
}
/**
* Called on server when World#addBlockEvent is called. If server returns true, then also called on the client. On
* the Server, this may perform additional changes to the world, like pistons replacing the block with an extended
* base. On the client, the update may involve replacing tile entities or effects such as sounds or particles
* @deprecated call via {@link IBlockState#onBlockEventReceived(World, BlockPos, int, int)} whenever possible.
* Implementing/overriding is fine.
*/
@Override
public boolean eventReceived(IBlockState state, World worldIn, BlockPos pos, int id, int param)
{
super.eventReceived(state, worldIn, pos, id, param);
TileEntity tileentity = worldIn.getTileEntity(pos);
return tileentity == null ? false : tileentity.receiveClientEvent(id, param);
}
/**
* Spawns the block's drops in the world. By the time this is called the Block has possibly been set to air via
* Block.removedByPlayer
*/
@Override
public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, ItemStack stack)
{
if (te instanceof INameable && ((INameable) te).hasCustomName())
{
player.addStat(StatList.BLOCK_MINED.get(this));
player.addExhaustion(0.005F);
if (worldIn.isRemote)
{
return;
}
int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, stack);
Item item = this.getItemDropped(state, worldIn, pos, i).asItem();
if (item == Items.AIR)
{
return;
}
ItemStack itemstack = new ItemStack(item, this.quantityDropped(state, worldIn.rand));
itemstack.setDisplayName(((INameable) te).getCustomName());
spawnAsEntity(worldIn, pos, itemstack);
}
else
{
super.harvestBlock(worldIn, player, pos, state, (TileEntity) null, stack);
}
}
}