1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

Стартап Сравниваем инвентари.

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

  1. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Всем доброго времени суток. Разговор будет о том, как сравнивать разные инвентари.

    Очень часто, я начал видеть такую картину:
    Код:
        @EventHandler
        public void onInventoryClickEvent(InventoryClickEvent event) {
            if (event.getClickedInventory().getName().equals("...")) {
              
            }
        }
    Это не плохо, но есть свои нюансы... К примеру, ты в своем плагине создал инвентарь с именем "Супер-Пупер-Инвентарь", и некий Вася создал такой же инвентарь. Игрок нажал по слоту и вам пришел ивент с нажатием по слоту. Далее вы начинаете обрабатывать его. У Васи по нажатию на первый слот игрок немедленно будет забанен, а у тебя выдается деревянный меч. В это и проблема...

    Чтобы этого избежать, я покажу 2 способа сравнения.

    1) При создании инвентаря есть один параметр (InventoryHolder), его обычно ставят "null", но мы его и будем использовать.

    Создадим новый класс с названием "MyCustomInventory" и скажем ему, что он реализует интерфейс InventoryHolder.
    Код:
    import org.*********ventory.InventoryHolder;
    
    public class MyCustomInventory implements InventoryHolder {
    
    }
    Далее нам нужно реализовать один метод интерфейса "InventoryHolder".
    Код:
    import org.*********ventory.Inventory;
    import org.*********ventory.InventoryHolder;
    
    public class MyCustomInventory implements InventoryHolder {
    
        @Override
        public Inventory getInventory() {
            return null;
        }
      
    }
    В это методе нужно вернуть наш инвентарь. Создаем конструктор для нашего инвентаря, который будет принимать 2 параметра: int rows (кол-во рядов в инвентаре) и String title (название инвентаря).
    В конструкторе создаем инвентарь. В качестве параметра "owner", мы передаем "this", то есть мы создатель инвентаря. Также нужно умножить кол-во рядов на 9.
    Код:
    import org.bukkit.Bukkit;
    import org.*********ventory.Inventory;
    import org.*********ventory.InventoryHolder;
    
    public class MyCustomInventory implements InventoryHolder {
    
        private final Inventory inventory;
    
        public MyCustomInventory(int rows, String title) {
            this.inventory = Bukkit.createInventory(this, rows * 9, title);
        }
    
        @Override
        public Inventory getInventory() {
            return this.inventory;
        }
    
    }
    Также в этом классе создаем метод для обработки кликов.
    Код:
    public void onInventoryClick(InventoryClickEvent event) {
        // ...
    }
    После создания нашего инвентаря, займемся обработкой его.
    Создадим класс "InventoryListener" и скажем ему, что он реализует интерфейс "Listener".
    Код:
    import org.bukkit.event.Listener;
    
    public class InventoryListener implements Listener {
      
    }
    Добавим обработчик нажатий в инвентаре.
    Код:
    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {
          
    }
    В нем делаем проверку на "null".
    Код:
    Inventory inventory = event.getClickedInventory();
    if (inventory == null || event.getClickedInventory().getHolder() == null) {
        return;
    }
    Проверяем, является ли "holder" инвентаря нашим инвентарем, если да, то кастуем его к нашему классу и передаем ему ивент.
    Код:
    if (inventory.getHolder() instanceof MyCustomInventory) {
        ((MyCustomInventory) inventory.getHolder()).onInventoryClick(event);
    }
    Чтобы создать инвентарь и открыть его игроку, пишем так..
    Код:
    MyCustomInventory myCustomInventory = new MyCustomInventory(3, "MyCustomInventory");
    Player player = ...;
    player.openInventory(myCustomInventory.getInventory());
    Вот и все. Это и есть первый способ.


    2) Второй способ будет сложнее, так как использует "Reflection".

    Создадим новый класс "InventoryUtils"
    Код:
    public class InventoryUtils {
    
    }
    Нам понадобиться одно статичное поле типа "Field"
    Код:
    private static Field field = null;
    Далее в статичном конструкторе нам нужно получить версию баккита и класс "CraftInventory"
    Код:
    static {
        try {
            // Получаем версию баккита
            String version = Pattern.compile("\\.").split(Bukkit.getServer().getClass().getPackage().getName())[3];
              
            // Получаем класс инвентаря
            Class<?> mcInventory = Class.forName(String.format("org.bukkit.craftbukkit.%s.inventory.CraftInventory", version));
              
            // Получаем приватное поле "inventory"
            field = mcInventory.getDeclaredField("inventory");
              
            // Разрешаем изменять
            field.setAccessible(true);
        }
        catch (ClassNotFoundException | NoSuchFieldException e) {
            e.printStackTrace();
        }
    }
    Создадим статичный метод для сравнения инвентарей.
    Код:
    public static boolean equalsInventory(Inventory i1, Inventory i2) {
    }
    А внутри проверку.
    Код:
    try {
        return field.get(i1) == field.get(i2);
    }
    catch (IllegalAccessException ignore) {
        return false;
    }
    Теперь можно в любом место кода вызвать этот метод для сравнения.
    Код:
    public class InventoryListener implements Listener {
    
        private final Inventory kits;
    
        public InventoryListener() {
          
            // Создаем свой инвентарь
            this.kits = Bukkit.createInventory(null, 3 * 9, "kits");
        }
    
        @EventHandler
        public void onPlayerJoin(PlayerJoinEvent event) {
          
            // Как только игрок заходит на сервер, открываем игроку наш инвентарь
            event.getPlayer().openInventory(this.kits);
        }
    
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
          
            // Проверяем нажал ли игрок на инвентарь
            if (event.getClickedInventory() != null) {
              
                // Сравниваем инвентарь по которому нажали с нашим инвентарем
                if (InventoryUtils.equalsInventory(event.getClickedInventory(), this.kits)) {
                    // your code
                }
            }
        }
    
    }


    Надеюсь после этого поста вы перестанете сравнивать инвентари по имени.
    p.s.: Не умею я оформлять темы...



    Код:
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.*********ventory.Inventory;
    
    public class InventoryListener implements Listener {
    
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            Inventory inventory = event.getClickedInventory();
            if (inventory == null || inventory.getHolder() == null) {
                return;
            }
    
            if (inventory.getHolder() instanceof MyCustomInventory) {
                ((MyCustomInventory) inventory.getHolder()).onInventoryClick(event);
            }
        }
    
    }
    Код:
    import org.bukkit.Bukkit;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.*********ventory.Inventory;
    import org.*********ventory.InventoryHolder;
    
    public class MyCustomInventory implements InventoryHolder {
    
        private final Inventory inventory;
    
        public MyCustomInventory(int rows, String title) {
            this.inventory = Bukkit.createInventory(this, rows * 9, title);
        }
    
        @Override
        public Inventory getInventory() {
            return this.inventory;
        }
    
        public void onInventoryClick(InventoryClickEvent event) {
            // ...
        }
    
    }
    Код:
    import org.bukkit.Bukkit;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.*********ventory.Inventory;
    
    public class InventoryListener implements Listener {
    
        private final Inventory kits;
    
        public InventoryListener() {
            this.kits = Bukkit.createInventory(null, 3 * 9, "kits");
        }
    
        @EventHandler
        public void onPlayerJoin(PlayerJoinEvent event) {
            event.getPlayer().openInventory(this.kits);
        }
    
        @EventHandler
        public void onInventoryClick(InventoryClickEvent event) {
            if (event.getClickedInventory() != null) {
                if (InventoryUtils.equalsInventory(event.getClickedInventory(), this.kits)) {
                    // your code
                }
            }
        }
    
    }
    Код:
    import java.lang.reflect.Field;
    import java.util.regex.Pattern;
    import org.bukkit.Bukkit;
    import org.*********ventory.Inventory;
    
    public class InventoryUtils {
    
        private static Field field = null;
    
        static {
            try {
                String version = Pattern.compile("\\.").split(Bukkit.getServer().getClass().getPackage().getName())[3];
                Class<?> mcInventory = Class.forName(String.format("org.bukkit.craftbukkit.%s.inventory.CraftInventory", version));
                field = mcInventory.getDeclaredField("inventory");
                field.setAccessible(true);
            }
            catch (ClassNotFoundException | NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    
        public static boolean equalsInventory(Inventory i1, Inventory i2) {
            try {
                return field.get(i1) == field.get(i2);
            }
            catch (IllegalAccessException ignore) {
                return false;
            }
        }
    
    }
     
  2. HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    А каким образом игрок может в игре создать инвентарь своим именем?
     
  3. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Наковальня.
     
  4. alexandrage

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

    Баллы:
    173
    Ну он же не сможет прописать коды цветов. Знак параграфа в игре нельзя писать.
     
  5. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    1) На сервере могут быть плагины которые разрешают это делать.
    2) В самом начале я привел пример: 2 разработчика, не зная друг о друге, создали свои инвентари с одинаковым названием и начали инвентари работать не так как нужно, а еще хуже, ошибки в консоль кидать..
     
  6. Blc_Dragon

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

    Баллы:
    76
    есть куча модов, позволяющих такое делать.
     
  7. alexandrage

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

    Баллы:
    173
    Первый раз слышу.
     
  8. Zнамя Юности

    Zнамя Юности Активный участник Пользователь

    Баллы:
    76
    в чем проблема просто поменять имя инвентаря?
     
  9. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Проблема в том, что придется посмотреть исходники всех существующих плагинов, чтобы не было конфликтов.
     
  10. Zнамя Юности

    Zнамя Юности Активный участник Пользователь

    Баллы:
    76
    нормальные люди оставляют их в конфигах
     
  11. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Нормальные люди не сравнивают инвентари по имени.
     
  12. Zнамя Юности

    Zнамя Юности Активный участник Пользователь

    Баллы:
    76
    сдался
     
  13. HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Го чекнем сейчас любой плагин, и я уверен что там сравнение идет по имени на 80%
     
  14. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Давай чекним нормальные плагины и я уверен, что сравнение идет не по имени в 80%??
     
  15. HunterGaming

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

    Баллы:
    96
    Имя в Minecraft:
    sqdFendy
    Давай
     
  16. Zнамя Юности

    Zнамя Юности Активный участник Пользователь

    Баллы:
    76
    ни в одном плагине не видел, чтобы кто-то ипал себе моск тем, что ты тут расписал
     
  17. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Сожалею, так как ты смотрел только на ковно-код... Если плагин заточен на гуи и стабильную работу, а не кое-как, то разработчик НИКОГДА не будет сравнивать инвентари по имени..
     
  18. Zнамя Юности

    Zнамя Юности Активный участник Пользователь

    Баллы:
    76
    в customgui тоже по имени сравнивает, и ничо, работает.
     
  19. Автор темы
    JekaRUS

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

    Баллы:
    66
    Имя в Minecraft:
    JekaRUS
    Можно ссылку?? Хочу посмотреть на это творение...
     
  20. Zнамя Юности

    Zнамя Юности Активный участник Пользователь

    Баллы:
    76
    ctrl+c + ctrl+v в гугол. сложно чтоле
     

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