public class XpShopCommand {

    // Classe représentant un article du catalogue (équivalent de ton objet JS)
    public static class ShopEntry {
        public String id;
        public int count;
        public String nbt;
        public int price;

        public ShopEntry(String id, int count, String nbt, int price) {
            this.id = id;
            this.count = count;
            this.nbt = nbt;
            this.price = price;
        }
    }

    public static void register(CommandDispatcher<CommandSourceStack> dispatcher) {
        LiteralArgumentBuilder<CommandSourceStack> shopCommand = Commands.literal("shop")
            // --- Commande Joueur : /xp shop ---
            .requires(source -> {
                ServerPlayer player = source.getPlayer();
                if (player == null) return false;
                if (!Config.REQUIRE_PERMISSION) return true;
                return player.hasPermissions(2) || player.getTags().contains(Config.PERMISSION_TAG);
            })
            .executes(ctx -> {
                ServerPlayer player = ctx.getSource().getPlayerOrException();
                ShopManager.openXpShop(player);
                return 1;
            });

        // --- Commande Admin : /xp shop add <prix> ---
        shopCommand.then(Commands.literal("add")
            .requires(source -> source.hasPermission(2))
            .then(Commands.argument("prix", IntegerArgumentType.integer(1))
                .executes(ctx -> {
                    ServerPlayer player = ctx.getSource().getPlayerOrException();
                    int price = IntegerArgumentType.getInteger(ctx, "prix");
                    ItemStack heldItem = player.getMainHandItem();

                    if (heldItem.isEmpty()) {
                        player.sendSystemMessage(Component.literal("§cVous devez tenir un objet (vanilla ou moddé) dans votre main !"));
                        return 0;
                    }
                    if (price <= 0) {
                        player.sendSystemMessage(Component.literal("§cLe prix doit être supérieur à 0 niveau."));
                        return 0;
                    }

                    List<ShopEntry> catalog = ShopManager.loadList(player.getServer(), "xpShopCatalog");
                    String nbtString = heldItem.hasTag() ? heldItem.getTag().toString() : "{}";
                    String itemId = heldItem.getItem().toString(); // Ou BuiltInRegistries.ITEM.getKey(heldItem.getItem()).toString()

                    catalog.add(new ShopEntry(itemId, heldItem.getCount(), nbtString, price));

                    ShopManager.saveList(player.getServer(), "xpShopCatalog", catalog);
                    player.sendSystemMessage(Component.literal("§aArticle ajouté au catalogue (#" + catalog.size() + ") pour §e" + price + " niveaux §a!"));
                    player.playNotifySound(SoundEvents.ANVIL_USE, SoundSource.PLAYERS, 1.0F, 1.0F);
                    return 1;
                })
            )
        );

        // --- Commande Admin : /xp shop list ---
        shopCommand.then(Commands.literal("list")
            .requires(source -> source.hasPermission(2))
            .executes(ctx -> {
                CommandSourceStack source = ctx.getSource();
                List<ShopEntry> catalog = ShopManager.loadList(source.getServer(), "xpShopCatalog");

                if (catalog.isEmpty()) {
                    source.sendSuccess(() -> Component.literal("§cLe catalogue du shop est actuellement vide."), false);
                    return 1;
                }

                source.sendSuccess(() -> Component.literal("§6=== Catalogue du Shop XP ==="), false);
                for (int i = 0; i < catalog.size(); i++) {
                    ShopEntry entry = catalog.get(i);
                    ItemStack item = ShopManager.buildItem(entry);
                    int index = i + 1;
                    source.sendSuccess(() -> Component.literal(
                        "§e#" + index + " §8- §f" + entry.count + "x §b" + item.getHoverName().getString() + " §7(§a" + entry.price + " niveaux§7)"
                    ), false);
                }
                return 1;
            })
        );

        // --- Commande Admin : /xp shop remove <numéro> ---
        shopCommand.then(Commands.literal("remove")
            .requires(source -> source.hasPermission(2))
            .then(Commands.argument("numero", IntegerArgumentType.integer(1))
                .executes(ctx -> {
                    CommandSourceStack source = ctx.getSource();
                    int num = IntegerArgumentType.getInteger(ctx, "numero");
                    List<ShopEntry> catalog = ShopManager.loadList(source.getServer(), "xpShopCatalog");

                    if (num < 1 || num > catalog.size()) {
                        source.sendFailure(Component.literal("§cNuméro invalide. Choisissez un numéro entre 1 et " + catalog.size() + "."));
                        return 0;
                    }

                    ShopEntry removed = catalog.remove(num - 1);
                    ItemStack removedItem = ShopManager.buildItem(removed);
                    ShopManager.saveList(source.getServer(), "xpShopCatalog", catalog);

                    source.sendSuccess(() -> Component.literal(
                        "§aArticle §e#" + num + " §7(" + removed.count + "x " + removedItem.getHoverName().getString() + ") §asupprimé."
                    ), false);
                    return 1;
                })
            )
        );

        // --- Commande Admin : /xp shop refresh ---
        shopCommand.then(Commands.literal("refresh")
            .requires(source -> source.hasPermission(2))
            .executes(ctx -> {
                CommandSourceStack source = ctx.getSource();
                ShopManager.rotateShopItems(source.getServer(), true);
                source.sendSuccess(() -> Component.literal("§aLa boutique a été renouvelée manuellement !"), false);
                return 1;
            })
        );

        // --- Commande Admin : /xp shop clear ---
        shopCommand.then(Commands.literal("clear")
            .requires(source -> source.hasPermission(2))
            .executes(ctx -> {
                CommandSourceStack source = ctx.getSource();
                ShopManager.saveList(source.getServer(), "xpShopCatalog", new ArrayList<>());
                ShopManager.saveList(source.getServer(), "xpShopActive", new ArrayList<>());
                source.sendSuccess(() -> Component.literal("§cTout le catalogue du shop a été vidé."), false);
                return 1;
            })
        );

        // Enregistrement final de la commande /xp shop
        dispatcher.register(Commands.literal("xp").then(shopCommand));
    }
}

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: