diff --git a/.gitignore b/.gitignore
index 7219eb8..5bf6210 100755
--- a/.gitignore
+++ b/.gitignore
@@ -218,7 +218,7 @@ pip-log.txt
.mr.developer.cfg
.metadata/*
TheButtonAutoFlair/out/artifacts/Autoflair/Autoflair.jar
-#*.iml
+*.iml
*.name
.idea
dependency-reduced-pom.xml
diff --git a/.idea/ButtonCore.iml b/.idea/ButtonCore.iml
deleted file mode 100755
index c32b2ad..0000000
--- a/.idea/ButtonCore.iml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
deleted file mode 100644
index a55e7a1..0000000
--- a/.idea/codeStyles/codeStyleConfig.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
deleted file mode 100755
index b5342db..0000000
--- a/.idea/compiler.xml
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/encodings.xml b/.idea/encodings.xml
deleted file mode 100755
index adcb5b6..0000000
--- a/.idea/encodings.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 14d4bba..0000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/libraries/Maven__org_projectlombok_lombok_1_16_16.xml b/.idea/libraries/Maven__org_projectlombok_lombok_1_16_16.xml
deleted file mode 100755
index d846a35..0000000
--- a/.idea/libraries/Maven__org_projectlombok_lombok_1_16_16.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/markdown-exported-files.xml b/.idea/markdown-exported-files.xml
deleted file mode 100644
index 5d1f129..0000000
--- a/.idea/markdown-exported-files.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/markdown-navigator.xml b/.idea/markdown-navigator.xml
deleted file mode 100644
index a280ac6..0000000
--- a/.idea/markdown-navigator.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/markdown-navigator/profiles_settings.xml b/.idea/markdown-navigator/profiles_settings.xml
deleted file mode 100644
index 57927c5..0000000
--- a/.idea/markdown-navigator/profiles_settings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100755
index 1014481..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
deleted file mode 100755
index 8c958b0..0000000
--- a/.idea/modules.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml
deleted file mode 100644
index e96534f..0000000
--- a/.idea/uiDesigner.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
- -
-
-
- -
-
-
-
-
-
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
deleted file mode 100755
index 35eb1dd..0000000
--- a/.idea/vcs.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/BuildConfigUpdater/BuildConfigUpdater.iml b/BuildConfigUpdater/BuildConfigUpdater.iml
deleted file mode 100644
index 781a0fd..0000000
--- a/BuildConfigUpdater/BuildConfigUpdater.iml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ButtonProcessor/ButtonProcessor.iml b/ButtonProcessor/ButtonProcessor.iml
deleted file mode 100755
index 6a0a7be..0000000
--- a/ButtonProcessor/ButtonProcessor.iml
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Chroma-Core/Chroma-Core.iml b/Chroma-Core/Chroma-Core.iml
deleted file mode 100644
index 112e8d8..0000000
--- a/Chroma-Core/Chroma-Core.iml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java
index 7557932..b450bf4 100755
--- a/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java
+++ b/Chroma-Core/src/main/java/buttondevteam/core/MainPlugin.java
@@ -117,8 +117,8 @@ public class MainPlugin extends ButtonPlugin {
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
diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberCommand.java b/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberCommand.java
index 395b71c..207e182 100644
--- a/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberCommand.java
+++ b/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberCommand.java
@@ -9,13 +9,9 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
-import java.time.Instant;
-import java.time.temporal.ChronoUnit;
-import java.util.Date;
+import java.util.concurrent.TimeUnit;
-import static buttondevteam.core.MainPlugin.permission;
-
-@CommandClass(modOnly = true, path = "member", helpText = { //
+@CommandClass(path = "member", helpText = { //
"Member command", //
"Add or remove server members.", //
})
@@ -27,12 +23,12 @@ public class MemberCommand extends ICommand2MC {
this.component = component;
}
- @Command2.Subcommand
+ @Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP)
public boolean add(CommandSender sender, OfflinePlayer player) {
return addRemove(sender, player, true);
}
- @Command2.Subcommand
+ @Command2.Subcommand(permGroup = Command2.Subcommand.MOD_GROUP)
public boolean remove(CommandSender sender, OfflinePlayer player) {
return addRemove(sender, player, false);
}
@@ -53,17 +49,25 @@ public class MemberCommand extends ICommand2MC {
}
@Command2.Subcommand
- public void def(CommandSender sender) {
- if(!(sender instanceof Player)) {
- sender.sendMessage("§cYou need to be a player to use this command.");
- return;
- }
- Player player= (Player) sender;
+ public void def(Player player) {
String msg;
- if (component.checkMember(player))
- msg="You are a member.";
+ if (!component.checkNotMember(player))
+ msg = "You are a member.";
else {
- component.getRegTime(player);
+ double pt = component.getPlayTime(player);
+ long rt = component.getRegTime(player);
+ if (pt == -1 || rt == -1) {
+ Boolean result = component.addPlayerAsMember(player);
+ if (result == null)
+ msg = "Can't assign member group because groups are not supported by the permissions plugin.";
+ else if (result)
+ msg = "You meet all the requirements.";
+ else
+ msg = "You should be a member but failed to add you to the group.";
+ } else
+ msg = String.format("You need to play for %.2f hours total or play for %d more days to become a member.",
+ pt, TimeUnit.MILLISECONDS.toDays(rt));
}
+ player.sendMessage(msg);
}
}
diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberComponent.java b/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberComponent.java
index d003526..8151d2e 100644
--- a/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberComponent.java
+++ b/Chroma-Core/src/main/java/buttondevteam/core/component/members/MemberComponent.java
@@ -62,37 +62,60 @@ public class MemberComponent extends Component implements Listener {
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
- if (checkMember(event.getPlayer()) && (checkRegTime(event.getPlayer()) || checkPlayTime(event.getPlayer()))) {
- 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.");
- }
+ if (checkNotMember(event.getPlayer()) && (checkRegTime(event.getPlayer()) || checkPlayTime(event.getPlayer()))) {
+ addPlayerAsMember(event.getPlayer());
}
}
- public boolean checkMember(Player player) {
+ public Boolean addPlayerAsMember(Player player) {
+ try {
+ if (permission.playerAddGroup(null, player, memberGroup().get())) {
+ player.sendMessage("§bYou are a member now!");
+ MainPlugin.Instance.getLogger().info("Added " + player.getName() + " as a member.");
+ return true;
+ } 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.");
+ return false;
+ }
+ } catch (UnsupportedOperationException e) {
+ MainPlugin.Instance.getLogger().warning("Failed to assign the member role! Groups are not supported by the permissions implementation.");
+ return null;
+ }
+ }
+
+ public boolean checkNotMember(Player player) {
return permission != null && !permission.playerInGroup(player, memberGroup().get());
}
public boolean checkRegTime(Player player) {
- return new Date(player.getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS).isBefore(Instant.now());
+ return getRegTime(player) == -1;
}
public boolean checkPlayTime(Player player) {
- return player.getStatistic(playtime.getKey()) > playtime.getValue() * playedHours().get();
+ return getPlayTime(player) > playtime.getValue() * playedHours().get();
}
+ /**
+ * Returns milliseconds
+ */
public long getRegTime(Player player) {
Instant date = new Date(player.getFirstPlayed()).toInstant().plus(registeredForDays().get(), ChronoUnit.DAYS);
- if(date.isBefore(Instant.now()))
- return date.toEpochMilli()-Instant.now().toEpochMilli();
+ if (date.isAfter(Instant.now()))
+ return date.toEpochMilli() - Instant.now().toEpochMilli();
return -1;
}
+ public int getPlayTimeTotal(Player player) {
+ return player.getStatistic(playtime.getKey());
+ }
+
+ /**
+ * Returns hours
+ */
+ public double getPlayTime(Player player) {
+ double pt = playedHours().get() - (double) getPlayTimeTotal(player) / playtime.getValue();
+ if (pt < 0) return -1;
+ return pt;
+ }
+
}
diff --git a/Chroma-Core/src/main/java/buttondevteam/core/component/restart/ScheduledRestartCommand.java b/Chroma-Core/src/main/java/buttondevteam/core/component/restart/ScheduledRestartCommand.java
index e9fd7c0..1182629 100755
--- a/Chroma-Core/src/main/java/buttondevteam/core/component/restart/ScheduledRestartCommand.java
+++ b/Chroma-Core/src/main/java/buttondevteam/core/component/restart/ScheduledRestartCommand.java
@@ -18,6 +18,8 @@ import org.bukkit.boss.BossBar;
import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitTask;
+import javax.annotation.Nonnull;
+
@CommandClass(modOnly = true, path = "schrestart", helpText = {
"Scheduled restart", //
"This command restarts the server 1 minute after it's executed, warning players every 10 seconds.", //
@@ -31,6 +33,7 @@ public class ScheduledRestartCommand extends ICommand2MC {
private BukkitTask restarttask;
private volatile BossBar restartbar;
@Getter
+ @Nonnull
private final RestartComponent component;
@Command2.Subcommand
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java
index b16b447..cf7db91 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonPlugin.java
@@ -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;
@@ -23,7 +24,7 @@ import java.util.Stack;
@HasConfig(global = true)
public abstract class ButtonPlugin extends JavaPlugin {
- @Getter
+ @Getter //Needs to be static as we don't know the plugin when a command is handled
private static Command2MC command2MC = new Command2MC();
@Getter(AccessLevel.PROTECTED)
private IHaveConfig iConfig;
@@ -84,7 +85,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); - TODO
+ getCommand2MC().unregisterCommands(this);
} catch (Exception e) {
TBMCCoreAPI.SendException("Error while disabling plugin " + getName() + "!", e);
}
@@ -147,6 +148,16 @@ public abstract class ButtonPlugin extends JavaPlugin {
}
}
+ /**
+ * 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 {
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java
index c0b7b63..ba9925f 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.java
@@ -24,7 +24,7 @@ import java.util.stream.Collectors;
*/
@HasConfig(global = false) //Used for obtaining javadoc
public abstract class Component {
- private static HashMap, Component extends JavaPlugin>> components = new HashMap<>();
+ @SuppressWarnings("rawtypes") private static HashMap, Component extends JavaPlugin>> components = new HashMap<>();
@Getter
private boolean enabled = false;
@@ -61,7 +61,7 @@ public abstract class Component {
* @param component The component to unregister
* @return Whether the component is unregistered successfully (it also got disabled)
*/
- public static boolean unregisterComponent(T plugin, Component component) {
+ public static boolean unregisterComponent(T plugin, Component component) {
return registerUnregisterComponent(plugin, component, false);
}
@@ -69,7 +69,7 @@ public abstract class Component {
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());
@@ -97,7 +97,6 @@ public abstract class Component {
return true;
}
}
- return true; //Component shouldn't be enabled
} else {
if (!components.containsKey(component.getClass()))
return true; //Already unregistered
@@ -111,8 +110,8 @@ public abstract class Component {
}
component.unregister(plugin);
components.remove(component.getClass());
- return true;
}
+ return true;
} catch (Exception e) {
TBMCCoreAPI.SendException("Failed to " + (register ? "" : "un") + "register component " + component.getClassName() + "!", e);
return false;
@@ -125,7 +124,7 @@ public abstract class Component {
*
* @param component The component to register
*/
- public static void setComponentEnabled(Component component, boolean enabled) throws UnregisteredComponentException {
+ public static void setComponentEnabled(Component> component, boolean enabled) throws UnregisteredComponentException {
if (!components.containsKey(component.getClass()))
throw new UnregisteredComponentException(component);
if (component.enabled == enabled) return; //Don't do anything
@@ -141,7 +140,7 @@ public abstract class Component {
//System.out.println("Done enabling "+component.getClassName());
} else {
component.disable();
- //TBMCChatAPI.RemoveCommands(component); - TODO
+ ButtonPlugin.getCommand2MC().unregisterCommands(component);
}
}
@@ -162,6 +161,7 @@ public abstract class Component {
*
* @return The currently registered components
*/
+ @SuppressWarnings("rawtypes")
public static Map, Component extends JavaPlugin>> getComponents() {
return Collections.unmodifiableMap(components);
}
@@ -202,13 +202,16 @@ public abstract class Component {
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 void registerCommand(ICommand2MC commandBase) {
- ButtonPlugin.getCommand2MC().registerCommand(commandBase);
+ protected final void registerCommand(ICommand2MC command) {
+ if (plugin instanceof ButtonPlugin)
+ command.registerToPlugin((ButtonPlugin) plugin);
+ command.registerToComponent(this);
+ ButtonPlugin.getCommand2MC().registerCommand(command);
}
/**
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java
index 3983f61..1d20d08 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2.java
@@ -12,6 +12,7 @@ import lombok.val;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.scheduler.BukkitTask;
+import org.jetbrains.annotations.NotNull;
import java.io.InputStreamReader;
import java.lang.annotation.ElementType;
@@ -113,6 +114,8 @@ public abstract class Command2
private ArrayList 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.
@@ -183,6 +186,7 @@ public abstract class Command2
params.add(cg);
else {
sender.sendMessage("§cYou need to be a " + sendertype.getSimpleName() + " to use this command.");
+ sender.sendMessage(sd.helpText); //Send what the command is about, could be useful for commands like /member where some subcommands aren't player-only
return;
}
val paramArr = sd.method.getParameters();
@@ -259,6 +263,7 @@ public abstract class Command2
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);
@@ -287,7 +292,7 @@ public abstract class Command2
var ht = command.getHelpText(method, ann);
if (ht != null) {
val subcommand = commandChar + path + //Add command path (class name by default)
- (method.getName().equals("def") ? "" : " " + method.getName().replace('_', ' ').toLowerCase()); //Add method name, unless it's 'def'
+ getCommandPath(method.getName(), ' '); //Add method name, unless it's 'def'
ht = getParameterHelp(method, ht, subcommand);
subcommands.put(subcommand, new SubcommandData<>(method, command, ht)); //Result of the above (def) is that it will show the help text
scmdHelpList.add(subcommand);
@@ -355,4 +360,31 @@ public abstract class Command2
/*public Set getAllSubcommands() {
return Collections.unmodifiableSet(subcommands.keySet());
}*/
+
+ /**
+ * Unregisters all of the subcommands in the given command.
+ *
+ * @param command The command object
+ */
+ public void unregisterCommand(ICommand2 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);
+ }
+ }
+
+ /**
+ * It will start with the given replace char.
+ *
+ * @param methodName The method's name, method.getName()
+ * @param replaceChar The character to use between subcommands
+ * @return The command path starting with the replace char.
+ */
+ @NotNull
+ public String getCommandPath(String methodName, char replaceChar) {
+ return methodName.equals("def") ? "" : replaceChar + methodName.replace('_', replaceChar).toLowerCase();
+ }
}
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java
index 2f52c69..ff4b7f4 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/Command2MC.java
@@ -1,6 +1,8 @@
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;
@@ -17,9 +19,15 @@ 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 extends Command2 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 command) {
super.registerCommand(command, '/');
@@ -29,6 +37,13 @@ public class Command2MC extends Command2 implemen
PermissionDefault.TRUE)); //Allow commands by default, it will check mod-only
for (val method : command.getClass().getMethods()) {
if (!method.isAnnotationPresent(Subcommand.class)) continue;
+ var path = getCommandPath(method.getName(), '.');
+ if (path.length() > 0) {
+ var subperm = perm + path;
+ if (Bukkit.getPluginManager().getPermission(subperm) == null) //Check needed for plugin reset
+ Bukkit.getPluginManager().addPermission(new Permission(subperm,
+ PermissionDefault.TRUE)); //Allow commands by default, it will check mod-only
+ }
String pg = permGroup(command, method);
if (pg.length() == 0) continue;
perm = "chroma." + pg;
@@ -45,10 +60,14 @@ public class Command2MC extends Command2 implemen
public boolean hasPermission(CommandSender sender, ICommand2MC command, Method method) {
if (sender instanceof ConsoleCommandSender) return true; //Always allow the console
+ if (command == null) return true; //Allow viewing the command - it doesn't do anything anyway
String pg;
boolean p = true;
+ var cmdperm = "chroma.command." + command.getCommandPath().replace(' ', '.');
+ var path = getCommandPath(method.getName(), '.');
String[] perms = {
- "chroma.command." + command.getCommandPath().replace(' ', '.'),
+ path.length() > 0 ? cmdperm + path : null,
+ cmdperm,
(pg = permGroup(command, method)).length() > 0 ? "chroma." + pg : null
};
for (String perm : perms) {
@@ -74,9 +93,11 @@ public class Command2MC extends Command2 implemen
* @return The permission group for the subcommand or empty string
*/
private String permGroup(ICommand2MC command, Method method) {
- val sc = method.getAnnotation(Subcommand.class);
- if (sc != null && sc.permGroup().length() > 0) {
- return sc.permGroup();
+ if (method != null) {
+ val sc = method.getAnnotation(Subcommand.class);
+ if (sc != null && sc.permGroup().length() > 0) {
+ return sc.permGroup();
+ }
}
if (getAnnForValue(command.getClass(), CommandClass.class, CommandClass::modOnly, false))
return Subcommand.MOD_GROUP;
@@ -112,6 +133,21 @@ public class Command2MC extends Command2 implemen
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 -> Optional.ofNullable(sd.command).map(ICommand2MC::getPlugin).map(plugin::equals).orElse(false));
+ }
+
+ 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).map(ICommand2MC::getComponent)
+ .map(comp -> component.getClass().getSimpleName().equals(comp.getClass().getSimpleName())).orElse(false));
+ }
+
@EventHandler
private void handleTabComplete(TabCompleteEvent event) {
String commandline = event.getBuffer();
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.java
index d0a202a..fc49c75 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.java
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2.java
@@ -47,7 +47,7 @@ public abstract class ICommand2 {
@Getter
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 ICommand2(Command2 manager) {
+ public > ICommand2(Command2 manager) {
path = getcmdpath();
this.manager = manager;
}
diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2MC.java b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2MC.java
index 566285d..af12d61 100644
--- a/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2MC.java
+++ b/Chroma-Core/src/main/java/buttondevteam/lib/chat/ICommand2MC.java
@@ -1,9 +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 {
+ @Getter
+ private ButtonPlugin plugin;
+ @Getter
+ @Nullable
+ private Component> component;
+
public ICommand2MC() {
super(ButtonPlugin.getCommand2MC());
}
+
+ /**
+ * 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!");
+ }
+
+ /**
+ * 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 > void onRegister(Command2 manager) {
+ super.onRegister(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*/
}
diff --git a/CorePOM/CorePOM.iml b/CorePOM/CorePOM.iml
deleted file mode 100644
index de84cf2..0000000
--- a/CorePOM/CorePOM.iml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file