コード例 #1
0
ファイル: SpoutWorld.java プロジェクト: akrieger/Spout
 @Override
 public Region getRegion(Point point, boolean load) {
   int x = MathHelper.floor(point.getX());
   int y = MathHelper.floor(point.getY());
   int z = MathHelper.floor(point.getZ());
   return regions.getRegionFromBlock(x, y, z, load);
 }
コード例 #2
0
 public void setBlockMaterial(int xx, int yy, int zz, BlockMaterial material, short data) {
   final Vector3 transformed = transform(xx, yy, zz);
   position
       .getWorld()
       .setBlockMaterial(
           transformed.getFloorX(),
           transformed.getFloorY(),
           transformed.getFloorZ(),
           material,
           data,
           null);
   if (material instanceof Directional) {
     final Directional directional = (Directional) material;
     final Block block = position.getWorld().getBlock(transformed);
     final BlockFace face = directional.getFacing(block);
     if (face != BlockFace.BOTTOM && face != BlockFace.TOP) {
       directional.setFacing(
           block, BlockFace.fromYaw(face.getDirection().getYaw() + rotation.getYaw()));
     }
   } else if (material instanceof Attachable) {
     final Attachable attachable = (Attachable) material;
     final Block block = position.getWorld().getBlock(transformed);
     final BlockFace face = attachable.getAttachedFace(block);
     if (face != BlockFace.BOTTOM && face != BlockFace.TOP) {
       attachable.setAttachedFace(
           block, BlockFace.fromYaw(face.getDirection().getYaw() + rotation.getYaw()), null);
     }
   }
 }
コード例 #3
0
ファイル: SpoutWorld.java プロジェクト: akrieger/Spout
 @Override
 public Block getBlock(Point point) {
   int x = MathHelper.floor(point.getX());
   int y = MathHelper.floor(point.getY());
   int z = MathHelper.floor(point.getZ());
   return getBlock(x, y, z);
 }
コード例 #4
0
  private void initChunkRaw(Point p) {
    int x = p.getChunkX();
    int y = p.getChunkY(); // + SEALEVEL_CHUNK;
    int z = p.getChunkZ();

    RepositionManager rm = getRepositionManager();

    int cY = rm.convertChunkY(y);

    if (cY < 0 || cY >= p.getWorld().getHeight() >> Chunk.BLOCKS.BITS) {
      return;
    }

    TSyncIntHashSet column = initializedChunks.get(x, z);
    if (column == null) {
      column = new TSyncIntHashSet();
      synchronized (initChunkLock) {
        TSyncIntHashSet oldColumn = initializedChunks.putIfAbsent(x, z, column);
        if (oldColumn != null) {
          column = oldColumn;
        }
      }
    }
    column.add(y);
  }
コード例 #5
0
  @Override
  public void finalizeTick() {
    Point currentPosition = player.getScene().getPosition();

    int y = currentPosition.getBlockY();

    if (y != lastY && !isTeleportPending()) {

      lastY = y;
      int cY = getRepositionManager().convertY(y);

      if (cY >= maxY || cY < minY) {
        int steps = (cY - ((maxY + minY) >> 1)) / stepY;

        offsetY -= steps * stepY;
        vpm.setOffset(offsetY);
        cY = getRepositionManager().convertY(y);

        if (cY >= maxY) {
          offsetY -= stepY;
        } else if (cY < minY) {
          offsetY += stepY;
        }

        vpm.setOffset(offsetY);
        setRespawned();
      }
    }

    super.finalizeTick();
  }
コード例 #6
0
  @Override
  protected void freeChunk(Point p) {
    int x = (int) p.getX() >> Chunk.BLOCKS.BITS;
    int y = (int) p.getY() >> Chunk.BLOCKS.BITS; // + SEALEVEL_CHUNK;
    int z = (int) p.getZ() >> Chunk.BLOCKS.BITS;

    if (y < 0 || y >= p.getWorld().getHeight() >> Chunk.BLOCKS.BITS) {
      return;
    }

    TIntSet column = initializedChunks.get(x, z);
    CompressedChunkMessage CCMsg;
    if (column != null) {
      column.remove(y);
      if (column.isEmpty()) {
        if (initializedChunks.remove(x, z) != null) {
          activeChunks.remove(x, z);
        }
        CCMsg = new CompressedChunkMessage(x, z, true, null, null, null, true);
      } else {
        CCMsg = new CompressedChunkMessage(x, z, false, null, null, null, true);
      }

      session.send(false, CCMsg);
    }
  }
コード例 #7
0
 @Command(
     aliases = {"biome"},
     usage = "",
     desc = "Print out the name of the biome at the current location",
     min = 0,
     max = 0)
 @CommandPermissions("vanilla.command.biome")
 public void getBiomeName(CommandContext args, CommandSource source) throws CommandException {
   if (!(source instanceof Player)) {
     throw new CommandException("Only a player may call this command.");
   }
   Player player = (Player) source;
   if (!(player.getTransform().getPosition().getWorld().getGenerator()
       instanceof BiomeGenerator)) {
     throw new CommandException("This map does not appear to have any biome data.");
   }
   Point pos = player.getTransform().getPosition();
   Biome biome = pos.getWorld().getBiome(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ());
   source.sendMessage(
       plugin.getPrefix(),
       ChatStyle.BRIGHT_GREEN,
       "Current biome: ",
       ChatStyle.WHITE,
       (biome != null ? biome.getName() : "none"));
 }
コード例 #8
0
ファイル: FlintAndSteel.java プロジェクト: Karang/Vanilla
  @Override
  public void onInteract(Entity entity, Block block, Action type, BlockFace clickedface) {
    super.onInteract(entity, block, type, clickedface);
    if (type == Action.RIGHT_CLICK) {
      BlockMaterial clickedmat = block.getMaterial();
      Cause<Entity> cause;
      if (entity instanceof Player) {
        cause = new PlayerCause((Player) entity);
      } else {
        cause = new EntityCause(entity);
      }
      if (clickedmat.equals(VanillaMaterials.TNT)) {
        // Detonate TntBlock
        VanillaMaterials.TNT.onIgnite(block, cause);
      } else {
        // Default fire creation
        Block target = block.translate(clickedface);
        // Default fire placement
        if (VanillaMaterials.FIRE.canCreate(target, (short) 0, cause)) {
          VanillaMaterials.FIRE.onCreate(target, (short) 0, cause);
          Slot held = PlayerUtil.getHeldSlot(entity);
          if (held != null && !PlayerUtil.isCostSuppressed(entity)) {
            held.addData(1);
          }
        }

        // Handle the creation of portals
        Point pos = target.translate(BlockFace.BOTTOM).getPosition();
        VanillaObjects.NETHER_PORTAL.setActive(
            pos.getWorld(), pos.getBlockX(), pos.getBlockY(), pos.getBlockZ(), true);
      }
    }
  }
コード例 #9
0
  @Override
  protected void worldChanged(World world) {
    GameMode gamemode = world.getComponentHolder().getData().get(VanillaData.GAMEMODE);
    // The world the player is entering has a different gamemode...
    if (gamemode != null) {
      if (gamemode != getPlayer().getData().get(VanillaData.GAMEMODE)) {
        PlayerGameModeChangedEvent event =
            Spout.getEngine()
                .getEventManager()
                .callEvent(new PlayerGameModeChangedEvent(player, gamemode));
        if (!event.isCancelled()) {
          gamemode = event.getMode();
        }
      }
    } else {
      // The world has no gamemode setting in its map so default to the Player's GameMode.
      gamemode = getPlayer().getData().get(VanillaData.GAMEMODE);
    }
    Difficulty difficulty = world.getComponentHolder().getData().get(VanillaData.DIFFICULTY);
    Dimension dimension = world.getComponentHolder().getData().get(VanillaData.DIMENSION);
    WorldType worldType = world.getComponentHolder().getData().get(VanillaData.WORLD_TYPE);

    // TODO Handle infinite height
    if (first) {
      first = false;
      int entityId = player.getId();
      Server server = (Server) session.getEngine();
      PlayerLoginRequestMessage idMsg =
          new PlayerLoginRequestMessage(
              entityId,
              worldType.toString(),
              gamemode.getId(),
              (byte) dimension.getId(),
              difficulty.getId(),
              (byte) server.getMaxPlayers());
      player.getSession().send(false, true, idMsg);
      player.getSession().setState(State.GAME);
      for (int slot = 0; slot < 4; slot++) {
        ItemStack slotItem = owner.get(Human.class).getInventory().getArmor().get(slot);
        player.getSession().send(false, new EntityEquipmentMessage(entityId, slot, slotItem));
      }
    } else {
      player
          .getSession()
          .send(
              false,
              new PlayerRespawnMessage(
                  dimension.getId(),
                  difficulty.getId(),
                  gamemode.getId(),
                  256,
                  worldType.toString()));
    }

    Point pos = world.getSpawnPoint().getPosition();
    PlayerSpawnPositionMessage SPMsg =
        new PlayerSpawnPositionMessage((int) pos.getX(), (int) pos.getY(), (int) pos.getZ());
    player.getSession().send(false, SPMsg);
  }
