parent
d2ab3511c2
commit
23f3c0f133
9 changed files with 119 additions and 43 deletions
|
@ -5,7 +5,6 @@ import buttondevteam.lib.architecture.ButtonPlugin;
|
|||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.Command2.Subcommand;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import lombok.val;
|
||||
|
@ -19,9 +18,8 @@ import java.util.Optional;
|
|||
"Component command",
|
||||
"Can be used to enable/disable/list components"
|
||||
})
|
||||
public class ComponentCommand extends ICommand2MC<MainPlugin> {
|
||||
@Override
|
||||
public void onRegister(Command2MC<MainPlugin> manager) {
|
||||
public class ComponentCommand extends ICommand2MC {
|
||||
public ComponentCommand() {
|
||||
getManager().addParamConverter(Plugin.class, arg -> Bukkit.getPluginManager().getPlugin(arg), "Plugin not found!");
|
||||
}
|
||||
|
||||
|
@ -31,7 +29,7 @@ public class ComponentCommand extends ICommand2MC<MainPlugin> {
|
|||
})
|
||||
public boolean enable(CommandSender sender, Plugin plugin, String component) {
|
||||
if (plugin instanceof ButtonPlugin) {
|
||||
if (!((ButtonPlugin<?>) plugin).justReload()) {
|
||||
if (!((ButtonPlugin) plugin).justReload()) {
|
||||
sender.sendMessage("§cCouldn't reload config, check console.");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ import java.util.Optional;
|
|||
import java.util.UUID;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MainPlugin extends ButtonPlugin<MainPlugin> {
|
||||
public class MainPlugin extends ButtonPlugin {
|
||||
public static MainPlugin Instance;
|
||||
public static Permission permission;
|
||||
@Nullable
|
||||
|
@ -117,8 +117,8 @@ public class MainPlugin extends ButtonPlugin<MainPlugin> {
|
|||
if (Bukkit.getPluginManager().isPluginEnabled("Votifier") && economy != null)
|
||||
Component.registerComponent(this, new VotifierComponent(economy));
|
||||
ComponentManager.enableComponents();
|
||||
getCommand2MC().registerCommand(new ComponentCommand());
|
||||
getCommand2MC().registerCommand(new ChromaCommand());
|
||||
registerCommand(new ComponentCommand());
|
||||
registerCommand(new ChromaCommand());
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(new PlayerListener(), this);
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(getCommand2MC(), this);
|
||||
ChromaGamerBase.addConverter(commandSender -> Optional.ofNullable(commandSender instanceof ConsoleCommandSender || commandSender instanceof BlockCommandSender
|
||||
|
|
|
@ -2,13 +2,13 @@ package buttondevteam.core;
|
|||
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.core.component.channel.ChannelComponent;
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.chat.Color;
|
||||
import buttondevteam.lib.chat.TBMCChatAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.bukkit.scheduler.BukkitScheduler;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
|
@ -42,7 +42,7 @@ public class TestPrepare {
|
|||
}
|
||||
}));
|
||||
//noinspection unchecked
|
||||
Component.registerComponent(Mockito.mock(ButtonPlugin.class), new ChannelComponent());
|
||||
Component.registerComponent(Mockito.mock(JavaPlugin.class), new ChannelComponent());
|
||||
TBMCChatAPI.RegisterChatChannel(Channel.GlobalChat = new Channel("§fg§f", Color.White, "g", null));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import buttondevteam.buttonproc.HasConfig;
|
|||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.chat.Command2MC;
|
||||
import buttondevteam.lib.chat.ICommand2MC;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
|
@ -22,9 +23,9 @@ import java.util.Optional;
|
|||
import java.util.Stack;
|
||||
|
||||
@HasConfig(global = true)
|
||||
public abstract class ButtonPlugin<TP extends ButtonPlugin<TP>> extends JavaPlugin {
|
||||
public abstract class ButtonPlugin extends JavaPlugin {
|
||||
@Getter //Needs to be static as we don't know the plugin when a command is handled
|
||||
private Command2MC<TP> command2MC = new Command2MC<>();
|
||||
private static Command2MC command2MC = new Command2MC();
|
||||
@Getter(AccessLevel.PROTECTED)
|
||||
private IHaveConfig iConfig;
|
||||
private CommentedConfiguration yaml;
|
||||
|
@ -84,7 +85,7 @@ public abstract class ButtonPlugin<TP extends ButtonPlugin<TP>> extends JavaPlug
|
|||
if (ConfigData.saveNow(getConfig()))
|
||||
getLogger().info("Saved configuration changes.");
|
||||
iConfig = null; //Clearing the hashmap is not enough, we need to update the section as well
|
||||
//TBMCChatAPI.RemoveCommands(this); - TODO
|
||||
getCommand2MC().unregisterCommands(this);
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
|
||||
}
|
||||
|
@ -147,6 +148,16 @@ public abstract class ButtonPlugin<TP extends ButtonPlugin<TP>> extends JavaPlug
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers command and sets its plugin.
|
||||
*
|
||||
* @param command The command to register
|
||||
*/
|
||||
protected void registerCommand(ICommand2MC command) {
|
||||
command.registerToPlugin(this);
|
||||
getCommand2MC().registerCommand(command);
|
||||
}
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ConfigOpts {
|
||||
|
|
|
@ -23,8 +23,8 @@ import java.util.stream.Collectors;
|
|||
* Configuration is based on class name
|
||||
*/
|
||||
@HasConfig(global = false) //Used for obtaining javadoc
|
||||
public abstract class Component<TP extends ButtonPlugin> {
|
||||
private static HashMap<Class<? extends Component>, Component<? extends JavaPlugin>> components = new HashMap<>();
|
||||
public abstract class Component<TP extends JavaPlugin> {
|
||||
@SuppressWarnings("rawtypes") private static HashMap<Class<? extends Component>, Component<? extends JavaPlugin>> components = new HashMap<>();
|
||||
|
||||
@Getter
|
||||
private boolean enabled = false;
|
||||
|
@ -44,11 +44,12 @@ public abstract class Component<TP extends ButtonPlugin> {
|
|||
* Registers a component checking it's dependencies and calling {@link #register(JavaPlugin)}.<br>
|
||||
* Make sure to register the dependencies first.<br>
|
||||
* The component will be enabled automatically, regardless of when it was registered.<br>
|
||||
* <b>If not using {@link ButtonPlugin}, call {@link ComponentManager#unregComponents(ButtonPlugin)} on plugin disable.</b>
|
||||
*
|
||||
* @param component The component to register
|
||||
* @return Whether the component is registered successfully (it may have failed to enable)
|
||||
*/
|
||||
public static <T extends ButtonPlugin> boolean registerComponent(T plugin, Component<T> component) {
|
||||
public static <T extends JavaPlugin> boolean registerComponent(T plugin, Component<T> component) {
|
||||
return registerUnregisterComponent(plugin, component, true);
|
||||
}
|
||||
|
||||
|
@ -64,11 +65,11 @@ public abstract class Component<TP extends ButtonPlugin> {
|
|||
return registerUnregisterComponent(plugin, component, false);
|
||||
}
|
||||
|
||||
public static <T extends ButtonPlugin> boolean registerUnregisterComponent(T plugin, Component<T> component, boolean register) {
|
||||
public static <T extends JavaPlugin> boolean registerUnregisterComponent(T plugin, Component<T> component, boolean register) {
|
||||
try {
|
||||
val metaAnn = component.getClass().getAnnotation(ComponentMetadata.class);
|
||||
if (metaAnn != null) {
|
||||
Class<? extends Component>[] dependencies = metaAnn.depends();
|
||||
@SuppressWarnings("rawtypes") Class<? extends Component>[] dependencies = metaAnn.depends();
|
||||
for (val dep : dependencies) { //TODO: Support dependencies at enable/disable as well
|
||||
if (!components.containsKey(dep)) {
|
||||
plugin.getLogger().warning("Failed to " + (register ? "" : "un") + "register component " + component.getClassName() + " as a required dependency is missing/disabled: " + dep.getSimpleName());
|
||||
|
@ -85,7 +86,8 @@ public abstract class Component<TP extends ButtonPlugin> {
|
|||
updateConfig(plugin, component);
|
||||
component.register(plugin);
|
||||
components.put(component.getClass(), component);
|
||||
plugin.getComponentStack().push(component);
|
||||
if (plugin instanceof ButtonPlugin)
|
||||
((ButtonPlugin) plugin).getComponentStack().push(component);
|
||||
if (ComponentManager.areComponentsEnabled() && component.shouldBeEnabled().get()) {
|
||||
try { //Enable components registered after the previous ones getting enabled
|
||||
setComponentEnabled(component, true);
|
||||
|
@ -138,8 +140,7 @@ public abstract class Component<TP extends ButtonPlugin> {
|
|||
//System.out.println("Done enabling "+component.getClassName());
|
||||
} else {
|
||||
component.disable();
|
||||
//TBMCChatAPI.RemoveCommands(component); - TODO
|
||||
component.getPlugin().getCommand2MC().unregisterCommand();
|
||||
ButtonPlugin.getCommand2MC().unregisterCommands(component);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,6 +161,7 @@ public abstract class Component<TP extends ButtonPlugin> {
|
|||
*
|
||||
* @return The currently registered components
|
||||
*/
|
||||
@SuppressWarnings("rawtypes")
|
||||
public static Map<Class<? extends Component>, Component<? extends JavaPlugin>> getComponents() {
|
||||
return Collections.unmodifiableMap(components);
|
||||
}
|
||||
|
@ -200,13 +202,16 @@ public abstract class Component<TP extends ButtonPlugin> {
|
|||
protected abstract void disable();
|
||||
|
||||
/**
|
||||
* Registers a TBMCCommand to the component. Make sure to use {@link buttondevteam.lib.chat.CommandClass} and {@link buttondevteam.lib.chat.Command2.Subcommand}.
|
||||
* Registers a command to the component. Make sure to use {@link buttondevteam.lib.chat.CommandClass} and {@link buttondevteam.lib.chat.Command2.Subcommand}.
|
||||
* You don't need to register the command in plugin.yml.
|
||||
*
|
||||
* @param commandBase Custom coded command class
|
||||
* @param command Custom coded command class
|
||||
*/
|
||||
protected final <T extends ButtonPlugin<T>> void registerCommand(ICommand2MC<T> commandBase) {
|
||||
getPlugin().getCommand2MC().registerCommand(commandBase);
|
||||
protected final void registerCommand(ICommand2MC command) {
|
||||
if (plugin instanceof ButtonPlugin)
|
||||
command.registerToPlugin((ButtonPlugin) plugin);
|
||||
command.registerToComponent(this);
|
||||
ButtonPlugin.getCommand2MC().registerCommand(command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -114,6 +114,8 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
|||
|
||||
private ArrayList<String> commandHelp = new ArrayList<>(); //Mainly needed by Discord
|
||||
|
||||
private char commandChar;
|
||||
|
||||
/**
|
||||
* Adds a param converter that obtains a specific object from a string parameter.
|
||||
* The converter may return null.
|
||||
|
@ -260,6 +262,7 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
|||
public abstract void registerCommand(TC command);
|
||||
|
||||
protected void registerCommand(TC command, @SuppressWarnings("SameParameterValue") char commandChar) {
|
||||
this.commandChar = commandChar;
|
||||
val path = command.getCommandPath();
|
||||
int x = path.indexOf(' ');
|
||||
val mainPath = commandChar + path.substring(0, x == -1 ? path.length() : x);
|
||||
|
@ -357,8 +360,19 @@ public abstract class Command2<TC extends ICommand2, TP extends Command2Sender>
|
|||
return Collections.unmodifiableSet(subcommands.keySet());
|
||||
}*/
|
||||
|
||||
public void unregisterCommand() {
|
||||
|
||||
/**
|
||||
* Unregisters all of the subcommands in the given command.
|
||||
*
|
||||
* @param command The command object
|
||||
*/
|
||||
public void unregisterCommand(ICommand2<TP> command) {
|
||||
var path = command.getCommandPath();
|
||||
for (val method : command.getClass().getMethods()) {
|
||||
val ann = method.getAnnotation(Subcommand.class);
|
||||
if (ann == null) continue;
|
||||
val subcommand = commandChar + path + getCommandPath(method.getName(), ' ');
|
||||
subcommands.remove(subcommand);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@ package buttondevteam.lib.chat;
|
|||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
|
@ -18,11 +19,17 @@ import java.lang.annotation.Annotation;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Command2MC<TP extends ButtonPlugin<TP>> extends Command2<ICommand2MC<TP>, Command2MCSender> implements Listener {
|
||||
public class Command2MC extends Command2<ICommand2MC, Command2MCSender> implements Listener {
|
||||
/**
|
||||
* Don't use directly, use the method in Component and ButtonPlugin to automatically unregister the command when needed.
|
||||
*
|
||||
* @param command The command to register
|
||||
*/
|
||||
@Override
|
||||
public void registerCommand(ICommand2MC<TP> command) {
|
||||
public void registerCommand(ICommand2MC command) {
|
||||
super.registerCommand(command, '/');
|
||||
var perm = "chroma.command." + command.getCommandPath().replace(' ', '.');
|
||||
if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset
|
||||
|
@ -47,11 +54,11 @@ public class Command2MC<TP extends ButtonPlugin<TP>> extends Command2<ICommand2M
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(Command2MCSender sender, ICommand2MC<TP> command, Method method) {
|
||||
public boolean hasPermission(Command2MCSender sender, ICommand2MC command, Method method) {
|
||||
return hasPermission(sender.getSender(), command, method);
|
||||
}
|
||||
|
||||
public boolean hasPermission(CommandSender sender, ICommand2MC<TP> command, Method method) {
|
||||
public boolean hasPermission(CommandSender sender, ICommand2MC command, Method method) {
|
||||
if (sender instanceof ConsoleCommandSender) return true; //Always allow the console
|
||||
String pg;
|
||||
boolean p = true;
|
||||
|
@ -81,7 +88,7 @@ public class Command2MC<TP extends ButtonPlugin<TP>> extends Command2<ICommand2M
|
|||
* @param method The subcommand to check
|
||||
* @return The permission group for the subcommand or empty string
|
||||
*/
|
||||
private String permGroup(ICommand2MC<TP> command, Method method) {
|
||||
private String permGroup(ICommand2MC command, Method method) {
|
||||
val sc = method.getAnnotation(Subcommand.class);
|
||||
if (sc != null && sc.permGroup().length() > 0) {
|
||||
return sc.permGroup();
|
||||
|
@ -120,6 +127,21 @@ public class Command2MC<TP extends ButtonPlugin<TP>> extends Command2<ICommand2M
|
|||
super.addParamConverter(cl, converter, "§c" + errormsg);
|
||||
}
|
||||
|
||||
public void unregisterCommands(ButtonPlugin plugin) {
|
||||
/*var cmds = subcommands.values().stream().map(sd -> sd.command).filter(cmd -> plugin.equals(cmd.getPlugin())).toArray(ICommand2MC[]::new);
|
||||
for (var cmd : cmds)
|
||||
unregisterCommand(cmd);*/
|
||||
subcommands.values().removeIf(sd -> plugin.equals(sd.command.getPlugin()));
|
||||
}
|
||||
|
||||
public void unregisterCommands(Component<?> component) {
|
||||
/*var cmds = subcommands.values().stream().map(sd -> sd.command).filter(cmd -> component.equals(cmd.getComponent())).toArray(ICommand2MC[]::new);
|
||||
for (var cmd : cmds)
|
||||
unregisterCommand(cmd);*/
|
||||
subcommands.values().removeIf(sd -> Optional.ofNullable(sd.command.getComponent())
|
||||
.map(comp -> component.getClass().getSimpleName().equals(comp.getClass().getSimpleName())).orElse(false));
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
private void handleTabComplete(TabCompleteEvent event) {
|
||||
String commandline = event.getBuffer();
|
||||
|
@ -129,7 +151,7 @@ public class Command2MC<TP extends ButtonPlugin<TP>> extends Command2<ICommand2M
|
|||
String subcommand = commandline.substring(0, i).toLowerCase();
|
||||
if (subcommand.length() == 0 || subcommand.charAt(0) != '/') subcommand = '/' + subcommand; //Console
|
||||
//System.out.println("Subcommand: " + subcommand);
|
||||
SubcommandData<ICommand2MC<TP>> sd = subcommands.get(subcommand); //O(1)
|
||||
SubcommandData<ICommand2MC> sd = subcommands.get(subcommand); //O(1)
|
||||
if (sd == null) continue;
|
||||
//System.out.println("ht: " + Arrays.toString(sd.helpText));
|
||||
Arrays.stream(sd.helpText).skip(1).map(ht -> new HashMap.SimpleEntry<>(ht, subcommands.get(ht))).filter(e -> e.getValue() != null)
|
||||
|
|
|
@ -45,13 +45,10 @@ public abstract class ICommand2<TP extends Command2Sender> {
|
|||
|
||||
private final String path;
|
||||
@Getter
|
||||
private Command2<?, TP> manager; //TIL that if I use a raw type on a variable then none of the type args will work (including what's defined on a method, not on the type)
|
||||
private final Command2<?, TP> manager; //TIL that if I use a raw type on a variable then none of the type args will work (including what's defined on a method, not on the type)
|
||||
|
||||
public <T extends ICommand2<TP>> ICommand2() {
|
||||
public <T extends ICommand2<TP>> ICommand2(Command2<T, TP> manager) {
|
||||
path = getcmdpath();
|
||||
}
|
||||
|
||||
public <T extends ICommand2<TP>> void onRegister(Command2<T, TP> manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,46 @@
|
|||
package buttondevteam.lib.chat;
|
||||
|
||||
import buttondevteam.lib.architecture.ButtonPlugin;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import lombok.Getter;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressWarnings("JavadocReference")
|
||||
public abstract class ICommand2MC extends ICommand2<Command2MCSender> {
|
||||
@Getter
|
||||
private ButtonPlugin plugin;
|
||||
@Getter
|
||||
@Nullable
|
||||
private Component<?> component;
|
||||
|
||||
public abstract class ICommand2MC<T extends ButtonPlugin<T>> extends ICommand2<Command2MCSender> {
|
||||
public ICommand2MC() {
|
||||
super(ButtonPlugin.getCommand2MC());
|
||||
}
|
||||
|
||||
public void onRegister(Command2MC<T> manager) {
|
||||
/**
|
||||
* Called from {@link buttondevteam.lib.architecture.Component#registerCommand(ICommand2MC)} and {@link ButtonPlugin#registerCommand(ICommand2MC)}
|
||||
*/
|
||||
public void registerToPlugin(ButtonPlugin plugin) {
|
||||
if (this.plugin == null)
|
||||
this.plugin = plugin;
|
||||
else
|
||||
throw new IllegalStateException("The command is already assigned to a plugin!");
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Called from {@link buttondevteam.lib.architecture.Component#registerCommand(ICommand2MC)}
|
||||
*/
|
||||
public void registerToComponent(Component<?> component) {
|
||||
if (this.component == null)
|
||||
this.component = component;
|
||||
else
|
||||
throw new IllegalStateException("The command is already assigned to a component!");
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public <TX extends ICommand2<Command2MCSender>> void onRegister(Command2<TX, Command2MCSender> manager) {
|
||||
super.onRegister(manager);
|
||||
onRegister((Command2MC<T>) manager);
|
||||
}
|
||||
onRegister((Command2MC) manager); //If ICommand2 is inherited with the same type arg, this would fail but I don't want to add another type param to ICommand2
|
||||
} //For example: class IOffender extends ICommand2<Command2MCSender>*/
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue