/** * Copyright (c) Lambda Innovation, 2013-2015 * 本作品版权由Lambda Innovation所有。 * http://www.li-dev.cn/ * <p/> * This project is open-source, and it is distributed under * the terms of GNU General Public License. You can modify * and distribute freely as long as you follow the license. * 本项目是一个开源项目,且遵循GNU通用公共授权协议。 * 在遵照该协议的情况下,您可以自由传播和修改。 * http://www.gnu.org/licenses/gpl.html */ package cn.liutils.util.mc; import cn.liutils.util.mc.EntitySelectors.SelectorList; import com.google.common.base.Predicate; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.MathHelper; import net.minecraft.util.Vec3; import net.minecraft.world.World; import java.util.ArrayList; import java.util.List; /** * Utils about block/entity lookup and interaction. * @author WeAthFolD */ public class WorldUtils { public static AxisAlignedBB getBoundingBox(Vec3 vec1, Vec3 vec2) { double minX = 0.0, minY = 0.0, minZ = 0.0, maxX = 0.0, maxY = 0.0, maxZ = 0.0; if (vec1.xCoord < vec2.xCoord) { minX = vec1.xCoord; maxX = vec2.xCoord; } else { minX = vec2.xCoord; maxX = vec1.xCoord; } if (vec1.yCoord < vec2.yCoord) { minY = vec1.yCoord; maxY = vec2.yCoord; } else { minY = vec2.yCoord; maxY = vec1.yCoord; } if (vec1.zCoord < vec2.zCoord) { minZ = vec1.zCoord; maxZ = vec2.zCoord; } else { minZ = vec2.zCoord; maxZ = vec1.zCoord; } return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); } /** * Return a minimum AABB that can hold the points given. */ public static AxisAlignedBB ofPoints(Vec3... points) { if (points.length == 0) { throw new RuntimeException("Invalid call: too few vectors"); } AxisAlignedBB ret = new AxisAlignedBB( points[0].xCoord, points[0].yCoord, points[0].zCoord, points[0].xCoord, points[0].yCoord, points[0].zCoord); double[] aabbData = new double[6]; for (int i = 1; i < points.length; ++i) { if (ret.minX > points[i].xCoord) aabbData[0] = points[i].xCoord; if (ret.maxX < points[i].xCoord) aabbData[3] = points[i].xCoord; if (ret.minY > points[i].yCoord) aabbData[1] = points[i].yCoord; if (ret.maxY < points[i].yCoord) aabbData[4] = points[i].yCoord; if (ret.minZ > points[i].zCoord) aabbData[2] = points[i].zCoord; if (ret.maxZ < points[i].zCoord) aabbData[5] = points[i].zCoord; } return new AxisAlignedBB(aabbData[0], aabbData[1], aabbData[2], aabbData[3], aabbData[4], aabbData[5]); } public static List<BlockPos> getBlocksWithin(Entity entity, double range, int max, IBlockFilter... filters) { return getBlocksWithin(entity.worldObj, entity.posX, entity.posY, entity.posZ, range, max, filters); } public static List<BlockPos> getBlocksWithin(TileEntity te, double range, int max, IBlockFilter... filters) { return getBlocksWithin(te.getWorld(), te.getPos().getX() + 0.5, te.getPos().getY() + 0.5, te.getPos().getZ() + 0.5, range, max, filters); } public static List<BlockPos> getBlocksWithin( World world, final double x, final double y, final double z, double range, int max, IBlockFilter... filter) { IBlockFilter[] fs = new IBlockFilter[filter.length + 1]; for (int i = 0; i < filter.length; ++i) fs[i] = filter[i]; final double rangeSq = range * range; fs[filter.length] = new IBlockFilter() { @Override public boolean accepts(World world, int xx, int yy, int zz, Block block) { double dx = xx - x, dy = yy - y, dz = zz - z; return dx * dx + dy * dy + dz * dz <= rangeSq; } }; int minX = MathHelper.floor_double(x - range), minY = MathHelper.floor_double(y - range), minZ = MathHelper.floor_double(z - range), maxX = MathHelper.ceiling_double_int(x + range), maxY = MathHelper.ceiling_double_int(y + range), maxZ = MathHelper.ceiling_double_int(z + range); return getBlocksWithin(world, minX, minY, minZ, maxX, maxY, maxZ, max, fs); } /** * WARNING: Not supported multi worlds */ public static List<BlockPos> getBlocksWithin( World world, int minX, int minY, int minZ, int maxX, int maxY, int maxZ, int max, IBlockFilter... filter) { List<BlockPos> ret = new ArrayList(); for (int x = minX; x <= maxX; ++x) { for (int y = minY; y <= maxY; ++y) { for (int z = minZ; z <= maxZ; ++z) { boolean match = true; for (IBlockFilter f : filter) { if (!f.accepts(world, x, y, z, world.getBlockState(new BlockPos(x, y, z)).getBlock())) { match = false; break; } } if (match) { ret.add(new BlockPos(x, y, z)); if (ret.size() == max) return ret; } } } } return ret; } public static List<Entity> getEntities(TileEntity te, double range, Predicate filter) { return getEntities(te.getWorld(), te.getPos().getX() + 0.5, te.getPos().getY() + 0.5, te.getPos().getZ() + 0.5, range, filter); } public static List<Entity> getEntities(Entity ent, double range, Predicate filter) { return getEntities(ent.worldObj, ent.posX, ent.posY, ent.posZ, range, filter); } public static List<Entity> getEntities(World world, double x, double y, double z, double range, Predicate filter) { AxisAlignedBB box = new AxisAlignedBB( x - range, y - range, z - range, x + range, y + range, z + range); SelectorList list = new SelectorList(filter, new EntitySelectors.RestrictRange(x, y, z, range)); return getEntities(world, box, list); } public static List<Entity> getEntities(World world, AxisAlignedBB box, Predicate filter) { return world.func_175674_a(null, box, filter); } }