コード例 #10
0
ファイル: Point.java プロジェクト: ArcheonK/Spout
 /**
  * Gets the largest distance between two points, when projected onto one of the axes.
  *
  * <p>This will return Double.MAX_VALUE if the other Point is null, either world is null, or the
  * two points are in different worlds.
  *
  * <p>Otherwise, it returns the max distance.
  */
 public double getMaxDistance(Point other) {
   if (other == null || world == null || other.world == null || !world.equals(other.world)) {
     return Double.MAX_VALUE;
   }
   return Math.max(
       Math.abs(getX() - other.getX()),
       Math.max(Math.abs(getY() - other.getY()), Math.abs(getZ() - other.getZ())));
 }
コード例 #11
0
ファイル: SpoutWorld.java プロジェクト: akrieger/Spout
 @Override
 public Chunk getChunk(Point point, boolean load) {
   int x = MathHelper.floor(point.getX());
   int y = MathHelper.floor(point.getY());
   int z = MathHelper.floor(point.getZ());
   return getChunk(
       x >> Chunk.CHUNK_SIZE_BITS, y >> Chunk.CHUNK_SIZE_BITS, z >> Chunk.CHUNK_SIZE_BITS, load);
 }
コード例 #12
0
ファイル: SpoutBlock.java プロジェクト: gohopper/Spout
 public SpoutBlock(Point position, Source source) {
   this(
       position.getWorld(),
       position.getBlockX(),
       position.getBlockY(),
       position.getBlockZ(),
       source);
 }
コード例 #13
0
ファイル: SignHandler.java プロジェクト: TomyLobo/routes
 @EventHandler
 public void onSpoutEvent(PlayerInteractEvent event) {
   final Point point = event.getInteractedPoint();
   Block block =
       point
           .getWorld()
           .getBlock(point, (org.spout.api.plugin.Plugin) plugin.getFrameworkPlugin());
   event.getPlayer().sendMessage("Stop messing with that " + block.getMaterial() + "!");
 }
コード例 #14
0
ファイル: Point.java プロジェクト: ArcheonK/Spout
 /**
  * Gets the square of the distance between two points.
  *
  * <p>This will return Double.MAX_VALUE if the other Point is null, either world is null, or the
  * two points are in different worlds.
  *
  * <p>Otherwise, it returns the Manhattan distance.
  */
 public double getSquaredDistance(Point other) {
   if (other == null || world == null || other.world == null || !world.equals(other.world)) {
     return Double.MAX_VALUE;
   }
   double dx = getX() - other.getX();
   double dy = getY() - other.getY();
   double dz = getZ() - other.getZ();
   return dx * dx + dy * dy + dz * dz;
 }
