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

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

Discussion in 'Разработка плагинов для новичков' started by JekaRUS, Apr 6, 2017.

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

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

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

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

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

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

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


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

    Создадим новый класс "InventoryUtils"
    Code:
    public class InventoryUtils {
    
    }
    Нам понадобиться одно статичное поле типа "Field"
    Code:
    private static Field field = null;
    Далее в статичном конструкторе нам нужно получить версию баккита и класс "CraftInventory"
    Code:
    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();
        }
    }
    Создадим статичный метод для сравнения инвентарей.
    Code:
    public static boolean equalsInventory(Inventory i1, Inventory i2) {
    }
    А внутри проверку.
    Code:
    try {
        return field.get(i1) == field.get(i2);
    }
    catch (IllegalAccessException ignore) {
        return false;
    }
    Теперь можно в любом место кода вызвать этот метод для сравнения.
    Code:
    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.: Не умею я оформлять темы...



    Code:
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.inventory.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);
            }
        }
    
    }
    Code:
    import org.bukkit.Bukkit;
    import org.bukkit.event.inventory.InventoryClickEvent;
    import org.bukkit.inventory.Inventory;
    import org.bukkit.inventory.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) {
            // ...
        }
    
    }
    Code:
    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.bukkit.inventory.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
                }
            }
        }
    
    }
    Code:
    import java.lang.reflect.Field;
    import java.util.regex.Pattern;
    import org.bukkit.Bukkit;
    import org.bukkit.inventory.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. Хостинг MineCraft
    <
  3. HunterGaming

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

    Trophy Points:
    46
    Имя в Minecraft:
    HunterGaming13
    А каким образом игрок может в игре создать инвентарь своим именем?
     
  4. Автор темы
    JekaRUS

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

    Trophy Points:
    66
    Имя в Minecraft:
    JekaRUS
    Наковальня.
     
  5. alexandrage

    alexandrage Администратор

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

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

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

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

    Trophy Points:
    76
    Имя в Minecraft:
    Blc_Dragon
    есть куча модов, позволяющих такое делать.
     
  8. alexandrage

    alexandrage Администратор

    Trophy Points:
    173
    Skype:
    alexandr0116
    Первый раз слышу.
     
  9. Zнамя Юности

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

    Trophy Points:
    46
    в чем проблема просто поменять имя инвентаря?
     
  10. Автор темы
    JekaRUS

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

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

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

    Trophy Points:
    46
    нормальные люди оставляют их в конфигах
     
  12. Автор темы
    JekaRUS

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

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

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

    Trophy Points:
    46
    сдался
     
  14. HunterGaming

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

    Trophy Points:
    46
    Имя в Minecraft:
    HunterGaming13
    Го чекнем сейчас любой плагин, и я уверен что там сравнение идет по имени на 80%
     
  15. Автор темы
    JekaRUS

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

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

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

    Trophy Points:
    46
    Имя в Minecraft:
    HunterGaming13
    Давай
     
  17. Zнамя Юности

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

    Trophy Points:
    46
    ни в одном плагине не видел, чтобы кто-то ипал себе моск тем, что ты тут расписал
     
  18. Автор темы
    JekaRUS

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

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

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

    Trophy Points:
    46
    в customgui тоже по имени сравнивает, и ничо, работает.
     
  20. Автор темы
    JekaRUS

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

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

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

    Trophy Points:
    46
    ctrl+c + ctrl+v в гугол. сложно чтоле
     

Share This Page