Начинающий разработчик ищет проект для сотрудничества. Готов писать плагины бесплатно

Здравствуйте! Я начинающий разработчик плагинов для Bedrock-серверов (работаю с ядрами Nukkit-MOT, Lumi). Опыт – 2-3 месяца. Писал легкие плагины: Buyer, Auction, экономику, клановую систему ,приваты с помощью блоков и тд . Моя цель: качественно выполненная работа для вас и ценный опыт для меня.

Кто заинтересован, пишите свой тг.

опыта мало

1 лайк

Спасибо за честность именно поэтому я предлагаю свои услуги бесплатно.

1 лайк


Аук


Buyer

Особенности buyer: допустим, игрок покупает кактус 64 штуки. Цена кактуса падает на 1 и рандомно повышается в той же категории на 1 рандомный предмет: если цена предмета 1, то она уже не упадет, и рандомный предмет не повысится на 1 в той же категории. То есть, цена в buyer зависит от игроков если игроки будут много покупать кактус, то цена резко упадет, и цена на другой товар повысится в той же категории так со всеми товарами работает.

Возможно в Java тематике он не 2-3 месяца, а больше

можешь кусок кода скинуть?

окей

package auction.org;

import cn.nukkit.Player;
import cn.nukkit.Server;
import cn.nukkit.command.Command;
import cn.nukkit.command.CommandSender;
import cn.nukkit.event.EventHandler;
import cn.nukkit.event.EventPriority;
import cn.nukkit.event.Listener;
import cn.nukkit.event.inventory.InventoryClickEvent;
import cn.nukkit.event.inventory.InventoryTransactionEvent;
import cn.nukkit.event.player.PlayerQuitEvent;
import cn.nukkit.inventory.InventoryType;
import cn.nukkit.item.Item;
import cn.nukkit.item.enchantment.Enchantment;
import cn.nukkit.nbt.tag.CompoundTag;
import cn.nukkit.scheduler.PluginTask;
import cn.nukkit.utils.Config;
import cn.nukkit.utils.TextFormat;
import com.chelimus4078.RankManagerNukkitMOT;
import me.iwareq.fakeinventories.FakeInventory;
import org.chelimus4078.EconomyManager;
import org.chelimus4078.MainPlugin;

import java.util.*;

public class auctionmanager extends Command implements Listener {
private final auction plugin;
private final Config auctionData;
private final Map<UUID, FakeInventory> openInventories = new HashMap<>();
private final Map<FakeInventory, Integer> auctionPages = new HashMap<>();
private final Map<FakeInventory, Integer> storagePages = new HashMap<>();
private final Set processingPlayers = new HashSet<>();
private String sortMode = “time_desc”;
private List<Map.Entry<String, Map<String, Object>>> cachedSortedLots = null;
private Map<UUID, List<Map.Entry<String, Map<String, Object>>>> cachedSortedStorage = new HashMap<>();
private static final int ITEMS_PER_PAGE = 45;
private static final int DELAY_TICKS = 20;

public auctionmanager(auction plugin) {
    super("auc", "Торговая Площадь", "/auc [sell <цена>]", new String[]{"ah", "auction"});
    this.plugin = plugin;
    this.auctionData = plugin.getConfig();
    plugin.getServer().getPluginManager().registerEvents(this, plugin);
}

@Override
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
    if (!(sender instanceof Player)) {
        sender.sendMessage(TextFormat.RED + "✘ Это команда только для игроков");
        return true;
    }
    Player player = (Player) sender;
    if (args.length > 0 && args[0].equalsIgnoreCase("sell")) {
        return itemSell(player, args);
    } else if (args.length == 0) {
        openAuction(player, 1);
        return true;
    }
    return false;
}

public void openAuction(Player player, int page) {
    FakeInventory inventory = new FakeInventory(InventoryType.DOUBLE_CHEST, TextFormat.BOLD.toString() + TextFormat.AQUA + "✨ Торговая Площадь - Страница " + page);
    inventory.setDefaultItemHandler((item, event) -> {
        // Пустой ItemHandler для предотвращения NullPointerException
    });
    updateAuctionInventory(inventory, player, page);
    auctionPages.put(inventory, page);
    openInventories.put(player.getUniqueId(), inventory);
    player.addWindow(inventory);
}

public void openStorage(Player player, int page) {
    FakeInventory inventory = new FakeInventory(InventoryType.DOUBLE_CHEST, TextFormat.GREEN + "Личное Хранилище - Страница " + page);
    inventory.setDefaultItemHandler((item, event) -> {
        // Пустой ItemHandler для предотвращения NullPointerException
    });
    updateStorageInventory(inventory, player, page);
    storagePages.put(inventory, page);
    openInventories.put(player.getUniqueId(), inventory);
    player.addWindow(inventory);
}

@EventHandler(priority = EventPriority.HIGHEST)
public void onInventoryTransaction(InventoryTransactionEvent event) {
    if (event.getTransaction().getInventories().stream().anyMatch(inv -> inv instanceof FakeInventory)) {
        event.setCancelled(true);
    }
}

