Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Скрыть объявление

Помогите EntityID++

Тема в разделе "Разработка плагинов для новичков", создана пользователем Stamorey, 22 дек 2016.

Статус темы:
Закрыта.
  1. Автор темы
    Stamorey

    Stamorey Активный участник Пользователь

    Баллы:
    66
    Имя в 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)
    Код:
    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, но мне было
    //удобнее так.
    Создаем ентити, который не спавнится в мире, но счетчик увеличится, возможно этого ентити как-то придется удалить, да и вообще лучше пользоваться первым способом.
    Код:
    EntityArrow entityA = new EntityArrow(((CraftWorld) p.getWorld()).getHandle());
     
    Последнее редактирование: 24 дек 2016
  2. Хостинг MineCraft
    <
  3. gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    Мои знания основываются на 1.7.10, но думаю, что для 1.8.8 тоже подойдёт. Есть два варианта:
    1. Через рефлексию лезем в NMS Entity и просто выставляем нужное значение счётчику (он, вроде, private static int).
    2. Просто создаём нужное кол-во экземпляров NMS Entity. Это увеличит счётчик, но спавниться никто не будет.
     
  4. Автор темы
    Stamorey

    Stamorey Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Stamorey
    хм по второму, то есть всего-то надо написать Entity namechetotam; и.. этого хватит? Пойду проверять, я думал сервер где-то в недрах обработчика моба увеличивает его,
    И по второму.. встречал статические переменные только в теории, но .. ни разу не встречал на практике)
    Если я не ошибаюсь, эта переменная общая для всех экземпляров класса...?
     
  5. gamerforEA

    gamerforEA Старожил Пользователь

    Баллы:
    143
    Skype:
    sk2000sk1
    Имя в Minecraft:
    gamerforEA_MCPC
    1. Entity entity = new Entity(world);
      Правда, Entity - абстрактный класс, так что просто создать его экземпляр не получится, но можно использовать любых его потомков (например, new EntityArrow(world)).
    2. Да, общая для всех экземпляров.
     
  6. Автор темы
    Stamorey

    Stamorey Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Stamorey
    Вроде сделял с помощью рефлексий, но хотел бы увидеть как можно это сделать с помощью
    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, но мне было
    //удобнее так.
     
  7. Fenix78563

    Fenix78563 Активный участник Пользователь

    Баллы:
    76
    Имя в Minecraft:
    Blc_Dragon
    Код:
    EntityArrow entityA = new EntityArrow(world));
    entityA.remove();
    Все. он создает экземпляр стрелы => счетчик прибавится, после этого стрела удаляется в этот же тик.
     
  8. Автор темы
    Stamorey

    Stamorey Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Stamorey
    Что подставить вместо world ?
    Перепробовал уже много способов, написал же, в обертке два класса World, и тот который требуется не понимаю где можно взять...
    Bukkit.getServer().getWorld("world"); не подходит
    Player p; p.getWorld(); не подходит[DOUBLEPOST=1482518515,1482517977][/DOUBLEPOST]Знаю как минимум два способа получить World, но они возвращают вот этот класс:
    import org.bukkit.World;

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

    Entity ggwp = (Entity)p;
    EntityArrow entityA = new EntityArrow(ggwp.getWorld());
    Тут уже как раз возвращается нужный класс. ggwp.getWorld()[DOUBLEPOST=1482519462][/DOUBLEPOST]А нет, проблема все еще осталась, сервер выдает ошибку, нельзя кастовать так
    Entity ggwp = (Entity)p;
     
  9. slavik123123123

    slavik123123123 Старожил Пользователь

    Баллы:
    143
    Имя в Minecraft:
    Leymooooooooooo
    Точно (CraftWorld) world не подходит?
     
  10. Автор темы
    Stamorey

    Stamorey Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Stamorey
    Точно, могу скинуть что пишет консоль.
    Ошибся, EntityArrow entityA = new EntityArrow( (CraftWorld)(p.getWorld()) );
    Такой код в иде подчеркивается, написано CrafftWorld cannot be converted to World

    А на это выдает ошибку консоль:
    Entity ggwp = (Entity)p;
    CraftPlayer cannot br cast to Entity
     
    Последнее редактирование: 23 дек 2016
  11. slavik123123123

    slavik123123123 Старожил Пользователь

    Баллы:
    143
    Имя в Minecraft:
    Leymooooooooooo
    ((CraftWorld) world).getHandle()
     
  12. Автор темы
    Stamorey

    Stamorey Активный участник Пользователь

    Баллы:
    66
    Имя в Minecraft:
    Stamorey
    Помогло, спасибо большое)
    EntityArrow entityA = new EntityArrow(((CraftWorld) p.getWorld()).getHandle());
    Но все же лучше первым способом, если как писал Fenix78563 надо удалять entity,
    то у меня даже нет такого метода ) entityA.remove();
     
    Последнее редактирование: 23 дек 2016
Статус темы:
Закрыта.

Поделиться этой страницей