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

[Решено] Работа с инвентарём.

Discussion in 'Разработка плагинов для новичков' started by CoolBoy, Jun 10, 2016.

Thread Status:
Not open for further replies.
  1. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Доброго времени суток, уважаемые форумчане.

    Сразу к делу.
    Не найдя нормального магазина на версию 1.9.4 решил написать свой.
    За небольшой срок написал таковой, но возникла проблема.
    Если в инвентаре имеется, к примеру, 4 блока земли и я продаю их - команда срабатывает.
    Если в инвентаре лежит 4 блока земли по одному блоку в каждом слоте - команда не работает и пишет что предметов не хватает.
    И это вполне очевидно, ведь я проверяю условия на каждый отдельный слот, а не на весь инвентарь в целом.

    Вопрос:
    Каким образом можно решить мою проблему?
    Я конечно, понимаю, что можно сделать HashMap, или просто Map и заносить туда инвентарь целиком, а после - работать с мапой.
    Но не представляю каким образом это может выглядеть.

    То, что имею на данный момент:
    - Commands:

    Code:
    if (args.length == 4 && args[0].equalsIgnoreCase("sell"))  
    {
        Player player = (Player) sender;
        Inventory inventory = player.getInventory();
        String[] split = args[1].split(":");
                   
        if (!inventory.containsAtLeast(new ItemStack(Material.valueOf(split[0]), 1, Byte.valueOf(split[1])), 1)) 
        {
            player.sendMessage(no_item);
            return true;
        }
                   
        for (int i = 0; i < inventory.getSize(); i++) 
        {
            ItemStack itemStack = inventory.getItem(i);
                       
            if (itemStack != null && itemStack.getType().equals(Material.valueOf(split[0]))) 
            {
                if (itemStack.getAmount() < Integer.valueOf(args[2])) 
                {
                     player.sendMessage(no_item_to_sell);
                     break;
                }
                           
                int amount = itemStack.getAmount() - Integer.valueOf(args[2]);
                ItemStack item = new ItemStack(Material.valueOf(split[0]), amount, Byte.valueOf(split[1]));
                itemStack.setAmount(amount);
                inventory.setItem(i, amount > 0 ? item : null);
                this.plugin.giveMoney(player, Double.parseDouble(args[3]));
                player.updateInventory();
                break;
            }
        }
    }
    
    Прошу помощи знающих людей)
    Любые комментарии по коду приветствуются :)
     
  2. Хостинг MineCraft
    <
  3. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Code:
    static int getItemCountInInventory(Inventory inv, Material type)
    {
        int count = 0;
      
        ItemStack[] contents = inv.getContents();
      
        for(int i = 0; i < contents.length; i++)
        {
            ItemStack s = contents[i];
          
            if(s.getType() == type)
                count += s.getAmount();
        }
      
        return count;
    }
    
    Возможно, я старомоден.
     
  4. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Спасибо за помощь, но ведь это просто счётчик?
    Как я смогу удалить ItemStack'и из всех слотов, в которых они расположены, зная только их количество?
    :)
     
  5. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Code:
    static boolean remove(Inventory inv, Material type, int count)
    {
        int realCount = 0;
        int nCnt = count;
     
        ItemStack[] contents = inv.getContents();
     
        for(int i = 0; i < contents.length; i++)
        {
            ItemStack s = contents[i];
         
            if(s.getType() == type)
                count += s.getAmount();
        }
     
        if(realCount < count)
            return false;//не достаточно предметов
     
        for(int i = 0; i < contents.length; i++)
        {
            ItemStack s = contents[i];
         
            if(s.getAmount() >= nCnt)
            {
                if(s.getAmount() > nCnt)
                    s.setAmount(s.getAmount() - nCnt);
                else
                    inv.remove(s);
    
                break;
            }
            else
            { 
                nCnt -= s.getAmount();
             
                inv.remove(s);
            }
        }
     
        return true;
    }
     
  6. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Вопрос.
    Зачем нужен realCount если он всегда = 0? И всегда отменяет метод?
    2 вопрос. :)
    1. if(s.getType() == type)
    2. count += s.getAmount(); // Тут разве нужно не realCount += s.getAmount(); ?
    3. }
    Подредактировав немного ваш метод у меня почти получилось сделать то, что я хочу.
    Но пока не всё идеально.
    То, что получилось:
    Code:
        public static boolean remove(Player player, Inventory inv, Material type, int count)
        {
           int realCount = 0;
           int nCnt = count;
           player.sendMessage("Поехали!");
        
           ItemStack[] contents = inv.getContents();
        
           for (int i = 0; i < contents.length; i++)
           {
               ItemStack stack = contents[i];
          
               if (stack != null && stack.getType() == type)
               {
                  player.sendMessage("Тип стака = типу нашего материала! Добавили к счётчику!");
                   realCount += stack.getAmount();
               }
           }
        
           if (realCount < count)
           {
              player.sendMessage("Ресов нету(");
               return false;
           }
        
           for (int i = 0; i < contents.length; i++)
           {
               ItemStack stack = contents[i];
          
               if (stack != null && stack.getAmount() >= nCnt)
               {
                  player.sendMessage("Количество больше либо равно вычитаемому!");
                
                   if (stack != null && stack.getAmount() > nCnt)
                   {
                       stack.setAmount(stack.getAmount() - nCnt);
                       player.sendMessage("Отняли количество от товара!");
                   } else {
                       inv.remove(stack);
                       player.sendMessage("Убрали стак!");
                       break;
                   }
               } else { 
                   nCnt -= stack.getAmount();
                   inv.remove(stack);
                   player.sendMessage("Отняли количество от товара!");
               }
           }
           return true;
        }
    
    Если вычитать из целого стака - всё нормально. Если разложить по слотам, то иногда считает правильно - иногда нет.
    Можете проверить ? :)

    Спасибо за помощь, ещё раз)[DOUBLEPOST=1465588614,1465560798][/DOUBLEPOST]UP!
     
  7. Dymeth

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

    Trophy Points:
    76
    У меня на данный момент так. Но, честно говоря, не особо нравится такое решение. Возможно позже переделаю. Ну а пока... Что есть...
    Code:
        public static boolean takeItem(GamePlayer gamePlayer, GameItem gameItem, short amount) {
            String name = gameItem.getStack().getItemMeta().getDisplayName();
            //gamePlayer - сам игрок (у меня просто наследует CraftPlayer)
            //name - название требуемых предметов (у меня сравнение производится не по материалу, но, думаю, переделать не составит труда)
            //amount - количество требуемых предметов
            ItemStack[] contents = gamePlayer.getInventory().getContents();
            HashMap<Integer, ItemStack> replacing = new HashMap<>(); // Таблица заменяемых предметов: слот, новый стак
            for (int slot = 0; slot < contents.length; slot++) {
                ItemStack current = contents[slot];
                if (current == null) continue;
                if (!current.getItemMeta().getDisplayName().equals(name)) continue;
                int currentAmount = current.getAmount();
                int newAmount = currentAmount - amount;
                if (newAmount < 1) //Удаляем стак из инвентаря, если количество предметов в нём меньше единицы
                    replacing.put(slot, null);
                else { //Иначе просто устанавливаем новый размер стака
                    current.setAmount(newAmount);
                    replacing.put(slot, current);
                }
                amount -= currentAmount; //Уменьшаем количество требуемых предметов на размер стака
                if (amount <= 0) {
                    Inventory inventory = gamePlayer.getInventory();
                    for (Map.Entry<Integer, ItemStack> entry : replacing.entrySet()) //Обновление изменённых стаков
                        inventory.setItem(entry.getKey(), entry.getValue());
                    //Предметов хватает
                    return true;
                }
            }
            //Недостаточно предметов
            return false;
        }
    
     
  8. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Спасибо. Протестирую ближе к утру.
     
  9. fall.us

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

    Trophy Points:
    76
    Имя в Minecraft:
    fallus
    Code:
    static boolean remove(Inventory inv, Material type, int count)
    {
        int realCount = 0;
        int nCnt = count;
    
        ItemStack[] contents = inv.getContents();
    
        for(int i = 0; i < contents.length; i++)
        {
            ItemStack s = contents[i];
      
            if(s != null)
               if(s.getType() == type)
                   realCount += s.getAmount();
        }
    
        if(realCount < count)
            return false;//не достаточно предметов
    
        for(int i = 0; i < contents.length; i++)
        {
            ItemStack s = contents[i];
      
            if(s == null)
                continue;
        
            if(s.getAmount() >= nCnt)
            {
                if(s.getAmount() > nCnt)
                    s.setAmount(s.getAmount() - nCnt);
                else
                    contents[i] = null;
    
                break;
            }
            else
            {
                nCnt -= s.getAmount();
          
                contents[i] = null;
            }
        }
    
        inv.setContents(contents);
    
        return true;
    }
    
    Code:
    if(remove(player.getInventory(), mat, count))
        player.sendMessage("Удалено " + count + " " + mat);
    else
        player.sendMessage("Не достаточно  " + mat);
        
    Проверил; вроде бы работает.
     
  10. Автор темы
    CoolBoy

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

    Trophy Points:
    96
    Skype:
    thecoolboy2070
    Имя в Minecraft:
    CoolBoy
    Просто огроменное тебе спасибо!
    Очень выручил, причём не в первый раз!

    P.S. До этого глядел исходник Essentials, как там предметы продаются, так там используется Мапа :)

    Решено. Закрыто.
     
Thread Status:
Not open for further replies.

Share This Page