Запомни код
package ru.dragonsfixer;

import com.google.inject.Inject;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.event.command.CommandExecuteEvent.CommandResult;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
import org.yaml.snakeyaml.Yaml;

@Plugin(
        id = "dragonsfixer",
        name = "DragonsFixer",
        version = "1.0",
        description = "Prevents command spam",
        authors = {"boboliii"}
)
public class DragonsFixer {
    private final ProxyServer server;
    private final Path dataDirectory;
    private final Map<UUID, Long> cooldowns = new HashMap<>();
    private final Map<UUID, Integer> warningCounts = new HashMap<>();
    private int cooldownTime;
    private String spamMessage;
    private int maxWarnings;
    private long blockTime;

    @Inject
    public DragonsFixer(ProxyServer server, @DataDirectory Path dataDirectory) {
        this.server = server;
        this.dataDirectory = dataDirectory;
    }

    @Subscribe
    public void onProxyInitialization(ProxyInitializeEvent event) {
        // Создание директории для хранения конфигурации, если она не существует
        if (!Files.exists(this.dataDirectory, new LinkOption[0])) {
            try {
                Files.createDirectory(this.dataDirectory);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Загрузка конфигурационного файла
        File configFile = this.dataDirectory.resolve("config.yml").toFile();
        if (!configFile.exists()) {
            try (InputStream in = this.getClass().getResourceAsStream("/config.yml")) {
                Files.copy(in, configFile.toPath(), new CopyOption[0]);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        // Чтение конфигурации
        try {
            Yaml yaml = new Yaml();
            Map<String, Object> config = yaml.load(new FileInputStream(configFile));

            this.cooldownTime = ((Number)config.get("cooldown")).intValue();
            this.spamMessage = (String)config.get("spam-message");
            this.maxWarnings = ((Number)config.get("max-warnings")).intValue();
            this.blockTime = ((Number)config.get("block-time")).longValue();
        } catch (Exception e) {
            e.printStackTrace();
            this.cooldownTime = 500;
            this.spamMessage = "§6DragonsGrief §7» §c§lНе спамь!";
            this.maxWarnings = 20;
            this.blockTime = 1500; // 1500 milliseconds по умолчанию
        }
    }

    @Subscribe
    public void onCommand(CommandExecuteEvent event) {
        CommandSource commandSource = event.getCommandSource();
        if (commandSource instanceof Player) {
            Player player = (Player) commandSource;
            UUID playerId = player.getUniqueId();
            long currentTime = System.currentTimeMillis();

            // Проверка кулдауна
            if (this.cooldowns.containsKey(playerId) && (currentTime - this.cooldowns.get(playerId) < this.cooldownTime)) {
                event.setResult(CommandResult.denied());
                warnPlayer(player);
                return;
            }

            // Проверка на максимальное количество варнингов
            if (warningCounts.getOrDefault(playerId, 0) >= maxWarnings) {
                event.setResult(CommandResult.denied());
                player.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(spamMessage.replace("§", "&")));
                return;
            }

            // Установка времени последней команды
            this.cooldowns.put(playerId, currentTime);
        }
    }

    private void warnPlayer(Player player) {
        UUID playerId = player.getUniqueId();
        int warnings = warningCounts.getOrDefault(playerId, 0) + 1;
        warningCounts.put(playerId, warnings);
        player.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(spamMessage.replace("§", "&")));

        // Проверка, превышает ли количество предупреждений лимит
        if (warnings >= maxWarnings) {
            // Блокируем команды на указанное время
            server.getScheduler().buildTask(this, () -> {
                warningCounts.remove(playerId); // Очистка предупреждений после истечения времени
            }).delay(java.time.Duration.ofMillis(blockTime)).schedule();
        }
    }
}


Config.yml
# Время кулдауна в миллисекундах
# 1000 = 1 секунда
# 10000 = 10 секунд
cooldown: 500

# Максимальное количество предупреждений, после которого игрок будет заблокирован от ввода команд
max-warnings: 30

# Время блокировки команд в миллисекундах
# 1500 = 1.5 секунды
# 5000 = 5 секунд
block-time: 2000

# Сообщение, которое будет отправлено игрокам, если они спамят команды.
# Используйте символы цвета для настройки формата сообщения:
# §6 - золотой
# §7 - серый
# §c - красный
# §l - жирный
spam-message: "§6DragonsGrief §7» §c§lНе спамь!"