Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 获取附近实体的最佳方法_Java_Minecraft_Bukkit - Fatal编程技术网

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
内部使用的NMS
getEntities
方法(甚至它调用的一些方法)需要一个
实体作为其第一个参数。您可以编写自己的方法,该方法采用两个参数并反映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) {