コード例 #15
0
  public void strikePlayers(List<Player> toStrike) {
    for (Player player : toStrike) {
      Point playerPos = player.getScene().getPosition();
      final int posX = GenericMath.floor(playerPos.getX());
      final int posY = GenericMath.floor(playerPos.getY());
      final int posZ = GenericMath.floor(playerPos.getZ());
      for (int tries = 0; tries < 10; tries++) {
        // pick a random chunk between -4, -4, to 4, 4 relative to the player's position to strike
        // at
        int cx = (ra.nextBoolean() ? -1 : 1) * ra.nextInt(5);
        int cz = (ra.nextBoolean() ? -1 : 1) * ra.nextInt(5);

        // pick random coords to try to strike at inside the chunk (0, 0) to (15, 15)
        int rx = ra.nextInt(16);
        int rz = ra.nextInt(16);

        // pick a offset from the player's y position to strike at (-15 - +15) of their position
        int offsetY = (ra.nextBoolean() ? -1 : 1) * ra.nextInt(15);

        int x = posX + cx * 16 + rx;
        int y = posY + offsetY;
        int z = posZ + cz * 16 + rz;

        if (weather.isRainingAt(x, y, z, false)) {
          int lightning = 1;
          // 30% chance of extra lightning at the spot
          if (ra.nextInt(10) < 3) {
            lightning += ra.nextInt(MAX_LIGHTNING_BRANCHES);
          }
          for (int strikes = 0; strikes < lightning; strikes++) {
            float adjustX = 0.5F;
            float adjustY = 0.0F;
            float adjustZ = 0.5F;
            // if there are extra strikes, tweak their placement slightly
            if (strikes > 0) {
              adjustX += (ra.nextBoolean() ? -1 : 1) * ra.nextInt(2);
              adjustY += (ra.nextBoolean() ? -1 : 1) * ra.nextInt(8);
              adjustZ += (ra.nextBoolean() ? -1 : 1) * ra.nextInt(2);
            }
            World world = getWorld();
            Point point = new Point(world, x + adjustX, y + adjustY, z + adjustZ);
            world.createAndSpawnEntity(point, Lightning.class, LoadOption.NO_LOAD);
            for (Player p : GeneralEffects.LIGHTNING_THUNDER.getNearbyPlayers(point, null, 600)) {
              double dist = p.getScene().getPosition().distanceSquared(point);
              float volume = (float) (10000F - Math.pow(dist, 0.73));
              if (volume > 0) {
                GeneralEffects.LIGHTNING_THUNDER.adjust(volume, 0.7F).play(p, point);
              }
            }
          }
          // success, go to the next player
          break;
        }
      }
    }
  }
コード例 #16
0
 @Override
 public boolean isInViewVolume(Point playerChunkBase, Point testChunkBase, int viewDistance) {
   if (playerChunkBase == null) {
     return false;
   }
   int distance =
       Math.abs(playerChunkBase.getChunkX() - testChunkBase.getChunkX())
           + Math.abs(playerChunkBase.getChunkZ() - testChunkBase.getChunkZ());
   return distance <= viewDistance;
 }
コード例 #17
0
ファイル: Jukebox.java プロジェクト: TomyLobo/Vanilla
 /** Ejects the currently playing music disc */
 public void eject() {
   ItemStack current = this.inventory.getMusicSlot();
   this.inventory.setMusicSlot(null);
   if (current != null) {
     Point position = this.getParent().getPosition();
     position
         .getWorld()
         .createAndSpawnEntity(position, new Item(current, Vector3.UP.multiply(0.5)));
     this.update();
   }
 }
コード例 #18
0
  private static int[][] getColumnHeights(Point p) {
    int[][] heights = new int[Chunk.BLOCKS.SIZE][Chunk.BLOCKS.SIZE];

    World w = p.getWorld();

    for (int xx = 0; xx < Chunk.BLOCKS.SIZE; xx++) {
      for (int zz = 0; zz < Chunk.BLOCKS.SIZE; zz++) {
        heights[xx][zz] = w.getSurfaceHeight(p.getBlockX() + xx, p.getBlockZ() + zz, true);
      }
    }
    return heights;
  }
コード例 #19
0
  private static BlockMaterial[][] getColumnTopmostMaterials(Point p) {
    BlockMaterial[][] materials = new BlockMaterial[Chunk.BLOCKS.SIZE][Chunk.BLOCKS.SIZE];

    World w = p.getWorld();

    for (int xx = 0; xx < Chunk.BLOCKS.SIZE; xx++) {
      for (int zz = 0; zz < Chunk.BLOCKS.SIZE; zz++) {
        materials[xx][zz] = w.getTopmostBlock(p.getBlockX() + xx, p.getBlockZ() + zz, true);
      }
    }
    return materials;
  }
