Помогите Лучший вариант getNearbyEntities

Exception_Prototype

Активный участник
Пользователь
Баллы
96
Всё таки и я задался вопросов о максимально лучшем варианте получения живности вокруг в указанном радиусе.
Нашёл код ниже здесь. Хотелось бы узнать мнение знающих людей, а частности очень интересует мнение @AtomicInteger, ибо он очень часто упоминал о доработке стандартного getNearbyEntities().
Java:
    public static List<Entity> getEntitiesAroundPoint(Location location, double radius) {
        List<Entity> entities = new ArrayList<>();
        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;
    }
Единственно IDE ругается на MathHelper.floor, чё это такое?
А всё, нашёл https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/MathHelper.java
 
Последнее редактирование:
вообще в яве есть Math.floor - округление до ближайшего наименьшего целого числа.
класс MathHelper вообще первый раз вижу
https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/MathHelper.java
Собственно провёл тесты:
"Родной" метод быстрей метода выше при маленьких радиуса на 1-2 секунды.
Но когда радиус был установлен типа 300000, то метод выше оказался быстрей на секунду.
Крч я хз.
 
https://github.com/Bukkit/mc-dev/blob/master/net/minecraft/server/MathHelper.java
Собственно провёл тесты:
"Родной" метод быстрей метода выше при маленьких радиуса на 1-2 секунды.
Но когда радиус был установлен типа 300000, то метод выше оказался быстрей на секунду.
Крч я хз.
Конечно быстрее, ибо он кубический.
P.s могу поделится своим извращением, рисовал от нефиг делать. :D

Java:
    Collection<Entity> test(Player p) {
        Location loc = p.getLocation().add(0,1.5,0);
        Collection<Entity> nearbyEntites = new ArrayList<Entity>();
        for(int i = 0;i<5; i++) {
            Vector durect = loc.getDirection().multiply(i);
            loc.add(durect);
            nearbyEntites.addAll(loc.getWorld().getNearbyEntities(loc, 1, 1, 1));
            nearbyEntites.remove(p);
            Iterator<Entity> it = nearbyEntites.iterator();
            while(it.hasNext()) {
                if(!(it.next() instanceof LivingEntity)) {
                    it.remove();
                }
            }
            if(nearbyEntites.size()!=0) {
                break;
            }
        }
        return nearbyEntites;
    }
 
Касаемо самого метода getNearbyEntities, метод достаточно хорош, на тех условиях, что никаких ограничений мы терпеть не собираемся.Конечно, метод достаточно ресурсозатратный, поэтому где можно, от его использования стоит отказаться.Если всё же, частого использования этого метода не избежать, но можно потерпеть некоторые ограничения, то стоит написать свой.Можно достать ключевые методы получения сущности из nms, написать свой метод просчёта координат, не учитывая координату Y.Можно сделать радиус не блочный, а чанковый.То есть, получать всех сущностей в чанке, не учитывая блочное расстояние.В методе выше, например, получают всех сущностей в чанке, но отсекают по радиусу, если для нас это не критично, то можно убрать.Опять таки, нужно терпеть разные ограничения, если это возможно.Изменив где-то в коде double на float, ситуация кардинально не изменится.Как пример, Влад в своем ядре UltraMineCore переписал алгоритм спавна животных, что позволило существенно снизить нагрузку на сервер, но, животные под крышей не спавнились.На счёт тестов, стоит учитывать то, что JIT имеет одну неприятную особенность - холодный старт.То есть, при первой итерации метода, время выполнения обычно больше, чем при последующих.Я не уверен, что холодный старт играет тут какую-либо роль, но на всякий случай стоит провести несколько итераций и вычислить среднее(с учётом первой итерации или без).На днях соберу несколько вариантов аналога с разных источников, накидаю своих(возможно даже на основе найденных) и проведу поверхностные тесты, о результатах сообщу в этой теме.
 
Java:
public static Set<Entity> getEntitiesNearLocation(Location center, int radius) 
{
    Set<Entity> entities = new HashSet<> ();

    for (Entity entity : center.getWorld().getEntities()) 
    {
        if (isEntityInRadius(center, radius, entity))
        {
            entities.add(entity);
        }
    }

    return entities;
}

public static boolean isEntityInRadius(Location center, double radius, Entity entity) 
{
    return isInRadius(center, entity.getLocation(), radius);
}

public static boolean isInRadius(Location center, Location loc, double radius) 
{
    if (!loc.getWorld().equals(center.getWorld())) 
    {
        return false;
    }

    return center.distanceSquared(loc) <= (radius * radius);
}
 
Назад
Верх