@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
    if (!(event.getInventory() instanceof FakeInventory)) {
        return;
    }
    event.setCancelled(true);
    FakeInventory inventory = (FakeInventory) event.getInventory();
    Player player = event.getPlayer();
    String playerKey = player.getUniqueId().toString() + ":" + System.currentTimeMillis();
    if (!processingPlayers.add(playerKey)) {
        return;
    }

    int slot = event.getSlot();
    if (slot == -1) {
        processingPlayers.remove(playerKey);
        return;
    }

    Item clickedItem = inventory.getItem(slot);
    if (clickedItem == null || clickedItem.getId() == 0) {
        processingPlayers.remove(playerKey);
        return;
    }

    if (auctionPages.containsKey(inventory)) {
        handleAuctionClick(player, inventory, slot, playerKey);
    } else if (storagePages.containsKey(inventory)) {
        handleStorageClick(player, inventory, slot, playerKey);
    } else {
        processingPlayers.remove(playerKey);
    }
}

@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
    Player player = event.getPlayer();
    String playerKeyPrefix = player.getUniqueId().toString() + ":";
    processingPlayers.removeIf(key -> key.startsWith(playerKeyPrefix));
    openInventories.remove(player.getUniqueId());
    auctionPages.keySet().removeIf(inv -> inv.getViewers().contains(player));
    storagePages.keySet().removeIf(inv -> inv.getViewers().contains(player));
    cachedSortedStorage.remove(player.getUniqueId());
}

private void handleAuctionClick(Player player, FakeInventory inventory, int slot, String playerKey) {
    Integer currentPage = auctionPages.get(inventory);
    if (currentPage == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: страница торговой площади не найдена!");
        plugin.getLogger().error("Страница торговой площади не найдена! Игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    if (!plugin.isEnabled()) {
        player.sendMessage(TextFormat.RED + "✘ Плагин отключен, действие невозможно!");
        plugin.getLogger().error("Попытка выполнить действие, когда плагин отключен! Игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    Item clickedItem = inventory.getItem(slot);
    String action = clickedItem.getNamedTag() != null ? clickedItem.getNamedTag().getString("action") : "";
    if (!action.isEmpty()) {
        switch (action) {
            case "prev":
                if (currentPage > 1) {
                    inventory.close(player);
                    openInventories.remove(player.getUniqueId());
                    auctionPages.remove(inventory);
                    Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                        @Override
                        public void onRun(int currentTick) {
                            if (player.isOnline()) {
                                openAuction(player, currentPage - 1);
                            }
                            processingPlayers.remove(playerKey);
                        }
                    }, DELAY_TICKS);
                } else {
                    processingPlayers.remove(playerKey);
                }
                break;
            case "next":
                @SuppressWarnings("unchecked")
                ArrayList<String> order = (ArrayList<String>) auctionData.getList("order", new ArrayList<>());
                if (currentPage * ITEMS_PER_PAGE < order.size()) {
                    inventory.close(player);
                    openInventories.remove(player.getUniqueId());
                    auctionPages.remove(inventory);
                    Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                        @Override
                        public void onRun(int currentTick) {
                            if (player.isOnline()) {
                                openAuction(player, currentPage + 1);
                            }
                            processingPlayers.remove(playerKey);
                        }
                    }, DELAY_TICKS);
                } else {
                    processingPlayers.remove(playerKey);
                }
                break;
            case "sort_price_asc":
                sortMode = "price_asc";
                cachedSortedLots = null;
                cachedSortedStorage.remove(player.getUniqueId());
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openAuction(player, currentPage);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "sort_price_desc":
                sortMode = "price_desc";
                cachedSortedLots = null;
                cachedSortedStorage.remove(player.getUniqueId());
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openAuction(player, currentPage);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "sort_time_asc":
                sortMode = "time_asc";
                cachedSortedLots = null;
                cachedSortedStorage.remove(player.getUniqueId());
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openAuction(player, currentPage);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "sort_time_desc":
                sortMode = "time_desc";
                cachedSortedLots = null;
                cachedSortedStorage.remove(player.getUniqueId());
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openAuction(player, currentPage);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "sort_item_asc":
                sortMode = "item_asc";
                cachedSortedLots = null;
                cachedSortedStorage.remove(player.getUniqueId());
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openAuction(player, currentPage);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "storage":
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openStorage(player, 1);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "close":
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                auctionPages.remove(inventory);
                processingPlayers.remove(playerKey);
                break;
        }
        return;
    }

    List<Map.Entry<String, Map<String, Object>>> sortedLots = getSortedLots();
    if (sortedLots.isEmpty()) {
        player.sendMessage(TextFormat.GRAY + "Торговая площадь пуста!");
        processingPlayers.remove(playerKey);
        return;
    }

    int index = (currentPage - 1) * ITEMS_PER_PAGE + slot;
    if (index >= sortedLots.size() || index < 0) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: предмет не найден!");
        plugin.getLogger().error("Неверный индекс предмета: " + index + ", игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    String auctionId = sortedLots.get(index).getKey();
    Map<String, Object> entry = sortedLots.get(index).getValue();
    if (entry == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: предмет не найден!");
        plugin.getLogger().error("Предмет не найден в конфиге: " + auctionId + ", игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    String ownerUUID = (String) entry.get("owner_uuid");
    @SuppressWarnings("unchecked")
    ArrayList<String> order = (ArrayList<String>) auctionData.getList("order", new ArrayList<>());
    int orderIndex = order.indexOf(auctionId);
    if (orderIndex == -1) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: предмет не найден в списке!");
        plugin.getLogger().error("Предмет не найден в order: " + auctionId + ", игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    if (ownerUUID.equals(player.getUniqueId().toString())) {
        returnToStorage(player, auctionId, entry, order, orderIndex);
        inventory.close(player);
        openInventories.remove(player.getUniqueId());
        auctionPages.remove(inventory);
        Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
            @Override
            public void onRun(int currentTick) {
                if (player.isOnline()) {
                    openAuction(player, currentPage);
                }
                processingPlayers.remove(playerKey);
            }
        }, DELAY_TICKS);
    } else {
        buyItem(player, auctionId, entry, order, orderIndex);
        inventory.close(player);
        openInventories.remove(player.getUniqueId());
        auctionPages.remove(inventory);
        Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
            @Override
            public void onRun(int currentTick) {
                if (player.isOnline()) {
                    openAuction(player, currentPage);
                }
                processingPlayers.remove(playerKey);
            }
        }, DELAY_TICKS);
    }
}

private void handleStorageClick(Player player, FakeInventory inventory, int slot, String playerKey) {
    Integer currentPage = storagePages.get(inventory);
    if (currentPage == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: страница хранилища не найдена!");
        plugin.getLogger().error("Страница хранилища не найдена! Игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    if (!plugin.isEnabled()) {
        player.sendMessage(TextFormat.RED + "✘ Плагин отключен, действие невозможно!");
        plugin.getLogger().error("Попытка выполнить действие, когда плагин отключен! Игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    Item clickedItem = inventory.getItem(slot);
    String action = clickedItem.getNamedTag() != null ? clickedItem.getNamedTag().getString("action") : "";
    if (!action.isEmpty()) {
        switch (action) {
            case "prev":
                if (currentPage > 1) {
                    inventory.close(player);
                    openInventories.remove(player.getUniqueId());
                    storagePages.remove(inventory);
                    Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                        @Override
                        public void onRun(int currentTick) {
                            if (player.isOnline()) {
                                openStorage(player, currentPage - 1);
                            }
                            processingPlayers.remove(playerKey);
                        }
                    }, DELAY_TICKS);
                } else {
                    processingPlayers.remove(playerKey);
                }
                break;
            case "next":
                @SuppressWarnings("unchecked")
                ArrayList<String> storageOrder = (ArrayList<String>) auctionData.getList("storage." + player.getUniqueId(), new ArrayList<>());
                if (currentPage * ITEMS_PER_PAGE < storageOrder.size()) {
                    inventory.close(player);
                    openInventories.remove(player.getUniqueId());
                    storagePages.remove(inventory);
                    Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                        @Override
                        public void onRun(int currentTick) {
                            if (player.isOnline()) {
                                openStorage(player, currentPage + 1);
                            }
                            processingPlayers.remove(playerKey);
                        }
                    }, DELAY_TICKS);
                } else {
                    processingPlayers.remove(playerKey);
                }
                break;
            case "back":
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                storagePages.remove(inventory);
                Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
                    @Override
                    public void onRun(int currentTick) {
                        if (player.isOnline()) {
                            openAuction(player, 1);
                        }
                        processingPlayers.remove(playerKey);
                    }
                }, DELAY_TICKS);
                break;
            case "close":
                inventory.close(player);
                openInventories.remove(player.getUniqueId());
                storagePages.remove(inventory);
                processingPlayers.remove(playerKey);
                break;
        }
        return;
    }

    List<Map.Entry<String, Map<String, Object>>> sortedStorage = getSortedStorage(player.getUniqueId());
    if (sortedStorage.isEmpty()) {
        player.sendMessage(TextFormat.GRAY + "Личное хранилище пусто!");
        processingPlayers.remove(playerKey);
        return;
    }

    int index = (currentPage - 1) * ITEMS_PER_PAGE + slot;
    if (index >= sortedStorage.size() || index < 0) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: предмет не найден!");
        plugin.getLogger().error("Неверный индекс предмета в хранилище: " + index + ", игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    String storageId = sortedStorage.get(index).getKey();
    Map<String, Object> entry = sortedStorage.get(index).getValue();
    if (entry == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: предмет не найден!");
        plugin.getLogger().error("Предмет не найден в хранилище: " + storageId + ", игрок: " + player.getName());
        processingPlayers.remove(playerKey);
        return;
    }

    Item item = createItemFromEntry(entry);
    if (item == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка: предмет поврежден!");
        plugin.getLogger().error("Не удалось создать предмет для storageId #" + storageId);
        processingPlayers.remove(playerKey);
        return;
    }

    if (player.getInventory().canAddItem(item)) {
        player.getInventory().addItem(item);
        auctionData.remove("storage_items." + storageId);
        @SuppressWarnings("unchecked")
        ArrayList<String> storageOrder = (ArrayList<String>) auctionData.getList("storage." + player.getUniqueId(), new ArrayList<>());
        storageOrder.remove(storageId);
        auctionData.set("storage." + player.getUniqueId(), storageOrder);
        auctionData.save();
        cachedSortedStorage.remove(player.getUniqueId());
        player.sendMessage(TextFormat.GREEN + "✔ Предмет успешно забран из хранилища!");
        inventory.close(player);
        openInventories.remove(player.getUniqueId());
        storagePages.remove(inventory);
        Server.getInstance().getScheduler().scheduleDelayedTask(new PluginTask<>(plugin) {
            @Override
            public void onRun(int currentTick) {
                if (player.isOnline()) {
                    openStorage(player, currentPage);
                }
                processingPlayers.remove(playerKey);
            }
        }, DELAY_TICKS);
    } else {
        player.sendMessage(TextFormat.RED + "✘ Ваш инвентарь полон!");
        processingPlayers.remove(playerKey);
    }
}

private void updateAuctionInventory(FakeInventory inventory, Player player, int page) {
    @SuppressWarnings("unchecked")
    ArrayList<String> order = (ArrayList<String>) auctionData.getList("order", new ArrayList<>());
    List<Map.Entry<String, Map<String, Object>>> sortedLots = getSortedLots();
    int maxPage = sortedLots.isEmpty() ? 1 : (sortedLots.size() + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE;
    page = Math.max(1, Math.min(page, maxPage));

    inventory.clearAll();

    int start = (page - 1) * ITEMS_PER_PAGE;
    int end = Math.min(start + ITEMS_PER_PAGE, sortedLots.size());

    for (int i = start; i < end; i++) {
        String auctionId = sortedLots.get(i).getKey();
        Map<String, Object> entry = sortedLots.get(i).getValue();
        Item displayItem = createItemFromEntry(entry);
        if (displayItem == null) {
            plugin.getLogger().error("Не удалось создать предмет для auctionId #" + auctionId);
            continue;
        }

        double price = ((Number) entry.get("price")).doubleValue();
        String ownerName = (String) entry.get("owner_name");
        List<String> lore = new ArrayList<>();
        lore.add(TextFormat.GRAY + "Владелец: " + TextFormat.WHITE + ownerName);
        lore.add(TextFormat.GRAY + "Цена: " + TextFormat.GOLD + price);
        lore.add(TextFormat.GRAY + "Количество: " + TextFormat.WHITE + displayItem.getCount());
        if (displayItem.getMaxDurability() > 0) {
            lore.add(TextFormat.GRAY + "Прочность: " + TextFormat.WHITE + (displayItem.getMaxDurability() - displayItem.getDamage()) + "/" + displayItem.getMaxDurability());
        }
        if (displayItem.hasEnchantments()) {
            lore.add(TextFormat.GRAY + "Чары:");
            for (Enchantment ench : displayItem.getEnchantments()) {
                lore.add(TextFormat.AQUA + ench.getName() + " " + ench.getLevel());
            }
        }
        lore.add(TextFormat.YELLOW + (entry.get("owner_uuid").equals(player.getUniqueId().toString()) ? "Нажмите, чтобы вернуть" : "Нажмите, чтобы купить"));
        displayItem.setLore(lore.toArray(new String[0]));
        inventory.setItem(i - start, displayItem);
    }

    Item prevItem = Item.get(Item.ARROW);
    prevItem.setNamedTag(new CompoundTag().putString("action", "prev"));
    prevItem.setCustomName(page > 1 ? TextFormat.YELLOW + "Предыдущая страница" : TextFormat.GRAY + "Предыдущая страница");
    inventory.setItem(48, prevItem);

    Item storageItem = Item.get(Item.CHEST);
    storageItem.setNamedTag(new CompoundTag().putString("action", "storage"));
    storageItem.setCustomName(TextFormat.GREEN + "Личное Хранилище");
    inventory.setItem(49, storageItem);

    Item nextItem = Item.get(Item.ARROW);
    nextItem.setNamedTag(new CompoundTag().putString("action", "next"));
    nextItem.setCustomName((end < sortedLots.size()) ? TextFormat.YELLOW + "Следующая страница" : TextFormat.GRAY + "Следующая страница");
    inventory.setItem(50, nextItem);

    Item sortPriceAsc = Item.get(Item.GOLD_INGOT);
    sortPriceAsc.setNamedTag(new CompoundTag().putString("action", "sort_price_asc"));
    sortPriceAsc.setCustomName(TextFormat.AQUA + " По стоимости (возр.)");
    inventory.setItem(45, sortPriceAsc);

    Item sortPriceDesc = Item.get(Item.GOLD_INGOT);
    sortPriceDesc.setNamedTag(new CompoundTag().putString("action", "sort_price_desc"));
    sortPriceDesc.setCustomName(TextFormat.AQUA + " По стоимости (убыв.)");
    inventory.setItem(46, sortPriceDesc);

    Item sortTimeAsc = Item.get(Item.CLOCK);
    sortTimeAsc.setNamedTag(new CompoundTag().putString("action", "sort_time_asc"));
    sortTimeAsc.setCustomName(TextFormat.AQUA + "\uE12C По дате (старые)");
    inventory.setItem(47, sortTimeAsc);

    Item sortTimeDesc = Item.get(Item.CLOCK);
    sortTimeDesc.setNamedTag(new CompoundTag().putString("action", "sort_time_desc"));
    sortTimeDesc.setCustomName(TextFormat.AQUA + " По дате (новые)");
    inventory.setItem(51, sortTimeDesc);

    Item sortItemAsc = Item.get(Item.BOOK);
    sortItemAsc.setNamedTag(new CompoundTag().putString("action", "sort_item_asc"));
    sortItemAsc.setCustomName(TextFormat.AQUA + " По алфавиту (A-Я)");
    inventory.setItem(52, sortItemAsc);

    Item closeButton = Item.get(Item.BARRIER);
    closeButton.setNamedTag(new CompoundTag().putString("action", "close"));
    closeButton.setCustomName(TextFormat.BOLD.toString() + TextFormat.RED + "✖ Закрыть");
    inventory.setItem(53, closeButton);

    auctionPages.put(inventory, page);
}

private void updateStorageInventory(FakeInventory inventory, Player player, int page) {
    @SuppressWarnings("unchecked")
    ArrayList<String> storageOrder = (ArrayList<String>) auctionData.getList("storage." + player.getUniqueId(), new ArrayList<>());
    List<Map.Entry<String, Map<String, Object>>> sortedStorage = getSortedStorage(player.getUniqueId());
    int maxPage = sortedStorage.isEmpty() ? 1 : (sortedStorage.size() + ITEMS_PER_PAGE - 1) / ITEMS_PER_PAGE;
    page = Math.max(1, Math.min(page, maxPage));

    inventory.clearAll();

    int start = (page - 1) * ITEMS_PER_PAGE;
    int end = Math.min(start + ITEMS_PER_PAGE, sortedStorage.size());

    for (int i = start; i < end; i++) {
        String storageId = sortedStorage.get(i).getKey();
        Map<String, Object> entry = sortedStorage.get(i).getValue();
        Item displayItem = createItemFromEntry(entry);
        if (displayItem == null) {
            plugin.getLogger().error("Не удалось создать предмет для storageId #" + storageId);
            continue;
        }

        List<String> lore = new ArrayList<>();
        lore.add(TextFormat.GRAY + "Количество: " + TextFormat.WHITE + displayItem.getCount());
        if (displayItem.getMaxDurability() > 0) {
            lore.add(TextFormat.GRAY + "Прочность: " + TextFormat.WHITE + (displayItem.getMaxDurability() - displayItem.getDamage()) + "/" + displayItem.getMaxDurability());
        }
        if (displayItem.hasEnchantments()) {
            lore.add(TextFormat.GRAY + "Чары:");
            for (Enchantment ench : displayItem.getEnchantments()) {
                lore.add(TextFormat.AQUA + ench.getName() + " " + ench.getLevel());
            }
        }
        lore.add(TextFormat.YELLOW + "Нажмите, чтобы забрать");
        displayItem.setLore(lore.toArray(new String[0]));
        inventory.setItem(i - start, displayItem);
    }

    Item prevItem = Item.get(Item.ARROW);
    prevItem.setNamedTag(new CompoundTag().putString("action", "prev"));
    prevItem.setCustomName(page > 1 ? TextFormat.YELLOW + "Предыдущая страница" : TextFormat.GRAY + "Предыдущая страница");
    inventory.setItem(48, prevItem);

    Item backItem = Item.get(Item.COMPASS);
    backItem.setNamedTag(new CompoundTag().putString("action", "back"));
    backItem.setCustomName(TextFormat.RED + "Вернуться на Торговую Площадь");
    inventory.setItem(49, backItem);

    Item nextItem = Item.get(Item.ARROW);
    nextItem.setNamedTag(new CompoundTag().putString("action", "next"));
    nextItem.setCustomName((end < sortedStorage.size()) ? TextFormat.YELLOW + "Следующая страница" : TextFormat.GRAY + "Следующая страница");
    inventory.setItem(50, nextItem);

    Item closeButton = Item.get(Item.BARRIER);
    closeButton.setNamedTag(new CompoundTag().putString("action", "close"));
    closeButton.setCustomName(TextFormat.BOLD.toString() + TextFormat.RED + "✖ Закрыть");
    inventory.setItem(53, closeButton);

    storagePages.put(inventory, page);
}

private List<Map.Entry<String, Map<String, Object>>> getSortedLots() {
    if (cachedSortedLots != null) {
        return cachedSortedLots;
    }

    List<Map.Entry<String, Map<String, Object>>> lots = new ArrayList<>();
    @SuppressWarnings("unchecked")
    ArrayList<String> order = (ArrayList<String>) auctionData.getList("order", new ArrayList<>());
    for (String auctionId : order) {
        Map<String, Object> lot = (Map<String, Object>) auctionData.get("auctions." + auctionId);
        if (lot == null || !lot.containsKey("timestamp") || !lot.containsKey("price") || !lot.containsKey("owner_uuid") || !lot.containsKey("item_id")) {
            plugin.getLogger().error("Лот #" + auctionId + " поврежден (отсутствуют обязательные ключи) и будет пропущен: " + (lot != null ? lot.toString() : "null"));
            continue;
        }
        lots.add(new AbstractMap.SimpleEntry<>(auctionId, lot));
    }

    lots.sort((entry1, entry2) -> {
        Map<String, Object> lot1 = entry1.getValue();
        Map<String, Object> lot2 = entry2.getValue();
        switch (sortMode) {
            case "price_asc":
                return Double.compare(((Number) lot1.get("price")).doubleValue(), ((Number) lot2.get("price")).doubleValue());
            case "price_desc":
                return Double.compare(((Number) lot2.get("price")).doubleValue(), ((Number) lot1.get("price")).doubleValue());
            case "time_asc":
            case "time_desc":
                Long timestamp1 = (Long) lot1.get("timestamp");
                Long timestamp2 = (Long) lot2.get("timestamp");
                long t1 = timestamp1 != null ? timestamp1 : 0;
                long t2 = timestamp2 != null ? timestamp2 : 0;
                return sortMode.equals("time_asc") ? Long.compare(t1, t2) : Long.compare(t2, t1);
            case "item_asc":
                Item item1 = createItemFromEntry(lot1);
                Item item2 = createItemFromEntry(lot2);
                String name1 = item1 != null ? (item1.hasCustomName() ? item1.getCustomName() : item1.getName()) : "";
                String name2 = item2 != null ? (item2.hasCustomName() ? item2.getCustomName() : item2.getName()) : "";
                return name1.compareToIgnoreCase(name2);
            default:
                return 0;
        }
    });

    cachedSortedLots = lots;
    return lots;
}

private List<Map.Entry<String, Map<String, Object>>> getSortedStorage(UUID playerUUID) {
    List<Map.Entry<String, Map<String, Object>>> cached = cachedSortedStorage.get(playerUUID);
    if (cached != null) {
        return cached;
    }

    List<Map.Entry<String, Map<String, Object>>> items = new ArrayList<>();
    @SuppressWarnings("unchecked")
    ArrayList<String> storageOrder = (ArrayList<String>) auctionData.getList("storage." + playerUUID, new ArrayList<>());
    for (String storageId : storageOrder) {
        Map<String, Object> item = (Map<String, Object>) auctionData.get("storage_items." + storageId);
        if (item == null || !item.containsKey("timestamp") || !item.containsKey("item_id")) {
            plugin.getLogger().error("Предмет хранилища #" + storageId + " поврежден (отсутствуют обязательные ключи) и будет пропущен: " + (item != null ? item.toString() : "null"));
            continue;
        }
        items.add(new AbstractMap.SimpleEntry<>(storageId, item));
    }

    items.sort((entry1, entry2) -> {
        Map<String, Object> item1 = entry1.getValue();
        Map<String, Object> item2 = entry2.getValue();
        switch (sortMode) {
            case "price_asc":
            case "price_desc":
                return sortMode.equals("price_asc") ?
                        Integer.compare(((Number) item1.get("item_id")).intValue(), ((Number) item2.get("item_id")).intValue()) :
                        Integer.compare(((Number) item2.get("item_id")).intValue(), ((Number) item1.get("item_id")).intValue());
            case "time_asc":
            case "time_desc":
                Long timestamp1 = (Long) item1.get("timestamp");
                Long timestamp2 = (Long) item2.get("timestamp");
                long t1 = timestamp1 != null ? timestamp1 : 0;
                long t2 = timestamp2 != null ? timestamp2 : 0;
                return sortMode.equals("time_asc") ? Long.compare(t1, t2) : Long.compare(t2, t1);
            case "item_asc":
                Item itemObj1 = createItemFromEntry(item1);
                Item itemObj2 = createItemFromEntry(item2);
                String name1 = itemObj1 != null ? (itemObj1.hasCustomName() ? itemObj1.getCustomName() : itemObj1.getName()) : "";
                String name2 = itemObj2 != null ? (itemObj2.hasCustomName() ? itemObj2.getCustomName() : itemObj2.getName()) : "";
                return name1.compareToIgnoreCase(name2);
            default:
                return 0;
        }
    });

    cachedSortedStorage.put(playerUUID, items);
    return items;
}

private Item createItemFromEntry(Map<String, Object> entry) {
    try {
        int itemId = ((Number) entry.get("item_id")).intValue();
        int itemDamage = ((Number) entry.get("item_damage")).intValue();
        int itemCount = ((Number) entry.get("item_count")).intValue();
        int itemDurability = ((Number) entry.get("item_durability")).intValue();

        Item item = Item.get(itemId, itemDamage, itemCount);
        if (itemDurability > 0) {
            item.setDamage(item.getMaxDurability() - itemDurability);
        }

        @SuppressWarnings("unchecked")
        ArrayList<Map<String, Object>> enchantmentsList = (ArrayList<Map<String, Object>>) entry.get("enchantments");
        for (Map<String, Object> enchData : enchantmentsList) {
            int enchId = ((Number) enchData.get("id")).intValue();
            int level = ((Number) enchData.get("level")).intValue();
            Enchantment ench = Enchantment.getEnchantment(enchId).setLevel(level);
            item.addEnchantment(ench);
        }
        return item;
    } catch (Exception e) {
        plugin.getLogger().error("Ошибка при создании предмета: " + e.getMessage());
        return null;
    }
}

private Map<String, Integer> getRankLimits(Player player) {
    RankManagerNukkitMOT rankManager = (RankManagerNukkitMOT) plugin.getServer().getPluginManager().getPlugin("RankManagerNukkit-MOT");
    String rank = rankManager != null ? rankManager.getPlayerRank(player) : "default";
    return plugin.getRankLimits(rank);
}

public boolean itemSell(Player player, String[] args) {
    if (args.length < 2) {
        player.sendMessage(TextFormat.DARK_RED + "✘ Использование: " + TextFormat.AQUA + "/auc " + TextFormat.GOLD + "sell " + TextFormat.GRAY + "цена");
        return true;
    }

    // Проверка лимита лотов на аукционе
    Map<String, Integer> limits = getRankLimits(player);
    int auctionLimit = limits.get("auction");
    @SuppressWarnings("unchecked")
    ArrayList<String> order = (ArrayList<String>) auctionData.getList("order", new ArrayList<>());
    long playerLots = order.stream()
            .filter(id -> {
                Map<String, Object> lot = (Map<String, Object>) auctionData.get("auctions." + id);
                return lot != null && lot.get("owner_uuid").equals(player.getUniqueId().toString());
            })
            .count();

    if (playerLots >= auctionLimit) {
        player.sendMessage(TextFormat.DARK_RED + "✘ Вы достигли лимита лотов на аукционе (" + auctionLimit + ") для вашего ранга!");
        return true;
    }

    double price;
    try {
        price = Double.parseDouble(args[1]);
        if (price <= 0) {
            player.sendMessage(TextFormat.DARK_RED + "✘ Цена должна быть " + TextFormat.GOLD + "положительным " + TextFormat.GRAY + "числом!");
            return true;
        }
    } catch (NumberFormatException e) {
        player.sendMessage(TextFormat.DARK_RED + "✘ Цена должна быть " + TextFormat.GOLD + "числом " + TextFormat.GRAY + "(например, 10 или 10.5)!");
        return true;
    }

    MainPlugin mainPlugin = MainPlugin.getInstance();
    if (mainPlugin == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка экономической системы!");
        plugin.getLogger().error("MainPlugin не инициализирован! Игрок: " + player.getName());
        return true;
    }
    EconomyManager economyManager = mainPlugin.getEconomyManager();
    if (economyManager == null) {
        player.sendMessage(TextFormat.RED + "✘ Экономика не инициализирована!");
        plugin.getLogger().error("EconomyManager не инициализирован! Игрок: " + player.getName());
        return true;
    }

    Item itemInHand = player.getInventory().getItemInHand();
    if (itemInHand == null || itemInHand.getId() == 0) {
        player.sendMessage(TextFormat.RED + "✘ В руке нет предмета! " + TextFormat.GOLD + "Возьмите в руку предмет " + TextFormat.GRAY + "чтобы продать");
        return true;
    }

    int itemId = itemInHand.getId();
    int itemCount = itemInHand.getCount();
    int itemDamage = itemInHand.getDamage();
    int itemDurability = itemInHand.getMaxDurability() > 0 ? itemInHand.getMaxDurability() - itemInHand.getDamage() : 0;
    Enchantment[] enchantments = itemInHand.getEnchantments();
    ArrayList<Map<String, Object>> enchantmentsList = new ArrayList<>();

    for (Enchantment enchantment : enchantments) {
        Map<String, Object> enchantmentData = new HashMap<>();
        enchantmentData.put("id", enchantment.getId());
        enchantmentData.put("level", enchantment.getLevel());
        enchantmentData.put("name", enchantment.getName());
        enchantmentsList.add(enchantmentData);
    }

    player.getInventory().setItemInHand(Item.get(0));

    String auctionEntryId = UUID.randomUUID().toString();
    Map<String, Object> auctionEntry = new HashMap<>();
    auctionEntry.put("owner_uuid", player.getUniqueId().toString());
    auctionEntry.put("owner_name", player.getName());
    auctionEntry.put("item_id", itemId);
    auctionEntry.put("item_count", itemCount);
    auctionEntry.put("item_damage", itemDamage);
    auctionEntry.put("item_durability", itemDurability);
    auctionEntry.put("enchantments", enchantmentsList);
    auctionEntry.put("price", price);
    auctionEntry.put("timestamp", System.currentTimeMillis());

    auctionData.set("auctions." + auctionEntryId, auctionEntry);
    order.add(0, auctionEntryId);
    auctionData.set("order", order);
    auctionData.save();
    cachedSortedLots = null;

    player.sendMessage(TextFormat.GREEN + "✔ Предмет успешно выставлен на торговую площадь за " + TextFormat.GOLD + price + TextFormat.GRAY + "!");
    return true;
}

private void returnToStorage(Player player, String auctionId, Map<String, Object> entry, ArrayList<String> order, int index) {
    // Проверка лимита хранилища
    Map<String, Integer> limits = getRankLimits(player);
    int storageLimit = limits.get("storage");
    @SuppressWarnings("unchecked")
    ArrayList<String> storageOrder = (ArrayList<String>) auctionData.getList("storage." + player.getUniqueId(), new ArrayList<>());
    if (storageOrder.size() >= storageLimit) {
        player.sendMessage(TextFormat.DARK_RED + "✘ Ваше хранилище заполнено! Лимит: " + storageLimit + " предметов для вашего ранга.");
        return;
    }

    String storageEntryId = UUID.randomUUID().toString();
    Map<String, Object> storageEntry = new HashMap<>();
    storageEntry.put("item_id", entry.get("item_id"));
    storageEntry.put("item_damage", entry.get("item_damage"));
    storageEntry.put("item_count", entry.get("item_count"));
    storageEntry.put("item_durability", entry.get("item_durability"));
    storageEntry.put("enchantments", entry.get("enchantments"));
    storageEntry.put("timestamp", System.currentTimeMillis());

    auctionData.set("storage_items." + storageEntryId, storageEntry);
    storageOrder.add(0, storageEntryId);
    auctionData.set("storage." + player.getUniqueId(), storageOrder);

    auctionData.remove("auctions." + auctionId);
    order.remove(index);
    auctionData.set("order", order);
    auctionData.save();
    cachedSortedLots = null;
    cachedSortedStorage.remove(player.getUniqueId());

    player.sendMessage(TextFormat.GREEN + "✔ Ваш предмет возвращен в личное хранилище!");
}

private void buyItem(Player player, String auctionId, Map<String, Object> entry, ArrayList<String> order, int index) {
    MainPlugin mainPlugin = MainPlugin.getInstance();
    if (mainPlugin == null) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка экономической системы!");
        plugin.getLogger().error("MainPlugin не инициализирован! Игрок: " + player.getName());
        return;
    }
    EconomyManager economyManager = mainPlugin.getEconomyManager();
    if (economyManager == null) {
        player.sendMessage(TextFormat.RED + "✘ Экономика не инициализирована!");
        plugin.getLogger().error("EconomyManager не инициализирован! Игрок: " + player.getName());
        return;
    }
    
    Map<String, Integer> limits = getRankLimits(player);
    int storageLimit = limits.get("storage");
    @SuppressWarnings("unchecked")
    ArrayList<String> storageOrder = (ArrayList<String>) auctionData.getList("storage." + player.getUniqueId(), new ArrayList<>());
    if (storageOrder.size() >= storageLimit) {
        player.sendMessage(TextFormat.DARK_RED + "✘ Ваше хранилище заполнено! Лимит: " + storageLimit + " предметов для вашего ранга.");
        return;
    }

    double price = ((Number) entry.get("price")).doubleValue();
    String ownerUUID = (String) entry.get("owner_uuid");
    double balance = economyManager.getBalance(player.getUniqueId());
    if (balance < price) {
        player.sendMessage(TextFormat.DARK_RED + "✘ Недостаточно средств!");
        return;
    }

    boolean success = economyManager.transferMoney(player, UUID.fromString(ownerUUID), price);
    if (!success) {
        player.sendMessage(TextFormat.RED + "✘ Ошибка перевода средств!");
        plugin.getLogger().error("Ошибка перевода средств для игрока: " + player.getName());
        return;
    }

    String storageEntryId = UUID.randomUUID().toString();
    Map<String, Object> storageEntry = new HashMap<>();
    storageEntry.put("item_id", entry.get("item_id"));
    storageEntry.put("item_damage", entry.get("item_damage"));
    storageEntry.put("item_count", entry.get("item_count"));
    storageEntry.put("item_durability", entry.get("item_durability"));
    storageEntry.put("enchantments", entry.get("enchantments"));
    storageEntry.put("timestamp", System.currentTimeMillis());

    auctionData.set("storage_items." + storageEntryId, storageEntry);
    storageOrder.add(0, storageEntryId);
    auctionData.set("storage." + player.getUniqueId(), storageOrder);

    auctionData.remove("auctions." + auctionId);
    order.remove(index);
    auctionData.set("order", order);
    auctionData.save();
    cachedSortedLots = null;
    cachedSortedStorage.remove(player.getUniqueId());

    player.sendMessage(TextFormat.GREEN + "✔ Предмет успешно куплен за " + TextFormat.GOLD + price + " и отправлен в личное хранилище!");
    Optional<Player> owner = plugin.getServer().getPlayer(UUID.fromString(ownerUUID));
    owner.ifPresent(p -> p.sendMessage(TextFormat.GREEN + player.getName() + " купил твой предмет за " + TextFormat.GOLD + price + "!"));
}

}

ООП бы еще , а так для 2-3х месяцев хорошо

нет, фигня

забыл что за 2-3 месяца писал?)

Спасибо, просто я школьник, из-за этого много свободного времени. лето = много свободного времени.

в целом если будешь развиваться в java и улучшать код, то все окей будет

его код - гпт бредятина, а тогда я писал не в сознании и не восхвалял свою работу как сейчас

возможно, в этот код он внес свой вклад, но гпт саму основу написал

не знаю что из чела выйдет, но если есть желание развиваться то даже не знаю

ну это ■■■■■■, гпт явный