Помогите ItemDrop

ItzFirstException

Новичок
Пользователь
Баллы
11
Имя в Minecraft
FirstException
Задача сделать так, чтобы когда игрок погибал, все предметы имеющие лор записывались в HashMap,
далее выдавались игроку, а без лора выпадали на землю.
И броня тоже, если имеет лор, то не выпадает, как реализовать?
 
Ну подскажите пожалуйста :3
то ли я плохо поиском работаю, то ли тема в небытие улетела.

посему вот код
Java:
private static HashMap<Player, ItemStack[]> items = new HashMap<>();
    @EventHandler
    public void onDeath(PlayerDeathEvent e){
        for (int i = e.getDrops().size()-1; i>=0; i--){ //запускаем такую форку, дабы не вылезти за пределы массива
            ItemStack item = e.getDrops().get(i);
            if (item==null) continue;
            if (!item.hasItemMeta()) continue;
            if (item.getItemMeta().hasLore()){
                e.getDrops().remove(i);
            }
        }
        /*
        * теперь вещи с лором не выпадут
        * осталось добавить их сохранение
        */
        Inventory inv = e.getEntity().getInventory();
        for (int i=0; i<inv.getSize(); i++){ //для начала чистим инвентарь от ненужных вещей. Тут можно было запустить и обычный foreach, но мне как то лень
            ItemStack item = inv.getItem(i);
            if (item==null) continue;
            if (item.hasItemMeta())
                if (item.getItemMeta().hasLore()) continue;
            inv.setItem(i, new ItemStack(Material.AIR));         
        }//все, сейчас в инвентаре лежат только вещи с лором
     
        items.put(e.getEntity(),inv.getContents()); //сохранили инвентарь
    }
    @EventHandler
    public void onRespawn(PlayerRespawnEvent e){
        if (items.containsKey(e.getPlayer())){ //если для этого игрока сохранен инвентарь то выдаем его
            e.getPlayer().getInventory().setContents(items.get(e.getPlayer()));
        }
    }
 
то ли я плохо поиском работаю, то ли тема в небытие улетела.

посему вот код
Java:
private static HashMap<Player, ItemStack[]> items = new HashMap<>();
    @EventHandler
    public void onDeath(PlayerDeathEvent e){
        for (int i = e.getDrops().size()-1; i>=0; i--){ //запускаем такую форку, дабы не вылезти за пределы массива
            ItemStack item = e.getDrops().get(i);
            if (item==null) continue;
            if (!item.hasItemMeta()) continue;
            if (item.getItemMeta().hasLore()){
                e.getDrops().remove(i);
            }
        }
        /*
        * теперь вещи с лором не выпадут
        * осталось добавить их сохранение
        */
        Inventory inv = e.getEntity().getInventory();
        for (int i=0; i<inv.getSize(); i++){ //для начала чистим инвентарь от ненужных вещей. Тут можно было запустить и обычный foreach, но мне как то лень
            ItemStack item = inv.getItem(i);
            if (item==null) continue;
            if (item.hasItemMeta())
                if (item.getItemMeta().hasLore()) continue;
            inv.setItem(i, new ItemStack(Material.AIR));        
        }//все, сейчас в инвентаре лежат только вещи с лором
    
        items.put(e.getEntity(),inv.getContents()); //сохранили инвентарь
    }
    @EventHandler
    public void onRespawn(PlayerRespawnEvent e){
        if (items.containsKey(e.getPlayer())){ //если для этого игрока сохранен инвентарь то выдаем его
            e.getPlayer().getInventory().setContents(items.get(e.getPlayer()));
        }
    }
В onRespawn следует использовать items.remove(e.getPlayer()) вместо items.get(e.getPlayer()), чтобы не было дюпа.
 
Улучшенный вариант сохранения предметов (устранена утечка памяти; добавлено адекватное поведение, если кто-то уже внёс изменения в инвентарь):
Java:
public final class TestPlugin extends JavaPlugin implements Listener
{
    private final Map<Player, ItemStack[]> items = new WeakHashMap<>();

    @Override
    public void onEnable()
    {
        this.getServer().getPluginManager().registerEvents(this, this);
    }

    @EventHandler
    public void onDeath(PlayerDeathEvent event)
    {
        // Удаляем из дропа всё, что можно сохранить
        event.getDrops().removeIf(TestPlugin::needSave);

        // Удаляем из инвентаря всё, что нельзя сохранить
        Inventory inv = event.getEntity().getInventory();
        for (int i = 0; i < inv.getSize(); i++)
        {
            ItemStack item = inv.getItem(i);
            if (item != null && !needSave(item))
                inv.setItem(i, null);
        }

        // Запоминаем инвентарь
        this.items.put(event.getEntity(), inv.getContents());
    }

