- Баллы
- 61
- Имя в Minecraft
- AlohaDanse
Представляю вашему вниманию простенькую утилиту для быстрой регистрации таб комплитеров и вообще, создания команд.
В этом интерфейсе мы задаем:
Класс, который мы будет использовать для классов наших команд:
Как это использовать:
Тут мы вначале названия нашего класса написали аннотацию @CommandInfo(), в которую передали name, permission и requirePlayer.
Теперь я хочу показать, как при помощи рефлексии быстро регистрировать наши команды.
Но для начала нужно добавить в свой проект зависимость:
MAVEN
Gradle
После добавления зависимости пишем в методе onEnable() в нашем основном классе вот это:
И все! Все ваши команды будут автоматически регистрироваться при загрузке вашего плагина!
Источник: Jordan Osterberg
Основной интерфейс:
Пройдемся по переменным:
Enum со всеми типами:
И еще нам нужен один интерфейс, который дает возможность добавлять неограниченное количество таб комплитеров в нашу команду:
И вот основной класс для регистрации наших автозаполнителей:
Далее мы должны добавить в метод onEnable() нашего плагина вот это:
Как это работает в классе команд?
В игре:
Как это работает?
Аннотация, которая ставится в начало класса вашей команды, и в ней содержится вся основная информация: название команды (сама команда), права на команду и от кого будет выполнятся команда.Примеры и сам код:
Создаем основной интерфейс:
Код:
package com.example.package;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface CommandInfo {
String name();
String permission() default "";
boolean requirePlayer();
}
В этом интерфейсе мы задаем:
- name() - название команды
- permission() - права (по дефолту, если не написали, пусто)
- requirePlayer() - true = команда используется только игроком, false = команда может использоваться в консоли и игроком тоже.
Класс, который мы будет использовать для классов наших команд:
Код:
package com.example.package;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Objects;
public class PluginCommand implements CommandExecutor {
private final CommandInfo commandInfo;
public PluginCommand() {
this.commandInfo = getClass().getDeclaredAnnotation(CommandInfo.class);
Objects.requireNonNull(commandInfo, "Команды должны быть помечены аннотацией @CommandInfo)");
}
public CommandInfo getCommandInfo() {
return commandInfo;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!commandInfo.permission().isEmpty()) {
if (!sender.hasPermission(commandInfo.permission())) {
Player player = (Player) sender;
sender.sendMessage(ChatColor.RED +"У вас нету прав!");
return true;
}
}
if (commandInfo.requirePlayer()) {
if (!(sender instanceof Player)) {
sender.sendMessage(ChatColor.RED + "Ты не игрок!");
return true;
}
execute((Player) sender, args);
}
execute(sender, args);
return true;
}
public void execute(Player player, String[] args) {}
public void execute(CommandSender sender, String[] args) {}
}
Как это использовать:
Код:
package com.example.package.commands;
import com.example.package.CommandInfo;
import com.example.package.PluginCommand;
import org.bukkit.entity.Player;
@CommandInfo(name = "example", permission = "example.use", requirePlayer = true)
// Команда /example с правами example.use может использоваться только игроками.
public class FraqMineCommand extends PluginCommand {
@Override
public void execute(Player player, String[] args) {
player.sendMessage("Привет!");
}
}
Теперь я хочу показать, как при помощи рефлексии быстро регистрировать наши команды.
Но для начала нужно добавить в свой проект зависимость:
MAVEN
Код:
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
</dependency>
Код:
implementation 'org.reflections:reflections:0.10.2'
После добавления зависимости пишем в методе onEnable() в нашем основном классе вот это:
Код:
String packageName = getClass().getPackage().getName();
for (Class<? extends PluginCommand> clazz : new Reflections(packageName + ".Commands") // тут вы можете поставить путь до своего пакета с классами команд
.getSubTypesOf(PluginCommand.class)
) {
try {
PluginCommand pluginCommand = clazz.getDeclaredConstructor().newInstance();
getCommand(pluginCommand.getCommandInfo().name()).setExecutor(pluginCommand);
} catch (InstantiationException | InvocationTargetException | IllegalAccessException |
NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
И все! Все ваши команды будут автоматически регистрироваться при загрузке вашего плагина!
Источник: Jordan Osterberg
И это все?
Нет, это не все! Хочу предоставить, почти такой же скрипт для создания Tab Completer, используя все те же аннотации.Основной интерфейс:
Код:
package com.example.package.TabCompleter;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(TabCompleterConfigs.class)
public @interface TabCompleterConfig {
TabType type();
String[] completers() default {};
int argument();
String[] follow() default {};
}[/SIZE]
Пройдемся по переменным:
- type() - тип (объяснение будет ниже)
- completers() - лист с автозаполнителями
- argument() - аргумент начиная с 1, на котором будет действовать этот TabCompleter
Enum со всеми типами:
Код:
package com.example.package.TabCompleter;
public enum TabType {
PLAYERS,
CUSTOM,
MATERIAL
}[/SIZE]
И еще нам нужен один интерфейс, который дает возможность добавлять неограниченное количество таб комплитеров в нашу команду:
Код:
package com.example.package.TabCompleter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface TabCompleterConfigs {
TabCompleterConfig[] value();
}[/SIZE]
И вот основной класс для регистрации наших автозаполнителей:
Код:
package com.example.package;
import com.example.package.Example;
import com.example.package.TabCompleter.TabCompleterConfig;
import com.example.package.TabCompleter.TabCompleterConfigs;
import com.example.package.TabCompleter.TabType;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.HumanEntity;
import org.reflections.Reflections;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CommandTabCompleter {
public static void registerTabCompleters(FraqMine plugin) {
String packageName = plugin.getClass().getPackage().getName();
// Сканируем все команды (CommandExecutor)
for (Class<?> clazz : new Reflections(packageName + ".Commands").getSubTypesOf(org.bukkit.command.CommandExecutor.class)) {
if (clazz.isAnnotationPresent(TabCompleterConfigs.class)) {
registerTabCompleter(plugin, clazz, clazz.getAnnotation(TabCompleterConfigs.class).value());
} else if (clazz.isAnnotationPresent(TabCompleterConfig.class)) {
registerTabCompleter(plugin, clazz, new TabCompleterConfig[]{clazz.getAnnotation(TabCompleterConfig.class)});
}
}
}
private static void registerTabCompleter(FraqMine plugin, Class<?> commandClass, TabCompleterConfig[] annotations) {
try {
// Получаем аннотацию @CommandInfo
CommandInfo commandInfo = commandClass.getAnnotation(CommandInfo.class);
if (commandInfo == null) {
plugin.getLogger().warning("Класс " + commandClass.getName() + " не имеет аннотации @CommandInfo!");
return;
}
String commandName = commandInfo.name(); // Используем имя команды из аннотации
PluginCommand command = plugin.getCommand(commandName);
if (command == null) {
plugin.getLogger().warning("Команда '" + commandName + "' не зарегистрирована!");
return;
}
TabCompleter tabCompleter = (sender, cmd, alias, args) -> {
for (TabCompleterConfig annotation : annotations) {
String input = (args.length > 0 ? args[args.length - 1] : "").toLowerCase();
// Если указаны условия follow, проверяем их:
if (annotation.follow().length > 0) {
// Если в follow содержится "*", условие считается выполненным для любого значения
boolean wildcard = Arrays.asList(annotation.follow()).contains("*");
if (!wildcard) {
// Определяем предыдущий аргумент:
// Если ожидается аргумент 2, то предыдущий – это args[0]
// Для аргументов больше 2 – берем args[annotation.argument() - 2]
if (annotation.argument() == 2) {
if (args.length < 1) continue;
String previousArg = args[0].toLowerCase();
if (Arrays.stream(annotation.follow()).noneMatch(f -> f.equalsIgnoreCase(previousArg))) {
continue;
}
} else {
if (args.length < annotation.argument()) continue;
String previousArg = args[annotation.argument() - 2].toLowerCase();
if (Arrays.stream(annotation.follow()).noneMatch(f -> f.equalsIgnoreCase(previousArg))) {
continue;
}
}
}
}
if (args.length == annotation.argument()) {
if (annotation.type() == TabType.PLAYERS) {
return Bukkit.getOnlinePlayers().stream()
.map(HumanEntity::getName)
.filter(name -> name.toLowerCase().startsWith(input))
.collect(Collectors.toList());
} else if (annotation.type() == TabType.CUSTOM) {
return Arrays.stream(annotation.args())
.filter(val -> val.toLowerCase().startsWith(input))
.collect(Collectors.toList());
} else if (annotation.type() == TabType.MATERIAL) {
return Arrays.stream(Material.values())
.map(material -> material.getKey().toString()
.replace(material.getKey().getNamespace() + ":", ""))
.filter(id -> id.toLowerCase().startsWith(input))
.collect(Collectors.toList());
}
}
}
return List.of();
};
// Назначаем TabCompleter для команды
command.setTabCompleter(tabCompleter);
} catch (Exception e) {
plugin.getLogger().severe("Ошибка при регистрации TabCompleter для " + commandClass.getName() + ": " + e.getMessage());
}
}
}
Далее мы должны добавить в метод onEnable() нашего плагина вот это:
Код:
CommandTabCompleter.registerTabCompleters(this);
Как это работает в классе команд?
Код:
package com.example.package.commands;
import com.example.package.CommandInfo;
import com.example.package.PluginCommand;
import com.example.package.TabCompleter.TabCompleterConfig;
import com.example.package.TabCompleter.TabType;
import org.bukkit.entity.Player;
@TabCompleterConfig(type = TabType.PLAYERS, argument = 1)
@TabCompleterConfig(type = TabType.CUSTOM, args = {"hi", "test", "ky"}, argument = 2)
@TabCompleterConfig(type = TabType.MATERIAL, argument = 3)
@CommandInfo(name = "example", permission = "example.use", requirePlayer = true)
public class ExampleCommand extends PluginCommand {
@Override
public void execute(Player player, String[] args) {
if (args.length == 1 && args[0].equals("hi")) {
// code
}
//....
}
}
В игре:
Последнее редактирование: