Spigot Plugin

PotatoLand

Create a complete production-ready Minecraft Paper plugin named PotatoLand. Target: - Paper 1.21.11 - Java 21 - Maven - Package: me.potatocraft.potatoland Generate a complete Maven project with all Java files, plugin.yml and config.yml. Must compile with: mvn clean package Plugin purpose: Land rental/selling system. COMMAND: /zamin /zamin tool /zamin add <name> /zamin delete <name> confirm /zamin list /zamin reload Permission: potatoland.admin LAND TOOL: Create a special WOODEN_AXE selector using PersistentDataContainer. Name: &6&lPotato Land Selector Only admins can use it.

Read the full description

Right click block = position 1 Left click block = position 2 LAND: Admins create lands with /zamin add. Store using SQLite: - name - world UUID - min/max XYZ - owner UUID/name - purchase time - expiration time - price - material - sign location Prevent duplicate names and overlapping regions. Database: Create automatically: plugins/PotatoLand/database.db MARKET SIGN: Format: [House1] 5 DIAMOND Support any Bukkit Material and any positive amount. Examples: 5 DIAMOND 32 EMERALD 10 GOLD_INGOT Case insensitive. BUY SYSTEM: Players right click signs. Check: - land exists - available - enough items Remove exact material amount. Set owner and rental time. Rental duration: 30 days using timestamps. After expiration: - remove owner - release land - update sign - allow repurchase PROTECTION: Protect owned lands from: - break/place blocks - containers - doors - trapdoors - gates - buttons - levers - furnaces - crafting tables - anvils - villagers - animals Owner allowed. Admins bypass. PLACEHOLDERAPI soft support: %potatoland_land% %potatoland_owner% %potatoland_days_left% %potatoland_expiration% %potatoland_has_land% Compatible with TAB and scoreboards. Do not create scoreboard or tablist. Use clean architecture: command database land listener sign placeholder util Include: PotatoLand.java ZaminCommand.java LandManager.java DatabaseManager.java SelectionManager.java ProtectionListener.java SignListener.java PurchaseManager.java ExpirationManager.java PlaceholderAPI expansion. Do not simplify. Do not remove features. Generate complete source code.

src/main/java/me/potatocraft/potatoland/command/ZaminCommand.java
package me.potatocraft.potatoland.command;

import me.potatocraft.potatoland.database.DatabaseManager;
import me.potatocraft.potatoland.land.LandManager;
import me.potatocraft.potatoland.land.PurchaseManager;
import me.potatocraft.potatoland.land.SelectionManager;
import me.potatocraft.potatoland.util.ConfigManager;
import me.potatocraft.potatoland.util.MessageUtil;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public final class ZaminCommand implements CommandExecutor, TabCompleter {

    private final LandManager landManager;
    private final SelectionManager selectionManager;
    private final PurchaseManager purchaseManager;
    private final MessageUtil messageUtil;
    private final ConfigManager configManager;
    private final DatabaseManager databaseManager;
    private final String permission = "potatoland.admin";

    public ZaminCommand(Object plugin,
                        LandManager landManager,
                        SelectionManager selectionManager,
                        PurchaseManager purchaseManager,
                        MessageUtil messageUtil,
                        ConfigManager configManager,
                        DatabaseManager databaseManager) {
        this.landManager = landManager;
        this.selectionManager = selectionManager;
        this.purchaseManager = purchaseManager;
        this.messageUtil = messageUtil;
        this.configManager = configManager;
        this.databaseManager = databaseManager;
    }

    @Override
    public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
        if (args.length == 0) {
            messageUtil.send(sender, "&6/zamin tool&7, &6/zamin add <name>&7, &6/zamin delete <name> confirm&7, &6/zamin list&7, &6/zamin reload");
            return true;
        }

        String sub = args[0].toLowerCase();
        if (!sender.hasPermission(permission)) {
            messageUtil.send(sender, "no-permission");
            return true;
        }

        switch (sub) {