mirror of
https://github.com/barkeser2002/CatServer.git
synced 2026-09-25 01:39:52 +03:00
1726 lines
69 KiB
Diff
1726 lines
69 KiB
Diff
--- ../src-base/minecraft/net/minecraft/block/Block.java
|
|
+++ ../src-work/minecraft/net/minecraft/block/Block.java
|
|
@@ -52,11 +52,12 @@
|
|
import net.minecraftforge.fml.relauncher.Side;
|
|
import net.minecraftforge.fml.relauncher.SideOnly;
|
|
|
|
-public class Block
|
|
+public class Block extends net.minecraftforge.registries.IForgeRegistryEntry.Impl<Block>
|
|
{
|
|
private static final ResourceLocation AIR_ID = new ResourceLocation("air");
|
|
- public static final RegistryNamespacedDefaultedByKey<ResourceLocation, Block> REGISTRY = new RegistryNamespacedDefaultedByKey<ResourceLocation, Block>(AIR_ID);
|
|
- public static final ObjectIntIdentityMap<IBlockState> BLOCK_STATE_IDS = new ObjectIntIdentityMap<IBlockState>();
|
|
+ public static final RegistryNamespacedDefaultedByKey<ResourceLocation, Block> REGISTRY = net.minecraftforge.registries.GameData.getWrapperDefaulted(Block.class);
|
|
+ @Deprecated //Modders: DO NOT use this! Use GameRegistry
|
|
+ public static final ObjectIntIdentityMap<IBlockState> BLOCK_STATE_IDS = net.minecraftforge.registries.GameData.getBlockStateIDMap();
|
|
public static final AxisAlignedBB FULL_BLOCK_AABB = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D);
|
|
@Nullable
|
|
public static final AxisAlignedBB NULL_AABB = null;
|
|
@@ -75,6 +76,7 @@
|
|
public float blockParticleGravity;
|
|
protected final Material blockMaterial;
|
|
protected final MapColor blockMapColor;
|
|
+ @Deprecated // Forge: State/world/pos/entity sensitive version below
|
|
public float slipperiness;
|
|
protected final BlockStateContainer blockState;
|
|
private IBlockState defaultBlockState;
|
|
@@ -319,7 +321,7 @@
|
|
|
|
public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
|
|
{
|
|
- return false;
|
|
+ return worldIn.getBlockState(pos).getMaterial().isReplaceable();
|
|
}
|
|
|
|
public Block setHardness(float hardness)
|
|
@@ -357,9 +359,10 @@
|
|
return this.needsRandomTick;
|
|
}
|
|
|
|
+ @Deprecated //Forge: New State sensitive version.
|
|
public boolean hasTileEntity()
|
|
{
|
|
- return this.hasTileEntity;
|
|
+ return hasTileEntity(getDefaultState());
|
|
}
|
|
|
|
@Deprecated
|
|
@@ -372,13 +375,13 @@
|
|
@SideOnly(Side.CLIENT)
|
|
public int getPackedLightmapCoords(IBlockState state, IBlockAccess source, BlockPos pos)
|
|
{
|
|
- int i = source.getCombinedLight(pos, state.getLightValue());
|
|
+ int i = source.getCombinedLight(pos, state.getLightValue(source, pos));
|
|
|
|
if (i == 0 && state.getBlock() instanceof BlockSlab)
|
|
{
|
|
pos = pos.down();
|
|
state = source.getBlockState(pos);
|
|
- return source.getCombinedLight(pos, state.getLightValue());
|
|
+ return source.getCombinedLight(pos, state.getLightValue(source, pos));
|
|
}
|
|
else
|
|
{
|
|
@@ -442,7 +445,7 @@
|
|
}
|
|
}
|
|
|
|
- return !blockAccess.getBlockState(pos.offset(side)).isOpaqueCube();
|
|
+ return !blockAccess.getBlockState(pos.offset(side)).doesSideBlockRendering(blockAccess, pos.offset(side), side.getOpposite());
|
|
}
|
|
|
|
@Deprecated
|
|
@@ -529,11 +532,14 @@
|
|
}
|
|
|
|
public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state)
|
|
- {
|
|
- }
|
|
+ {}
|
|
|
|
public void breakBlock(World worldIn, BlockPos pos, IBlockState state)
|
|
{
|
|
+ if (hasTileEntity(state) && !(this instanceof BlockContainer))
|
|
+ {
|
|
+ worldIn.removeTileEntity(pos);
|
|
+ }
|
|
}
|
|
|
|
public int quantityDropped(Random random)
|
|
@@ -549,16 +555,7 @@
|
|
@Deprecated
|
|
public float getPlayerRelativeBlockHardness(IBlockState state, EntityPlayer player, World worldIn, BlockPos pos)
|
|
{
|
|
- float f = state.getBlockHardness(worldIn, pos);
|
|
-
|
|
- if (f < 0.0F)
|
|
- {
|
|
- return 0.0F;
|
|
- }
|
|
- else
|
|
- {
|
|
- return !player.canHarvestBlock(state) ? player.getDigSpeed(state) / f / 100.0F : player.getDigSpeed(state) / f / 30.0F;
|
|
- }
|
|
+ return net.minecraftforge.common.ForgeHooks.blockStrength(state, player, worldIn, pos);
|
|
}
|
|
|
|
public final void dropBlockAsItem(World worldIn, BlockPos pos, IBlockState state, int fortune)
|
|
@@ -568,20 +565,17 @@
|
|
|
|
public void dropBlockAsItemWithChance(World worldIn, BlockPos pos, IBlockState state, float chance, int fortune)
|
|
{
|
|
- if (!worldIn.isRemote)
|
|
+ if (!worldIn.isRemote && !worldIn.restoringBlockSnapshots) // do not drop items while restoring blockstates, prevents item dupe
|
|
{
|
|
- int i = this.quantityDroppedWithBonus(fortune, worldIn.rand);
|
|
+ List<ItemStack> drops = getDrops(worldIn, pos, state, fortune); // use the old method until it gets removed, for backward compatibility
|
|
+ chance = net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(drops, worldIn, pos, state, fortune, chance, false, harvesters.get());
|
|
|
|
- for (int j = 0; j < i; ++j)
|
|
+ for (ItemStack drop : drops)
|
|
{
|
|
- if (worldIn.rand.nextFloat() <= chance)
|
|
+ // CraftBukkit - <= to < to allow for plugins to completely disable block drops from explosions
|
|
+ if (worldIn.rand.nextFloat() < chance)
|
|
{
|
|
- Item item = this.getItemDropped(state, worldIn.rand, fortune);
|
|
-
|
|
- if (item != Items.AIR)
|
|
- {
|
|
- spawnAsEntity(worldIn, pos, new ItemStack(item, 1, this.damageDropped(state)));
|
|
- }
|
|
+ spawnAsEntity(worldIn, pos, drop);
|
|
}
|
|
}
|
|
}
|
|
@@ -589,18 +583,31 @@
|
|
|
|
public static void spawnAsEntity(World worldIn, BlockPos pos, ItemStack stack)
|
|
{
|
|
- if (!worldIn.isRemote && !stack.isEmpty() && worldIn.getGameRules().getBoolean("doTileDrops"))
|
|
+ if (!worldIn.isRemote && !stack.isEmpty() && worldIn.getGameRules().getBoolean("doTileDrops")&& !worldIn.restoringBlockSnapshots) // do not drop items while restoring blockstates, prevents item dupe
|
|
{
|
|
+ if (captureDrops.get())
|
|
+ {
|
|
+ capturedDrops.get().add(stack);
|
|
+ return;
|
|
+ }
|
|
float f = 0.5F;
|
|
double d0 = (double)(worldIn.rand.nextFloat() * 0.5F) + 0.25D;
|
|
double d1 = (double)(worldIn.rand.nextFloat() * 0.5F) + 0.25D;
|
|
double d2 = (double)(worldIn.rand.nextFloat() * 0.5F) + 0.25D;
|
|
EntityItem entityitem = new EntityItem(worldIn, (double)pos.getX() + d0, (double)pos.getY() + d1, (double)pos.getZ() + d2, stack);
|
|
entityitem.setDefaultPickupDelay();
|
|
- worldIn.spawnEntity(entityitem);
|
|
+ if (worldIn.captureDrops != null) {
|
|
+ worldIn.captureDrops.add(entityitem);
|
|
+ } else {
|
|
+ worldIn.spawnEntity(entityitem);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+ public int getExpDrop(World world, IBlockState state, int enchantmentLevel) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
public void dropXpOnBlockBreak(World worldIn, BlockPos pos, int amount)
|
|
{
|
|
if (!worldIn.isRemote && worldIn.getGameRules().getBoolean("doTileDrops"))
|
|
@@ -619,6 +626,7 @@
|
|
return 0;
|
|
}
|
|
|
|
+ @Deprecated //Forge: State sensitive version
|
|
public float getExplosionResistance(Entity exploder)
|
|
{
|
|
return this.blockResistance / 5.0F;
|
|
@@ -657,7 +665,7 @@
|
|
|
|
public boolean canPlaceBlockAt(World worldIn, BlockPos pos)
|
|
{
|
|
- return worldIn.getBlockState(pos).getBlock().blockMaterial.isReplaceable();
|
|
+ return worldIn.getBlockState(pos).getBlock().isReplaceable(worldIn, pos);
|
|
}
|
|
|
|
public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
|
|
@@ -669,6 +677,8 @@
|
|
{
|
|
}
|
|
|
|
+ // Forge: use getStateForPlacement
|
|
+ @Deprecated
|
|
public IBlockState getStateForPlacement(World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
|
|
{
|
|
return this.getStateFromMeta(meta);
|
|
@@ -710,21 +720,35 @@
|
|
player.addStat(StatList.getBlockStats(this));
|
|
player.addExhaustion(0.005F);
|
|
|
|
- if (this.canSilkHarvest() && EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, stack) > 0)
|
|
+ if (this.canSilkHarvest(worldIn, pos, state, player) && EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, stack) > 0)
|
|
{
|
|
+ List<ItemStack> items = new java.util.ArrayList<ItemStack>();
|
|
ItemStack itemstack = this.getSilkTouchDrop(state);
|
|
- spawnAsEntity(worldIn, pos, itemstack);
|
|
+
|
|
+ if (!itemstack.isEmpty())
|
|
+ {
|
|
+ items.add(itemstack);
|
|
+ }
|
|
+
|
|
+ net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(items, worldIn, pos, state, 0, 1.0f, true, player);
|
|
+ for (ItemStack item : items)
|
|
+ {
|
|
+ spawnAsEntity(worldIn, pos, item);
|
|
+ }
|
|
}
|
|
else
|
|
{
|
|
+ harvesters.set(player);
|
|
int i = EnchantmentHelper.getEnchantmentLevel(Enchantments.FORTUNE, stack);
|
|
this.dropBlockAsItem(worldIn, pos, state, i);
|
|
+ harvesters.set(null);
|
|
}
|
|
}
|
|
|
|
+ @Deprecated //Forge: State sensitive version
|
|
protected boolean canSilkHarvest()
|
|
{
|
|
- return this.getDefaultState().isFullCube() && !this.hasTileEntity;
|
|
+ return this.getDefaultState().isFullCube() && !this.hasTileEntity(silk_check_state.get());
|
|
}
|
|
|
|
protected ItemStack getSilkTouchDrop(IBlockState state)
|
|
@@ -810,6 +834,7 @@
|
|
entityIn.motionY = 0.0D;
|
|
}
|
|
|
|
+ @Deprecated // Forge: Use more sensitive version below: getPickBlock
|
|
public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
|
|
{
|
|
return new ItemStack(Item.getItemFromBlock(this), 1, this.damageDropped(state));
|
|
@@ -898,27 +923,28 @@
|
|
return this.defaultBlockState;
|
|
}
|
|
|
|
- public Block.EnumOffsetType getOffsetType()
|
|
+ public EnumOffsetType getOffsetType()
|
|
{
|
|
- return Block.EnumOffsetType.NONE;
|
|
+ return EnumOffsetType.NONE;
|
|
}
|
|
|
|
@Deprecated
|
|
public Vec3d getOffset(IBlockState state, IBlockAccess worldIn, BlockPos pos)
|
|
{
|
|
- Block.EnumOffsetType block$enumoffsettype = this.getOffsetType();
|
|
+ EnumOffsetType block$enumoffsettype = this.getOffsetType();
|
|
|
|
- if (block$enumoffsettype == Block.EnumOffsetType.NONE)
|
|
+ if (block$enumoffsettype == EnumOffsetType.NONE)
|
|
{
|
|
return Vec3d.ZERO;
|
|
}
|
|
else
|
|
{
|
|
long i = MathHelper.getCoordinateRandom(pos.getX(), 0, pos.getZ());
|
|
- return new Vec3d(((double)((float)(i >> 16 & 15L) / 15.0F) - 0.5D) * 0.5D, block$enumoffsettype == Block.EnumOffsetType.XYZ ? ((double)((float)(i >> 20 & 15L) / 15.0F) - 1.0D) * 0.2D : 0.0D, ((double)((float)(i >> 24 & 15L) / 15.0F) - 0.5D) * 0.5D);
|
|
+ return new Vec3d(((double)((float)(i >> 16 & 15L) / 15.0F) - 0.5D) * 0.5D, block$enumoffsettype == EnumOffsetType.XYZ ? ((double)((float)(i >> 20 & 15L) / 15.0F) - 1.0D) * 0.2D : 0.0D, ((double)((float)(i >> 24 & 15L) / 15.0F) - 0.5D) * 0.5D);
|
|
}
|
|
}
|
|
|
|
+ @Deprecated // Forge - World/state/pos/entity sensitive version below
|
|
public SoundType getSoundType()
|
|
{
|
|
return this.blockSoundType;
|
|
@@ -934,6 +960,1388 @@
|
|
{
|
|
}
|
|
|
|
+ /* ======================================== FORGE START =====================================*/
|
|
+ //For ForgeInternal use Only!
|
|
+ protected ThreadLocal<EntityPlayer> harvesters = new ThreadLocal();
|
|
+ private ThreadLocal<IBlockState> silk_check_state = new ThreadLocal();
|
|
+ protected static Random RANDOM = new Random(); // Useful for random things without a seed.
|
|
+
|
|
+ /**
|
|
+ * Gets the slipperiness at the given location at the given state. Normally
|
|
+ * between 0 and 1.
|
|
+ * <p>
|
|
+ * Note that entities may reduce slipperiness by a certain factor of their own;
|
|
+ * for {@link net.minecraft.entity.EntityLivingBase}, this is {@code .91}.
|
|
+ * {@link net.minecraft.entity.item.EntityItem} uses {@code .98}, and
|
|
+ * {@link net.minecraft.entity.projectile.EntityFishHook} uses {@code .92}.
|
|
+ *
|
|
+ * @param state state of the block
|
|
+ * @param world the world
|
|
+ * @param pos the position in the world
|
|
+ * @param entity the entity in question
|
|
+ * @return the factor by which the entity's motion should be multiplied
|
|
+ */
|
|
+ public float getSlipperiness(IBlockState state, IBlockAccess world, BlockPos pos, @Nullable Entity entity)
|
|
+ {
|
|
+ return slipperiness;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets the base slipperiness level. Normally between 0 and 1.
|
|
+ * <p>
|
|
+ * <b>Calling this method may have no effect on the function of this block</b>,
|
|
+ * or may not have the expected result. This block is free to caclculate
|
|
+ * its slipperiness arbitrarily. This method is guaranteed to work on the
|
|
+ * base {@code Block} class.
|
|
+ *
|
|
+ * @param slipperiness the base slipperiness of this block
|
|
+ * @see #getSlipperiness(IBlockState, IBlockAccess, BlockPos, Entity)
|
|
+ */
|
|
+ public void setDefaultSlipperiness(float slipperiness)
|
|
+ {
|
|
+ this.slipperiness = slipperiness;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a light value for this block, taking into account the given state and coordinates, normal ranges are between 0 and 15
|
|
+ *
|
|
+ * @param state Block state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return The light value
|
|
+ */
|
|
+ public int getLightValue(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return state.getLightValue();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Checks if a player or entity can use this block to 'climb' like a ladder.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param entity The entity trying to use the ladder, CAN be null.
|
|
+ * @return True if the block should act like a ladder
|
|
+ */
|
|
+ public boolean isLadder(IBlockState state, IBlockAccess world, BlockPos pos, EntityLivingBase entity) { return false; }
|
|
+
|
|
+ /**
|
|
+ * Return true if the block is a normal, solid cube. This
|
|
+ * determines indirect power state, entity ejection from blocks, and a few
|
|
+ * others.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True if the block is a full cube
|
|
+ */
|
|
+ public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return state.isNormalCube();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Check if the face of a block should block rendering.
|
|
+ *
|
|
+ * Faces which are fully opaque should return true, faces with transparency
|
|
+ * or faces which do not span the full size of the block should return false.
|
|
+ *
|
|
+ * @param state The current block state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param face The side to check
|
|
+ * @return True if the block is opaque on the specified side.
|
|
+ */
|
|
+ public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face)
|
|
+ {
|
|
+ return state.isOpaqueCube();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Checks if the block is a solid face on the given side, used by placement logic.
|
|
+ *
|
|
+ * @param base_state The base state, getActualState should be called first
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param side The side to check
|
|
+ * @return True if the block is solid on the specified side.
|
|
+ */
|
|
+ @Deprecated //Use IBlockState.getBlockFaceShape
|
|
+ public boolean isSideSolid(IBlockState base_state, IBlockAccess world, BlockPos pos, EnumFacing side)
|
|
+ {
|
|
+ if (base_state.isTopSolid() && side == EnumFacing.UP) // Short circuit to vanilla function if its true
|
|
+ return true;
|
|
+
|
|
+ if (this instanceof BlockSlab)
|
|
+ {
|
|
+ IBlockState state = this.getActualState(base_state, world, pos);
|
|
+ return base_state.isFullBlock()
|
|
+ || (state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.TOP && side == EnumFacing.UP )
|
|
+ || (state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM && side == EnumFacing.DOWN);
|
|
+ }
|
|
+ else if (this instanceof BlockFarmland)
|
|
+ {
|
|
+ return (side != EnumFacing.DOWN && side != EnumFacing.UP);
|
|
+ }
|
|
+ else if (this instanceof BlockStairs)
|
|
+ {
|
|
+ IBlockState state = this.getActualState(base_state, world, pos);
|
|
+ boolean flipped = state.getValue(BlockStairs.HALF) == BlockStairs.EnumHalf.TOP;
|
|
+ BlockStairs.EnumShape shape = (BlockStairs.EnumShape)state.getValue(BlockStairs.SHAPE);
|
|
+ EnumFacing facing = (EnumFacing)state.getValue(BlockStairs.FACING);
|
|
+ if (side == EnumFacing.UP) return flipped;
|
|
+ if (side == EnumFacing.DOWN) return !flipped;
|
|
+ if (facing == side) return true;
|
|
+ if (flipped)
|
|
+ {
|
|
+ if (shape == BlockStairs.EnumShape.INNER_LEFT ) return side == facing.rotateYCCW();
|
|
+ if (shape == BlockStairs.EnumShape.INNER_RIGHT) return side == facing.rotateY();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (shape == BlockStairs.EnumShape.INNER_LEFT ) return side == facing.rotateY();
|
|
+ if (shape == BlockStairs.EnumShape.INNER_RIGHT) return side == facing.rotateYCCW();
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+ else if (this instanceof BlockSnow)
|
|
+ {
|
|
+ IBlockState state = this.getActualState(base_state, world, pos);
|
|
+ return ((Integer)state.getValue(BlockSnow.LAYERS)) >= 8;
|
|
+ }
|
|
+ else if (this instanceof BlockHopper && side == EnumFacing.UP)
|
|
+ {
|
|
+ return true;
|
|
+ }
|
|
+ else if (this instanceof BlockCompressedPowered)
|
|
+ {
|
|
+ return true;
|
|
+ }
|
|
+ return isNormalCube(base_state, world, pos);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if this block should set fire and deal fire damage
|
|
+ * to entities coming into contact with it.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True if the block should deal damage
|
|
+ */
|
|
+ public boolean isBurning(IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines this block should be treated as an air block
|
|
+ * by the rest of the code. This method is primarily
|
|
+ * useful for creating pure logic-blocks that will be invisible
|
|
+ * to the player and otherwise interact as air would.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True if the block considered air
|
|
+ */
|
|
+ public boolean isAir(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return state.getMaterial() == Material.AIR;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed.
|
|
+ *
|
|
+ * @param player The player damaging the block
|
|
+ * @param pos The block's current position
|
|
+ * @return True to spawn the drops
|
|
+ */
|
|
+ public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player)
|
|
+ {
|
|
+ return net.minecraftforge.common.ForgeHooks.canHarvestBlock(this, player, world, pos);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when a player removes a block. This is responsible for
|
|
+ * actually destroying the block, and the block is intact at time of call.
|
|
+ * This is called regardless of whether the player can harvest the block or
|
|
+ * not.
|
|
+ *
|
|
+ * Return true if the block is actually destroyed.
|
|
+ *
|
|
+ * Note: When used in multiplayer, this is called on both client and
|
|
+ * server sides!
|
|
+ *
|
|
+ * @param state The current state.
|
|
+ * @param world The current world
|
|
+ * @param player The player damaging the block, may be null
|
|
+ * @param pos Block position in world
|
|
+ * @param willHarvest True if Block.harvestBlock will be called after this, if the return in true.
|
|
+ * Can be useful to delay the destruction of tile entities till after harvestBlock
|
|
+ * @return True if the block is actually destroyed.
|
|
+ */
|
|
+ public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
|
|
+ {
|
|
+ this.onBlockHarvested(world, pos, state, player);
|
|
+ return world.setBlockState(pos, Blocks.AIR.getDefaultState(), world.isRemote ? 11 : 3);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Chance that fire will spread and consume this block.
|
|
+ * 300 being a 100% chance, 0, being a 0% chance.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param face The face that the fire is coming from
|
|
+ * @return A number ranging from 0 to 300 relating used to determine if the block will be consumed by fire
|
|
+ */
|
|
+ public int getFlammability(IBlockAccess world, BlockPos pos, EnumFacing face)
|
|
+ {
|
|
+ return Blocks.FIRE.getFlammability(this);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when fire is updating, checks if a block face can catch fire.
|
|
+ *
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param face The face that the fire is coming from
|
|
+ * @return True if the face can be on fire, false otherwise.
|
|
+ */
|
|
+ public boolean isFlammable(IBlockAccess world, BlockPos pos, EnumFacing face)
|
|
+ {
|
|
+ return getFlammability(world, pos, face) > 0;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when fire is updating on a neighbor block.
|
|
+ * The higher the number returned, the faster fire will spread around this block.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param face The face that the fire is coming from
|
|
+ * @return A number that is used to determine the speed of fire growth around the block
|
|
+ */
|
|
+ public int getFireSpreadSpeed(IBlockAccess world, BlockPos pos, EnumFacing face)
|
|
+ {
|
|
+ return Blocks.FIRE.getEncouragement(this);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Currently only called by fire when it is on top of this block.
|
|
+ * Returning true will prevent the fire from naturally dying during updating.
|
|
+ * Also prevents firing from dying from rain.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param side The face that the fire is coming from
|
|
+ * @return True if this block sustains fire, meaning it will never go out.
|
|
+ */
|
|
+ public boolean isFireSource(World world, BlockPos pos, EnumFacing side)
|
|
+ {
|
|
+ if (side != EnumFacing.UP)
|
|
+ return false;
|
|
+ if (this == Blocks.NETHERRACK || this == Blocks.MAGMA)
|
|
+ return true;
|
|
+ if ((world.provider instanceof net.minecraft.world.WorldProviderEnd) && this == Blocks.BEDROCK)
|
|
+ return true;
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private boolean isTileProvider = this instanceof ITileEntityProvider;
|
|
+ /**
|
|
+ * Called throughout the code as a replacement for block instanceof BlockContainer
|
|
+ * Moving this to the Block base class allows for mods that wish to extend vanilla
|
|
+ * blocks, and also want to have a tile entity on that block, may.
|
|
+ *
|
|
+ * Return true from this function to specify this block has a tile entity.
|
|
+ *
|
|
+ * @param state State of the current block
|
|
+ * @return True if block has a tile entity, false otherwise
|
|
+ */
|
|
+ public boolean hasTileEntity(IBlockState state)
|
|
+ {
|
|
+ return isTileProvider;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called throughout the code as a replacement for ITileEntityProvider.createNewTileEntity
|
|
+ * Return the same thing you would from that function.
|
|
+ * This will fall back to ITileEntityProvider.createNewTileEntity(World) if this block is a ITileEntityProvider
|
|
+ *
|
|
+ * @param state The state of the current block
|
|
+ * @return A instance of a class extending TileEntity
|
|
+ */
|
|
+ @Nullable
|
|
+ public TileEntity createTileEntity(World world, IBlockState state)
|
|
+ {
|
|
+ if (isTileProvider)
|
|
+ {
|
|
+ return ((ITileEntityProvider)this).createNewTileEntity(world, getMetaFromState(state));
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * State and fortune sensitive version, this replaces the old (int meta, Random rand)
|
|
+ * version in 1.1.
|
|
+ *
|
|
+ * @param state Current state
|
|
+ * @param fortune Current item fortune level
|
|
+ * @param random Random number generator
|
|
+ * @return The number of items to drop
|
|
+ */
|
|
+ public int quantityDropped(IBlockState state, int fortune, Random random)
|
|
+ {
|
|
+ return quantityDroppedWithBonus(fortune, random);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @deprecated use {@link #getDrops(NonNullList, IBlockAccess, BlockPos, IBlockState, int)}
|
|
+ */
|
|
+ @Deprecated
|
|
+ public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune)
|
|
+ {
|
|
+ NonNullList<ItemStack> ret = NonNullList.create();
|
|
+ getDrops(ret, world, pos, state, fortune);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * This gets a complete list of items dropped from this block.
|
|
+ *
|
|
+ * @param drops add all items this block drops to this drops list
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param state Current state
|
|
+ * @param fortune Breakers fortune level
|
|
+ */
|
|
+ public void getDrops(NonNullList<ItemStack> drops, IBlockAccess world, BlockPos pos, IBlockState state, int fortune)
|
|
+ {
|
|
+ Random rand = world instanceof World ? ((World)world).rand : RANDOM;
|
|
+
|
|
+ int count = quantityDropped(state, fortune, rand);
|
|
+ for (int i = 0; i < count; i++)
|
|
+ {
|
|
+ Item item = this.getItemDropped(state, rand, fortune);
|
|
+ if (item != Items.AIR)
|
|
+ {
|
|
+ drops.add(new ItemStack(item, 1, this.damageDropped(state)));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Return true from this function if the player with silk touch can harvest this block directly, and not it's normal drops.
|
|
+ *
|
|
+ * @param world The world
|
|
+ * @param pos Block position in world
|
|
+ * @param state current block state
|
|
+ * @param player The player doing the harvesting
|
|
+ * @return True if the block can be directly harvested using silk touch
|
|
+ */
|
|
+ public boolean canSilkHarvest(World world, BlockPos pos, IBlockState state, EntityPlayer player)
|
|
+ {
|
|
+ silk_check_state.set(state);;
|
|
+ boolean ret = this.canSilkHarvest();
|
|
+ silk_check_state.set(null);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if a specified mob type can spawn on this block, returning false will
|
|
+ * prevent any mob from spawning on the block.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param type The Mob Category Type
|
|
+ * @return True to allow a mob of the specified category to spawn, false to prevent it.
|
|
+ */
|
|
+ public boolean canCreatureSpawn(IBlockState state, IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
|
|
+ {
|
|
+ return isSideSolid(state, world, pos, EnumFacing.UP);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if this block is classified as a Bed, Allowing
|
|
+ * players to sleep in it, though the block has to specifically
|
|
+ * perform the sleeping functionality in it's activated event.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param player The player or camera entity, null in some cases.
|
|
+ * @return True to treat this as a bed
|
|
+ */
|
|
+ public boolean isBed(IBlockState state, IBlockAccess world, BlockPos pos, @Nullable Entity player)
|
|
+ {
|
|
+ return this == Blocks.BED;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the position that the player is moved to upon
|
|
+ * waking up, or respawning at the bed.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param player The player or camera entity, null in some cases.
|
|
+ * @return The spawn position
|
|
+ */
|
|
+ @Nullable
|
|
+ public BlockPos getBedSpawnPosition(IBlockState state, IBlockAccess world, BlockPos pos, @Nullable EntityPlayer player)
|
|
+ {
|
|
+ if (world instanceof World)
|
|
+ return BlockBed.getSafeExitLocation((World)world, pos, 0);
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when a user either starts or stops sleeping in the bed.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param player The player or camera entity, null in some cases.
|
|
+ * @param occupied True if we are occupying the bed, or false if they are stopping use of the bed
|
|
+ */
|
|
+ public void setBedOccupied(IBlockAccess world, BlockPos pos, EntityPlayer player, boolean occupied)
|
|
+ {
|
|
+ if (world instanceof World)
|
|
+ {
|
|
+ IBlockState state = world.getBlockState(pos);
|
|
+ state = state.getBlock().getActualState(state, world, pos);
|
|
+ state = state.withProperty(BlockBed.OCCUPIED, occupied);
|
|
+ ((World)world).setBlockState(pos, state, 4);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Returns the direction of the block. Same values that
|
|
+ * are returned by BlockDirectional
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return Bed direction
|
|
+ */
|
|
+ public EnumFacing getBedDirection(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return (EnumFacing)getActualState(state, world, pos).getValue(BlockHorizontal.FACING);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if the current block is the foot half of the bed.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True if the current block is the foot side of a bed.
|
|
+ */
|
|
+ public boolean isBedFoot(IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return getActualState(world.getBlockState(pos), world, pos).getValue(BlockBed.PART) == BlockBed.EnumPartType.FOOT;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when a leaf should start its decay process.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ */
|
|
+ public void beginLeavesDecay(IBlockState state, World world, BlockPos pos){}
|
|
+
|
|
+ /**
|
|
+ * Determines if this block can prevent leaves connected to it from decaying.
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return true if the presence this block can prevent leaves from decaying.
|
|
+ */
|
|
+ public boolean canSustainLeaves(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if this block is considered a leaf block, used to apply the leaf decay and generation system.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return true if this block is considered leaves.
|
|
+ */
|
|
+ public boolean isLeaves(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return state.getMaterial() == Material.LEAVES;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Used during tree growth to determine if newly generated leaves can replace this block.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return true if this block can be replaced by growing leaves.
|
|
+ */
|
|
+ public boolean canBeReplacedByLeaves(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return isAir(state, world, pos) || isLeaves(state, world, pos); //!state.isFullBlock();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return true if the block is wood (logs)
|
|
+ */
|
|
+ public boolean isWood(IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if the current block is replaceable by Ore veins during world generation.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param target The generic target block the gen is looking for, Standards define stone
|
|
+ * for overworld generation, and neatherack for the nether.
|
|
+ * @return True to allow this block to be replaced by a ore
|
|
+ */
|
|
+ public boolean isReplaceableOreGen(IBlockState state, IBlockAccess world, BlockPos pos, com.google.common.base.Predicate<IBlockState> target)
|
|
+ {
|
|
+ return target.apply(state);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Location sensitive version of getExplosionResistance
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param exploder The entity that caused the explosion, can be null
|
|
+ * @param explosion The explosion
|
|
+ * @return The amount of the explosion absorbed.
|
|
+ */
|
|
+ public float getExplosionResistance(World world, BlockPos pos, @Nullable Entity exploder, Explosion explosion)
|
|
+ {
|
|
+ return getExplosionResistance(exploder);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when the block is destroyed by an explosion.
|
|
+ * Useful for allowing the block to take into account tile entities,
|
|
+ * state, etc. when exploded, before it is removed.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param explosion The explosion instance affecting the block
|
|
+ */
|
|
+ public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
|
|
+ {
|
|
+ world.setBlockToAir(pos);
|
|
+ onBlockDestroyedByExplosion(world, pos, explosion);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determine if this block can make a redstone connection on the side provided,
|
|
+ * Useful to control which sides are inputs and outputs for redstone wires.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param side The side that is trying to make the connection, CAN BE NULL
|
|
+ * @return True to make the connection
|
|
+ */
|
|
+ public boolean canConnectRedstone(IBlockState state, IBlockAccess world, BlockPos pos, @Nullable EnumFacing side)
|
|
+ {
|
|
+ return state.canProvidePower() && side != null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if a torch can be placed on the top surface of this block.
|
|
+ * Useful for creating your own block that torches can be on, such as fences.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True to allow the torch to be placed
|
|
+ */
|
|
+ public boolean canPlaceTorchOnTop(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ if (this == Blocks.END_GATEWAY || this == Blocks.LIT_PUMPKIN)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+ else if (state.isTopSolid() || this instanceof BlockFence || this == Blocks.GLASS || this == Blocks.COBBLESTONE_WALL || this == Blocks.STAINED_GLASS)
|
|
+ {
|
|
+ return true;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ BlockFaceShape shape = state.getBlockFaceShape(world, pos, EnumFacing.UP);
|
|
+ return (shape == BlockFaceShape.SOLID || shape == BlockFaceShape.CENTER || shape == BlockFaceShape.CENTER_BIG) && !isExceptionBlockForAttaching(this);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when a user uses the creative pick block button on this block
|
|
+ *
|
|
+ * @param target The full target the player is looking at
|
|
+ * @return A ItemStack to add to the player's inventory, empty itemstack if nothing should be added.
|
|
+ */
|
|
+ public ItemStack getPickBlock(IBlockState state, RayTraceResult target, World world, BlockPos pos, EntityPlayer player)
|
|
+ {
|
|
+ return getItem(world, pos, state);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Used by getTopSolidOrLiquidBlock while placing biome decorations, villages, etc
|
|
+ * Also used to determine if the player can spawn on this block.
|
|
+ *
|
|
+ * @return False to disallow spawning
|
|
+ */
|
|
+ public boolean isFoliage(IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Allows a block to override the standard EntityLivingBase.updateFallState
|
|
+ * particles, this is a server side method that spawns particles with
|
|
+ * WorldServer.spawnParticle
|
|
+ *
|
|
+ * @param blockPosition of the block that the entity landed on.
|
|
+ * @param iblockstate State at the specific world/pos
|
|
+ * @param entity the entity that hit landed on the block.
|
|
+ * @param numberOfParticles that vanilla would have spawned.
|
|
+ * @return True to prevent vanilla landing particles form spawning.
|
|
+ */
|
|
+ public boolean addLandingEffects(IBlockState state, net.minecraft.world.WorldServer worldObj, BlockPos blockPosition, IBlockState iblockstate, EntityLivingBase entity, int numberOfParticles )
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Allows a block to override the standard vanilla running particles.
|
|
+ * This is called from {@link Entity#spawnRunningParticles} and is called both,
|
|
+ * Client and server side, it's up to the implementor to client check / server check.
|
|
+ * By default vanilla spawns particles only on the client and the server methods no-op.
|
|
+ *
|
|
+ * @param state The BlockState the entity is running on.
|
|
+ * @param world The world.
|
|
+ * @param pos The position at the entities feet.
|
|
+ * @param entity The entity running on the block.
|
|
+ * @return True to prevent vanilla running particles from spawning.
|
|
+ */
|
|
+ public boolean addRunningEffects(IBlockState state, World world, BlockPos pos, Entity entity)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Spawn a digging particle effect in the world, this is a wrapper
|
|
+ * around EffectRenderer.addBlockHitEffects to allow the block more
|
|
+ * control over the particles. Useful when you have entirely different
|
|
+ * texture sheets for different sides/locations in the world.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param worldObj The current world
|
|
+ * @param target The target the player is looking at {x/y/z/side/sub}
|
|
+ * @param manager A reference to the current particle manager.
|
|
+ * @return True to prevent vanilla digging particles form spawning.
|
|
+ */
|
|
+ @SideOnly(Side.CLIENT)
|
|
+ public boolean addHitEffects(IBlockState state, World worldObj, RayTraceResult target, net.minecraft.client.particle.ParticleManager manager)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Spawn particles for when the block is destroyed. Due to the nature
|
|
+ * of how this is invoked, the x/y/z locations are not always guaranteed
|
|
+ * to host your block. So be sure to do proper sanity checks before assuming
|
|
+ * that the location is this block.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Position to spawn the particle
|
|
+ * @param manager A reference to the current particle manager.
|
|
+ * @return True to prevent vanilla break particles from spawning.
|
|
+ */
|
|
+ @SideOnly(Side.CLIENT)
|
|
+ public boolean addDestroyEffects(World world, BlockPos pos, net.minecraft.client.particle.ParticleManager manager)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if this block can support the passed in plant, allowing it to be planted and grow.
|
|
+ * Some examples:
|
|
+ * Reeds check if its a reed, or if its sand/dirt/grass and adjacent to water
|
|
+ * Cacti checks if its a cacti, or if its sand
|
|
+ * Nether types check for soul sand
|
|
+ * Crops check for tilled soil
|
|
+ * Caves check if it's a solid surface
|
|
+ * Plains check if its grass or dirt
|
|
+ * Water check if its still water
|
|
+ *
|
|
+ * @param state The Current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param direction The direction relative to the given position the plant wants to be, typically its UP
|
|
+ * @param plantable The plant that wants to check
|
|
+ * @return True to allow the plant to be planted/stay.
|
|
+ */
|
|
+ public boolean canSustainPlant(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing direction, net.minecraftforge.common.IPlantable plantable)
|
|
+ {
|
|
+ IBlockState plant = plantable.getPlant(world, pos.offset(direction));
|
|
+ net.minecraftforge.common.EnumPlantType plantType = plantable.getPlantType(world, pos.offset(direction));
|
|
+
|
|
+ if (plant.getBlock() == Blocks.CACTUS)
|
|
+ {
|
|
+ return this == Blocks.CACTUS || this == Blocks.SAND;
|
|
+ }
|
|
+
|
|
+ if (plant.getBlock() == Blocks.REEDS && this == Blocks.REEDS)
|
|
+ {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ if (plantable instanceof BlockBush && ((BlockBush)plantable).canSustainBush(state))
|
|
+ {
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ switch (plantType)
|
|
+ {
|
|
+ case Desert: return this == Blocks.SAND || this == Blocks.HARDENED_CLAY || this == Blocks.STAINED_HARDENED_CLAY;
|
|
+ case Nether: return this == Blocks.SOUL_SAND;
|
|
+ case Crop: return this == Blocks.FARMLAND;
|
|
+ case Cave: return state.isSideSolid(world, pos, EnumFacing.UP);
|
|
+ case Plains: return this == Blocks.GRASS || this == Blocks.DIRT || this == Blocks.FARMLAND;
|
|
+ case Water: return state.getMaterial() == Material.WATER && state.getValue(BlockLiquid.LEVEL) == 0;
|
|
+ case Beach:
|
|
+ boolean isBeach = this == Blocks.GRASS || this == Blocks.DIRT || this == Blocks.SAND;
|
|
+ boolean hasWater = (world.getBlockState(pos.east()).getMaterial() == Material.WATER ||
|
|
+ world.getBlockState(pos.west()).getMaterial() == Material.WATER ||
|
|
+ world.getBlockState(pos.north()).getMaterial() == Material.WATER ||
|
|
+ world.getBlockState(pos.south()).getMaterial() == Material.WATER);
|
|
+ return isBeach && hasWater;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when a plant grows on this block, only implemented for saplings using the WorldGen*Trees classes right now.
|
|
+ * Modder may implement this for custom plants.
|
|
+ * This does not use ForgeDirection, because large/huge trees can be located in non-representable direction,
|
|
+ * so the source location is specified.
|
|
+ * Currently this just changes the block to dirt if it was grass.
|
|
+ *
|
|
+ * Note: This happens DURING the generation, the generation may not be complete when this is called.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world Current world
|
|
+ * @param pos Block position in world
|
|
+ * @param source Source plant's position in world
|
|
+ */
|
|
+ public void onPlantGrow(IBlockState state, World world, BlockPos pos, BlockPos source)
|
|
+ {
|
|
+ if (this == Blocks.GRASS || this == Blocks.FARMLAND)
|
|
+ {
|
|
+ world.setBlockState(pos, Blocks.DIRT.getDefaultState(), 2);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Checks if this soil is fertile, typically this means that growth rates
|
|
+ * of plants on this soil will be slightly sped up.
|
|
+ * Only vanilla case is tilledField when it is within range of water.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True if the soil should be considered fertile.
|
|
+ */
|
|
+ public boolean isFertile(World world, BlockPos pos)
|
|
+ {
|
|
+ if (this == Blocks.FARMLAND)
|
|
+ {
|
|
+ return ((Integer)world.getBlockState(pos).getValue(BlockFarmland.MOISTURE)) > 0;
|
|
+ }
|
|
+
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Location aware and overrideable version of the lightOpacity array,
|
|
+ * return the number to subtract from the light value when it passes through this block.
|
|
+ *
|
|
+ * This is not guaranteed to have the tile entity in place before this is called, so it is
|
|
+ * Recommended that you have your tile entity call relight after being placed if you
|
|
+ * rely on it for light info.
|
|
+ *
|
|
+ * @param state The Block state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return The amount of light to block, 0 for air, 255 for fully opaque.
|
|
+ */
|
|
+ public int getLightOpacity(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return state.getLightOpacity();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if this block is can be destroyed by the specified entities normal behavior.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return True to allow the ender dragon to destroy this block
|
|
+ */
|
|
+ public boolean canEntityDestroy(IBlockState state, IBlockAccess world, BlockPos pos, Entity entity)
|
|
+ {
|
|
+ if (entity instanceof net.minecraft.entity.boss.EntityDragon)
|
|
+ {
|
|
+ return this != Blocks.BARRIER &&
|
|
+ this != Blocks.OBSIDIAN &&
|
|
+ this != Blocks.END_STONE &&
|
|
+ this != Blocks.BEDROCK &&
|
|
+ this != Blocks.END_PORTAL &&
|
|
+ this != Blocks.END_PORTAL_FRAME &&
|
|
+ this != Blocks.COMMAND_BLOCK &&
|
|
+ this != Blocks.REPEATING_COMMAND_BLOCK &&
|
|
+ this != Blocks.CHAIN_COMMAND_BLOCK &&
|
|
+ this != Blocks.IRON_BARS &&
|
|
+ this != Blocks.END_GATEWAY;
|
|
+ }
|
|
+ else if ((entity instanceof net.minecraft.entity.boss.EntityWither) ||
|
|
+ (entity instanceof net.minecraft.entity.projectile.EntityWitherSkull))
|
|
+ {
|
|
+ return net.minecraft.entity.boss.EntityWither.canDestroyBlock(this);
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if this block can be used as the base of a beacon.
|
|
+ *
|
|
+ * @param worldObj The current world
|
|
+ * @param pos Block position in world
|
|
+ * @param beacon Beacon position in world
|
|
+ * @return True, to support the beacon, and make it active with this block.
|
|
+ */
|
|
+ public boolean isBeaconBase(IBlockAccess worldObj, BlockPos pos, BlockPos beacon)
|
|
+ {
|
|
+ return this == Blocks.EMERALD_BLOCK || this == Blocks.GOLD_BLOCK || this == Blocks.DIAMOND_BLOCK || this == Blocks.IRON_BLOCK;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Rotate the block. For vanilla blocks this rotates around the axis passed in (generally, it should be the "face" that was hit).
|
|
+ * Note: for mod blocks, this is up to the block and modder to decide. It is not mandated that it be a rotation around the
|
|
+ * face, but could be a rotation to orient *to* that face, or a visiting of possible rotations.
|
|
+ * The method should return true if the rotation was successful though.
|
|
+ *
|
|
+ * @param world The world
|
|
+ * @param pos Block position in world
|
|
+ * @param axis The axis to rotate around
|
|
+ * @return True if the rotation was successful, False if the rotation failed, or is not possible
|
|
+ */
|
|
+ public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis)
|
|
+ {
|
|
+ IBlockState state = world.getBlockState(pos);
|
|
+ for (IProperty<?> prop : state.getProperties().keySet())
|
|
+ {
|
|
+ if ((prop.getName().equals("facing") || prop.getName().equals("rotation")) && prop.getValueClass() == EnumFacing.class)
|
|
+ {
|
|
+ Block block = state.getBlock();
|
|
+ if (!(block instanceof BlockBed) && !(block instanceof BlockPistonExtension))
|
|
+ {
|
|
+ IBlockState newState;
|
|
+ //noinspection unchecked
|
|
+ IProperty<EnumFacing> facingProperty = (IProperty<EnumFacing>) prop;
|
|
+ EnumFacing facing = state.getValue(facingProperty);
|
|
+ java.util.Collection<EnumFacing> validFacings = facingProperty.getAllowedValues();
|
|
+
|
|
+ // rotate horizontal facings clockwise
|
|
+ if (validFacings.size() == 4 && !validFacings.contains(EnumFacing.UP) && !validFacings.contains(EnumFacing.DOWN))
|
|
+ {
|
|
+ newState = state.withProperty(facingProperty, facing.rotateY());
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // rotate other facings about the axis
|
|
+ EnumFacing rotatedFacing = facing.rotateAround(axis.getAxis());
|
|
+ if (validFacings.contains(rotatedFacing))
|
|
+ {
|
|
+ newState = state.withProperty(facingProperty, rotatedFacing);
|
|
+ }
|
|
+ else // abnormal facing property, just cycle it
|
|
+ {
|
|
+ newState = state.cycleProperty(facingProperty);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ world.setBlockState(pos, newState);
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the rotations that can apply to the block at the specified coordinates. Null means no rotations are possible.
|
|
+ * Note, this is up to the block to decide. It may not be accurate or representative.
|
|
+ * @param world The world
|
|
+ * @param pos Block position in world
|
|
+ * @return An array of valid axes to rotate around, or null for none or unknown
|
|
+ */
|
|
+ @Nullable
|
|
+ public EnumFacing[] getValidRotations(World world, BlockPos pos)
|
|
+ {
|
|
+ IBlockState state = world.getBlockState(pos);
|
|
+ for (IProperty<?> prop : state.getProperties().keySet())
|
|
+ {
|
|
+ if ((prop.getName().equals("facing") || prop.getName().equals("rotation")) && prop.getValueClass() == EnumFacing.class)
|
|
+ {
|
|
+ @SuppressWarnings("unchecked")
|
|
+ java.util.Collection<EnumFacing> values = ((java.util.Collection<EnumFacing>)prop.getAllowedValues());
|
|
+ return values.toArray(new EnumFacing[values.size()]);
|
|
+ }
|
|
+ }
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines the amount of enchanting power this block can provide to an enchanting table.
|
|
+ * @param world The World
|
|
+ * @param pos Block position in world
|
|
+ * @return The amount of enchanting power this block produces.
|
|
+ */
|
|
+ public float getEnchantPowerBonus(World world, BlockPos pos)
|
|
+ {
|
|
+ return this == Blocks.BOOKSHELF ? 1 : 0;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Common way to recolor a block with an external tool
|
|
+ * @param world The world
|
|
+ * @param pos Block position in world
|
|
+ * @param side The side hit with the coloring tool
|
|
+ * @param color The color to change to
|
|
+ * @return If the recoloring was successful
|
|
+ */
|
|
+ @SuppressWarnings({ "unchecked", "rawtypes" })
|
|
+ public boolean recolorBlock(World world, BlockPos pos, EnumFacing side, EnumDyeColor color)
|
|
+ {
|
|
+ IBlockState state = world.getBlockState(pos);
|
|
+ for (IProperty prop : state.getProperties().keySet())
|
|
+ {
|
|
+ if (prop.getName().equals("color") && prop.getValueClass() == EnumDyeColor.class)
|
|
+ {
|
|
+ EnumDyeColor current = (EnumDyeColor)state.getValue(prop);
|
|
+ if (current != color && prop.getAllowedValues().contains(color))
|
|
+ {
|
|
+ world.setBlockState(pos, state.withProperty(prop, color));
|
|
+ return true;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gathers how much experience this block drops when broken.
|
|
+ *
|
|
+ * @param state The current state
|
|
+ * @param world The world
|
|
+ * @param pos Block position
|
|
+ * @param fortune
|
|
+ * @return Amount of XP from breaking this block.
|
|
+ */
|
|
+ public int getExpDrop(IBlockState state, IBlockAccess world, BlockPos pos, int fortune)
|
|
+ {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when a tile entity on a side of this block changes is created or is destroyed.
|
|
+ * @param world The world
|
|
+ * @param pos Block position in world
|
|
+ * @param neighbor Block position of neighbor
|
|
+ */
|
|
+ public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor){}
|
|
+
|
|
+ /**
|
|
+ * Called on an Observer block whenever an update for an Observer is received.
|
|
+ *
|
|
+ * @param observerState The Observer block's state.
|
|
+ * @param world The current world.
|
|
+ * @param observerPos The Observer block's position.
|
|
+ * @param changedBlock The updated block.
|
|
+ * @param changedBlockPos The updated block's position.
|
|
+ */
|
|
+ public void observedNeighborChange(IBlockState observerState, World world, BlockPos observerPos, Block changedBlock, BlockPos changedBlockPos){}
|
|
+
|
|
+ /**
|
|
+ * Called to determine whether to allow the a block to handle its own indirect power rather than using the default rules.
|
|
+ * @param world The world
|
|
+ * @param pos Block position in world
|
|
+ * @param side The INPUT side of the block to be powered - ie the opposite of this block's output side
|
|
+ * @return Whether Block#isProvidingWeakPower should be called when determining indirect power
|
|
+ */
|
|
+ public boolean shouldCheckWeakPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side)
|
|
+ {
|
|
+ return state.isNormalCube();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * If this block should be notified of weak changes.
|
|
+ * Weak changes are changes 1 block away through a solid block.
|
|
+ * Similar to comparators.
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos Block position in world
|
|
+ * @return true To be notified of changes
|
|
+ */
|
|
+ public boolean getWeakChanges(IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private String[] harvestTool = new String[16];;
|
|
+ private int[] harvestLevel = new int[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
|
|
+ /**
|
|
+ * Sets or removes the tool and level required to harvest this block.
|
|
+ *
|
|
+ * @param toolClass Class
|
|
+ * @param level Harvest level:
|
|
+ * Wood: 0
|
|
+ * Stone: 1
|
|
+ * Iron: 2
|
|
+ * Diamond: 3
|
|
+ * Gold: 0
|
|
+ */
|
|
+ public void setHarvestLevel(String toolClass, int level)
|
|
+ {
|
|
+ java.util.Iterator<IBlockState> itr = getBlockState().getValidStates().iterator();
|
|
+ while (itr.hasNext())
|
|
+ {
|
|
+ setHarvestLevel(toolClass, level, itr.next());
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sets or removes the tool and level required to harvest this block.
|
|
+ *
|
|
+ * @param toolClass Class
|
|
+ * @param level Harvest level:
|
|
+ * Wood: 0
|
|
+ * Stone: 1
|
|
+ * Iron: 2
|
|
+ * Diamond: 3
|
|
+ * Gold: 0
|
|
+ * @param state The specific state.
|
|
+ */
|
|
+ public void setHarvestLevel(String toolClass, int level, IBlockState state)
|
|
+ {
|
|
+ int idx = this.getMetaFromState(state);
|
|
+ this.harvestTool[idx] = toolClass;
|
|
+ this.harvestLevel[idx] = level;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Queries the class of tool required to harvest this block, if null is returned
|
|
+ * we assume that anything can harvest this block.
|
|
+ */
|
|
+ @Nullable public String getHarvestTool(IBlockState state)
|
|
+ {
|
|
+ return harvestTool[getMetaFromState(state)];
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Queries the harvest level of this item stack for the specified tool class,
|
|
+ * Returns -1 if this tool is not of the specified type
|
|
+ *
|
|
+ * @return Harvest level, or -1 if not the specified tool type.
|
|
+ */
|
|
+ public int getHarvestLevel(IBlockState state)
|
|
+ {
|
|
+ return harvestLevel[getMetaFromState(state)];
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Checks if the specified tool type is efficient on this block,
|
|
+ * meaning that it digs at full speed.
|
|
+ */
|
|
+ public boolean isToolEffective(String type, IBlockState state)
|
|
+ {
|
|
+ if ("pickaxe".equals(type) && (this == Blocks.REDSTONE_ORE || this == Blocks.LIT_REDSTONE_ORE || this == Blocks.OBSIDIAN))
|
|
+ return false;
|
|
+ return type != null && type.equals(getHarvestTool(state));
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Can return IExtendedBlockState
|
|
+ */
|
|
+ public IBlockState getExtendedState(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return state;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when the entity is inside this block, may be used to determined if the entity can breathing,
|
|
+ * display material overlays, or if the entity can swim inside a block.
|
|
+ *
|
|
+ * @param world that is being tested.
|
|
+ * @param blockpos position thats being tested.
|
|
+ * @param iblockstate state at world/blockpos
|
|
+ * @param entity that is being tested.
|
|
+ * @param yToTest, primarily for testingHead, which sends the the eye level of the entity, other wise it sends a y that can be tested vs liquid height.
|
|
+ * @param materialIn to test for.
|
|
+ * @param testingHead when true, its testing the entities head for vision, breathing ect... otherwise its testing the body, for swimming and movement adjustment.
|
|
+ * @return null for default behavior, true if the entity is within the material, false if it was not.
|
|
+ */
|
|
+ @Nullable
|
|
+ public Boolean isEntityInsideMaterial(IBlockAccess world, BlockPos blockpos, IBlockState iblockstate, Entity entity, double yToTest, Material materialIn, boolean testingHead)
|
|
+ {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when boats or fishing hooks are inside the block to check if they are inside
|
|
+ * the material requested.
|
|
+ *
|
|
+ * @param world world that is being tested.
|
|
+ * @param pos block thats being tested.
|
|
+ * @param boundingBox box to test, generally the bounds of an entity that are besting tested.
|
|
+ * @param materialIn to check for.
|
|
+ * @return null for default behavior, true if the box is within the material, false if it was not.
|
|
+ */
|
|
+ @Nullable
|
|
+ public Boolean isAABBInsideMaterial(World world, BlockPos pos, AxisAlignedBB boundingBox, Material materialIn)
|
|
+ {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when entities are moving to check if they are inside a liquid
|
|
+ *
|
|
+ * @param world world that is being tested.
|
|
+ * @param pos block thats being tested.
|
|
+ * @param boundingBox box to test, generally the bounds of an entity that are besting tested.
|
|
+ * @return null for default behavior, true if the box is within the material, false if it was not.
|
|
+ */
|
|
+ @Nullable
|
|
+ public Boolean isAABBInsideLiquid(World world, BlockPos pos, AxisAlignedBB boundingBox)
|
|
+ {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Called when entities are swimming in the given liquid and returns the relative height (used by {@link net.minecraft.entity.item.EntityBoat})
|
|
+ *
|
|
+ * @param world world that is being tested.
|
|
+ * @param pos block thats being tested.
|
|
+ * @param state state at world/pos
|
|
+ * @param material liquid thats being tested.
|
|
+ * @return relative height of the given liquid (material), a value between 0 and 1
|
|
+ */
|
|
+ public float getBlockLiquidHeight(World world, BlockPos pos, IBlockState state, Material material)
|
|
+ {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Queries if this block should render in a given layer.
|
|
+ * ISmartBlockModel can use {@link net.minecraftforge.client.MinecraftForgeClient#getRenderLayer()} to alter their model based on layer.
|
|
+ */
|
|
+ public boolean canRenderInLayer(IBlockState state, BlockRenderLayer layer)
|
|
+ {
|
|
+ return getBlockLayer() == layer;
|
|
+ }
|
|
+ // For Internal use only to capture droped items inside getDrops
|
|
+ protected static ThreadLocal<Boolean> captureDrops = ThreadLocal.withInitial(() -> false);
|
|
+ protected static ThreadLocal<NonNullList<ItemStack>> capturedDrops = ThreadLocal.withInitial(NonNullList::create);
|
|
+ protected NonNullList<ItemStack> captureDrops(boolean start)
|
|
+ {
|
|
+ if (start)
|
|
+ {
|
|
+ captureDrops.set(true);
|
|
+ capturedDrops.get().clear();
|
|
+ return NonNullList.create();
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ captureDrops.set(false);
|
|
+ return capturedDrops.get();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Sensitive version of getSoundType
|
|
+ * @param state The state
|
|
+ * @param world The world
|
|
+ * @param pos The position. Note that the world may not necessarily have {@code state} here!
|
|
+ * @param entity The entity that is breaking/stepping on/placing/hitting/falling on this block, or null if no entity is in this context
|
|
+ * @return A SoundType to use
|
|
+ */
|
|
+ public SoundType getSoundType(IBlockState state, World world, BlockPos pos, @Nullable Entity entity)
|
|
+ {
|
|
+ return getSoundType();
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @param state The state
|
|
+ * @param world The world
|
|
+ * @param pos The position of this state
|
|
+ * @param beaconPos The position of the beacon
|
|
+ * @return A float RGB [0.0, 1.0] array to be averaged with a beacon's existing beam color, or null to do nothing to the beam
|
|
+ */
|
|
+ @Nullable
|
|
+ public float[] getBeaconColorMultiplier(IBlockState state, World world, BlockPos pos, BlockPos beaconPos)
|
|
+ {
|
|
+ return null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Use this to change the fog color used when the entity is "inside" a material.
|
|
+ * Vec3d is used here as "r/g/b" 0 - 1 values.
|
|
+ *
|
|
+ * @param world The world.
|
|
+ * @param pos The position at the entity viewport.
|
|
+ * @param state The state at the entity viewport.
|
|
+ * @param entity the entity
|
|
+ * @param originalColor The current fog color, You are not expected to use this, Return as the default if applicable.
|
|
+ * @return The new fog color.
|
|
+ */
|
|
+ @SideOnly (Side.CLIENT)
|
|
+ public Vec3d getFogColor(World world, BlockPos pos, IBlockState state, Entity entity, Vec3d originalColor, float partialTicks)
|
|
+ {
|
|
+ if (state.getMaterial() == Material.WATER)
|
|
+ {
|
|
+ float f12 = 0.0F;
|
|
+
|
|
+ if (entity instanceof net.minecraft.entity.EntityLivingBase)
|
|
+ {
|
|
+ net.minecraft.entity.EntityLivingBase ent = (net.minecraft.entity.EntityLivingBase)entity;
|
|
+ f12 = (float)net.minecraft.enchantment.EnchantmentHelper.getRespirationModifier(ent) * 0.2F;
|
|
+
|
|
+ if (ent.isPotionActive(net.minecraft.init.MobEffects.WATER_BREATHING))
|
|
+ {
|
|
+ f12 = f12 * 0.3F + 0.6F;
|
|
+ }
|
|
+ }
|
|
+ return new Vec3d(0.02F + f12, 0.02F + f12, 0.2F + f12);
|
|
+ }
|
|
+ else if (state.getMaterial() == Material.LAVA)
|
|
+ {
|
|
+ return new Vec3d(0.6F, 0.1F, 0.0F);
|
|
+ }
|
|
+ return originalColor;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Used to determine the state 'viewed' by an entity (see
|
|
+ * {@link net.minecraft.client.renderer.ActiveRenderInfo#getBlockStateAtEntityViewpoint(World, Entity, float)}).
|
|
+ * Can be used by fluid blocks to determine if the viewpoint is within the fluid or not.
|
|
+ *
|
|
+ * @param state the state
|
|
+ * @param world the world
|
|
+ * @param pos the position
|
|
+ * @param viewpoint the viewpoint
|
|
+ * @return the block state that should be 'seen'
|
|
+ */
|
|
+
|
|
+ public IBlockState getStateAtViewpoint(IBlockState state, IBlockAccess world, BlockPos pos, Vec3d viewpoint)
|
|
+ {
|
|
+ return state;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Gets the {@link IBlockState} to place
|
|
+ * @param world The world the block is being placed in
|
|
+ * @param pos The position the block is being placed at
|
|
+ * @param facing The side the block is being placed on
|
|
+ * @param hitX The X coordinate of the hit vector
|
|
+ * @param hitY The Y coordinate of the hit vector
|
|
+ * @param hitZ The Z coordinate of the hit vector
|
|
+ * @param meta The metadata of {@link ItemStack} as processed by {@link Item#getMetadata(int)}
|
|
+ * @param placer The entity placing the block
|
|
+ * @param hand The player hand used to place this block
|
|
+ * @return The state to be placed in the world
|
|
+ */
|
|
+ public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand)
|
|
+ {
|
|
+ return getStateForPlacement(world, pos, facing, hitX, hitY, hitZ, meta, placer);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Determines if another block can connect to this block
|
|
+ *
|
|
+ * @param world The current world
|
|
+ * @param pos The position of this block
|
|
+ * @param facing The side the connecting block is on
|
|
+ * @return True to allow another block to connect to this block
|
|
+ */
|
|
+ public boolean canBeConnectedTo(IBlockAccess world, BlockPos pos, EnumFacing facing)
|
|
+ {
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ /** @deprecated use {@link #getAiPathNodeType(IBlockState, IBlockAccess, BlockPos, net.minecraft.entity.EntityLiving)} */
|
|
+ @Nullable
|
|
+ @Deprecated // TODO: remove
|
|
+ public net.minecraft.pathfinding.PathNodeType getAiPathNodeType(IBlockState state, IBlockAccess world, BlockPos pos)
|
|
+ {
|
|
+ return isBurning(world, pos) ? net.minecraft.pathfinding.PathNodeType.DAMAGE_FIRE : null;
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get the {@code PathNodeType} for this block. Return {@code null} for vanilla behavior.
|
|
+ *
|
|
+ * @return the PathNodeType
|
|
+ */
|
|
+ @Nullable
|
|
+ public net.minecraft.pathfinding.PathNodeType getAiPathNodeType(IBlockState state, IBlockAccess world, BlockPos pos, @Nullable net.minecraft.entity.EntityLiving entity)
|
|
+ {
|
|
+ return getAiPathNodeType(state, world, pos);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @param blockState The state for this block
|
|
+ * @param world The world this block is in
|
|
+ * @param pos The position of this block
|
|
+ * @param side The side of this block that the chest lid is trying to open into
|
|
+ * @return true if the chest should be prevented from opening by this block
|
|
+ */
|
|
+ public boolean doesSideBlockChestOpening(IBlockState blockState, IBlockAccess world, BlockPos pos, EnumFacing side)
|
|
+ {
|
|
+ ResourceLocation registryName = this.getRegistryName();
|
|
+ if (registryName != null && "minecraft".equals(registryName.getResourceDomain()))
|
|
+ {
|
|
+ // maintain the vanilla behavior of https://bugs.mojang.com/browse/MC-378
|
|
+ return isNormalCube(blockState, world, pos);
|
|
+ }
|
|
+ return isSideSolid(blockState, world, pos, side);
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * @param state The state
|
|
+ * @return true if the block is sticky block which used for pull or push adjacent blocks (use by piston)
|
|
+ */
|
|
+ public boolean isStickyBlock(IBlockState state)
|
|
+ {
|
|
+ return state.getBlock() == Blocks.SLIME_BLOCK;
|
|
+ }
|
|
+
|
|
+ /* ========================================= FORGE END ======================================*/
|
|
+
|
|
public static void registerBlocks()
|
|
{
|
|
registerBlock(0, AIR_ID, (new BlockAir()).setUnlocalizedName("air"));
|
|
@@ -1105,7 +2513,7 @@
|
|
Block block11 = (new BlockQuartz()).setSoundType(SoundType.STONE).setHardness(0.8F).setUnlocalizedName("quartzBlock");
|
|
registerBlock(155, "quartz_block", block11);
|
|
registerBlock(156, "quartz_stairs", (new BlockStairs(block11.getDefaultState().withProperty(BlockQuartz.VARIANT, BlockQuartz.EnumType.DEFAULT))).setUnlocalizedName("stairsQuartz"));
|
|
- registerBlock(157, "activator_rail", (new BlockRailPowered()).setHardness(0.7F).setSoundType(SoundType.METAL).setUnlocalizedName("activatorRail"));
|
|
+ registerBlock(157, "activator_rail", (new BlockRailPowered(true)).setHardness(0.7F).setSoundType(SoundType.METAL).setUnlocalizedName("activatorRail"));
|
|
registerBlock(158, "dropper", (new BlockDropper()).setHardness(3.5F).setSoundType(SoundType.STONE).setUnlocalizedName("dropper"));
|
|
registerBlock(159, "stained_hardened_clay", (new BlockStainedHardenedClay()).setHardness(1.25F).setResistance(7.0F).setSoundType(SoundType.STONE).setUnlocalizedName("clayHardenedStained"));
|
|
registerBlock(160, "stained_glass_pane", (new BlockStainedGlassPane()).setHardness(0.3F).setSoundType(SoundType.GLASS).setUnlocalizedName("thinStainedGlass"));
|
|
@@ -1230,31 +2638,6 @@
|
|
block15.useNeighborBrightness = flag;
|
|
}
|
|
}
|
|
-
|
|
- Set<Block> set = Sets.newHashSet(REGISTRY.getObject(new ResourceLocation("tripwire")));
|
|
-
|
|
- for (Block block16 : REGISTRY)
|
|
- {
|
|
- if (set.contains(block16))
|
|
- {
|
|
- for (int i = 0; i < 15; ++i)
|
|
- {
|
|
- int j = REGISTRY.getIDForObject(block16) << 4 | i;
|
|
- BLOCK_STATE_IDS.put(block16.getStateFromMeta(i), j);
|
|
- }
|
|
- }
|
|
- else
|
|
- {
|
|
- UnmodifiableIterator unmodifiableiterator = block16.getBlockState().getValidStates().iterator();
|
|
-
|
|
- while (unmodifiableiterator.hasNext())
|
|
- {
|
|
- IBlockState iblockstate = (IBlockState)unmodifiableiterator.next();
|
|
- int k = REGISTRY.getIDForObject(block16) << 4 | block16.getMetaFromState(iblockstate);
|
|
- BLOCK_STATE_IDS.put(iblockstate, k);
|
|
- }
|
|
- }
|
|
- }
|
|
}
|
|
|
|
private static void registerBlock(int id, ResourceLocation textualID, Block block_)
|
|
@@ -1266,7 +2649,17 @@
|
|
{
|
|
registerBlock(id, new ResourceLocation(textualID), block_);
|
|
}
|
|
-
|
|
+ // Spigot start
|
|
+ public static float range(float min, float value, float max) {
|
|
+ if (value < min) {
|
|
+ return min;
|
|
+ }
|
|
+ if (value > max) {
|
|
+ return max;
|
|
+ }
|
|
+ return value;
|
|
+ }
|
|
+ // Spigot end
|
|
public static enum EnumOffsetType
|
|
{
|
|
NONE,
|