Skip to content

Quick Start

Petrus Pradella edited this page Aug 1, 2026 · 5 revisions

Quick Start

This builds a tiny but complete Bukkit plugin on top of EverNifeCore: an annotated command with a typed argument, a configurable value, and a localized message - the four things almost every plugin needs. It assumes you have the dependency set up (Installation).

The shape is always the same:

onEnable → grab your ECPluginData → open a config → scan your messages → register your command.


1. The command

A command is a plain class annotated with @FinalCMD. Each method annotated with @FinalCMD.SubCMD is a subcommand. Method parameters are auto-injected: an FCommandSender (or FPlayer) for the caller, and any @Arg-annotated parameter is parsed from the typed input - <amount> means required, [amount] would mean optional.

package com.example.myplugin;

import br.com.finalcraft.evernifecore.api.common.commandsender.FCommandSender;
import br.com.finalcraft.evernifecore.api.common.player.FPlayer;
import br.com.finalcraft.evernifecore.commands.finalcmd.annotations.Arg;
import br.com.finalcraft.evernifecore.commands.finalcmd.annotations.FinalCMD;

@FinalCMD(
        aliases = {"greet", "hi"},
        permission = "myplugin.greet"
)
public class GreetCommand {

    @FCLocale(lang = LocaleType.EN_US, text = "&aWelcome, ${player}&a! Your join bonus is &6${bonus}&a.")
    @FCLocale(lang = LocaleType.PT_BR, text = "&aBem-vindo, ${player}&a! Seu bônus de entrada é &6${bonus}&a.")
    private static LocaleMessage WELCOME_MESSAGE_INSIDE_THE_COMMAND;

    // /greet me
    @FinalCMD.SubCMD(
      subcmd = "me"
    )
    public void greetMe(FPlayer player) {
      WELCOME_MESSAGE_INSIDE_THE_COMMAND
                .addPlaceholder("player", player.getName())
                .addPlaceholder("bonus", ConfigManager.joinBonus)
                .send(player);
    }

    // /greet bonus <amount>   -> <amount> is parsed straight into an int
    @FinalCMD.SubCMD(
      subcmd = "bonus",
      permission = "myplugin.greet.bonus"
    )
    public void setBonus(FCommandSender sender, @Arg("<amount>") Integer amount) {
        ConfigManager.joinBonus = amount;
        Messages.BONUS_SET
                .addPlaceholder("amount", amount)
                .send(sender);
    }
}

Integer, String, Boolean, Player, enums and more are parsed out of the box. To parse your own types, or for the <>/[] rules and tab-completion, see Argument Parsing; for subcommands, per-subcommand permissions, help and access validation, see Command Framework.


2. The messages

Localized messages are static LocaleMessage fields, each declared with one @FCLocale per language. ${placeholder} tokens are filled at send time - the key is declared bare and cited with its delimiters in the text. Use & color codes.

package com.example.myplugin;

import br.com.finalcraft.evernifecore.locale.FCLocale;
import br.com.finalcraft.evernifecore.locale.LocaleMessage;
import br.com.finalcraft.evernifecore.locale.LocaleType;

public class Messages {

    @FCLocale(lang = LocaleType.EN_US, text = "&eJoin bonus set to &6${amount}&e.")
    @FCLocale(lang = LocaleType.PT_BR, text = "&eBônus de entrada definido para &6${amount}&e.")
    public static LocaleMessage BONUS_SET;

}

The fields start out null; they are populated when the class is scanned at startup (step 4). Each language is synced to a file under your plugin's data folder, so server owners can edit the wording. Full details on Localization.


3. The config

Open a config through ConfigFactory and read values with getOrSetValueIfAbsent(path, default, comment) - on a fresh install it seeds the key and its comment into the file, on an existing install it just reads it. The commented config.yml is therefore generated from your code; you never ship a bundled default file.

package com.example.myplugin;

import br.com.finalcraft.evernifecore.config.ConfigFactory;
import br.com.finalcraft.evernifecore.ecplugin.ECPluginData;
import br.com.finalcraft.evernifecore.locale.scanner.FCLocaleScanner;
import br.com.finalcraft.everyconfig.config.Config;

public final class ConfigManager {

    public static Config config;
    public static int joinBonus;

    private ConfigManager() {
    }

    public static void initialize(ECPluginData plugin) {
        config = ConfigFactory.open(plugin, "config.yml");

        joinBonus = config.getOrSetValueIfAbsent(
              "settings.join-bonus", 
              100,
              "Bonus shown to a player when they run /greet me."
        );

        // getOrSetValueIfAbsent only stages seeded keys in memory - write them out once.
        config.saveIfNewSeededDefaults();

        // Populate the static LocaleMessage fields of Messages.
        FCLocaleScanner.scanForLocale(plugin, false, Messages.class);
    }
}

Config comes from the bundled EveryConfig layer; the full API (nested sections, lists, custom types, async save, reload) is on Configuration.


4. Wiring it up

The entry point is an ordinary JavaPlugin. The one EverNifeCore-specific step is turning your plugin into an ECPluginData - the handle every EverNifeCore facility takes (config, locale, commands, player data). The @ECPlugin annotation opts your plugin into the framework's lifecycle.

package com.example.myplugin;

import br.com.finalcraft.evernifecore.commands.finalcmd.FinalCMDManager;
import br.com.finalcraft.evernifecore.ecplugin.ECPluginData;
import br.com.finalcraft.evernifecore.ecplugin.ECPluginManager;
import br.com.finalcraft.evernifecore.ecplugin.annotations.ECPlugin;
import org.bukkit.plugin.java.JavaPlugin;

@ECPlugin
public class MyPlugin extends JavaPlugin {

    @Override
    public void onEnable() {
        ECPluginData ecPluginData = ECPluginManager.getOrCreateECorePluginData(this);

        ConfigManager.initialize(ecPluginData);                      // config + locale scan
        FinalCMDManager.registerCommand(ecPluginData, GreetCommand.class);

        getLogger().info("MyPlugin enabled.");
    }
}

And the plugin.yml (EverNifeCore must load first, so depend on it):

name: MyPlugin
version: 1.0.0
main: com.example.myplugin.MyPlugin
api-version: 1.13
depend: [EverNifeCore]

What you get

Build the JAR, drop it next to EverNifeCore in plugins/, and restart. On first boot the plugin creates plugins/MyPlugin/config.yml (with your seeded join-bonus and its comment) and a language file for the messages. Then:

  • /greet me sends the localized welcome with the configured bonus.
  • /greet bonus 250 parses 250 into an int, updates the value, and confirms - gated behind myplugin.greet.bonus.

No onCommand boilerplate, no manual argument parsing, no hardcoded English strings.


Next steps

Clone this wiki locally