package eiteam.esteemedinnovation.commons.util; import com.google.common.collect.ImmutableList; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemTool; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ChunkCache; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.util.Random; public class WorldHelper { /** * @param random Random object * @return A random value of North, South, East, or West. Like {@link EnumFacing#random(Random)} but does not include * up and down. */ public static EnumFacing randomHorizontal(Random random) { return EnumFacing.HORIZONTALS[random.nextInt(EnumFacing.HORIZONTALS.length)]; } /** * Handles the rotation of a block correctly. If it is already facing the provided direction, then it will flip it. * @param property The property to get the current facing direction from and to set the new one in. * @param world The world. * @param state The block's blockstate. * @param pos The position of the block in the world. * @param tryDir The direction to rotate to (or its opposite). */ public static void rotateProperly(IProperty<EnumFacing> property, World world, IBlockState state, BlockPos pos, EnumFacing tryDir) { EnumFacing currentFacing = state.getValue(property); EnumFacing newFacing = currentFacing == tryDir ? tryDir.getOpposite() : tryDir; world.setBlockState(pos, state.withProperty(property, newFacing)); } /** * Overload for getDirectionalBoundingBox using a base AABB instead of a bunch of floats. * @param dir The direction the block is facing * @param base The base AxisAlignedBB * @param allowsUpDown Whether it allows vertical rotation (facing UP or facing DOWN) * @return The rotated AABB. */ public static AxisAlignedBB getDirectionalBoundingBox(EnumFacing dir, AxisAlignedBB base, boolean allowsUpDown) { return getDirectionalBoundingBox(dir, (float) base.minX, (float) base.minY, (float) base.minZ, (float) base.maxX, (float) base.maxY, (float) base.maxZ, allowsUpDown); } /** * Gets an AxisAlignedBB according to the provided direction (rotation). * @param dir The direction * @param minX Minimum X for the AABB * @param minY Minimum Y * @param minZ Minimum Z * @param maxX Maximum X * @param maxY Maximum Y * @param maxZ Maximum Z * @param allowsUpDown Whether it allows vertical rotation (facing UP and facing DOWN) * @return The rotated AABB. */ public static AxisAlignedBB getDirectionalBoundingBox(EnumFacing dir, float minX, float minY, float minZ, float maxX, float maxY, float maxZ, boolean allowsUpDown) { switch (dir) { case NORTH: { return new AxisAlignedBB(1 - maxX, minY, 1 - maxZ, 1 - minX, maxY, 1 - minZ); } case SOUTH: { return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); } case EAST: { return new AxisAlignedBB(minZ, minY, minX, maxZ, maxY, maxX); } case WEST: { return new AxisAlignedBB(1 - maxZ, minY, 1 - maxX, 1 - minZ, maxY, 1 - minX); } case UP: { if (!allowsUpDown) { break; } return new AxisAlignedBB(minX, minZ, minY, maxX, maxZ, maxY); } case DOWN: { if (!allowsUpDown) { break; } return new AxisAlignedBB(minX, 1 - minZ, minY, maxX, 1 - maxZ, maxY); } } return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); } /** * Thread-safe world mutation-safe version of getTileEntity. This should be used in methods which might be called * on alternative threads, namely getActualState and getExtendedState. * @param world The world * @param pos The position * @return The tile entity in the position */ public static TileEntity getTileEntitySafely(IBlockAccess world, BlockPos pos) { return world instanceof ChunkCache ? ((ChunkCache) world).func_190300_a(pos, Chunk.EnumCreateEntityType.CHECK) : world.getTileEntity(pos); } // { x, y, z } relatively public static final int[][] EXTRA_BLOCKS_SIDE = { { 0, 1, -1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 0, -1 }, { 0, 0, 0 }, { 0, 0, 1 }, { 0, -1, 0 }, { 0, -1, 0 }, { 0, -1, 1 } }; public static final int[][] EXTRA_BLOCKS_FORWARD = { { -1, 1, 0 }, { 0, 1, 0 }, { 1, 1, 0 }, { -1, 0, 0 }, { 0, 0, 0 }, { 1, 0, 0 }, { -1, -1, 0 }, { 0, -1, 0 }, { 1, -1, 0 } }; public static final int[][] EXTRA_BLOCKS_VERTICAL = { { -1, 0, 1 }, { 0, 0, 1 }, { 1, 0, 1 }, { -1, 0, 0 }, { 0, 0, 0 }, { 1, 0, 0 }, { -1, 0, -1 }, { 0, 0, -1 }, { 1, 0, -1 } }; public static final int[][] EXTRA_BLOCKS_9_SIDE = { { 0, 4, -4 }, { 0, 4, -3 }, { 0, 4, -2 }, { 0, 4, -1 }, { 0, 4, 0 }, { 0, 4, 1 }, { 0, 4, 2 }, { 0, 4, 3 }, { 0, 4, 4 }, { 0, 3, -4 }, { 0, 3, -3 }, { 0, 3, -2 }, { 0, 3, -1 }, { 0, 3, 0 }, { 0, 3, 1 }, { 0, 3, 2 }, { 0, 3, 3 }, { 0, 3, 4 }, { 0, 2, -4 }, { 0, 3, -3 }, { 0, 2, -2 }, { 0, 2, -1 }, { 0, 2, 0 }, { 0, 2, 1 }, { 0, 2, 2 }, { 0, 2, 3 }, { 0, 2, 4 }, { 0, 1, -4 }, { 0, 2, -3 }, { 0, 1, -2 }, { 0, 1, -1 }, { 0, 1, 0 }, { 0, 1, 1 }, { 0, 1, 2 }, { 0, 1, 3 }, { 0, 1, 4 }, { 0, 0, -4 }, { 0, 0, -3 }, { 0, 0, -2 }, { 0, 0, -1 }, { 0, 0, 0 }, { 0, 0, 1 }, { 0, 0, 2 }, { 0, 0, 3 }, { 0, 0, 4 }, { 0, -1, -4 }, { 0, -1, -3 }, { 0, -1, -2 }, { 0, -1, -1 }, { 0, -1, 0 }, { 0, -1, 1 }, { 0, -1, 2 }, { 0, -1, 3 }, { 0, -1, 4 }, { 0, -2, -4 }, { 0, -2, -3 }, { 0, -2, -2 }, { 0, -2, -1 }, { 0, -2, 0 }, { 0, -2, 1 }, { 0, -2, 2 }, { 0, -2, 3 }, { 0, -2, 4 }, { 0, -3, -4 }, { 0, -3, -3 }, { 0, -3, -2 }, { 0, -3, -1 }, { 0, -3, 0 }, { 0, -3, 1 }, { 0, -3, 2 }, { 0, -3, 3 }, { 0, -3, 4 }, { 0, -4, -4 }, { 0, -4, -3 }, { 0, -4, -2 }, { 0, -4, -1 }, { 0, -4, 0 }, { 0, -4, 1 }, { 0, -4, 2 }, { 0, -4, 3 }, { 0, -4, 4 }, }; public static final int[][] EXTRA_BLOCKS_9_FORWARD = { { -4, 4, 0 }, { -3, 4, 0 }, { -2, 4, 0 }, { -1, 4, 0 }, { 0, 4, 0 }, { 1, 4, 0 }, { 2, 4, 0 }, { 3, 4, 0 }, { 4, 4, 0 }, { -4, 3, 0 }, { -3, 3, 0 }, { -2, 3, 0 }, { -1, 3, 0 }, { 0, 3, 0 }, { 1, 3, 0 }, { 2, 3, 0 }, { 3, 3, 0 }, { 4, 3, 0 }, { -4, 2, 0 }, { -3, 2, 0 }, { -2, 2, 0 }, { -1, 2, 0 }, { 0, 2, 0 }, { 1, 2, 0 }, { 2, 2, 0 }, { 3, 2, 0 }, { 4, 2, 0 }, { -4, 1, 0 }, { -3, 1, 0 }, { -2, 1, 0 }, { -1, 1, 0 }, { 0, 1, 0 }, { 1, 1, 0 }, { 2, 1, 0 }, { 3, 1, 0 }, { 4, 1, 0 }, { -4, 0, 0 }, { -3, 0, 0 }, { -2, 0, 0 }, { -1, 0, 0 }, { 0, 0, 0 }, { 1, 0, 0 }, { 2, 0, 0 }, { 3, 0 , 0 }, { 4, 0, 0 }, { -4, -1, 0 }, { -3, -1, 0 }, { -2, -1, 0 }, { -1, -1, 0 }, { 0, -1, 0 }, { 1, -1, 0 }, { 2, -1, 0 }, { 3, -1, 0 }, { 4, -1, 0 }, { -4, -2, 0 }, { -3, -2, 0 }, { -2, -2, 0 }, { -1, -2, 0 }, { 0, -2, 0 }, { 1, -2, 0 }, { 2, -2, 0 }, { 3, -2, 0 }, { 4, -2, 0 }, { -4, -3, 0 }, { -3, -3, 0 }, { -2, -3, 0 }, { -1, -3, 0 }, { 0, -3, 0 }, { 1, -3, 0 }, { 2, -3, 0 }, { 3, -3, 0 }, { 4, -3, 0 }, { -4, -4, 0 }, { -3, -4, 0 }, { -2, -4, 0 }, { -1, -4, 0 }, { 0, -4, 0 }, { 1, -4, 0 }, { 2, -4, 0 }, { 3, -4, 0 }, { 4, -4, 0 }, }; public static final int[] [] EXTRA_BLOCKS_9_VERTICAL = { { -4, 0, 4 }, { -4, 0, 4 }, { -2, 0, 4 }, { -4, 0, 4 }, { 0, 0, 4 }, { 1, 0, 4 }, { 2, 0, 4 }, { 3, 0, 4 }, { 4, 0, 4}, { -4, 0, 3 }, { -3, 0, 3 }, { -2, 0, 3 }, { -3, 0, 3 }, { 0, 0, 3 }, { 1, 0, 3 }, { 2, 0, 3 }, { 3, 0, 3 }, { 4, 0, 3}, { -4, 0, 2 }, { -3, 0, 2 }, { -2, 0, 2 }, { -1, 0, 2 }, { 0, 0, 2 }, { 1, 0, 2 }, { 2, 0, 2 }, { 3, 0, 2 }, { 4, 0, 2 }, { -4, 0, 1 }, { -3, 0, 1 }, { -2, 0, 1 }, { -1, 0, 1 }, { 0, 0, 1 }, { 1, 0, 1 }, { 2, 0, 1 }, { 3, 0, 1 }, { 4, 0, 1 }, { -4, 0, 0 }, { -3, 0, 0 }, { -2, 0, 0 }, { -1, 0, 0 }, { 0, 0, 0 }, { 1, 0, 0 }, { 2, 0, 0 }, { 3, 0, 0 }, { 4, 0, 0 }, { -4, 0, -1 }, { -3, 0, -1 }, { -2, 0, -1 }, { -1, 0, -1 }, { 0, 0, -1 }, { 1, 0, -1 }, { 2, 0, -1 }, { 3, 0, -1 }, { 4, 0, -1 }, { -4, 0, -2 }, { -3, 0, -2 }, { -2, 0, -2 }, { -1, 0, -2 }, { 0, 0, -2 }, { 1, 0, -2 }, { 2, 0, -2 }, { 3, 0, -2 }, { 4, 0, -2 }, { -4, 0, -3 }, { -3, 0, -3 }, { -2, 0, -3 }, { -1, 0, -3 }, { 0, 0, -3 }, { 1, 0, -3 }, { 2, 0, -3 }, { 3, 0, -3 }, { 4, 0, -3 }, { -4, 0, -4 }, { -3, 0, -4 }, { -2, 0, -4 }, { -1, 0, -4 }, { 0, 0, -4 }, { 1, 0, -4 }, { 2, 0, -4 }, { 3, 0, -4 }, { 4, 0, -4 }, }; public static int[][] getExtraBlockCoordinates(EnumFacing sideHit) { return getExtraBlockCoordinates(sideHit.getIndex()); } public static int[][] getExtraBlockCoordinates(int sideHit) { switch (sideHit) { case 5: return EXTRA_BLOCKS_SIDE; case 4: return EXTRA_BLOCKS_SIDE; case 3: return EXTRA_BLOCKS_FORWARD; case 1: return EXTRA_BLOCKS_VERTICAL; case 0: return EXTRA_BLOCKS_VERTICAL; default: return EXTRA_BLOCKS_FORWARD; } } public static int[][] getExtraBlock9Coordinates(EnumFacing sideHit) { return getExtraBlockCoordinates(sideHit.getIndex()); } public static int[][] getExtraBlock9Coordinates(int sideHit) { switch (sideHit) { case 5: return EXTRA_BLOCKS_9_SIDE; case 4: return EXTRA_BLOCKS_9_SIDE; case 3: return EXTRA_BLOCKS_9_FORWARD; case 1: return EXTRA_BLOCKS_9_VERTICAL; case 0: return EXTRA_BLOCKS_9_VERTICAL; default: return EXTRA_BLOCKS_9_FORWARD; } } /** * This mines the extra blocks within the coordinate array. * @param coordinateArray The array of arrays containing the coordinates to add to x, y, z. * @param startPos The starting position * @param world The world. * @param tool The tool mining. * @param toolStack The ItemStack of the tool. * @param player The player mining. */ public static void mineExtraBlocks(int[][] coordinateArray, BlockPos startPos, World world, ItemTool tool, ItemStack toolStack, EntityPlayer player) { BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(startPos); for (int[] aCoordinateArray : coordinateArray) { int thisX = startPos.getX() + aCoordinateArray[0]; int thisY = startPos.getY() + aCoordinateArray[1]; int thisZ = startPos.getZ() + aCoordinateArray[2]; pos.setPos(thisX, thisY, thisZ); IBlockState state = world.getBlockState(pos); Block block = state.getBlock(); if (block != null && !world.isAirBlock(pos) && tool.canHarvestBlock(state, toolStack)) { // world.spawnParticle("") // world.func_147480_a(thisX, thisY, thisZ, false); world.setBlockToAir(pos); block.harvestBlock(world, player, pos, state, world.getTileEntity(pos), toolStack); } } } public static final ImmutableList<Material> LEAF_MATERIALS = new ImmutableList.Builder<Material>() .add(Material.LEAVES) .add(Material.CORAL) .add(Material.CRAFTED_SNOW) .add(Material.PLANTS) .build(); /** * Returns whether the block can be blown by the leaf blower. * @param block The block * @param world The world * @param pos The block's position * @return Whether the leaf blower should blow this block away. */ public static boolean isLeaves(Block block, World world, BlockPos pos) { IBlockState state = world.getBlockState(pos); return (OreDictHelper.listHasItem(OreDictHelper.leaves, Item.getItemFromBlock(block)) || block.isLeaves(state, world, pos) || LEAF_MATERIALS.contains(block.getMaterial(state))); } /** * Gets whether the block can be tilled into farmland. * @param block The block to check * @return True if it is dirt or grass, else false. */ public static boolean isFarmable(Block block) { return (block != null && (block == Blocks.DIRT || block == Blocks.GRASS)); } }