001package com.mrivanplays.commandworker.bukkit;
002
003import com.mrivanplays.commandworker.bukkit.argtypes.MinecraftArgumentTypesAccessor;
004import com.mrivanplays.commandworker.bukkit.internal.BukkitBridgeCommand;
005import com.mrivanplays.commandworker.bukkit.registry.CmdRegistry;
006import com.mrivanplays.commandworker.bukkit.registry.CmdRegistryHandler;
007import com.mrivanplays.commandworker.core.Command;
008import com.mrivanplays.commandworker.core.CommandManager;
009import com.mrivanplays.commandworker.core.RegisteredCommand;
010import java.lang.reflect.Field;
011import java.util.ArrayList;
012import java.util.Collections;
013import java.util.List;
014import java.util.Objects;
015import java.util.function.Predicate;
016import org.bukkit.Bukkit;
017import org.bukkit.command.CommandMap;
018import org.bukkit.command.CommandSender;
019import org.bukkit.plugin.java.JavaPlugin;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.annotations.Nullable;
022
023public class BukkitCommandManager implements CommandManager<CommandSender> {
024
025  private List<RegisteredCommand<CommandSender>> registeredCommands;
026
027  private final JavaPlugin plugin;
028
029  private boolean shouldFallback = true;
030
031  public BukkitCommandManager(JavaPlugin plugin) {
032    this.plugin = plugin;
033    this.registeredCommands = new ArrayList<>();
034    if (CmdRegistryHandler.isSupported()) {
035      MinecraftArgumentTypesAccessor.ensureSetup();
036    }
037  }
038
039  @Override
040  public void register(
041      @NotNull Command<CommandSender> command,
042      @Nullable Predicate<CommandSender> permissionCheck,
043      @NotNull String... aliases) {
044    Objects.requireNonNull(command, "command");
045    if (permissionCheck == null) {
046      permissionCheck = (sender) -> true;
047    }
048    Objects.requireNonNull(aliases, "aliases");
049    String[] populatedAliases = CommandManager.getAliases(plugin.getName(), aliases);
050    if (!aliasesFree(registeredCommands, populatedAliases)) {
051      return;
052    }
053    RegisteredCommand<CommandSender> registeredCommand =
054        new RegisteredCommand<>(populatedAliases, command, permissionCheck);
055    registeredCommands.add(registeredCommand);
056    CmdRegistry registry = CmdRegistryHandler.getRegistry();
057    if (!isBrigadierSupported()) {
058      if (shouldFallback) {
059        // fallback to registering with bukkit
060        getBukkitCommandMap()
061            .register(
062                aliases[0], plugin.getName(), new BukkitBridgeCommand(registeredCommand, aliases));
063      }
064    } else {
065      registry.register(registeredCommand);
066    }
067  }
068
069  @Override
070  public boolean shouldFallback() {
071    return shouldFallback;
072  }
073
074  @Override
075  public void setShouldFallback(boolean shouldFallback) {
076    this.shouldFallback = shouldFallback;
077  }
078
079  @Override
080  public boolean isBrigadierSupported() {
081    return CmdRegistryHandler.isSupported();
082  }
083
084  private CommandMap getBukkitCommandMap() {
085    try {
086      Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap");
087      field.setAccessible(true);
088      return (CommandMap) field.get(Bukkit.getServer());
089    } catch (IllegalAccessException | NoSuchFieldException e) {
090      throw new RuntimeException(e);
091    }
092  }
093
094  @Override
095  @NotNull
096  public List<RegisteredCommand<CommandSender>> getRegisteredCommands() {
097    return Collections.unmodifiableList(registeredCommands);
098  }
099
100  @Override
101  public String toString() {
102    return "BukkitCommandManager(plugin="
103        + plugin
104        + ", shouldFallback="
105        + shouldFallback
106        + ", brigadierSupported="
107        + isBrigadierSupported()
108        + ", registeredCommands="
109        + registeredCommands;
110  }
111}