package blusunrize.immersiveengineering.common.blocks.metal.conveyors; import blusunrize.immersiveengineering.api.tool.ConveyorHandler; import blusunrize.immersiveengineering.api.tool.ConveyorHandler.ConveyorDirection; import blusunrize.immersiveengineering.api.tool.ConveyorHandler.IConveyorBelt; import blusunrize.immersiveengineering.api.tool.ConveyorHandler.IConveyorTile; import blusunrize.immersiveengineering.client.ClientUtils; import blusunrize.immersiveengineering.client.models.ModelConveyor; import blusunrize.immersiveengineering.common.util.Utils; import blusunrize.immersiveengineering.common.util.chickenbones.Matrix4; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing.Axis; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nullable; import javax.vecmath.Matrix4f; import java.util.ArrayList; import java.util.List; /** * @author BluSunrize - 20.08.2016 */ public class ConveyorVertical extends ConveyorBasic { @Override public boolean renderWall(TileEntity tile, EnumFacing facing, int wall) { return true; } @Override public boolean changeConveyorDirection() { return false; } @Override public boolean setConveyorDirection(ConveyorDirection dir) { return false; } @Override public String getModelCacheKey(TileEntity tile, EnumFacing facing) { String key = ConveyorHandler.reverseClassRegistry.get(this.getClass()).toString(); key += "f" + facing.ordinal(); key += "a" + (isActive(tile) ? 1 : 0); key += "b" + (renderBottomBelt(tile, facing)?("1"+(super.renderWall(tile,facing,0)?"1":"0")+(super.renderWall(tile,facing,1)?"1":"0")):"000"); key += "c" + getDyeColour(); return key; } boolean renderBottomBelt(TileEntity tile, EnumFacing facing) { TileEntity te = tile.getWorld().getTileEntity(tile.getPos().add(0, -1, 0)); if(te instanceof IConveyorTile && ((IConveyorTile)te).getConveyorSubtype() != null) for(EnumFacing f : ((IConveyorTile)te).getConveyorSubtype().sigTransportDirections(te, ((IConveyorTile)te).getFacing())) if(f == EnumFacing.UP) return false; for(EnumFacing f : EnumFacing.HORIZONTALS) if(f != facing) { te = tile.getWorld().getTileEntity(tile.getPos().offset(f)); if(te instanceof IConveyorTile) { IConveyorBelt sub = ((IConveyorTile)te).getConveyorSubtype(); if (sub!=null) for(EnumFacing f2 : sub.sigTransportDirections(te, ((IConveyorTile)te).getFacing())) if(f == f2.getOpposite()) return true; } te = tile.getWorld().getTileEntity(tile.getPos().add(0, -1, 0).offset(f)); if(te instanceof IConveyorTile) { IConveyorBelt sub = ((IConveyorTile)te).getConveyorSubtype(); if (sub!=null) { int b = 0; for(EnumFacing f2 : sub.sigTransportDirections(te, ((IConveyorTile)te).getFacing())) { if(f == f2.getOpposite()) b++; else if(EnumFacing.UP == f2) b++; if(b == 2) return true; } } } } return false; } @Override public EnumFacing[] sigTransportDirections(TileEntity conveyorTile, EnumFacing facing) { return new EnumFacing[]{EnumFacing.UP, facing}; } @Override public Vec3d getDirection(TileEntity conveyorTile, Entity entity, EnumFacing facing) { BlockPos posWall = conveyorTile.getPos().offset(facing); double d = .625 + entity.width; double distToWall = Math.abs((facing.getAxis() == Axis.Z ? posWall.getZ() : posWall.getX()) + .5 - (facing.getAxis() == Axis.Z ? entity.posZ : entity.posX)); if(distToWall > d) return super.getDirection(conveyorTile, entity, facing); double vBase = entity instanceof EntityLivingBase ? 1.5 : 1.15; double distY = Math.abs(conveyorTile.getPos().add(0, 1, 0).getY() + .5 - entity.posY); double treshold = .9; boolean contact = distY < treshold; double vX = entity.motionX; double vY = 0.1 * vBase; double vZ = entity.motionZ; if(entity.motionY < 0) vY += entity.motionY * .9; if(!(entity instanceof EntityPlayer)) { vX = 0.05 * facing.getFrontOffsetX(); vZ = 0.05 * facing.getFrontOffsetZ(); if(facing == EnumFacing.WEST || facing == EnumFacing.EAST) { if(entity.posZ > conveyorTile.getPos().getZ() + 0.65D) vZ = -0.1D * vBase; else if(entity.posZ < conveyorTile.getPos().getZ() + 0.35D) vZ = 0.1D * vBase; } else if(facing == EnumFacing.NORTH || facing == EnumFacing.SOUTH) { if(entity.posX > conveyorTile.getPos().getX() + 0.65D) vX = -0.1D * vBase; else if(entity.posX < conveyorTile.getPos().getX() + 0.35D) vX = 0.1D * vBase; } } //Little boost at the top of a conveyor to help players and minecarts to get off if(contact && !(conveyorTile.getWorld().getTileEntity(conveyorTile.getPos().add(0, 1, 0)) instanceof IConveyorTile)) vY *= 2.25; return new Vec3d(vX, vY, vZ); } @Override public void onEntityCollision(TileEntity tile, Entity entity, EnumFacing facing) { if(!isActive(tile)) return; BlockPos posWall = tile.getPos().offset(facing); double d = .625 + entity.width; double distToWall = Math.abs((facing.getAxis() == Axis.Z ? posWall.getZ() : posWall.getX()) + .5 - (facing.getAxis() == Axis.Z ? entity.posZ : entity.posX)); if(distToWall > d) { super.onEntityCollision(tile, entity, facing); return; } if(entity != null && !entity.isDead && !(entity instanceof EntityPlayer && entity.isSneaking())) { double distY = Math.abs(tile.getPos().add(0, 1, 0).getY() + .5 - entity.posY); double treshold = .9; boolean contact = distY < treshold; entity.onGround = false; if(entity.fallDistance < 3) entity.fallDistance = 0; else entity.fallDistance *= .9; Vec3d vec = getDirection(tile, entity, facing); entity.motionX = vec.xCoord; entity.motionY = vec.yCoord; entity.motionZ = vec.zCoord; if(!contact) ConveyorHandler.applyMagnetSupression(entity, (IConveyorTile) tile); else { BlockPos posTop = tile.getPos().add(0, 1, 0); if(!((tile.getWorld().getTileEntity(posTop) instanceof IConveyorTile) || (tile.getWorld().isAirBlock(posTop) && (tile.getWorld().getTileEntity(posTop.offset(facing)) instanceof IConveyorTile)))) ConveyorHandler.revertMagnetSupression(entity, (IConveyorTile) tile); } if(entity instanceof EntityItem) { ((EntityItem) entity).setNoDespawn(); TileEntity inventoryTile; inventoryTile = tile.getWorld().getTileEntity(tile.getPos().add(0, 1, 0)); if(!tile.getWorld().isRemote) { if(contact && inventoryTile != null && !(inventoryTile instanceof IConveyorTile)) { ItemStack stack = ((EntityItem) entity).getEntityItem(); if(stack != null) { ItemStack ret = Utils.insertStackIntoInventory(inventoryTile, stack, EnumFacing.DOWN); if(ret == null) entity.setDead(); else if(ret.stackSize < stack.stackSize) ((EntityItem) entity).setEntityItemStack(ret); } } } } } } static AxisAlignedBB[] verticalBounds = {new AxisAlignedBB(0, 0, 0, 1, 1, .125f), new AxisAlignedBB(0, 0, .875f, 1, 1, 1), new AxisAlignedBB(0, 0, 0, .125f, 1, 1), new AxisAlignedBB(.875f, 0, 0, 1, 1, 1)}; @Override public List<AxisAlignedBB> getSelectionBoxes(TileEntity tile, EnumFacing facing) { ArrayList list = new ArrayList(); if(facing.ordinal() > 1) list.add(verticalBounds[facing.ordinal() - 2]); if(renderBottomBelt(tile, facing) || list.isEmpty()) list.add(conveyorBounds); return list; } @Override public List<AxisAlignedBB> getColisionBoxes(TileEntity tile, EnumFacing facing) { ArrayList list = new ArrayList(); if(facing.ordinal() > 1) list.add(verticalBounds[facing.ordinal() - 2]); if(renderBottomBelt(tile, facing) || list.isEmpty()) list.add(conveyorBounds); return list; } @Override @SideOnly(Side.CLIENT) public Matrix4f modifyBaseRotationMatrix(Matrix4f matrix, TileEntity tile, EnumFacing facing) { return new Matrix4(matrix).translate(0, 1, 0).rotate(Math.PI / 2, 1, 0, 0).toMatrix4f(); } public static ResourceLocation texture_on = new ResourceLocation("immersiveengineering:blocks/conveyor_vertical"); public static ResourceLocation texture_off = new ResourceLocation("immersiveengineering:blocks/conveyor_vertical_off"); @Override public ResourceLocation getActiveTexture() { return texture_on; } @Override public ResourceLocation getInactiveTexture() { return texture_off; } @Override @SideOnly(Side.CLIENT) public List<BakedQuad> modifyQuads(List<BakedQuad> baseModel, @Nullable TileEntity tile, EnumFacing facing) { if(tile != null && this.renderBottomBelt(tile, facing)) { TextureAtlasSprite sprite = ClientUtils.getSprite(isActive(tile) ? ConveyorBasic.texture_on : ConveyorBasic.texture_off); TextureAtlasSprite spriteColour = ClientUtils.getSprite(getColouredStripesTexture()); boolean[] walls = {super.renderWall(tile, facing, 0), super.renderWall(tile, facing, 1)}; baseModel.addAll(ModelConveyor.getBaseConveyor(facing, .875f, new Matrix4(facing), ConveyorDirection.HORIZONTAL, sprite, walls, new boolean[]{true, false}, spriteColour, getDyeColour())); } return baseModel; } }