BlackSpigot

Guide Spigot command project: validate config reloads and keep the last working settings

  • Thread starter Thread starter BlackSpigot Guides
  • Start date Start date
B

BlackSpigot Guides

Guest
Build on your first command
Start with the /workshop starter project, using its Maven project, Java 21 and Spigot API 1.21.1. This lesson adds /workshop reload. A broken YAML file must not replace the last working greeting, and ordinary players must not gain an administration command.

1. Replace the main class
Save this as src/main/java/com/example/workshop/WorkshopPlugin.java:
Java:
package com.example.workshop;
import java.io.File;
import java.io.IOException;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;

public final class WorkshopPlugin extends JavaPlugin {
    private String message;
    @Override public void onEnable() {
        saveDefaultConfig();
        if (!loadMessage()) getServer().getPluginManager().disablePlugin(this);
    }
    private boolean loadMessage() {
        YamlConfiguration candidate = new YamlConfiguration();
        try {
            candidate.load(new File(getDataFolder(), "config.yml"));
        } catch (IOException | InvalidConfigurationException error) {
            getLogger().warning("Could not load config.yml: " + error.getMessage());
            return false;
        }
        Object value = candidate.get("message");
        if (!(value instanceof String text) || text.isBlank()) {
            getLogger().warning("message must be a non-empty string.");
            return false;
        }
        message = text;
        return true;
    }
    @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
            if (!sender.hasPermission("workshop.reload")) {
                sender.sendMessage("You cannot reload this plugin.");
                return true;
            }
            sender.sendMessage(loadMessage() ? "Workshop configuration reloaded."
                : "Reload rejected; the previous message is still active. Check the console.");
            return true;
        }
        if (args.length != 0) return false;
        sender.sendMessage(message.replace("{player}", sender.getName()));
        return true;
    }
}

2. Declare both permissions
Replace src/main/resources/plugin.yml with:
YAML:
name: WorkshopHello
version: 1.1.0
main: com.example.workshop.WorkshopPlugin
api-version: '1.21'
commands:
  workshop:
    description: Show or reload the workshop greeting
    usage: /workshop [reload]
    permission: workshop.hello
permissions:
  workshop.hello:
    default: true
  workshop.reload:
    default: op
Keep src/main/resources/config.yml:
YAML:
message: 'Welcome, {player}! Your configuration loaded.'
Build with mvn clean package, replace the old plugin JAR on a stopped development server, and start it. Match the Java/API target to your server when adapting the project. The plugin descriptor reference explains command permissions and defaults.

3. Why the old message survives
The candidate configuration is separate from the active message. File parsing and the string check finish before assignment. A failed reload leaves that field alone; an invalid first startup disables this example because no working value exists yet. This is intentionally a one-setting exercise. For several related settings, validate all of them before replacing the active configuration together.

saveDefaultConfig preserves an existing administrator-edited file. The JavaPlugin configuration API also provides reloadConfig, but this example uses an explicit candidate to demonstrate validation and rejection. It does not use the server-wide /reload command.

4. Prove the failure cases
  • Run /workshop as a player and workshop from the console; both should receive a greeting.
  • Edit plugins/WorkshopHello/config.yml, then run /workshop reload as an operator. The next greeting should use the new text.
  • Set message to a YAML list or leave it blank. Reload should report rejection and preserve the previous greeting.
  • Introduce an unmatched quote. Reload should fail with a console explanation; restore the file and retry.
  • Use a non-operator account with workshop.reload denied. The reload attempt should be refused.
  • Run /workshop unknown; expect usage. Restart with an invalid file; expect this example to disable instead of reporting a successful load.
The permission belongs to the reload branch as well as the command declaration. Granting workshop.hello does not grant workshop.reload.

The Java example is compiled against the stated API. The player, console and restart checks require your development server.
 
Top