Package com.bergerkiller.bukkit.common.controller

Source Code of com.bergerkiller.bukkit.common.controller.EntityController

package com.bergerkiller.bukkit.common.controller;

import java.util.List;

import org.bukkit.Sound;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Vehicle;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.vehicle.VehicleBlockCollisionEvent;

import net.minecraft.server.AxisAlignedBB;
import net.minecraft.server.Block;
import net.minecraft.server.Blocks;
import net.minecraft.server.DamageSource;
import net.minecraft.server.Entity;

import com.bergerkiller.bukkit.common.entity.CommonEntity;
import com.bergerkiller.bukkit.common.entity.CommonEntityController;
import com.bergerkiller.bukkit.common.entity.nms.NMSEntityHook;
import com.bergerkiller.bukkit.common.internal.CommonNMS;
import com.bergerkiller.bukkit.common.reflection.classes.EntityRef;
import com.bergerkiller.bukkit.common.utils.CommonUtil;
import com.bergerkiller.bukkit.common.utils.MathUtil;

public class EntityController<T extends CommonEntity<?>> extends CommonEntityController<T> {

  /**
   * Binds this Entity Controller to an Entity.
   * This is called from elsewhere, and should be ignored entirely.
   *
   * @param entity to bind with
   */
  @SuppressWarnings("unchecked")
  public final void bind(CommonEntity<?> entity) {
    if (this.entity != null) {
      this.onDetached();
    }
    this.entity = (T) entity;
    if (this.entity != null) {
      final Object handle = this.entity.getHandle();
      if (handle instanceof NMSEntityHook) {
        ((NMSEntityHook) handle).setController(this);
      }
      if (entity.isSpawned()) {
        this.onAttached();
      }
    }
  }

  /**
   * Called when this Entity dies (could be called more than one time)
   */
  public void onDie() {
    entity.getHandle(NMSEntityHook.class).super_die();
  }

  /**
   * Called every tick to update the entity
   */
  public void onTick() {
    entity.getHandle(NMSEntityHook.class).super_h();
  }

  /**
   * Called when the entity is interacted by something
   *
   * @param interacter that interacted
   * @return True if interaction occurred, False if not
   */
  public boolean onInteractBy(HumanEntity interacter) {
    return entity.getHandle(NMSEntityHook.class).super_c(CommonNMS.getNative(interacter));
  }

  /**
   * Called when the entity is damaged by something
   *
   * @param damageSource of the damage
   * @param damage amount
   */
  public void onDamage(com.bergerkiller.bukkit.common.wrappers.DamageSource damageSource, double damage) {
    entity.getHandle(NMSEntityHook.class).super_damageEntity((DamageSource) damageSource.getHandle(), (float) damage);
  }

  /**
   * Handles the collision of this minecart with another Entity
   *
   * @param e entity with which is collided
   * @return True if collision is allowed, False if it is ignored
   */
  public boolean onEntityCollision(org.bukkit.entity.Entity e) {
    return true;
  }

  /**
   * Handles the collision of this minecart with a Block
   *
   * @param block with which this minecart collided
   * @param hitFace of the block that the minecart hit
   * @return True if collision is allowed, False if it is ignored
   */
  public boolean onBlockCollision(org.bukkit.block.Block block, BlockFace hitFace) {
    return true;
  }

  /**
   * Fired when the entity is getting burned by something
   *
   * @param damage dealt
   */
  public void onBurnDamage(double damage) {
    entity.getHandle(NMSEntityHook.class).super_burn((float) damage);
  }

  /**
   * Gets whether this Entity Controller allows players to take this Entity with them.
   * With this enabled, players take the vehicle with them.
   * To disable this default behavior, override this method.
   *
   * @return True if players can take the entity with them, False if not
   */
  public boolean isPlayerTakable() {
    return true;
  }

  /**
   * Gets the localized name of this Entity. Override this method to change the name.
   *
   * @return Localized name
   */
  public String getLocalizedName() {
    return entity.getHandle(NMSEntityHook.class).super_getName();
  }
 
  public void onPush(double dx, double dy, double dz) {
    entity.getHandle(NMSEntityHook.class).super_g(dx, dy, dz);
  }

  /**
   * Performs Entity movement logic, to move the Entity and handle collisions
   *
   * @param dx offset to move
   * @param dy offset to move
   * @param dz offset to move
   */
  public void onMove(double dx, double dy, double dz) {
    final Entity handle = entity.getHandle(Entity.class);
    if (handle.X) {
      handle.boundingBox.d(dx, dy, dz);
      handle.locX = CommonNMS.getMiddleX(handle.boundingBox);
      handle.locY = (handle.boundingBox.b + (double) handle.height) - (double) handle.W;
      handle.locZ = CommonNMS.getMiddleZ(handle.boundingBox);
    } else {
      handle.W *= 0.4f;
      final double oldLocX = handle.locX;
      final double oldLocY = handle.locY;
      final double oldLocZ = handle.locZ;
      if (EntityRef.justLanded.get(handle)) {
        EntityRef.justLanded.set(handle, false);
        dx *= 0.25;
        dy *= 0.05;
        dz *= 0.25;
        entity.vel.setZero();
      }

      // Don't perform any movement updates when not moving
      if (dx == 0 && dy == 0 && dz == 0 && !entity.hasPassenger() && !entity.isInsideVehicle()) {
        onPostMove(0.0, 0.0, 0.0);
        return;
      }

      // Perform movement updates
      final double oldDx = dx;
      final double oldDy = dy;
      final double oldDz = dz;
      AxisAlignedBB axisalignedbb = handle.boundingBox.clone();
      List<AxisAlignedBB> list = EntityControllerCollisionHelper.getCollisions(this, handle.boundingBox.a(dx, dy, dz));

      // Collision testing using Y
      for (AxisAlignedBB aabb : list) {
        dy = aabb.b(handle.boundingBox, dy);
      }
      handle.boundingBox.d(0.0, dy, 0.0);
      if (!handle.J && oldDy != dy) {
        dx = dy = dz = 0.0;
      }
      boolean isOnGround = handle.onGround || oldDy != dy && oldDy < 0.0;

      // Collision testing using X
      for (AxisAlignedBB aabb : list) {
        dx = aabb.a(handle.boundingBox, dx);
      }
      handle.boundingBox.d(dx, 0.0, 0.0);
      if (!handle.J && oldDx != dx) {
        dx = dy = dz = 0.0;
      }

      // Collision testing using Z
      for (AxisAlignedBB aabb : list) {
        dz = aabb.c(handle.boundingBox, dz);
      }
      handle.boundingBox.d(0.0, 0.0, dz);
      if (!handle.J && oldDz != dz) {
        dx = dy = dz = 0.0;
      }

      double moveDx;
      double moveDy;
      double moveDz;
      if (handle.Y > 0.0f && handle.Y < 0.05f && isOnGround && (oldDx != dx || oldDz != dz)) {
        moveDx = dx;
        moveDy = dy;
        moveDz = dz;
        dx = oldDx;
        dy = (double) handle.Y;
        dz = oldDz;

        AxisAlignedBB axisalignedbb1 = handle.boundingBox.clone();
        handle.boundingBox.d(axisalignedbb);

        list = EntityControllerCollisionHelper.getCollisions(this, handle.boundingBox.a(oldDx, dy, oldDz));

        // Collision testing using Y
        for (AxisAlignedBB aabb : list) {
          dy = aabb.b(handle.boundingBox, dy);
        }
        handle.boundingBox.d(0.0, dy, 0.0);
        if (!handle.J && oldDy != dy) {
          dx = dy = dz = 0.0;
        }

        // Collision testing using X
        for (AxisAlignedBB aabb : list) {
          dx = aabb.a(handle.boundingBox, dx);
        }
        handle.boundingBox.d(dx, 0.0, 0.0);
        if (!handle.J && oldDx != dx) {
          dx = dy = dz = 0.0;
        }

        // Collision testing using Z
        for (AxisAlignedBB aabb : list) {
          dz = aabb.c(handle.boundingBox, dz);
        }
        handle.boundingBox.d(0.0, 0.0, dz);
        if (!handle.J && oldDz != dz) {
          dx = dy = dz = 0.0;
        }

        if (!handle.J && oldDy != dy) {
          dx = dy = dz = 0.0;
        } else {
          dy = (double) -handle.Y;
          for (int k = 0; k < list.size(); k++) {
            dy = list.get(k).b(handle.boundingBox, dy);
          }
          handle.boundingBox.d(0.0, dy, 0.0);
        }
        if (MathUtil.lengthSquared(moveDx, moveDz) >= MathUtil.lengthSquared(dx, dz)) {
          dx = moveDx;
          dy = moveDy;
          dz = moveDz;
          handle.boundingBox.d(axisalignedbb1);
        } else {
          double subY = handle.boundingBox.b - (int) handle.boundingBox.b;
          if (subY > 0.0) {
            handle.Y += subY + 0.01;
          }
        }
      }
      handle.locX = CommonNMS.getMiddleX(handle.boundingBox);
      handle.locY = handle.boundingBox.b + (double) handle.height - (double) handle.Y;
      handle.locZ = CommonNMS.getMiddleZ(handle.boundingBox);
      entity.setMovementImpaired(oldDx != dx || oldDz != dz);
      handle.onGround = oldDy != dy && oldDy < 0.0;
      handle.G = oldDy != dy;
      handle.F = entity.isMovementImpaired() || handle.G;
      EntityRef.updateFalling(handle, dy, handle.onGround);

      // ================ Collision slowdown caused by ==============
      if (oldDy != dy) {
        handle.motY = 0.0;
      }
      if (oldDx != dx && entity.vel.x.abs() > entity.vel.z.abs()) {
        handle.motX = 0.0;
      }
      if (oldDz != dz && entity.vel.z.abs() > entity.vel.x.abs()) {
        handle.motZ = 0.0;
      }
      // =============================================================

      moveDx = handle.locX - oldLocX;
      moveDy = handle.locY - oldLocY;
      moveDz = handle.locZ - oldLocZ;
      if (entity.getEntity() instanceof Vehicle && entity.isMovementImpaired()) {
        Vehicle vehicle = (Vehicle) entity.getEntity();
        org.bukkit.block.Block block = entity.getWorld().getBlockAt(entity.loc.x.block(), MathUtil.floor(handle.locY - (double) handle.height), entity.loc.z.block());
        if (oldDx > dx) {
          block = block.getRelative(BlockFace.EAST);
        } else if (oldDx < dx) {
          block = block.getRelative(BlockFace.WEST);
        } else if (oldDz > dz) {
          block = block.getRelative(BlockFace.SOUTH);
        } else if (oldDz < dz) {
          block = block.getRelative(BlockFace.NORTH);
        }
        CommonUtil.callEvent(new VehicleBlockCollisionEvent(vehicle, block));
      }
      // Perform post movement logic
      onPostMove(moveDx, moveDy, moveDz);
    }
  }

