Помогите EntityID++

Статус
Закрыто для дальнейших ответов.

Stamorey

Активный участник
Пользователь
Баллы
76
Имя в Minecraft
Stamorey
Spigot 1.8
В общем, при спавне Entity ему дается уникальный id. Следующему заспавненном мобу id+1 и так далее, даже если моб умирает, этот id навсегда остается за ним(до рестарта), и другой моб с тем же id уже не заспавнится...
Нужно как-то вручную увеличить этот итератор, чтобы одно или несколько его значений были пропущены.

То есть, например есть id последнего заспавненного Entity - 30. Нужно пропустить одно или несколько следующих id , не давая серверу зарегистрировать моба c несколькими следующими id (31 32...).

(эти id нужны мне для отправки пакетов о спавне мобов, которых на самом деле нет)

Пока вижу два способа решения:

1. Сделать свой итератор, и начать его не с нуля, а например с 100 000, но все может быть, вдруг entity на сервере окажется больше 100 000 и тогда все будет очень плохо.

2. Спавнить entity, сразу же его убивать setHealth(0) например, использовать этот id для своих нужд, но в таком случае появится лишняя нагрузка на сервер, + игроку будет отправлять сразу два пакета спавна - от сервера и мой. (Пробовал спавнить моба под игроком в 1к блоков, все равно пакет отсылается, можно еще попробовать по X или У на 1к от игрока спавнить его, но если не ошибаюсь так будут грузиться чанки.)

Можно ли решить проблему без этих костылей? Заранее спасибо за ответ.)

Решение:
С помощью рефлексии достаем нужную переменную и увеличиваем её(в данном примере на 1)
JavaScript:
Field fieldZ = Entity.class.getDeclaredField("entityCount");
                fieldZ.setAccessible(true);
                fieldZ.setInt((CraftPlayer)p, fieldZ.getInt((CraftPlayer)p)+1);
                int z = fieldZ.getInt((CraftPlayer)p);
                p.sendMessage("ID: "+z);
//Последние две строки для проверки.
// Вместо (CraftPlayer)p можно было брать любой
// другой экземпляр наследника Entity, но мне было
//удобнее так.
Создаем ентити, который не спавнится в мире, но счетчик увеличится, возможно этого ентити как-то придется удалить, да и вообще лучше пользоваться первым способом.
JavaScript:
EntityArrow entityA = new EntityArrow(((CraftWorld) p.getWorld()).getHandle());
 
Последнее редактирование:
Мои знания основываются на 1.7.10, но думаю, что для 1.8.8 тоже подойдёт. Есть два варианта:
  1. Через рефлексию лезем в NMS Entity и просто выставляем нужное значение счётчику (он, вроде, private static int).
  2. Просто создаём нужное кол-во экземпляров NMS Entity. Это увеличит счётчик, но спавниться никто не будет.
 
Мои знания основываются на 1.7.10, но думаю, что для 1.8.8 тоже подойдёт. Есть два варианта:
  1. Через рефлексию лезем в NMS Entity и просто выставляем нужное значение счётчику (он, вроде, private static int).
  2. Просто создаём нужное кол-во экземпляров NMS Entity. Это увеличит счётчик, но спавниться никто не будет.
хм по второму, то есть всего-то надо написать Entity namechetotam; и.. этого хватит? Пойду проверять, я думал сервер где-то в недрах обработчика моба увеличивает его,
И по второму.. встречал статические переменные только в теории, но .. ни разу не встречал на практике)
Если я не ошибаюсь, эта переменная общая для всех экземпляров класса...?
 
  1. Entity entity = new Entity(world);
    Правда, Entity - абстрактный класс, так что просто создать его экземпляр не получится, но можно использовать любых его потомков (например, new EntityArrow(world)).
  2. Да, общая для всех экземпляров.
 
Вроде сделял с помощью рефлексий, но хотел бы увидеть как можно это сделать с помощью
EntityArrow entityA = new EntityArrow(world));
Так как очень долго мучался с параметром (world) , обычный p.getWorld() не принимает, пытался его кастовать к CraftWorld, компилятор перестает ругаться, а вот в консоли ошибки, так же пробовал кастовать в другой World.
Код:
Field fieldZ = Entity.class.getDeclaredField("entityCount");
                fieldZ.setAccessible(true);
                fieldZ.setInt((CraftPlayer)p, fieldZ.getInt((CraftPlayer)p)+1);
                int z = fieldZ.getInt((CraftPlayer)p);
                p.sendMessage("ID: "+z);
//Последние две строки для проверки.
// Вместо (CraftPlayer)p можно было брать любой
// другой экземпляр наследника Entity, но мне было
//удобнее так.
 
Java:
EntityArrow entityA = new EntityArrow(world));
entityA.remove();

Все. он создает экземпляр стрелы => счетчик прибавится, после этого стрела удаляется в этот же тик.
 
Java:
EntityArrow entityA = new EntityArrow(world));
entityA.remove();

Все. он создает экземпляр стрелы => счетчик прибавится, после этого стрела удаляется в этот же тик.
Что подставить вместо world ?
Перепробовал уже много способов, написал же, в обертке два класса World, и тот который требуется не понимаю где можно взять...
Bukkit.getServer().getWorld("world"); не подходит
Player p; p.getWorld(); не подходит
Знаю как минимум два способа получить World, но они возвращают вот этот класс:
import org.bukkit.World;

Но для EntityArrow entityA =new EntityArrow(world));
нужен этот:
import net.minecraft.server.v1_8_R1.World;
Чет слишком изи было -_-

Entity ggwp = (Entity)p;
EntityArrow entityA = new EntityArrow(ggwp.getWorld());
Тут уже как раз возвращается нужный класс. ggwp.getWorld()
А нет, проблема все еще осталась, сервер выдает ошибку, нельзя кастовать так
Entity ggwp = (Entity)p;
 
Точно, могу скинуть что пишет консоль.
Ошибся, EntityArrow entityA = new EntityArrow( (CraftWorld)(p.getWorld()) );
Такой код в иде подчеркивается, написано CrafftWorld cannot be converted to World

А на это выдает ошибку консоль:
Entity ggwp = (Entity)p;
CraftPlayer cannot br cast to Entity
 
Последнее редактирование:
((CraftWorld) world).getHandle()
Помогло, спасибо большое)
EntityArrow entityA = new EntityArrow(((CraftWorld) p.getWorld()).getHandle());
Но все же лучше первым способом, если как писал Fenix78563 надо удалять entity,
то у меня даже нет такого метода ) entityA.remove();
 
Последнее редактирование:
Статус
Закрыто для дальнейших ответов.
Назад
Верх