    @EventHandler
    public void onRespawn(PlayerRespawnEvent event)
    {
        Player player = event.getPlayer();
        ItemStack[] oldArr = this.items.remove(player); // Удаляем инвентарь и сохраняем ссылку на него в переменную
        if (oldArr != null)
        {
            Inventory inv = player.getInventory();
            ItemStack[] newArr = inv.getContents();
            mergeOrDrop(player.getLocation(), newArr, oldArr); // Добавляем сохранённые предметы в инвентарь к игроку или дропаем их, если слоты уже заняты
            inv.setContents(newArr);
        }
    }

    private static boolean needSave(ItemStack item)
    {
        return item != null && item.hasItemMeta() && item.getItemMeta().hasLore();
    }

    private static void mergeOrDrop(Location location, ItemStack[] newArr, ItemStack[] oldArr)
    {
        int length = Math.min(newArr.length, oldArr.length);
        for (int i = 0; i < length; i++)
        {
            ItemStack item = oldArr[i];
            if (item != null)
                if (newArr[i] == null)
                    newArr[i] = item; // Добавляем предмет
                else
                    location.getWorld().dropItem(location, item); // Дропаем предмет, если слот занят
        }
    }
}
 
Только мне нужно сделать так, чтобы вещи с лором оставлялись, а без лора просто выпадали на землю.
 
Какой из них именно? Я просто пробую у меня получается дюп предметов.


Улучшенный вариант сохранения предметов (устранена утечка памяти; добавлено адекватное поведение, если кто-то уже внёс изменения в инвентарь):
Java:
public final class TestPlugin extends JavaPlugin implements Listener
{
    private final Map<Player, ItemStack[]> items = new WeakHashMap<>();

    @Override
    public void onEnable()
    {
        this.getServer().getPluginManager().registerEvents(this, this);
    }

    @EventHandler
    public void onDeath(PlayerDeathEvent event)
    {
        // Удаляем из дропа всё, что можно сохранить
        event.getDrops().removeIf(TestPlugin::needSave);

        // Удаляем из инвентаря всё, что нельзя сохранить
        Inventory inv = event.getEntity().getInventory();
        for (int i = 0; i < inv.getSize(); i++)
        {
            ItemStack item = inv.getItem(i);
            if (item != null && !needSave(item))
                inv.setItem(i, null);
        }

        // Запоминаем инвентарь
        this.items.put(event.getEntity(), inv.getContents());
    }

    @EventHandler
    public void onRespawn(PlayerRespawnEvent event)
    {
        Player player = event.getPlayer();
        ItemStack[] oldArr = this.items.remove(player); // Удаляем инвентарь и сохраняем ссылку на него в переменную
        if (oldArr != null)
        {
            Inventory inv = player.getInventory();
            ItemStack[] newArr = inv.getContents();
            mergeOrDrop(player.getLocation(), newArr, oldArr); // Добавляем сохранённые предметы в инвентарь к игроку или дропаем их, если слоты уже заняты
            inv.setContents(newArr);
        }
    }

    private static boolean needSave(ItemStack item)
    {
        return item != null && item.hasItemMeta() && item.getItemMeta().hasLore();
    }

    private static void mergeOrDrop(Location location, ItemStack[] newArr, ItemStack[] oldArr)
    {
        int length = Math.min(newArr.length, oldArr.length);
        for (int i = 0; i < length; i++)
        {
            ItemStack item = oldArr[i];
            if (item != null)
                if (newArr[i] == null)
                    newArr[i] = item; // Добавляем предмет
                else
                    location.getWorld().dropItem(location, item); // Дропаем предмет, если слот занят
        }
    }
}
 
Я не понял, что такое NeedSave, и понять как это используют.
 
Какой из них именно? Я просто пробую у меня получается дюп предметов.
возможно включен Gamerule keepInventory или есть другие плагины на сохранение инвентаря (Scavenger)
Я не понял, что такое NeedSave, и понять как это используют.
Метод который возвращает True или false в зависимости от того что за вещь он получил, и какие проверки указаны в самом методе
 
upload_2017-3-2_12-39-14.png
У меня он просто не видит метод.
Что делать, кто подскажет?
Что делать, кто подскажет? Я просто не знаю, ибо с методом, что-то, ибо с ide.
 
Попробуйте так:
Java:
Main::needSave
 
Назад
Верх