コード例 #20
0
  /** Called when the tick is finished and collisions need to be resolved and move events fired */
  public void resolve() {
    if (Spout.debugMode()) {
      //	System.out.println("COLLISION DEBUGGING");
      //	System.out.println("Current Collision: " + this.collision.toString());
    }

    List<CollisionVolume> colliding =
        ((SpoutWorld) collisionPoint.getWorld()).getCollidingObject(this.collision);

    Vector3 offset = this.lastTransform.getPosition().subtract(collisionPoint);
    for (CollisionVolume box : colliding) {
      if (Spout.debugMode()) {
        //	System.out.println("Colliding box: " + box.toString());
      }
      Vector3 collision = this.collision.resolve(box);
      if (Spout.debugMode()) {
        //	System.out.println("Collision vector: " + collision.toString());
      }
      if (collision != null) {
        collision = collision.subtract(collisionPoint);
        if (Spout.debugMode()) {
          //	System.out.println("Collision point: " + collision.toString() + " Collision vector: " +
          // collision);
        }

        if (collision.getX() != 0F) {
          offset = new Vector3(collision.getX(), offset.getY(), offset.getZ());
        }
        if (collision.getY() != 0F) {
          offset = new Vector3(offset.getX(), collision.getY(), offset.getZ());
        }
        if (collision.getZ() != 0F) {
          offset = new Vector3(offset.getX(), offset.getY(), collision.getZ());
        }

        if (Spout.debugMode()) {
          //	System.out.println("Collision offset: " + offset.toString());
        }
        if (this.getCollision().getStrategy() == CollisionStrategy.SOLID
            && box.getStrategy() == CollisionStrategy.SOLID) {
          this.setPosition(collisionPoint.add(offset));
          if (Spout.debugMode()) {
            //	System.out.println("New Position: " + this.getPosition());
          }
        }

        controllerLive.get().onCollide(getWorld().getBlock(box.getPosition()));
      }
    }

    // Check to see if we should fire off a Move event
  }
コード例 #21
0
ファイル: Point.java プロジェクト: ArcheonK/Spout
 @Override
 public boolean equals(Object obj) {
   if (!(obj instanceof Point)) {
     return false;
   } else {
     Point point = (Point) obj;
     boolean worldEqual =
         point.world == world || (point.world != null && point.world.equals(world));
     return worldEqual
         && point.getX() == getX()
         && point.getY() == getY()
         && point.getZ() == getZ();
   }
 }
コード例 #22
0
  /**
   * Called when a player interacts
   *
   * @param event Relevant event details
   */
  @EventHandler(event = PlayerInteractEvent.class)
  public void onPlayerInteract(PlayerInteractEvent event) {

    final LocalPlayer player = plugin.wrapPlayer(event.getPlayer());
    final LocalWorld world = player.getWorld();
    final WorldEdit we = plugin.getWorldEdit();

    PlayerInteractEvent.Action action = event.getAction();
    if (action == Action.LEFT_CLICK) {
      if (event.isAir() && ignoreLeftClickAir) {
        return;
      }

      if (!event.isAir()) {
        final Point clickedBlock = event.getInteractedPoint();
        final WorldVector pos =
            new WorldVector(world, clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());

        if (we.handleBlockLeftClick(player, pos)) {
          event.setCancelled(true);
        }
      }

      if (we.handleArmSwing(player)) {
        event.setCancelled(true);
      }

      if (!event.isAir() && !ignoreLeftClickAir) {
        final int taskId =
            Spout.getGame()
                .getScheduler()
                .scheduleSyncDelayedTask(
                    plugin,
                    new Runnable() {
                      public void run() {
                        ignoreLeftClickAir = false;
                      }
                    },
                    2);

        if (taskId != -1) {
          ignoreLeftClickAir = true;
        }
      }
    } else if (action == Action.RIGHT_CLICK) {
      if (!event.isAir()) {
        final Point clickedBlock = event.getInteractedPoint();
        final WorldVector pos =
            new WorldVector(world, clickedBlock.getX(), clickedBlock.getY(), clickedBlock.getZ());

        if (we.handleBlockRightClick(player, pos)) {
          event.setCancelled(true);
        }
      }

      if (we.handleRightClick(player)) {
        event.setCancelled(true);
      }
    }
  }
コード例 #23
0
 public void placeObject(int xx, int yy, int zz, WorldGeneratorObject object) {
   final Vector3 transformed = transform(xx, yy, zz);
   if (object.canPlaceObject(
       position.getWorld(),
       transformed.getFloorX(),
       transformed.getFloorY(),
       transformed.getFloorZ())) {
     object.placeObject(
         position.getWorld(),
         transformed.getFloorX(),
         transformed.getFloorY(),
         transformed.getFloorZ());
   }
 }
コード例 #24
0
 @Override
 protected void sendPosition(Point p, Quaternion rot) {
   PlayerPositionLookMessage PPLMsg =
       new PlayerPositionLookMessage(
           p.getX(),
           p.getY() + STANCE,
           p.getZ(),
           p.getY(),
           rot.getYaw(),
           rot.getPitch(),
           true,
           VanillaBlockDataChannelMessage.CHANNEL_ID,
           getRepositionManager());
   session.send(false, PPLMsg);
 }
