@Override public List<Message> getSpawnMessages(Entity entity, RepositionManager rm) { FallingBlock block = entity.get(FallingBlock.class); if (block != null) { VanillaBlockMaterial material = block.getMaterial(); int messageData = material.getMinecraftId() | (material.getMinecraftData(material.getData()) >> 16); List<Message> messages = new ArrayList<Message>(); final double p = 32d; Point pos = entity.getScene().getPosition(); int x = (int) Math.floor(pos.getX() * p); int y = (int) Math.floor(pos.getY() * p); int z = (int) Math.floor(pos.getZ() * p); byte yaw = (byte) ChannelBufferUtils.protocolifyYaw(entity.getScene().getRotation().getYaw()); byte pitch = (byte) ChannelBufferUtils.protocolifyPitch(entity.getScene().getRotation().getPitch()); short fallSpeed = (short) (block.getFallingSpeed() * 8000d); messages.add( new EntityObjectMessage( entity.getId(), (byte) typeId, x, y, z, messageData, (short) 0, fallSpeed, (short) 0, yaw, pitch, rm)); messages.add(new EntityMetadataMessage(entity.getId(), getSpawnParameters(entity))); return messages; } else { return Collections.emptyList(); } }
/** * Simulates the result of a blocks falling inside a buffer. If the blocks reach the bottom of the * buffer without hitting any obstacles they may either be removed or stopped at the bottom. If * the block at (x, y, z) is not a SolidMoving, nothing will happen, else it and the blocks above * will be subject to the simulation. If the blocks fall on a placement obstacle (such as a torch) * they will be removed. * * @param buffer The buffer in which to simulate the fall. * @param x The x coordinate of the block. * @param y The y coordinate of the block. * @param z The Z coordinate of the block. * @param remove If the blocks should be removed after reaching the bottom of the buffer, or * stopped. */ public static void simulateFall( CuboidBlockMaterialBuffer buffer, int x, int y, int z, boolean remove) { if (!buffer.isInside(x, y, z)) { return; } BlockMaterial falling = buffer.get(x, y, z); if (!(falling instanceof SolidMoving)) { return; } int baseY = buffer.getBase().getFloorY(); for (int obstacleY = y; --obstacleY >= baseY; ) { if (FallingBlock.isFallingObstacle(buffer.get(x, obstacleY, z))) { // obstacle found if (obstacleY == y - 1) { // right underneath, nowhere to fall return; } if (buffer.get(x, ++obstacleY, z).isPlacementObstacle()) { // blocks can't stay here. Delete them remove = true; break; } do { // move the blocks above the obstacle buffer.set(x, obstacleY++, z, falling); buffer.set(x, y++, z, VanillaMaterials.AIR); } while ((falling = buffer.get(x, y, z)) instanceof SolidMoving); return; } } // no obstacle found if (remove) { // delete the blocks final int topY = buffer.getTop().getFloorY() - 1; do { buffer.set(x, y++, z, VanillaMaterials.AIR); } while (y <= topY && buffer.get(x, y, z) instanceof SolidMoving); } else { // move the blocks to the bottom of the buffer do { buffer.set(x, baseY++, z, falling); buffer.set(x, y++, z, VanillaMaterials.AIR); } while ((falling = buffer.get(x, y, z)) instanceof SolidMoving); } }