diff --git a/BuildConfigUpdater/BuildConfigUpdater.iml b/BuildConfigUpdater/BuildConfigUpdater.iml index c77ce8b..b0f9142 100644 --- a/BuildConfigUpdater/BuildConfigUpdater.iml +++ b/BuildConfigUpdater/BuildConfigUpdater.iml @@ -24,6 +24,7 @@ + diff --git a/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java b/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java deleted file mode 100755 index e93d386..0000000 --- a/ButtonCore/src/main/java/buttondevteam/core/CommandCaller.java +++ /dev/null @@ -1,107 +0,0 @@ -package buttondevteam.core; - -import buttondevteam.lib.TBMCCoreAPI; -import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.chat.TBMCCommandBase; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; -import org.bukkit.command.PluginCommand; -import org.bukkit.plugin.java.JavaPlugin; - -import java.util.Arrays; - -public class CommandCaller implements CommandExecutor { - - private CommandCaller() { - } - - private static CommandCaller instance; - - public static void RegisterCommand(TBMCCommandBase cmd) throws Exception { - if (instance == null) - instance = new CommandCaller(); - String[] topcmd = new String[1]; //Holds out param - PluginCommand pc = getPluginCommand(cmd, topcmd); - pc.setExecutor(instance); - String[] helptext = cmd.GetHelpText(topcmd[0]); - if (helptext == null || helptext.length == 0) - throw new Exception("Command " + cmd.GetCommandPath() + " has no help text!"); - pc.setUsage(helptext.length > 1 ? helptext[1] : helptext[0]); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) { - StringBuilder path = new StringBuilder(command.getName().toLowerCase()); - for (String arg : args) - path.append(" ").append(arg); - TBMCCommandBase cmd = TBMCChatAPI.GetCommands().get(path.toString()); - int argc = 0; - String[] subcmds = null; - while (cmd == null && (subcmds = TBMCChatAPI.GetSubCommands(path.toString(), sender)).length == 0 && path.toString().contains(" ")) { - path = new StringBuilder(path.substring(0, path.toString().lastIndexOf(' '))); - argc++; - cmd = TBMCChatAPI.GetCommands().get(path.toString()); - } - if (cmd == null) { - if (subcmds.length > 0) //Subcmds will always have value here (see assignment above) - sender.sendMessage(subcmds); - else { - final String errormsg = "§cYou don't have access to any of this command's subcommands or it doesn't have any."; - sender.sendMessage(errormsg); - } - return true; - } - if (cmd.isModOnly() && (MainPlugin.permission != null ? !MainPlugin.permission.has(sender, "tbmc.admin") : !sender.isOp())) { - sender.sendMessage("§cYou need to be a mod to use this command."); - return true; - } - final String[] cmdargs = args.length > 0 ? Arrays.copyOfRange(args, args.length - argc, args.length) : args; - try { - if (!cmd.OnCommand(sender, alias, cmdargs)) { - if (cmd.GetHelpText(alias) == null) { - sender.sendMessage("Wrong usage, but there's no help text! Error is being reported to devs."); - throw new NullPointerException("GetHelpText is null for comand /" + cmd.GetCommandPath()); - } else - sender.sendMessage(cmd.GetHelpText(alias)); - } - } catch (Exception e) { - TBMCCoreAPI.SendException("Failed to execute command /" + cmd.GetCommandPath() + " with arguments " - + Arrays.toString(cmdargs), e); - } - return true; - } - - public static void UnregisterCommand(TBMCCommandBase cmd) throws Exception { - PluginCommand pc = getPluginCommand(cmd, null); - pc.setExecutor(null); //Sets the executor to this plugin - } - - /** - * Gets the plugin command from the TBMC command. - * - * @param cmd The TBMC command - * @param out_topcmd An array with at least 1 elements or null - * @return The Bukkit plugin command - an exception is generated if null - * @throws Exception If the command isn't set up properly (or a different error) - */ - public static PluginCommand getPluginCommand(TBMCCommandBase cmd, String[] out_topcmd) throws Exception { - String topcmd = cmd.GetCommandPath(); - if (topcmd == null) - throw new Exception("Command " + cmd.getClass().getSimpleName() + " has no command path!"); - if (cmd.getPlugin() == null) - throw new Exception("Command " + cmd.GetCommandPath() + " has no plugin!"); - int i; - if ((i = topcmd.indexOf(' ')) != -1) // Get top-level command - topcmd = topcmd.substring(0, i); - if (out_topcmd != null && out_topcmd.length > 0) - out_topcmd[0] = topcmd; - { - PluginCommand pc = ((JavaPlugin) cmd.getPlugin()).getCommand(topcmd); - if (pc == null) - throw new Exception("Top level command " + topcmd + " not registered in plugin.yml for plugin: " - + cmd.getPlugin().getName()); - return pc; - } - } -} diff --git a/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java b/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java index 5fd411e..7557932 100755 --- a/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java +++ b/ButtonCore/src/main/java/buttondevteam/core/MainPlugin.java @@ -84,6 +84,15 @@ public class MainPlugin extends ButtonPlugin { return getIConfig().getData("test", false); } + /* + * By default, the plugin uses Vault for all command permission checks, but this can have issues (with PEX for example) where default permissions aren't granted. + * When this setting is off, the plugin uses Bukkit's built-in way of handling permissions, which usually works fine for players. + * You can also grant chroma.command.* to each player (mod-only commands need another permission, chroma.mod). + */ + /*public ConfigData useVaultForCommands() { + return getIConfig().getData("useVaultForCommands", true); + }*/ + @Override public void pluginEnable() { // Logs "Plugin Enabled", registers commands diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/members/MemberComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/members/MemberComponent.java index 735cf40..0c13f10 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/component/members/MemberComponent.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/members/MemberComponent.java @@ -64,11 +64,15 @@ public class MemberComponent extends Component implements Listener { if (permission != null && !permission.playerInGroup(event.getPlayer(), memberGroup().get()) && (new Date(event.getPlayer().getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now()) || event.getPlayer().getStatistic(playtime.getKey()) > playtime.getValue() * playedHours().get())) { - if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) { - event.getPlayer().sendMessage("§bYou are a member now. YEEHAW"); - MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member."); - } else { - MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused."); + try { + if (permission.playerAddGroup(null, event.getPlayer(), memberGroup().get())) { + event.getPlayer().sendMessage("§bYou are a member now. YEEHAW"); + MainPlugin.Instance.getLogger().info("Added " + event.getPlayer().getName() + " as a member."); + } else { + MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Please make sure the member group exists or disable the component if it's unused."); + } + } catch (UnsupportedOperationException e) { + MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Groups are not supported by the permissions implementation."); } } } diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java index 6b44848..e841d76 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTP.java @@ -1,9 +1,8 @@ package buttondevteam.core.component.randomtp; -import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.CommandClass; -import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.chat.TBMCCommandBase; +import buttondevteam.lib.chat.ICommand2MC; import org.bukkit.*; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -11,8 +10,11 @@ import org.bukkit.entity.Player; import java.util.logging.Logger; // @formatter:off -@SuppressWarnings("FieldCanBeLocal")@CommandClass -public class RandomTP extends TBMCCommandBase +@SuppressWarnings("FieldCanBeLocal")@CommandClass(helpText = { + "§6---- Random Teleport ----", + "Teleport player to random location within world border. Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players." +}) +public class RandomTP extends ICommand2MC { private final int radius = 70; //set how far apart the five teleport positions are @@ -53,10 +55,8 @@ public class RandomTP extends TBMCCommandBase /*================================================================================================*/ - public void onEnable(Component component) + public void onEnable(RandomTPComponent component) { - TBMCChatAPI.AddCommand(component, this); - world = Bukkit.getWorld("World"); border = world.getWorldBorder(); Logger logger = component.getPlugin().getLogger(); @@ -65,25 +65,13 @@ public class RandomTP extends TBMCCommandBase logger.warning("World border is wide, it may take a minute..."); logger.info("Success: "+newLocation()); } - - /*================================================================================================*/ - - public String[] GetHelpText(String alias) - { - return new String[] - { - "§6---- Random Teleport ----", - "Teleport player to random location within world border. Every five players teleport to the same general area, and then a new general area is randomly selected for the next five players." - }; - } /*================================================================================================*/ - - public boolean OnCommand(CommandSender sender, String command, String[] args) + + @Command2.Subcommand + public boolean def(CommandSender sender, Player player) { - if (args.length == 0) return false; - - if (sender.isOp()) return rtp(Bukkit.getPlayer(args[0])); + if (sender.isOp()) return rtp(player); else sender.sendMessage("§7 hmm, " + sender.getName() + "... " + sender.getName() + "... nope, no operator permissions."); diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java index 19ef768..c5a0a30 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/randomtp/RandomTPComponent.java @@ -13,7 +13,9 @@ import buttondevteam.lib.architecture.ComponentMetadata; public class RandomTPComponent extends Component { @Override protected void enable() { - new RandomTP().onEnable(this); //It registers it's command + var rtp = new RandomTP(); + registerCommand(rtp); + rtp.onEnable(this); } @Override diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/restart/PrimeRestartCommand.java b/ButtonCore/src/main/java/buttondevteam/core/component/restart/PrimeRestartCommand.java index 389da82..c2b56c8 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/component/restart/PrimeRestartCommand.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/restart/PrimeRestartCommand.java @@ -1,48 +1,43 @@ package buttondevteam.core.component.restart; import buttondevteam.core.component.channel.Channel; +import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.CommandClass; +import buttondevteam.lib.chat.ICommand2MC; import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.chat.TBMCCommandBase; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; -@CommandClass(path = "primerestart", modOnly = true) +@CommandClass(path = "primerestart", modOnly = true, helpText = { + "§6---- Prime restart ----", // + "Restarts the server as soon as nobody is online.", // + "To be loud, type something after, like /primerestart lol (it doesn't matter what you write)", // + "To be silent, don't type anything" // +}) @RequiredArgsConstructor -public class PrimeRestartCommand extends TBMCCommandBase { +public class PrimeRestartCommand extends ICommand2MC { private final RestartComponent component; - @Override - public boolean OnCommand(CommandSender sender, String alias, String[] args) { - loud = args.length > 0; - if (Bukkit.getOnlinePlayers().size() > 0) { - sender.sendMessage("§bPlayers online, restart delayed."); - if (loud) + + public void def(CommandSender sender, @Command2.TextArg @Command2.OptionalArg String somethingrandom) { + loud = somethingrandom != null; + if (Bukkit.getOnlinePlayers().size() > 0) { + sender.sendMessage("§bPlayers online, restart delayed."); + if (loud) TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, ChatColor.DARK_RED + "The server will restart as soon as nobody is online.", component.getRestartBroadcast()); - plsrestart = true; - } else { - sender.sendMessage("§bNobody is online. Restarting now."); - if (loud) + plsrestart = true; + } else { + sender.sendMessage("§bNobody is online. Restarting now."); + if (loud) TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, Channel.RecipientTestResult.ALL, "§cNobody is online. Restarting server.", component.getRestartBroadcast()); - Bukkit.spigot().restart(); - } - return true; - } + Bukkit.spigot().restart(); + } + } @Getter private static boolean plsrestart = false; @Getter private static boolean loud = false; - - @Override - public String[] GetHelpText(String alias) { - return new String[]{ // - "§6---- Prime restart ----", // - "Restarts the server as soon as nobody is online.", // - "To be loud, type something after, like /primerestart lol (it doesn't matter what you write)", // - "To be silent, don't type anything" // - }; - } } diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/restart/RestartComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/restart/RestartComponent.java index d0104a0..83df9f5 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/component/restart/RestartComponent.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/restart/RestartComponent.java @@ -20,7 +20,7 @@ public class RestartComponent extends Component implements Listener @Override public void enable() { registerCommand(new ScheduledRestartCommand(this)); - TBMCChatAPI.AddCommand(this, new PrimeRestartCommand(this)); + registerCommand(new PrimeRestartCommand(this)); registerListener(this); restartBroadcast = TBMCSystemChatEvent.BroadcastTarget.add("restartCountdown"); } diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/updater/PluginUpdaterComponent.java b/ButtonCore/src/main/java/buttondevteam/core/component/updater/PluginUpdaterComponent.java index 68a0002..4ed8f63 100644 --- a/ButtonCore/src/main/java/buttondevteam/core/component/updater/PluginUpdaterComponent.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/updater/PluginUpdaterComponent.java @@ -3,16 +3,15 @@ package buttondevteam.core.component.updater; import buttondevteam.core.MainPlugin; import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.ComponentMetadata; -import buttondevteam.lib.chat.TBMCChatAPI; /** - * Downloads plugin updates built from their source using JitPack - older code + * Downloads plugin updates built from their source using JitPack - doesn't work anymore */ @ComponentMetadata(enabledByDefault = false) public class PluginUpdaterComponent extends Component { //TODO: Config @Override public void enable() { - TBMCChatAPI.AddCommand(this, new UpdatePluginCommand()); + registerCommand(new UpdatePluginCommand()); } @Override diff --git a/ButtonCore/src/main/java/buttondevteam/core/component/updater/UpdatePluginCommand.java b/ButtonCore/src/main/java/buttondevteam/core/component/updater/UpdatePluginCommand.java index 0569e89..d236be5 100755 --- a/ButtonCore/src/main/java/buttondevteam/core/component/updater/UpdatePluginCommand.java +++ b/ButtonCore/src/main/java/buttondevteam/core/component/updater/UpdatePluginCommand.java @@ -2,40 +2,41 @@ package buttondevteam.core.component.updater; import buttondevteam.core.MainPlugin; import buttondevteam.lib.TBMCCoreAPI; +import buttondevteam.lib.chat.Command2; import buttondevteam.lib.chat.CommandClass; -import buttondevteam.lib.chat.TBMCCommandBase; +import buttondevteam.lib.chat.ICommand2MC; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import java.lang.reflect.Method; + @CommandClass(modOnly = true) -public class UpdatePluginCommand extends TBMCCommandBase { - @Override - public boolean OnCommand(CommandSender sender, String alias, String[] args) { - Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> { - if (args.length == 0) { - sender.sendMessage("Downloading plugin names..."); - boolean first = true; - for (String plugin : PluginUpdater.GetPluginNames()) { - if (first) { - sender.sendMessage("§6---- Plugin names ----"); - first = false; - } - sender.sendMessage("- " + plugin); - } - } else { - TBMCCoreAPI.UpdatePlugin(args[0], sender, args.length == 1 ? "master" : args[1]); - } - }); - return true; +public class UpdatePluginCommand extends ICommand2MC { + public void def(CommandSender sender, @Command2.OptionalArg String plugin, @Command2.OptionalArg String branch) { + Bukkit.getScheduler().runTaskAsynchronously(MainPlugin.Instance, () -> { + if (plugin == null) { + sender.sendMessage("Downloading plugin names..."); + boolean first = true; + for (String plugin2 : PluginUpdater.GetPluginNames()) { + if (first) { + sender.sendMessage("§6---- Plugin names ----"); + first = false; + } + sender.sendMessage("- " + plugin2); + } + } else { + TBMCCoreAPI.UpdatePlugin(plugin, sender, branch == null ? "master" : branch); + } + }); } @Override - public String[] GetHelpText(String alias) { - return new String[] { // - "§6---- Update plugin ----", // - "This command downloads the latest version of a TBMC plugin from GitHub", // - "To update a plugin: /" + alias + " ", // - "To list the plugin names: /" + alias // + public String[] getHelpText(Method method, Command2.Subcommand ann) { + return new String[]{ // + "§6---- Update plugin ----", // + "This command downloads the latest version of a custom plugin from GitHub", // + "To update a plugin: add its name", // + "To list the plugin names: don't type a name" // }; } } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java index 2bba1c8..b16b447 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java @@ -4,7 +4,6 @@ import buttondevteam.buttonproc.HasConfig; import buttondevteam.core.ComponentManager; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.chat.Command2MC; -import buttondevteam.lib.chat.TBMCChatAPI; import lombok.AccessLevel; import lombok.Getter; import org.bukkit.configuration.InvalidConfigurationException; @@ -85,7 +84,7 @@ public abstract class ButtonPlugin extends JavaPlugin { 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); + //TBMCChatAPI.RemoveCommands(this); - TODO } catch (Exception e) { TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e); } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java index 08ee576..c0b7b63 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/Component.java @@ -5,8 +5,6 @@ import buttondevteam.core.ComponentManager; import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.architecture.exceptions.UnregisteredComponentException; import buttondevteam.lib.chat.ICommand2MC; -import buttondevteam.lib.chat.TBMCChatAPI; -import buttondevteam.lib.chat.TBMCCommandBase; import lombok.Getter; import lombok.NonNull; import lombok.val; @@ -143,7 +141,7 @@ public abstract class Component { //System.out.println("Done enabling "+component.getClassName()); } else { component.disable(); - TBMCChatAPI.RemoveCommands(component); + //TBMCChatAPI.RemoveCommands(component); - TODO } } @@ -213,15 +211,6 @@ public abstract class Component { ButtonPlugin.getCommand2MC().registerCommand(commandBase); } - /** - * Registers a TBMCCommand to the component. Make sure to add it to plugin.yml and use {@link buttondevteam.lib.chat.CommandClass}. - * - * @param commandBase Custom coded command class - */ - protected final void registerCommand(TBMCCommandBase commandBase) { - TBMCChatAPI.AddCommand(this, commandBase); - } - /** * Registers a Listener to this component * diff --git a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ListConfigData.java b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ListConfigData.java index 4391f7b..3e89172 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/architecture/ListConfigData.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/architecture/ListConfigData.java @@ -1,9 +1,8 @@ package buttondevteam.lib.architecture; -import lombok.AccessLevel; -import lombok.Setter; import lombok.val; import org.bukkit.configuration.ConfigurationSection; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; @@ -12,14 +11,25 @@ import java.util.function.Predicate; import java.util.function.UnaryOperator; public class ListConfigData extends ConfigData> { + @SuppressWarnings("unchecked") ListConfigData(ConfigurationSection config, String path, List def, Runnable saveAction) { - super(config, path, def, def, saveAction); + super(config, path, def, new ArrayList<>(def), list -> { + var l = new List<>((ArrayList) list); + l.listConfig = def.listConfig; + return l; + }, ArrayList::new, saveAction); def.listConfig = this; //Can't make the List class non-static or pass this in the super() constructor } public static class List extends ArrayList { - @Setter(AccessLevel.PACKAGE) - ListConfigData listConfig; + private ListConfigData listConfig; + + public List(@NotNull Collection c) { + super(c); + } + + public List() { + } private void update() { listConfig.set(this); //Update the config model and start save task if needed diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java index 2538c63..3983f61 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2.java @@ -135,7 +135,7 @@ public abstract class Command2 try { handleCommandAsync(sender, commandline, sd, subcommand, sync); } catch (Exception e) { - TBMCCoreAPI.SendException("Command execution failed for sender " + sender + " and message " + commandline, e); + TBMCCoreAPI.SendException("Command execution failed for sender " + sender.getName() + "(" + sender.getClass().getCanonicalName() + ") and message " + commandline, e); } }); return true; //We found a method diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MC.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MC.java index 561befc..2f52c69 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MC.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MC.java @@ -6,6 +6,7 @@ import org.bukkit.Bukkit; import org.bukkit.OfflinePlayer; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.server.TabCompleteEvent; @@ -16,7 +17,6 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; -import java.util.UUID; import java.util.function.Function; public class Command2MC extends Command2 implements Listener { @@ -26,7 +26,7 @@ public class Command2MC extends Command2 implemen var perm = "chroma.command." + command.getCommandPath().replace(' ', '.'); if (Bukkit.getPluginManager().getPermission(perm) == null) //Check needed for plugin reset Bukkit.getPluginManager().addPermission(new Permission(perm, - modOnly(command) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only - TODO: Test + PermissionDefault.TRUE)); //Allow commands by default, it will check mod-only for (val method : command.getClass().getMethods()) { if (!method.isAnnotationPresent(Subcommand.class)) continue; String pg = permGroup(command, method); @@ -34,7 +34,6 @@ public class Command2MC extends Command2 implemen perm = "chroma." + pg; if (Bukkit.getPluginManager().getPermission(perm) == null) //It may occur multiple times Bukkit.getPluginManager().addPermission(new Permission(perm, - //pg.equals(Subcommand.MOD_GROUP) ? PermissionDefault.OP : PermissionDefault.TRUE)); //Allow commands by default, unless it's mod only PermissionDefault.OP)); //Do not allow any commands that belong to a group } } @@ -50,16 +49,18 @@ public class Command2MC extends Command2 implemen boolean p = true; String[] perms = { "chroma.command." + command.getCommandPath().replace(' ', '.'), - (pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null, - modOnly(command) ? "tbmc.admin" : null + (pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null }; for (String perm : perms) { if (perm != null) { if (p) { //Use OfflinePlayer to avoid fetching player data if (sender instanceof OfflinePlayer) - p = MainPlugin.permission.playerHas(null, (OfflinePlayer) sender, perm); + p = MainPlugin.permission.playerHas(sender instanceof Player ? ((Player) sender).getLocation().getWorld().getName() : null, (OfflinePlayer) sender, perm); else - p = MainPlugin.permission.playerHas(null, Bukkit.getOfflinePlayer(new UUID(0, 0)), perm); + p = false; //Use sender's method + //System.out.println("playerHas " + perm + ": " + p); + //System.out.println("hasPermission: " + sender.hasPermission(perm)); + if (!p) p = sender.hasPermission(perm); } else break; //If any of the permissions aren't granted then don't allow } } @@ -67,17 +68,7 @@ public class Command2MC extends Command2 implemen } /** - * Returns true if this class or any of the superclasses are mod only. - * - * @param command The command to check - * @return Whether the command is mod only - */ - private boolean modOnly(ICommand2MC command) { - return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false); - } - - /** - * Returns true if this class or any of the superclasses are mod only. + * Returns the first group found in the hierarchy starting from the command method or the mod group if any of the superclasses are mod only. * * @param method The subcommand to check * @return The permission group for the subcommand or empty string @@ -87,6 +78,8 @@ public class Command2MC extends Command2 implemen if (sc != null && sc.permGroup().length() > 0) { return sc.permGroup(); } + if (getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false)) + return Subcommand.MOD_GROUP; return getAnnForValue(command.getClass(), CommandClass.class, CommandClass::permGroup, ""); } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MCSender.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MCSender.java index 059d953..18df19c 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MCSender.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2MCSender.java @@ -17,4 +17,9 @@ public class Command2MCSender implements Command2Sender { public void sendMessage(String[] message) { sender.sendMessage(message); } + + @Override + public String getName() { + return sender.getName(); + } } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2Sender.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2Sender.java index ebb2b66..9da1b30 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2Sender.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/Command2Sender.java @@ -4,4 +4,6 @@ public interface Command2Sender { //We don't need the 'extras' of CommandSender void sendMessage(String message); void sendMessage(String[] message); + + String getName(); } diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/ICommand2.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/ICommand2.java index b55a85a..d0a202a 100644 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/ICommand2.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/ICommand2.java @@ -73,7 +73,7 @@ public abstract class ICommand2 { String path = getClass().getAnnotation(CommandClass.class).path(), prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path; for (Class cl = getClass().getSuperclass(); cl != null - && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl + && !cl.getPackage().getName().equals(ICommand2MC.class.getPackage().getName()); cl = cl .getSuperclass()) { // String newpath; if (!cl.isAnnotationPresent(CommandClass.class) diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/OptionallyPlayerCommandBase.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/OptionallyPlayerCommandBase.java deleted file mode 100755 index d5095ee..0000000 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/OptionallyPlayerCommandBase.java +++ /dev/null @@ -1,29 +0,0 @@ -package buttondevteam.lib.chat; - -import buttondevteam.lib.TBMCCoreAPI; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public abstract class OptionallyPlayerCommandBase extends TBMCCommandBase { - public boolean OnCommand(Player player, String alias, String[] args) { - if (getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class) - && getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly()) - TBMCCoreAPI.SendException("Error while executing command " + getClass().getSimpleName() + "!", - new Exception( - "The PlayerCommand annotation is present and set to playerOnly but the Player overload isn't overriden!")); - return true; - } - - @Override - public boolean OnCommand(CommandSender sender, String alias, String[] args) { - if (sender instanceof Player) - return OnCommand((Player) sender, alias, args); - if (!getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class) - || !getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly()) - TBMCCoreAPI.SendException("Error while executing command " + getClass().getSimpleName() + "!", - new Exception( - "Command class doesn't override the CommandSender overload and no PlayerCommandClass annotation is present or playerOnly is false!")); - sender.sendMessage("§cYou need to be a player to use this command."); - return true; - } -} diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/OptionallyPlayerCommandClass.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/OptionallyPlayerCommandClass.java deleted file mode 100755 index 1850df2..0000000 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/OptionallyPlayerCommandClass.java +++ /dev/null @@ -1,16 +0,0 @@ -package buttondevteam.lib.chat; - -import java.lang.annotation.*; - -/** - * Only needed to use with {@link OptionallyPlayerCommandBase} command classes - * - * @author NorbiPeti - * - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Inherited -public @interface OptionallyPlayerCommandClass { - boolean playerOnly(); -} diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/PlayerCommandBase.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/PlayerCommandBase.java deleted file mode 100755 index 3b30ff5..0000000 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/PlayerCommandBase.java +++ /dev/null @@ -1,16 +0,0 @@ -package buttondevteam.lib.chat; - -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -public abstract class PlayerCommandBase extends TBMCCommandBase { - public abstract boolean OnCommand(Player player, String alias, String[] args); - - @Override - public final boolean OnCommand(CommandSender sender, String alias, String[] args) { - if (sender instanceof Player) - return OnCommand((Player) sender, alias, args); - sender.sendMessage("§cYou need to be a player to use this command."); - return true; - } -} diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java index b6b160b..421515b 100755 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java +++ b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCChatAPI.java @@ -1,250 +1,19 @@ package buttondevteam.lib.chat; -import buttondevteam.core.CommandCaller; -import buttondevteam.core.MainPlugin; import buttondevteam.core.component.channel.Channel; import buttondevteam.core.component.channel.Channel.RecipientTestResult; -import buttondevteam.lib.*; -import buttondevteam.lib.architecture.Component; +import buttondevteam.lib.ChromaUtils; +import buttondevteam.lib.TBMCChatEvent; +import buttondevteam.lib.TBMCChatPreprocessEvent; +import buttondevteam.lib.TBMCSystemChatEvent; import lombok.val; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; -import org.bukkit.plugin.java.JavaPlugin; -import org.reflections.Reflections; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; -import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; -import java.util.Map.Entry; -import java.util.Set; -import java.util.function.Consumer; import java.util.function.Supplier; public class TBMCChatAPI { - - private static final HashMap commands = new HashMap<>(); - - public static HashMap GetCommands() { - return commands; - } - - /** - * Returns messages formatted for Minecraft chat listing the subcommands of the command. - * - * @param command The command which we want the subcommands of - * @param sender The sender for permissions - * @return The subcommands - */ - public static String[] GetSubCommands(TBMCCommandBase command, CommandSender sender) { - return GetSubCommands(command.GetCommandPath(), sender); - } - - /** - * Returns messages formatted for Minecraft chat listing the subcommands of the command.
- * Returns a header if subcommands were found, otherwise returns an empty array. - * - * @param command The command which we want the subcommands of - * @param sender The sender for permissions - * @return The subcommands - */ - public static String[] GetSubCommands(String command, CommandSender sender) { - ArrayList cmds = new ArrayList(); - Consumer addToCmds = cmd -> { - if (cmds.size() == 0) - cmds.add("§6---- Subcommands ----"); - cmds.add(cmd); - }; - for (Entry cmd : TBMCChatAPI.GetCommands().entrySet()) { - if (cmd.getKey().startsWith(command + " ")) { - if (cmd.getValue().isPlayerOnly() && !(sender instanceof Player)) - continue; - if (cmd.getValue().isModOnly() && (MainPlugin.permission != null ? !MainPlugin.permission.has(sender, "tbmc.admin") : !sender.isOp())) - continue; - int ind = cmd.getKey().indexOf(' ', command.length() + 2); - if (ind >= 0) { - String newcmd = cmd.getKey().substring(0, ind); - if (!cmds.contains("/" + newcmd)) - addToCmds.accept("/" + newcmd); - } else - addToCmds.accept("/" + cmd.getKey()); - } - } - return cmds.toArray(new String[0]); //Apparently it's faster to use an empty array in modern Java - } - - /** - *

- * This method adds a plugin's commands to help and sets their executor. - *

- *

- *

- * The command classes have to have a constructor each with no parameters - *

- * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage to console. - *

- *

- * Using this method after the server is done loading will have no effect. - *

- * - * @param plugin The caller plugin - * @param acmdclass A command's class to get the package name for commands. The provided class's package and subpackages are scanned for commands. - */ - public static synchronized void AddCommands(JavaPlugin plugin, Class acmdclass) { - plugin.getLogger().info("Registering commands from " + acmdclass.getPackage().getName()); - Reflections rf = new Reflections(new ConfigurationBuilder() - .setUrls(ClasspathHelper.forPackage(acmdclass.getPackage().getName(), - plugin.getClass().getClassLoader())) - .addUrls( - ClasspathHelper.forClass(OptionallyPlayerCommandBase.class, - OptionallyPlayerCommandBase.class.getClassLoader()), - ClasspathHelper.forClass(PlayerCommandBase.class, PlayerCommandBase.class.getClassLoader())) // http://stackoverflow.com/questions/12917417/using-reflections-for-finding-the-transitive-subtypes-of-a-class-when-not-all - .addClassLoader(plugin.getClass().getClassLoader()).addScanners(new SubTypesScanner())); - Set> cmds = rf.getSubTypesOf(TBMCCommandBase.class); - for (Class cmd : cmds) { - try { - if (!cmd.getPackage().getName().startsWith(acmdclass.getPackage().getName())) - continue; // It keeps including the commands from here - if (Modifier.isAbstract(cmd.getModifiers())) - continue; - TBMCCommandBase c = cmd.newInstance(); - c.plugin = plugin; - CommandCaller.RegisterCommand(c); //Will check for nulls - commands.put(c.GetCommandPath(), c); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + cmd.getName(), e); - } - } - } - - /** - *

- * This method adds a plugin's command to help and sets it's executor. They will be automatically unregistered on plugin disable. - *

- *

- * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a messsage to console. - *

- *

- * Using this method after the server is done loading will have no effect. - *

- * - * @param plugin The caller plugin - * @param thecmdclass The command's class to create it (because why let you create the command class) - */ - public static void AddCommand(JavaPlugin plugin, Class thecmdclass, Object... params) { - // plugin.getLogger().info("Registering command " + thecmdclass.getSimpleName() + " for " + plugin.getName()); - try { - TBMCCommandBase c; - if (params.length > 0) - c = thecmdclass.getConstructor(Arrays.stream(params).map(Object::getClass).toArray(Class[]::new)) - .newInstance(params); - else - c = thecmdclass.newInstance(); - c.plugin = plugin; - CommandCaller.RegisterCommand(c); //Will check for nulls - commands.put(c.GetCommandPath(), c); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + thecmdclass.getSimpleName(), e); - } - } - - /** - *

- * This method adds a plugin's command to help and sets its executor. They will be automatically unregistered on plugin disable. - *

- *

- * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a message to console. - *

- *

- * Using this method after the server is done loading will have no effect. - *

- * - * @param plugin The caller plugin - * @param cmd The command to add - */ - public static void AddCommand(JavaPlugin plugin, TBMCCommandBase cmd) { - try { - if (plugin == null) throw new IllegalArgumentException("The plugin is null!"); - if (cmd == null) throw new IllegalArgumentException("The command is null!"); - cmd.plugin = plugin; - CommandCaller.RegisterCommand(cmd); //Checks for other nulls - commands.put(cmd.GetCommandPath(), cmd); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + (cmd == null ? "n u l l" : cmd.GetCommandPath()), e); - } - } - - /** - *

- * This method adds a plugin's command to help and sets its executor. They will be automatically unregistered on component disable. - *

- *

- * The command must be registered in the caller plugin's plugin.yml. Otherwise the plugin will output a message to console. - *

- *

- * Using this method after the server is done loading will have no effect. - *

- * - * @param component The caller component - * @param cmd The command to add - */ - public static void AddCommand(Component component, TBMCCommandBase cmd) { - try { - if (component == null) throw new IllegalArgumentException("The component is null!"); - if (cmd == null) throw new IllegalArgumentException("The command is null!"); - cmd.plugin = component.getPlugin(); - cmd.component = component; - CommandCaller.RegisterCommand(cmd); //Checks for other nulls - commands.put(cmd.GetCommandPath(), cmd); - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while registering command " + (cmd == null ? "n u l l" : cmd.GetCommandPath()), e); - } - } - - /** - * Removes all commands from the plugin - * - * @param plugin The plugin to remove commands from - */ - public static void RemoveCommands(JavaPlugin plugin) { - commands.values().removeIf(c -> { - try { - if (c.plugin == plugin) { - CommandCaller.UnregisterCommand(c); - return true; //Remove - } - return false; - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while unregistering commands for " + plugin.getName(), e); - return true; //Remove if it couldn't get the plugin command - } - }); - } - - /** - * Removes all commands from the component - * - * @param component The component to remove commands from - */ - public static void RemoveCommands(Component component) { - commands.values().removeIf(c -> { - try { - if (c.component == component) { - CommandCaller.UnregisterCommand(c); - return true; //Remove - } - return false; - } catch (Exception e) { - TBMCCoreAPI.SendException("An error occured while unregistering commands for " + component.getClass().getSimpleName(), e); - return true; //Remove if it couldn't get the plugin command - } - }); - } - /** * Sends a chat message to Minecraft. Make sure that the channel is registered with {@link #RegisterChatChannel(Channel)}.
* This will also send the error message to the sender, if they can't send the message. diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java deleted file mode 100755 index dbd3b9f..0000000 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandBase.java +++ /dev/null @@ -1,111 +0,0 @@ -package buttondevteam.lib.chat; - -import buttondevteam.lib.architecture.Component; -import javassist.Modifier; -import lombok.Getter; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; - -import java.util.function.Function; - -/** - * Extend this class to create new TBMCCommand and use {@link TBMCChatAPI#AddCommand(org.bukkit.plugin.java.JavaPlugin, TBMCCommandBase)} to add it. Note: The command path (command name - * and subcommand arguments) will be the class name by default, removing any "command" from it. To change it (especially for subcommands), use the path field in the {@link CommandClass} annotation. - * - * @author Norbi - * - */ -@TBMCCommandEnforcer -public abstract class TBMCCommandBase { - - public TBMCCommandBase() { - path = getcmdpath(); - modonly = ismodonly(); - } - - public abstract boolean OnCommand(CommandSender sender, String alias, String[] args); - - public abstract String[] GetHelpText(String alias); - - private final String path; - - /** - * The command's path, or name if top-level command.
- * For example:
- * "u admin updateplugin" or "u" for the top level one
- * The path must be lowercase!
- * Abstract classes with no {@link CommandClass} annotations will be ignored. - * - * @return The command path, which is the command class name by default (removing any "command" from it) - Change via the {@link CommandClass} annotation - */ - public final String GetCommandPath() { - return path; - } - - private String getcmdpath() { - if (!getClass().isAnnotationPresent(CommandClass.class)) - throw new RuntimeException( - "No @CommandClass annotation on command class " + getClass().getSimpleName() + "!"); - Function, String> getFromClass = cl -> cl.getSimpleName().toLowerCase().replace("commandbase", "") // <-- ... - .replace("command", ""); - String path = getClass().getAnnotation(CommandClass.class).path(), - prevpath = path = path.length() == 0 ? getFromClass.apply(getClass()) : path; - for (Class cl = getClass().getSuperclass(); cl != null - && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl - .getSuperclass()) { // - String newpath; - if (!cl.isAnnotationPresent(CommandClass.class) - || (newpath = cl.getAnnotation(CommandClass.class).path()).length() == 0 - || newpath.equals(prevpath)) { - if ((Modifier.isAbstract(cl.getModifiers()) && !cl.isAnnotationPresent(CommandClass.class)) - || cl.getAnnotation(CommandClass.class).excludeFromPath()) // <-- - continue; - newpath = getFromClass.apply(cl); - } - path = (prevpath = newpath) + " " + path; - } - return path; - } - - Plugin plugin; // Used By TBMCChatAPI - - public final Plugin getPlugin() { // Used by CommandCaller (ButtonChat) - return plugin; - } - - public final boolean isPlayerOnly() { - return this instanceof PlayerCommandBase || - (this instanceof OptionallyPlayerCommandBase && - (!getClass().isAnnotationPresent(OptionallyPlayerCommandClass.class) - || getClass().getAnnotation(OptionallyPlayerCommandClass.class).playerOnly())); - } - - private final boolean modonly; - - /** - * Returns true if this class' or any superclass' modOnly property is set to true. - */ - public final boolean isModOnly() { - return modonly; - } - - private boolean ismodonly() { - if (!getClass().isAnnotationPresent(CommandClass.class)) - throw new RuntimeException( - "No @CommandClass annotation on command class " + getClass().getSimpleName() + "!"); - boolean modOnly = getClass().getAnnotation(CommandClass.class).modOnly(); - for (Class cl = getClass().getSuperclass(); cl != null - && !cl.getPackage().getName().equals(TBMCCommandBase.class.getPackage().getName()); cl = cl - .getSuperclass()) { // - if (cl.isAnnotationPresent(CommandClass.class) && !modOnly - && cl.getAnnotation(CommandClass.class).modOnly()) { - modOnly = true; - break; - } - } - return modOnly; - } - - @Getter - Component component; //May be null -} diff --git a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandEnforcer.java b/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandEnforcer.java deleted file mode 100644 index b644679..0000000 --- a/ButtonCore/src/main/java/buttondevteam/lib/chat/TBMCCommandEnforcer.java +++ /dev/null @@ -1,14 +0,0 @@ -package buttondevteam.lib.chat; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.CLASS) -@Target(ElementType.TYPE) -@Inherited -public @interface TBMCCommandEnforcer { - -}