package openblocks.common.block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import openblocks.common.tileentity.TileEntityTarget;
import openmods.block.BlockRotationMode;
import openmods.geometry.BlockSpaceTransform;
import openmods.geometry.Orientation;
public class BlockTarget extends OpenBlock {
private int lastEntityHit = 0;
public BlockTarget() {
super(Material.rock);
setLightLevel(0.3f);
setRotationMode(BlockRotationMode.FOUR_DIRECTIONS);
setRenderMode(RenderMode.TESR_ONLY);
}
@Override
public boolean isOpaqueCube() {
return false;
}
@Override
public void onEntityCollidedWithBlock(World world, int x, int y, int z, Entity entity) {
if (!world.isRemote && entity != null && entity instanceof EntityArrow) {
if (lastEntityHit != entity.getEntityId()) {
lastEntityHit = entity.getEntityId();
return;
}
lastEntityHit = entity.getEntityId();
onTargetHit(world, x, y, z, Vec3.createVectorHelper(entity.posX, entity.posY, entity.posZ));
}
}
public void onTargetHit(World world, int x, int y, int z, Vec3 entityPosition) {
if (world.isRemote) return;
final TileEntityTarget target = getTileEntity(world, x, y, z, TileEntityTarget.class);
if (target == null) return;
/**
* onEntityCollidedWithBlock is called twice when the arrow is hit
* The first is from the raytracing, which is predictive and
* inaccurate The second is from the bounding box collision. We only
* care about the second one
*/
if (!target.isEnabled()) return;
ForgeDirection opposite = target.getOrientation().south();
double centerX = x + 0.5 + (opposite.offsetX * 0.5);
double centerY = y + 0.55 + (opposite.offsetY * 0.45);
double centerZ = z + 0.5 + (opposite.offsetZ * 0.5);
switch (opposite) {
case NORTH:
case SOUTH:
entityPosition.zCoord = centerZ;
break;
case EAST:
case WEST:
entityPosition.xCoord = centerX;
break;
default:
break;
}
Vec3 bullseye = Vec3.createVectorHelper(centerX, centerY, centerZ);
double distance = entityPosition.distanceTo(bullseye);
target.setStrength(15 - Math.min(15, Math.max(0, (int)(distance * 32))));
}
@Override
public int isProvidingWeakPower(IBlockAccess world, int x, int y, int z, int m) {
final TileEntityTarget tile = getTileEntity(world, x, y, z, TileEntityTarget.class);
return tile != null? tile.getStrength() : 0;
}
@Override
public int isProvidingStrongPower(IBlockAccess world, int x, int y, int z, int m) {
return isProvidingWeakPower(world, x, y, z, m);
}
@Override
public AxisAlignedBB getSelectedBoundingBoxFromPool(World world, int x, int y, int z) {
setBlockBoundsBasedOnState(world, x, y, z);
return super.getSelectedBoundingBoxFromPool(world, x, y, z);
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
setBlockBoundsBasedOnState(world, x, y, z);
return super.getCollisionBoundingBoxFromPool(world, x, y, z);
}
@Override
public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) {
TileEntity tile = world.getTileEntity(x, y, z);
if (tile == null || !(tile instanceof TileEntityTarget)) { return; }
TileEntityTarget target = (TileEntityTarget)tile;
if (!target.isEnabled()) {
setBlockBounds(0, 0, 0, 1.0f, 0.1f, 1.0f);
return;
}
final Orientation orientation = target.getOrientation();
final AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(0.0, 0.0, 0.9, 1.0, 1.0, 1.0);
final AxisAlignedBB rotatedAabb = BlockSpaceTransform.instance.mapBlockToWorld(orientation, aabb);
setBlockBounds(rotatedAabb);
}
@Override
public boolean canPlaceBlockOnSide(World world, int x, int y, int z, ForgeDirection side) {
return isOnTopOfSolidBlock(world, x, y, z, side);
}
}