### Java Example Command with Blade Annotations Source: https://github.com/vaperion/blade/blob/master/README.md Illustrates the creation of a command using Blade's annotation-based system in Java. It showcases various annotations for command definition, descriptions, permissions, hiding commands, asynchronous execution, argument parsing (including optional and greedy arguments), custom providers, and flags. The example defines a static method that accepts a CommandSender and other parameters like Player and String. ```java public class ExampleCommand { @Command("example") @Description("The description of your command, optional.") @Permission("command.permission") // Optional, set to "op" to require OP @Hidden // Optional, hides the command from the generated help @Async // Optional @Quoted // Optional, parses quoted strings into a single argument public static void example( // Command sender, required: @Sender CommandSender sender, // Type can be: CommandSender, Player, ConsoleCommandSender // Or any custom type if you register a SenderProvider. // Regular arguments: @Name("player") Player player, // You can make the argument optional (will be null if not provided): @Name("player") @Opt Player player, // or, you can make it default to the sender if not provided: @Name("player") @Opt(Opt.Type.SENDER) Player player, // Multi-word (combined) string arguments: @Name("message") @Greedy String message, // Number arguments with a range: @Name("amount") @Range(min = 1, max = 64) int amount, // You can also use custom providers for just one argument: @Provider(MyPlayerProvider.class) Player customPlayer, // And you can specify the scope (`BOTH`, `PARSER`, `SUGGESTIONS`), defaults to `BOTH`: @Provider(value = MyPlayerProvider.class, scope = Provider.Scope.SUGGESTIONS) Player customPlayer2, // Command flags: @Flag(value = 's', description = "Optional description") boolean flagSilent, // You can also have complex types as flags: @Flag('p') Player anotherPlayer ) { sender.sendMessage("(You -> " + anotherPlayer + ") $" + amount); if (!flagSilent) { player.sendMessage("(" + sender.getName() + " -> You) +$" + amount); } else { player.sendMessage("(Anonymous -> You) +$" + amount); } } } ``` -------------------------------- ### Initialize Blade for Bukkit Platform Source: https://context7.com/vaperion/blade/llms.txt Initializes the Blade command framework for the Bukkit platform. This example shows how to configure command qualifiers, default permission messages, argument parsing, custom sender types, permission predicates, and register commands. ```java import me.vaperion.blade.Blade; import me.vaperion.blade.bukkit.BladeBukkitPlatform; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.ChatColor; import org.bukkit.GameMode; public class MyPlugin extends JavaPlugin { private Blade blade; @Override public void onEnable() { blade = Blade.forPlatform(new BladeBukkitPlatform(this)) .config(cfg -> { cfg.commandQualifier("myplugin"); cfg.defaultPermissionMessage(ChatColor.RED + "No permission!"); cfg.strictArgumentCount(true); // Reject excess arguments cfg.lenientFlagMatching(false); // Strict flag validation }) .bind(binder -> { // Register custom argument types binder.bind(GameMode.class, new GameModeArgument()); binder.bind(TimeAmount.class, new TimeAmountArgument()); // Register custom sender types binder.bindSender(AdminSender.class, new AdminSenderProvider()); // Override default Player provider if needed binder.release(Player.class); binder.bind(Player.class, new CustomPlayerArgument()); }) .permission(predicates -> { // Register custom permission predicates predicates.predicate("@vip", (sender, permission) -> sender.hasPermission("rank.vip") || sender.hasPermission("rank.premium") ); predicates.predicate("@moderator", (sender, permission) -> sender.hasPermission("rank.moderator") || sender.isOp() ); }) .build() // Register all commands in a package (scans recursively) .registerPackage(MyPlugin.class, "com.example.plugin.commands") // Or register individual command classes .register(TeleportCommand.class) .register(new PayCommand()); // Can also pass instances } } ``` -------------------------------- ### Initialize Blade for Velocity Platform Source: https://context7.com/vaperion/blade/llms.txt Initializes the Blade command framework for the Velocity platform. This example demonstrates setting up Blade within a Velocity plugin, including configuration and package-based command registration. ```java import com.velocitypowered.api.proxy.ProxyServer; import com.velocitypowered.api.plugin.Plugin; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import me.vaperion.blade.Blade; import me.vaperion.blade.velocity.BladeVelocityPlatform; import com.google.inject.Inject; @Plugin(id = "myplugin", name = "My Plugin", version = "1.0.0") public class MyVelocityPlugin { private final ProxyServer server; private Blade blade; @Inject public MyVelocityPlugin(ProxyServer server) { this.server = server; } @Subscribe public void onProxyInitialization(ProxyInitializeEvent event) { blade = Blade.forPlatform(new BladeVelocityPlatform(server)) .config(cfg -> { cfg.commandQualifier("myvelocityplugin"); }) .bind(binder -> { // Player type is already registered for Velocity // Add custom argument providers here }) .build() .registerPackage(MyVelocityPlugin.class, "com.example.velocityplugin.commands"); } } ``` -------------------------------- ### Initialize Blade for Paper Platform Source: https://context7.com/vaperion/blade/llms.txt Initializes the Blade command framework for the Paper platform, leveraging its enhanced features. This example shows basic configuration and argument binding, emphasizing the use of `BladePaperPlatform` for improved Brigadier support. ```java import me.vaperion.blade.Blade; import me.vaperion.blade.paper.BladePaperPlatform; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.ChatColor; public class MyPaperPlugin extends JavaPlugin { private Blade blade; @Override public void onEnable() { // Use BladePaperPlatform for enhanced Brigadier support // For Minecraft 1.13+ (Java 21+): use the 'paper' artifact // For Minecraft 1.13+ (Java 17-21): use the 'paper-legacy' artifact // For Minecraft <1.13 or Java <17: use the 'bukkit' artifact with BladeBukkitPlatform blade = Blade.forPlatform(new BladePaperPlatform(this)) .config(cfg -> { cfg.commandQualifier("mypaperplugin"); cfg.defaultPermissionMessage(ChatColor.RED + "No permission!"); }) .bind(binder -> { // Register custom argument providers binder.bind(GameMode.class, new GameModeArgument()); }) .build() .registerPackage(MyPaperPlugin.class, "com.example.plugin.commands"); } } ``` -------------------------------- ### Basic Command with Required Parameters Source: https://context7.com/vaperion/blade/llms.txt Defines a simple command with a required player target. The framework automatically handles player validation and permission checks based on the annotations. This example demonstrates the basic structure of a command using `@Command`, `@Description`, `@Permission`, `@Sender`, and `@Name` annotations. ```java import me.vaperion.blade.annotation.command.Command; import me.vaperion.blade.annotation.command.Description; import me.vaperion.blade.annotation.command.Permission; import me.vaperion.blade.annotation.parameter.Sender; import me.vaperion.blade.annotation.parameter.Name; import org.bukkit.entity.Player; import org.bukkit.command.CommandSender; public class TeleportCommand { @Command("teleport") @Description("Teleport to a player") @Permission("server.teleport") public void teleport( @Sender Player sender, @Name("target") Player target ) { sender.teleport(target.getLocation()); sender.sendMessage("Teleported to " + target.getName()); } } // Usage: /teleport // Automatically validates player argument and checks permission ``` -------------------------------- ### Hierarchical Commands with Class-Level Prefix (Java) Source: https://context7.com/vaperion/blade/llms.txt Demonstrates how to define hierarchical commands using class-level annotations. It shows how to register commands with specific permissions and handle command arguments like players and reasons. The example includes 'kick' and 'ban' commands under the 'admin' command group. ```java import me.vaperion.blade.annotation.Command; import me.vaperion.blade.annotation.Permission; import me.vaperion.blade.annotation.Sender; import me.vaperion.blade.annotation.Name; import me.vaperion.blade.annotation.Opt; import org.bukkit.entity.Player; import com.destroystokyo.paper.entity.CraftPlayer; import net.md_5.bungee.api.CommandSender; @Command("admin") public class AdminCommands { @Command("kick") @Permission("admin.kick") public void kick(@Sender CommandSender sender, @Name("player") Player player) { player.kickPlayer("Kicked by administrator"); } @Command("ban") @Permission("admin.ban") public void ban( @Sender CommandSender sender, @Name("player") Player player, @Name("reason") @Opt @Greedy String reason ) { String banReason = reason != null ? reason : "Banned by administrator"; player.banPlayer(banReason); } } // Commands registered as: // /admin kick // /admin ban [reason...] ``` -------------------------------- ### Initialize Blade with Fabric Platform Source: https://context7.com/vaperion/blade/llms.txt This snippet demonstrates how to initialize the Blade command framework within a Fabric mod. It shows setting a command qualifier, binding custom providers, and registering command packages. ```java import net.fabricmc.api.ModInitializer; import me.vaperion.blade.Blade; import me.vaperion.blade.fabric.BladeFabricPlatform; public class MyFabricMod implements ModInitializer { private Blade blade; @Override public void onInitialize() { blade = Blade.forPlatform(new BladeFabricPlatform()) .config(cfg -> { cfg.commandQualifier("myfabricmod"); }) .bind(binder -> { // Register custom argument providers }) .build() .registerPackage(MyFabricMod.class, "com.example.fabricmod.commands"); } } ``` -------------------------------- ### Register Commands and Argument Types in a Java Plugin with Blade Source: https://github.com/vaperion/blade/blob/master/README.md Illustrates the process of enabling and configuring a Java plugin using the Blade framework. This includes setting up command qualifiers, default permission messages, binding custom providers for classes like Player and MySender, and registering commands either by package or individually. ```java public class MyPlugin extends JavaPlugin { @Override public void onEnable() { Blade.forPlatform(new BladeBukkitPlatform(this)) .config(cfg -> { cfg.commandQualifier("myplugin"); // Optional, defaults to your plugin's name cfg.defaultPermissionMessage("No permission!"); // Optional }) .bind(binder -> { binder.release(Player.class); // To remove the default provider binder.bind(Player.class, new MyPlayerProvider()); // To add your own binder.bindSender(MySender.class, new MySenderProvider()); // To add your own sender provider }) .build() // Now, you can register all commands in a package (including sub-packages): .registerPackage(MyPlugin.class, "com.example.commands") // or, you can register them individually: .register(ExampleCommand.class).register(AnotherCommand.class) ; } } ``` -------------------------------- ### Manual Argument Parsing with Context Source: https://context7.com/vaperion/blade/llms.txt Illustrates how to manually parse command arguments using the Blade Context. It shows accessing raw arguments, replying to the sender, and retrieving the Blade instance and command alias. ```java import me.vaperion.blade.context.Context; public class FlexibleCommand { @Command("flexible") public void flexible(@Sender Player sender, Context context) { // Access raw arguments String[] args = context.arguments(); // Reply to sender through context context.reply("Processing command with " + args.length + " arguments"); // Access the blade instance Blade blade = context.blade(); // Access the command alias used String alias = context.alias(); } } ``` -------------------------------- ### Command with Optional Parameters and Defaults Source: https://context7.com/vaperion/blade/llms.txt Illustrates a command with optional parameters, including a default sender for the target if not provided, a range-validated amount, and a greedy string for the reason. The `@Opt` annotation marks parameters as optional, `@Range` enforces numeric limits, and `@Greedy` captures remaining arguments. ```java import me.vaperion.blade.annotation.parameter.Opt; import me.vaperion.blade.annotation.parameter.Range; import me.vaperion.blade.annotation.parameter.Greedy; public class GiveMoneyCommand { @Command("givemoney") @Description("Give money to a player") @Permission("economy.admin") public void giveMoney( @Sender CommandSender sender, @Name("target") @Opt(Opt.Type.SENDER) Player target, @Name("amount") @Range(min = 1, max = 10000) int amount, @Name("reason") @Opt @Greedy String reason ) { // If no target specified, defaults to sender (if sender is Player) // If no reason specified, reason will be null // Amount is validated to be between 1 and 10000 // @Greedy consumes all remaining arguments into single string givePlayerMoney(target, amount); sender.sendMessage("Gave $" + amount + " to " + target.getName()); if (reason != null) { target.sendMessage("Reason: " + reason); } } } // Usage: /givemoney [player] [reason...] // Examples: // /givemoney 100 - gives self 100 // /givemoney Steve 500 - gives Steve 500 // /givemoney Steve 500 daily reward - gives Steve 500 with multi-word reason ``` -------------------------------- ### Optional Arguments with Default Types Source: https://context7.com/vaperion/blade/llms.txt Demonstrates the usage of the @Opt annotation for optional command arguments, showcasing different default value strategies including null, sender, and custom parsed values. ```java public class OptionalExamplesCommand { @Command("optexamples") public void optExamples( @Sender CommandSender sender, // Default to null (or primitive default for primitives) @Name("player1") @Opt Player player1, // Default to sender (for player types) @Name("player2") @Opt(Opt.Type.SENDER) Player player2, // Default to custom parsed value @Name("amount") @Opt(value = Opt.Type.CUSTOM, custom = "100") int amount, // Treat parse errors as empty instead of failing @Name("number") @Opt(treatErrorAsEmpty = true) Integer number ) { sender.sendMessage("Player1: " + (player1 != null ? player1.getName() : "null")); sender.sendMessage("Player2: " + player2.getName()); sender.sendMessage("Amount: " + amount); sender.sendMessage("Number: " + (number != null ? number : "invalid/empty")); } } ``` -------------------------------- ### Gradle Dependency Configuration for Blade Source: https://github.com/vaperion/blade/blob/master/README.md Demonstrates how to add the Blade framework as a dependency in a Gradle project. Similar to Maven, replace PLATFORM with the target artifact and VERSION with the desired version. The implementation configuration is used for runtime dependencies. ```groovy dependencies { // Replace VERSION with your desired version implementation 'io.github.vaperion.blade:PLATFORM:VERSION' } ``` -------------------------------- ### Custom Argument Provider for GameMode (Java) Source: https://context7.com/vaperion/blade/llms.txt Illustrates the creation of a custom argument provider for the `GameMode` enum in the Vaperion Blade framework. This provider handles parsing user input into `GameMode` values and offers tab completion suggestions. It also manages optional arguments and potential parsing errors gracefully. ```java import me.vaperion.blade.argument.ArgumentProvider; import me.vaperion.blade.argument.InputArgument; import me.vaperion.blade.context.Context; import me.vaperion.blade.exception.BladeParseError; import me.vaperion.blade.util.command.SuggestionsBuilder; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.bukkit.GameMode; public class GameModeArgument implements ArgumentProvider { @Override public @Nullable GameMode provide(@NotNull Context ctx, @NotNull InputArgument arg) { String input = arg.value(); // Handle optional arguments if (arg.status() == InputArgument.Status.NOT_PRESENT) { if (arg.isOptionalAcceptingNull()) { return null; } // Use custom default if specified if (arg.optional() != null && !arg.optional().custom().isEmpty()) { input = arg.optional().custom(); } } // Parse the game mode try { return GameMode.valueOf(input.toUpperCase()); } catch (IllegalArgumentException e) { // Check if parsing can fail silently for optional args if (arg.optional() != null && arg.optional().treatErrorAsEmpty()) { return null; } throw BladeParseError.recoverable("Invalid game mode: " + input); } } @Override public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) { // Provide tab completion suggestions suggestions.suggest("survival"); suggestions.suggest("creative"); suggestions.suggest("adventure"); suggestions.suggest("spectator"); } } // Usage in command: public class GameModeCommand { @Command("gamemode") @Permission("server.gamemode") public void gamemode( @Sender Player sender, @Name("mode") GameMode mode, @Name("target") @Opt(Opt.Type.SENDER) Player target ) { target.setGameMode(mode); sender.sendMessage("Set " + target.getName() + " to " + mode); } } // Usage: /gamemode [player] ``` -------------------------------- ### Command with Flags and Asynchronous Execution Source: https://context7.com/vaperion/blade/llms.txt Demonstrates a command that can be executed asynchronously using the `@Async` annotation, suitable for I/O operations. It also includes boolean flags for silent and anonymous payments, defined with `@Flag`, supporting both short and long name syntaxes. ```java import me.vaperion.blade.annotation.command.Async; import me.vaperion.blade.annotation.parameter.Flag; public class PayCommand { @Command("pay") @Description("Send money to a player") @Async // Executes in async thread for database operations public void pay( @Sender Player sender, @Name("target") Player target, @Name("amount") @Range(min = 1) double amount, @Flag(value = 's', description = "Silent payment") boolean silent, @Flag(value = 'a', longName = "anonymous", description = "Anonymous") boolean anonymous ) { // This runs asynchronously automatically database.transferMoney(sender, target, amount); String senderName = anonymous ? "Anonymous" : sender.getName(); if (!silent) { target.sendMessage("Received $" + amount + " from " + senderName); } sender.sendMessage("Sent $" + amount + " to " + target.getName()); } } // Usage: /pay [-s] [-a|--anonymous] // Examples: // /pay Steve 50 - normal payment // /pay Steve 50 -s - silent, Steve doesn't get notification // /pay Steve 50 -sa - silent and anonymous // /pay Steve 50 --anonymous - using long flag name ``` -------------------------------- ### Custom Annotations with @Forwarded Source: https://context7.com/vaperion/blade/llms.txt Shows how to create and use custom annotations for command parameters, leveraging @Forwarded to pass annotation data to argument providers for type-safe and context-aware argument resolution. ```java import me.vaperion.blade.annotation.api.Forwarded; import java.lang.annotation.*; // Define custom annotation with @Forwarded @Forwarded @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface DatabaseField { String table(); String column(); boolean required() default true; } // Access it in your argument provider public class DatabaseValueArgument implements ArgumentProvider { @Override public DatabaseValue provide(@NotNull Context ctx, @NotNull InputArgument arg) { // Access the custom annotation DatabaseField field = arg.annotation(DatabaseField.class); if (field != null) { String table = field.table(); String column = field.column(); boolean required = field.required(); // Use these values to query database return queryDatabase(table, column, arg.requireValue(), required); } throw BladeParseError.fatal("DatabaseField annotation required"); } @Override public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) { DatabaseField field = arg.annotation(DatabaseField.class); if (field != null) { // Provide suggestions based on database field suggestions.suggestAll(getDatabaseValues(field.table(), field.column())); } } } // Use in command public class DatabaseCommand { @Command("dbquery") public void query( @Sender CommandSender sender, @DatabaseField(table = "users", column = "username") DatabaseValue user, @DatabaseField(table = "items", column = "item_id", required = false) DatabaseValue item ) { sender.sendMessage("Queried: " + user + ", " + item); } } ``` -------------------------------- ### Create Java Data Argument Type for Blade Source: https://github.com/vaperion/blade/blob/master/README.md Demonstrates how to create a custom argument type in Java for the Blade framework. It includes a data class to hold the argument's value and status, and an ArgumentProvider implementation to parse and provide the data. Error handling for parsing and suggestion generation are also shown. ```java public class Data { public String message; public boolean wasProvided; } public class DataArgumentProvider implements ArgumentProvider { @Override public @Nullable Data provide(@NotNull Context ctx, @NotNull InputArgument arg) { Data data = new Data(); if (arg.status() == InputArgument.Status.NOT_PRESENT) { data.wasProvided = false; data.message = "Default value: " + arg.value(); } else { data.wasProvided = true; data.message = arg.value(); } // If you encounter an error while parsing, you may: throw new BladeUsageMessage(); // to show the usage message // or, to fail the command execution with a custom message: throw BladeParseError.fatal("Custom error message"); // or, to allow recovery if the argument is optional: throw BladeParseError.recoverable("Custom error message"); return data; } @Override public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) { suggestions.suggest("example"); } } ``` -------------------------------- ### Maven Dependency Configuration for Blade Source: https://github.com/vaperion/blade/blob/master/README.md Specifies how to include the Blade framework as a dependency in a Maven project. Replace PLATFORM with the appropriate artifact (e.g., 'bukkit', 'paper', 'fabric', 'velocity') and VERSION with the desired version. The scope is set to 'provided' as the server environment typically provides the necessary libraries. ```xml io.github.vaperion.blade PLATFORM VERSION provided ``` -------------------------------- ### Implement Custom Sender Provider for Admin Access in Java Source: https://context7.com/vaperion/blade/llms.txt This Java code defines a custom sender provider for the Blade framework. It creates an AdminSender class that wraps the original CommandSender and adds admin-specific functionality. The AdminSenderProvider checks for admin permissions before creating an AdminSender instance, ensuring that commands using this provider are only accessible to users with the required privileges. This enhances security and allows for role-specific command handling. ```java import me.vaperion.blade.sender.SenderProvider; import me.vaperion.blade.context.Sender; import me.vaperion.blade.context.Context; import me.vaperion.blade.exception.BladeParseError; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; public class AdminSender { private final CommandSender sender; private final boolean hasAdminAccess; public AdminSender(CommandSender sender, boolean hasAdminAccess) { this.sender = sender; this.hasAdminAccess = hasAdminAccess; } public void sendAdminMessage(String message) { sender.sendMessage(ChatColor.RED + "[ADMIN] " + message); } public CommandSender getSender() { return sender; } } public class AdminSenderProvider implements SenderProvider { @Override public @Nullable AdminSender provide(@NotNull Context ctx, @NotNull Sender sender) { CommandSender bukkitSender = (CommandSender) sender.sender(); boolean hasAdmin = bukkitSender.hasPermission("admin.access"); if (!hasAdmin) { throw BladeParseError.fatal("You must have admin access to use this command"); } return new AdminSender(bukkitSender, true); } } // Usage in command: public class AdminToolCommand { @Command("admintool") public void adminTool(@Sender AdminSender admin, @Name("action") String action) { admin.sendAdminMessage("Executing admin action: " + action); // Sender is guaranteed to have admin access } } ``` -------------------------------- ### Java Custom Usage Messages with Annotations Source: https://context7.com/vaperion/blade/llms.txt Shows how to customize command usage messages in Java using @Usage, @MainLabel, and @ExtraUsage annotations. @Usage provides a complete override, @MainLabel selects the primary alias for usage, and @ExtraUsage appends additional information. ```java import me.vaperion.blade.annotation.command.Usage; import me.vaperion.blade.annotation.command.MainLabel; import me.vaperion.blade.annotation.command.ExtraUsage; public class CustomUsageCommand { @Command({"give", "giveitem", "item"}) @MainLabel("give") // Sets "give" as the main label in usage messages @Usage("/give [amount] [-s]") @Description("Give an item to a player") public void giveWithCustomUsage( @Sender CommandSender sender, @Name("target") Player target, @Name("item") Material item, @Name("amount") @Opt(value = Opt.Type.CUSTOM, custom = "1") int amount, @Flag(value = 's', description = "Silent mode") boolean silent ) { target.getInventory().addItem(new ItemStack(item, amount)); if (!silent) { target.sendMessage("Received " + amount + "x " + item.name()); } } @Command("complex") @ExtraUsage("\nNote: This command requires special permissions.") @Description("A complex command with extra usage info") public void complexWithExtraUsage( @Sender Player sender, @Name("action") String action ) { // The @ExtraUsage text will be appended to the auto-generated usage sender.sendMessage("Executing: " + action); } } // @Usage overrides the auto-generated usage message completely // @MainLabel controls which alias appears in usage (useful with multiple aliases) // @ExtraUsage appends additional text to the end of the generated usage ``` -------------------------------- ### Implement Custom Argument Providers with @Provider (Java) Source: https://context7.com/vaperion/blade/llms.txt The @Provider annotation allows specifying a custom `ArgumentProvider` for a particular command parameter. This enables tailored logic for parsing and suggesting argument values, enhancing flexibility for parameter handling. ```java public class SpecialPlayerProvider implements ArgumentProvider { @Override public Player provide(@NotNull Context ctx, @NotNull InputArgument arg) { // Custom logic - e.g., search by partial name, UUID, or nickname String input = arg.requireValue(); return findPlayerByPartialName(input); } @Override public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) { // Suggest all online players plus offline VIPs suggestions.suggestAll(getOnlinePlayerNames()); suggestions.suggestAll(getVIPPlayerNames()); } } public class CustomProviderCommand { @Command("customfind") public void customFind( @Sender Player sender, // Use default Player provider @Name("normalPlayer") Player normalPlayer, // Use custom provider for this parameter only @Name("specialPlayer") @Provider(SpecialPlayerProvider.class) Player specialPlayer, // Use custom provider only for suggestions @Name("suggestionPlayer") @Provider(value = SpecialPlayerProvider.class, scope = Provider.Scope.SUGGESTIONS) Player suggestionPlayer ) { sender.sendMessage("Normal: " + normalPlayer.getName()); sender.sendMessage("Special: " + specialPlayer.getName()); sender.sendMessage("Suggestion: " + suggestionPlayer.getName()); } } ``` -------------------------------- ### Java Quote-Aware Parsing with @Quoted Source: https://context7.com/vaperion/blade/llms.txt Illustrates how to use the @Quoted annotation in Java for quote-aware argument parsing. This is useful when command arguments might contain spaces and need to be treated as a single unit, especially for messages. ```java import me.vaperion.blade.annotation.command.Quoted; public class MessageCommand { @Command("message") @Quoted // Enable quote-aware parsing public void message( @Sender Player sender, @Name("target") Player target, @Name("message") @Greedy String message ) { target.sendMessage("[From " + sender.getName() + "] " + message); } } // Without @Quoted: /message Steve hello world -> message = "hello world" // With @Quoted: /message Steve "hello world" -> message = "hello world" (quotes stripped) // With @Quoted: /message Steve hello "world test" -> message = "hello world test" ``` -------------------------------- ### Use Permission Predicates for Dynamic Command Access (Java) Source: https://context7.com/vaperion/blade/llms.txt Permission predicates allow for more dynamic permission checks in commands. A predicate is registered with a unique name and can then be referenced in the @Permission annotation. This enables complex permission logic beyond simple string checks. ```java // First register the predicate during initialization: .permission(predicates -> { predicates.predicate("@staff", (sender, perm) -> sender.hasPermission("rank.helper") || sender.hasPermission("rank.moderator") || sender.hasPermission("rank.admin") ); }) // Then use it in commands: public class StaffCommand { @Command("staff broadcast") @Permission("@staff") // Uses predicate instead of direct permission @Description("Broadcast message to all staff members") public void staffBroadcast( @Sender Player sender, @Name("message") @Greedy String message ) { broadcastToStaff("[STAFF] " + sender.getName() + ": " + message); } } ``` -------------------------------- ### Configure Strictness Control in Blade (Java) Source: https://context7.com/vaperion/blade/llms.txt This snippet demonstrates how to configure various strictness and logging options for the Blade framework. It allows control over argument count, flag matching, duplicate flags, verbose logging, execution time warnings, command overriding, and custom async executors. This configuration is crucial for tailoring the framework's behavior to specific plugin needs. ```java blade = Blade.forPlatform(new BladeBukkitPlatform(this)) .config(cfg -> { // Strict mode: reject excess arguments (default: true) cfg.strictArgumentCount(true); // Lenient flags: ignore unknown flags instead of treating as arguments (default: false) cfg.lenientFlagMatching(false); // Strict flags: reject duplicate flags (default: true) cfg.strictFlagCount(true); // Verbose logging for debugging cfg.verbose(true); // Warn about slow commands (in milliseconds) cfg.executionTimeWarningThreshold(1000); // Override vanilla commands cfg.overrideCommands(true); // Custom async executor cfg.asyncExecutor(Executors.newFixedThreadPool(4)); }) .build(); ``` -------------------------------- ### Java Complex Flag Usage with Required Flags Source: https://context7.com/vaperion/blade/llms.txt Demonstrates complex flag usage in Java, including long names, descriptions, and required flags. The 'transfer' command allows for various options like forcing a transfer, requesting confirmation, notifying admins, and specifying the transaction type, which is mandatory. ```java public class TransferCommand { @Command("transfer") @Permission("economy.transfer") public void transfer( @Sender Player sender, @Name("target") Player target, @Name("amount") @Range(min = 1) double amount, @Flag(value = 'f', longName = "force", description = "Force transfer") boolean force, @Flag(value = 'r', longName = "request", description = "Request confirmation") boolean requireConfirm, @Flag(value = 'n', longName = "notify", description = "Notify admins") boolean notifyAdmins, @Flag(value = 't', longName = "type", description = "Transaction type", required = true) String transactionType ) { if (requireConfirm && !force) { sendTransferRequest(sender, target, amount); sender.sendMessage("Transfer request sent to " + target.getName()); return; } boolean success = processTransfer(sender, target, amount, force, transactionType); if (success) { sender.sendMessage("Transferred $" + amount + " to " + target.getName()); target.sendMessage("Received $" + amount + " from " + sender.getName()); if (notifyAdmins) { notifyStaff(sender.getName() + " transferred $" + amount + " to " + target.getName()); } } } } // Usage: /transfer -t [-f|--force] [-r|--request] [-n|--notify] // Examples: // /transfer Steve 1000 -t payment --request // /transfer Steve 1000 --type refund --force // /transfer Steve 1000 -t gift -fn ``` -------------------------------- ### Parse Time Durations with Custom Argument Provider in Java Source: https://context7.com/vaperion/blade/llms.txt This snippet demonstrates how to create a custom ArgumentProvider in Java for parsing time durations (e.g., '5m', '1h', '30s', '1d') into a TimeAmount object. It handles parsing the value and unit, converting it to milliseconds, and includes suggestions for valid formats. This provider can be used in Blade commands to accept time-based arguments. ```java public class TimeAmount { public final long milliseconds; public final String formatted; public TimeAmount(long milliseconds, String formatted) { this.milliseconds = milliseconds; this.formatted = formatted; } } public class TimeAmountArgument implements ArgumentProvider { @Override public @Nullable TimeAmount provide(@NotNull Context ctx, @NotNull InputArgument arg) { if (arg.status() == InputArgument.Status.NOT_PRESENT) { return null; } String input = arg.requireValue(); // Parse formats like: 5m, 2h, 30s, 1d try { char unit = input.charAt(input.length() - 1); int value = Integer.parseInt(input.substring(0, input.length() - 1)); long millis = switch (unit) { case 's' -> value * 1000L; case 'm' -> value * 60000L; case 'h' -> value * 3600000L; case 'd' -> value * 86400000L; default -> throw new IllegalArgumentException(); }; return new TimeAmount(millis, input); } catch (Exception e) { throw BladeParseError.fatal("Invalid time format. Use: "); } } @Override public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) { suggestions.suggest("5m"); suggestions.suggest("1h"); suggestions.suggest("30s"); suggestions.suggest("1d"); } } // Usage in command: public class TempBanCommand { @Command("tempban") @Permission("admin.tempban") public void tempban( @Sender CommandSender sender, @Name("player") Player player, @Name("duration") TimeAmount duration, @Name("reason") @Opt @Greedy String reason ) { long expiry = System.currentTimeMillis() + duration.milliseconds; banPlayer(player, expiry, reason); sender.sendMessage("Banned " + player.getName() + " for " + duration.formatted); } } // Usage: /tempban <5m|1h|30s|1d> [reason...] ``` -------------------------------- ### Customize Parameters with @Data Annotation (Java) Source: https://context7.com/vaperion/blade/llms.txt The @Data annotation allows passing simple string values to parameter providers for customization. These values can be used to filter or modify the provided argument. For type-safe metadata, @Forwarded is recommended. ```java import me.vaperion.blade.annotation.parameter.Data; public class ItemArgument implements ArgumentProvider { @Override public @Nullable Material provide(@NotNull Context ctx, @NotNull InputArgument arg) { String input = arg.requireValue(); // Access the @Data annotation values List allowedCategories = arg.getData(); Material material = Material.matchMaterial(input); if (material == null) { throw BladeParseError.recoverable("Unknown item: " + input); } // Filter by category if specified if (!allowedCategories.isEmpty()) { String category = allowedCategories.get(0); if (category.equals("blocks") && !material.isBlock()) { throw BladeParseError.recoverable("Only blocks are allowed"); } if (category.equals("items") && material.isBlock()) { throw BladeParseError.recoverable("Only items are allowed"); } } return material; } @Override public void suggest(@NotNull Context ctx, @NotNull InputArgument arg, @NotNull SuggestionsBuilder suggestions) { List categories = arg.getData(); String category = categories.isEmpty() ? "all" : categories.get(0); for (Material mat : Material.values()) { if (category.equals("blocks") && !mat.isBlock()) continue; if (category.equals("items") && mat.isBlock()) continue; suggestions.suggest(mat.name().toLowerCase()); } } } public class DataExampleCommand { @Command("giveblock") public void giveBlock( @Sender Player sender, @Name("block") @Data("blocks") Material block ) { // Only accepts blocks due to @Data("blocks") sender.getInventory().addItem(new ItemStack(block, 1)); } @Command("giveitem") public void giveItem( @Sender Player sender, @Name("item") @Data("items") Material item ) { // Only accepts non-block items due to @Data("items") sender.getInventory().addItem(new ItemStack(item, 1)); } } // Note: @Data passes string values, for type-safe metadata use @Forwarded instead ``` -------------------------------- ### Java Enum Value Hiding with @HiddenEnumValue Source: https://context7.com/vaperion/blade/llms.txt Demonstrates using @HiddenEnumValue in Java to control enum value visibility in command arguments. This annotation can hide enum options from tab completion and optionally prevent their usage altogether. ```java import me.vaperion.blade.annotation.api.HiddenEnumValue; public enum GameDifficulty { PEACEFUL, EASY, NORMAL, HARD, @HiddenEnumValue // Hides from suggestions AND blocks usage HARDCORE, @HiddenEnumValue(block = false) // Hides from suggestions but still allows usage CREATIVE_MODE } public class DifficultyCommand { @Command("setdifficulty") @Permission("server.difficulty") public void setDifficulty( @Sender CommandSender sender, @Name("difficulty") GameDifficulty difficulty ) { // HARDCORE will be hidden from tab completion and rejected if used // CREATIVE_MODE will be hidden but still work if player types it manually world.setDifficulty(difficulty); sender.sendMessage("Set difficulty to " + difficulty); } } // Tab completion will show: peaceful, easy, normal, hard // Using "hardcore" as argument will fail // Using "creative_mode" will work but won't appear in suggestions ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.