License GPLv2.
This is a duck typing implementation based on reflection and dynamic proxies with force methods access. Perhaps it can be used as a wrapper for reflect.
Call with parameter contravariant.
class Foo {
void run() {
println("I'm running")
}
void print(String msg) {
println(msg)
}
}
Foo foo = new Foo()
Runnable runnable = Types.asType(foo, Runnable.class)
runnable.run()// I'm runningCall with method name map.
class Foo {
void run() {
println("I'm running")
}
}
Foo foo = new Foo()
Types.desc(Foo.class).map("run", Closeable.class, "close")
Types.asType(foo, Closeable.class).close()// I'm running
10x faster than PlaceholderAPI.setPlaceholder(Player, String)
import com.mengcraft.util.CompiledStr
import org.bukkit.Bukkit
def compiled = CompiledStr.compile("My name is %player_name%")
println compiled.apply(Bukkit.getPlayerExact("HIM")) // My name is HIMA fluent API for routing complex Bukkit/Spigot command trees with built-in support for tab-completion and argument validation. It simplifies the creation of multi-level commands (e.g., /mycmd user <name> set <value>).
- Declarative Syntax: Define entire command structures with a single string like
"user $player set $property $value". - Placeholder Arguments: Use
$-prefixed words (e.g.,$player) to capture arguments. - Context-Aware Tab Completion: Easily attach tab-completion logic to any argument.
- Argument Validation: Add validation rules to placeholder arguments.
- Clean Execution Logic: Assign an execution block to a valid command path.
- Automatic Routing: The router handles matching subcommands and arguments, delegating to the correct logic.
Here is how you can implement a command like /mycmd <subcommand> ... using the router.
import org.bukkit.Bukkit;
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 java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class MyCommand implements CommandExecutor, TabCompleter {
private final CommandRouter router = new CommandRouter();
public MyCommand() {
// Define '/mycmd user $user_name set $property $value'
router.addDefined("user $user_name set $property $value", def -> {
def.completion("user_name", (sender, context) ->
// Suggest online players for the $user_name argument
Bukkit.getOnlinePlayers().stream()
.map(Player::getName)
.filter(name -> name.toLowerCase().startsWith(context.poll().toLowerCase()))
.collect(Collectors.toList())
);
def.validation("user_name", (sender, context) -> {
// Optional: validate that the player is online
return Bukkit.getPlayer(context.tag("user_name")) != null;
});
def.completion("property", (sender, context) ->
// Suggest properties for the $property argument
Arrays.asList("health", "food", "level")
);
def.execution((sender, context) -> {
// This code runs when the full command is entered correctly
String userName = context.tag("user_name");
String property = context.tag("property");
String value = context.tag("value");
Player target = Bukkit.getPlayer(userName);
if (target == null) {
sender.sendMessage("Player " + userName + " not found.");
return true;
}
sender.sendMessage(String.format("Set %s's %s to %s.", userName, property, value));
// ... add logic to actually set the property
return true;
});
});
// Define '/mycmd reload'
router.addDefined("reload", def -> {
def.execution((sender, context) -> {
sender.sendMessage("Configuration reloaded.");
// ... add reload logic
return true;
});
});
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
// Delegate command execution to the router
if (!router.execute(sender, args)) {
sender.sendMessage("Unknown command. Use /mycmd help for help.");
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String label, String[] args) {
// Delegate tab completion to the router
return router.complete(sender, args);
}
}
// In your onEnable() method:
// this.getCommand("mycmd").setExecutor(new MyCommand());