Java 获取附近实体的最佳方法
我对这个问题思考了很长时间,只是想知道是否真的有更好的方法来获取附近的实体,而不是在世界上的每个实体中循环并测试它们的位置 对于我正在开发的插件,我每一次都在使用它,但它根本没有效率Java 获取附近实体的最佳方法,java,minecraft,bukkit,Java,Minecraft,Bukkit,我对这个问题思考了很长时间,只是想知道是否真的有更好的方法来获取附近的实体,而不是在世界上的每个实体中循环并测试它们的位置 对于我正在开发的插件,我每一次都在使用它,但它根本没有效率 public static List<Entity> getEntitiesAroundPoint(Location location, double radius) { List<Entity> entities = new ArrayList<Entity>();
public static List<Entity> getEntitiesAroundPoint(Location location, double radius) {
List<Entity> entities = new ArrayList<Entity>();
for (Entity entity : location.getWorld().getEntities()) {
if (entity.getWorld() != location.getWorld()) {
continue;
} else if (entity instanceof Player && ((Player) entity).getGameMode().equals(GameMode.SPECTATOR)) {
continue; //Don't want spectators
} else if (entity.getLocation().distanceSquared(location) <= radius * radius) {
entities.add(entity);
}
}
return entity;
}
公共静态列表getEntitiesAroundPoint(位置,双半径){
列表实体=新的ArrayList();
对于(实体:location.getWorld().getEntities()){
if(entity.getWorld()!=location.getWorld()){
继续;
}else if(Player的实体实例&((Player)entity).getGameMode().equals(GameMode.cobservator)){
继续;//不要观众
}否则,如果(entity.getLocation().distanceSquared(location)在引擎盖下,来自org.bukkit.entity.entity
的getNearbyEntities()
方法会在所有相关的块中循环,因此我假设这样做比在世界上的每个实体中循环更快
不幸的是,getNearbyEntities
内部使用的NMSgetEntities
方法(甚至它调用的一些方法)需要一个实体作为其第一个参数。您可以编写自己的方法,该方法采用两个参数并反映NMS方法的行为
由于Craftbukkit DMC的删除和堆栈溢出规则,我不知道是否可以在这里发布NMS方法的确切源代码,但据我所知,getEntities
方法采用一个轴对齐的边界框,在该框中查找块并返回这些块中的实体
因为您使用的是球体而不是长方体作为周长,所以我首先使用长方体,然后进行距离检查,以查看实体是否确实位于给定的球体中
下面是一个可能的示例:
public static List<Entity> getEntitiesAroundPoint(Location location, double radius) {
List<Entity> entities = new ArrayList<Entity>();
World world = location.getWorld();
// To find chunks we use chunk coordinates (not block coordinates!)
int smallX = MathHelper.floor((location.getX() - radius) / 16.0D);
int bigX = MathHelper.floor((location.getX() + radius) / 16.0D);
int smallZ = MathHelper.floor((location.getZ() - radius) / 16.0D);
int bigZ = MathHelper.floor((location.getZ() + radius) / 16.0D);
for (int x = smallX; x <= bigX; x++) {
for (int z = smallZ; z <= bigZ; z++) {
if (world.isChunkLoaded(x, z)) {
entities.addAll(Arrays.asList(world.getChunkAt(x, z).getEntities())); // Add all entities from this chunk to the list
}
}
}
// Remove the entities that are within the box above but not actually in the sphere we defined with the radius and location
// This code below could probably be replaced in Java 8 with a stream -> filter
Iterator<Entity> entityIterator = entities.iterator(); // Create an iterator so we can loop through the list while removing entries
while (entityIterator.hasNext()) {
if (entityIterator.next().getLocation().distanceSquared(location) > radius * radius) { // If the entity is outside of the sphere...
entityIterator.remove(); // Remove it
}
}
return entities;
}
公共静态列表getEntitiesAroundPoint(位置,双半径){
列表实体=新的ArrayList();
World=location.getWorld();
//为了找到块,我们使用块坐标(不是块坐标!)
int smallX=MathHelper.floor((location.getX()-radius)/16.0D);
int bigX=MathHelper.floor((location.getX()+radius)/16.0D);
int smallZ=MathHelper.floor((location.getZ()-radius)/16.0D);
int bigZ=MathHelper.floor((location.getZ()+radius)/16.0D);
对于(int x=smallX;x radius*radius){//如果实体位于球体外部。。。
entityIterator.remove();//删除它
}
}
返回实体;
}
此方法可能仍然比使用getNearbyEntities
稍慢,因为我不确定调用此处用于检索Chunk
及其内部实体的Bukkit方法是否与直接调用NMS方法(如getNearbyEntities
方法)一样有效。getNearbyEntities方法也可用于世界对象!
公共静态列表getEntitiesAroundPoint(位置,双半径){
返回location.getWorld().getNearbyEntities(位置、半径、半径、半径);
}
但请注意,“半径”实际上是一个长方体区域,而不是一个球体
如果需要球形ara,则必须循环当前世界中的块/实体并检查:
if (entityLoc.distanceSqared(radius * radius) <= radius) {
if(entityLoc.distanceSqared(radius*radius)有趣的是,这将时间减少到了我的基本测试服务器上的十分之一,这太神奇了。感谢堆!亲爱的,我没想到它会工作得那么好,很高兴它起到了作用!
if (entityLoc.distanceSqared(radius * radius) <= radius) {