  private void onPostMove(double moveDx, double moveDy, double moveDz) {
    Entity handle = this.entity.getHandle(Entity.class);
    // Update entity movement sounds
    if (EntityRef.hasMovementSound(handle) && handle.vehicle == null) {
      int bX = entity.loc.x.block();
      int bY = MathUtil.floor(handle.locY - 0.2 - (double) handle.height);
      int bZ = entity.loc.z.block();
      Block block = handle.world.getType(bX, bY, bZ);
      int j1 = handle.world.getType(bX, bY - 1, bZ).b();

      // Magic values! *gasp* Bad, BAD Minecraft! Go sit in a corner!
      if (j1 == 11 || j1 == 32 || j1 == 21) {
        block = handle.world.getType(bX, bY - 1, bZ);
      }
      if (block != Blocks.LADDER) {
        moveDy = 0.0;
      }

      handle.Q += MathUtil.length(moveDx, moveDz) * 0.6;
      handle.O += MathUtil.length(moveDx, moveDy, moveDz) * 0.6;
      if (handle.O > EntityRef.stepCounter.get(entity.getHandle()) && block != Blocks.AIR) {
        EntityRef.stepCounter.set(entity.getHandle(), (int) handle.O + 1);
        if (entity.isInWater(true)) {
          float f = (float) Math.sqrt(entity.vel.y.squared() + 0.2 * entity.vel.xz.lengthSquared()) * 0.35f;
          if (f > 1.0f) {
            f = 1.0f;
          }
          entity.makeRandomSound(EntityRef.getSwimSound.invoke(handle), f, 1.0f);
        }
        entity.makeStepSound(bX, bY, bZ, CommonNMS.getMaterial(block));
        block.b(handle.world, bX, bY, bZ, handle);
      }
    }

    EntityRef.updateBlockCollision(handle);

    // Fire tick calculation (check using block collision)
    final boolean isInWater = handle.L(); // In water or raining
    if (handle.world.e(handle.boundingBox.shrink(0.001, 0.001, 0.001))) {
      onBurnDamage(1);
      if (!isInWater) {
        handle.fireTicks++;
        if (handle.fireTicks <= 0) {
          EntityCombustEvent event = new EntityCombustEvent(entity.getEntity(), 8);
          if (!CommonUtil.callEvent(event).isCancelled()) {
            handle.setOnFire(event.getDuration());
          }
        } else {
          handle.setOnFire(8);
        }
      }
    } else if (handle.fireTicks <= 0) {
      handle.fireTicks = -handle.maxFireTicks;
    }
    if (isInWater && handle.fireTicks > 0) {
      entity.makeRandomSound(Sound.FIZZ, 0.7f, 1.6f);
      handle.fireTicks = -handle.maxFireTicks;
    }
  }
}
TOP

Related Classes of com.bergerkiller.bukkit.common.controller.EntityController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.