コード例 #25
0
 public BlockMaterial getBlockMaterial(int xx, int yy, int zz) {
   final Vector3 transformed = transform(xx, yy, zz);
   return position
       .getWorld()
       .getBlockMaterial(
           transformed.getFloorX(), transformed.getFloorY(), transformed.getFloorZ());
 }
コード例 #26
0
ファイル: SoundEffect.java プロジェクト: midget3111/Vanilla
 /**
  * Gets all the Players nearby a certain Point that can receive this Effect
  *
  * @param position of this Effect
  * @param ignore Entity to ignore
  * @return a Set of nearby Players
  */
 public List<Player> getNearbyPlayers(Point position, Player ignore, float volume) {
   int range = this.getRange();
   if (volume > 1.0f) {
     // Multiply range for different volumes
     range *= volume;
   }
   return position.getWorld().getNearbyPlayers(position, ignore, range);
 }
コード例 #27
0
  @Override
  protected void worldChanged(World world) {
    // Grab world characteristics.
    GameMode gamemode = world.getDataMap().get(VanillaData.GAMEMODE);
    Difficulty difficulty = world.getDataMap().get(VanillaData.DIFFICULTY);
    Dimension dimension = world.getDataMap().get(VanillaData.DIMENSION);
    WorldType worldType = world.getDataMap().get(VanillaData.WORLD_TYPE);

    // TODO Handle infinite height
    if (first) {
      first = false;
      int entityId = owner.getEntity().getId();
      VanillaPlayer vc = (VanillaPlayer) owner.getEntity().getController();
      LoginRequestMessage idMsg =
          new LoginRequestMessage(
              entityId,
              worldType.toString(),
              gamemode.getId(),
              (byte) dimension.getId(),
              difficulty.getId(),
              (byte) session.getEngine().getMaxPlayers());
      owner.getSession().send(false, true, idMsg);
      owner.getSession().setState(State.GAME);
      for (int slot = 0; slot < 4; slot++) {
        ItemStack slotItem = vc.getInventory().getArmor().getItem(slot);
        owner.getSession().send(false, new EntityEquipmentMessage(entityId, slot, slotItem));
      }
    } else {
      owner
          .getSession()
          .send(
              false,
              new RespawnMessage(
                  dimension.getId(),
                  difficulty.getId(),
                  gamemode.getId(),
                  256,
                  worldType.toString()));
    }

    Point pos = world.getSpawnPoint().getPosition();
    SpawnPositionMessage SPMsg =
        new SpawnPositionMessage((int) pos.getX(), (int) pos.getY(), (int) pos.getZ());
    owner.getSession().send(false, SPMsg);
  }
コード例 #28
0
ファイル: NoteParticleEffect.java プロジェクト: Grafe/Vanilla
 @Override
 public void play(Player player, Point position, int note) {
   Block block = position.getWorld().getBlock(position);
   player
       .getSession()
       .getNetworkSynchronizer()
       .callProtocolEvent(
           new BlockActionEvent(block, VanillaMaterials.NOTEBLOCK, (byte) 0, (byte) note));
 }
コード例 #29
0
ファイル: MinecartItem.java プロジェクト: joansmith/Vanilla
 @Override
 @SuppressWarnings("unchecked")
 public Minecart spawnEntity(Point position) {
   Class<? extends Minecart> component = this.getSpawnedComponent();
   Entity spawned =
       position
           .getWorld()
           .createAndSpawnEntity(position, LoadOption.NO_LOAD, component, getMinecartType());
   return spawned.add(component);
 }
コード例 #30
0
ファイル: FallingBlock.java プロジェクト: md-5/Vanilla
 @Override
 public void onTick(float dt) {
   Point pos = this.getOwner().getTransform().getPosition();
   BlockMaterial material =
       pos.getWorld().getBlockMaterial(pos.getBlockX(), pos.getBlockY() - 1, pos.getBlockZ());
   if (isObstacle(material)) {
     pos.getWorld()
         .setBlockMaterial(
             pos.getBlockX(),
             pos.getBlockY(),
             pos.getBlockZ(),
             getMaterial(),
             getMaterial().getData(),
             getMaterial().toCause(pos));
     this.getOwner().remove();
   } else {
     this.getOwner().getTransform().setPosition(pos.add(0, fallSpeed, 0F));
     fallSpeed = Math.max(-1F, fallSpeed - dt);
   }
 }