@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();
    }
  }
Example #2
0
 /**
  * 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);
   }
 }