package net.glowstone.block.blocktype; import net.glowstone.block.GlowBlock; import net.glowstone.block.GlowBlockState; import net.glowstone.entity.GlowPlayer; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.inventory.ItemStack; /** * Represents a block that falls down, when there's no block below it. */ public class BlockFalling extends BlockType { private final Material drop; public BlockFalling(Material drop) { this.drop = drop; } @Override public void afterPlace(GlowPlayer player, GlowBlock block, ItemStack holding, GlowBlockState oldState) { updatePhysics(block); } @Override public void onNearBlockChanged(GlowBlock me, BlockFace face, GlowBlock other, Material oldType, byte oldData, Material newType, byte newData) { if (face == BlockFace.DOWN) { updatePhysics(me); } } @Override public void updatePhysics(GlowBlock me) { Block below = me.getRelative(BlockFace.DOWN); if (!supportingBlock(below.getType())) { transformToFallingEntity(me); } } protected void transformToFallingEntity(final GlowBlock me) { final Material oldType = me.getType(); final byte data = me.getData(); me.setTypeId(0, false); // todo: replace with me.getWorld().spawnFallingBlock(me.getLocation(), drop, me.getData()); // on a delay to prevent the block not being visible because its new location was just dug me.getWorld().getServer().getScheduler().runTask(null, new Runnable() { @Override public void run() { int x = me.getX(), y = me.getY(), z = me.getZ(); for (; y > 0; --y) { Material check = me.getWorld().getBlockAt(x, y - 1, z).getType(); if (supportingBlock(check)) { me.getWorld().getBlockAt(x, y, z).setTypeIdAndData(drop.getId(), data, true); break; } } me.applyPhysics(oldType, 0, data, (byte) 0); } }); } private boolean supportingBlock(Material material) { switch (material) { case AIR: case FIRE: case WATER: case STATIONARY_WATER: case LAVA: case STATIONARY_LAVA: return false; } return true; } }