简体   繁体   English

获取附近实体的最佳方法

[英]Best way to get nearby entities

I've pondered over this problem for a long time, and was just wondering if there really was a better way to get nearby entities instead of looping through every entity in the world and testing their location? 我已经考虑了很长时间了,只是想知道是否真的有更好的方法来获取附近的实体,而不是遍历世界上的每个实体并测试其位置?

For the plugin I'm developing, I'm using this every tick and in no way at all is it efficient. 对于我正在开发的插件,我在每一刻都在使用它,根本没有效率。

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;
}

I don't have access to a player object so player.getNearbyEntities() isn't really an option (and I don't know if that is any better, either). 我没有访问播放器对象的权限,所以player.getNearbyEntities()并不是一个真正的选择(我也不知道这样做是否更好)。 I did wonder if location.getChunk().getEntities() would be any better to loop but again, I have no idea of the process behind that. 我确实想知道location.getChunk().getEntities()是否会更好地循环播放,但是再次,我不知道其背后的过程。 Could anyone share some insight with me as to what might be a better way to go about this effeciently ? 任何人都可以分享一些见解与我,什么可能是一个更好的方式去了解这个effeciently?

Thanks in advance. 提前致谢。

Under the hood, the getNearbyEntities() method from org.bukkit.entity.Entity loops through all relevant chunks, so I would assume doing that is faster than looping through every entity in the world. 引擎盖下,在getNearbyEntities()从法org.bukkit.entity.Entity遍历所有相关的块,所以我会认为这样做是不是通过世界上每一个实体循环更快。

Unfortunately, the NMS getEntities method (and even some methods it calls) that getNearbyEntities uses internally requires an Entity as its first argument. 不幸的是, getNearbyEntities内部使用的NMS getEntities方法(甚至它调用的某些方法)需要将Entity作为其第一个参数。 You could write your own method that takes your two parameters and mirrors the behavior of the NMS method. 您可以编写自己的方法,该方法带有两个参数并反映NMS方法的行为。

I don't know if I can post the exact source code of the NMS method here because of the Craftbukkit DMC takedown and the Stack Overflow rules, but the way I understand it the getEntities method takes an axis aligned bounding box, finds the chunks within that box and returns the entities in those chunks. 由于Craftbukkit DMC移除和Stack Overflow规则,我不知道是否可以在此发布NMS方法的确切源代码,但是据我了解, getEntities方法采用轴对齐的边界框,在其中找到了块该框并返回这些块中的实体。

Since you're using a sphere and not a box as a perimeter, I would initially use the box and then do a distance check to see whether the entities are really in the given sphere. 由于您使用的是一个球体而不是一个框作为周长,因此我将首先使用该框,然后进行距离检查以查看实体是否确实在给定的球体中。

Here is an example of what this might look like: 这是一个可能看起来像的示例:

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;
}

This method might still be slightly slower than using getNearbyEntities because I'm not sure whether calling the Bukkit methods used here for retrieving a Chunk and entities inside it is as efficient as directly calling the NMS methods like the getNearbyEntities method does. 此方法可能仍比使用getNearbyEntities慢一点,因为我不确定调用此处用于检索Chunk和其中的实体的getNearbyEntities方法是否像直接调用NMS方法(如getNearbyEntities方法一样)一样有效。

The getNearbyEntities method is also available for world objects! getNearbyEntities方法也可用于世界对象!

public static List<Entity> getEntitiesAroundPoint(Location location, double radius) {
    return location.getWorld().getNearbyEntities(location, radius, radius, radius);
}

But be aware that 'radius' is actually a cuboid area, not a spherical. 但是请注意,“半径”实际上是一个长方体区域,而不是球形区域。

If you want a spherical ara, you must loop through the chunks/entities in the current world and check: 如果要使用球形ara,则必须遍历当前世界中的块/实体并检查:

if (entityLoc.distanceSqared(radius * radius) <= radius) {

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 映射和查询此实体的最佳方法 - Best way to map and query this entities JPA 2 / Hibernate - 更新复杂实体的最佳方法? - JPA 2/Hibernate - Best way to update complex entities? EJB实体:更新单个列的最佳方式 - EJB entities: Best way to update a single column 在Spring Data JPA中处理实体继承的最佳方法 - Best way of handling entities inheritance in Spring Data JPA 在JPA中选择具有子实体的许多实体的最佳优化方法是什么? - What is the best optimized way to select many entities with subentities in JPA? 使用 QueryDsl、JPA 和 EclipseLink 更新实体列表的最佳方式 - Best way to update a list of entities with QueryDsl, JPA and EclipseLink 在Spring MVC中处理泛型实体的最佳方法(泛型,反射或其他)? - Best way of handling generic entities in Spring MVC(Generics, Reflection, or other)? 确保在StringTemplate中转义HTML实体的最佳方法是什么 - What is the best way to ensure HTML entities are escaped in StringTemplate 处理延迟加载的EJB JPA实体的JAX-WS代理对象的最佳方法是什么? - What's the best way to deal with JAX-WS proxy objects for EJB JPA entities that are Lazy Loaded? 从JDBC结果集中获取XML的最佳方法 - Best Way to get XML from a JDBC resultset
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM