Minor fixes

This commit is contained in:
Paul Reilly 2023-06-10 21:41:14 -05:00
parent a22f7fb215
commit e18a0c0808
7 changed files with 203 additions and 47 deletions

View File

@ -48,20 +48,16 @@ public class CageCommand extends Commander
@Subcommand(permission = "datura.cage", args = {Player.class, String.class}) @Subcommand(permission = "datura.cage", args = {Player.class, String.class})
public void cagePlayer(final CommandSender sender, final Player player, final String string) public void cagePlayer(final CommandSender sender, final Player player, final String string)
{ {
switch (string.toLowerCase()) if (string.equalsIgnoreCase("on"))
{ {
case "on" -> ((Datura) getPlugin()).getCager()
{ .cagePlayer(player.getUniqueId());
((Datura) getPlugin()).getCager() sender.sendPlainMessage("Caged " + player.getName() + ".");
.cagePlayer(player.getUniqueId()); } else if (string.equalsIgnoreCase("off"))
sender.sendPlainMessage("Caged " + player.getName() + "."); {
} ((Datura) getPlugin()).getCager()
case "off" -> .uncagePlayer(player.getUniqueId());
{ sender.sendPlainMessage("Liberated " + player.getName() + ".");
((Datura) getPlugin()).getCager()
.uncagePlayer(player.getUniqueId());
sender.sendPlainMessage("Liberated " + player.getName() + ".");
}
} }
} }
@ -70,20 +66,16 @@ public class CageCommand extends Commander
public void cagePlayer(final CommandSender sender, final Player player, final String string, public void cagePlayer(final CommandSender sender, final Player player, final String string,
final Material material) final Material material)
{ {
switch (string.toLowerCase()) if (string.equalsIgnoreCase("on"))
{ {
case "on" -> ((Datura) getPlugin()).getCager()
{ .cagePlayer(player.getUniqueId(), material);
((Datura) getPlugin()).getCager() sender.sendPlainMessage("Caged " + player.getName() + ".");
.cagePlayer(player.getUniqueId(), material); } else if (string.equalsIgnoreCase("off"))
sender.sendPlainMessage("Caged " + player.getName() + "."); {
} ((Datura) getPlugin()).getCager()
case "off" -> .uncagePlayer(player.getUniqueId());
{ sender.sendPlainMessage("Liberated " + player.getName() + ".");
((Datura) getPlugin()).getCager()
.uncagePlayer(player.getUniqueId());
sender.sendPlainMessage("Liberated " + player.getName() + ".");
}
} }
} }
} }

View File

@ -0,0 +1,90 @@
package me.totalfreedom.datura.cmd;
import me.totalfreedom.base.Shortcuts;
import me.totalfreedom.command.Commander;
import me.totalfreedom.command.annotation.Info;
import me.totalfreedom.command.annotation.Permissive;
import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.datura.Datura;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "halt", description = "Halt a single player, or every player.", usage = "/<command> <player | all> <on, off>")
@Permissive(perm = "datura.halt")
public class HaltCommand extends Commander
{
private final Datura plugin = Shortcuts.provideModule(Datura.class)
.getModule();
/**
* Initializes this command object. The provided {@link JavaPlugin} should be the plugin which contains the
* command.
* <p>
* This constructor will automatically register all subcommands and completions for this command. It will also
* automatically infer all required information from the provided {@link Info} and {@link Permissive} annotations.
*
* @param plugin The plugin which contains this command.
*/
protected HaltCommand(@NotNull final JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.halt", args = {Player.class, String.class})
public void haltPlayer(final CommandSender sender, final Player target, final String toggle)
{
if (toggle.equalsIgnoreCase("on"))
{
plugin.getHalter()
.halt(target.getUniqueId());
target.sendPlainMessage("You have been frozen!");
sender.sendPlainMessage("You have halted " + target.getName() + ".");
} else if (toggle.equalsIgnoreCase("off"))
{
plugin.getHalter()
.stop(target.getUniqueId());
target.sendPlainMessage("You have been unfrozen!");
sender.sendPlainMessage("You have unhalted " + target.getName() + ".");
}
}
@Subcommand(permission = "datura.halt.all", args = {String.class, String.class})
public void haltAll(final CommandSender sender, final String all, final String toggle)
{
if (all.equalsIgnoreCase("all"))
{
if (toggle.equalsIgnoreCase("on"))
{
Bukkit.getServer()
.getOnlinePlayers()
.forEach(player ->
{
plugin.getHalter()
.halt(player.getUniqueId());
});
final Component message = sender.name()
.append(Component.text(": Freezing all players"))
.color(NamedTextColor.AQUA);
Bukkit.broadcast(message);
sender.sendPlainMessage("All players have been halted.");
} else if (toggle.equalsIgnoreCase("off"))
{
plugin.getHalter()
.clear();
Bukkit.broadcast(Component.text("All players have been unfrozen!", NamedTextColor.AQUA));
sender.sendPlainMessage("All players have been unhalted.");
}
}
}
}

View File

@ -22,6 +22,15 @@ public class Halter implements Listener
this.haltedPlayers.add(uuid); this.haltedPlayers.add(uuid);
} }
public void stop(final UUID uuid)
{
this.haltedPlayers.remove(uuid);
}
public void clear() {
this.haltedPlayers.clear();
}
@EventHandler @EventHandler
public void playerMove(final PlayerMoveEvent event) public void playerMove(final PlayerMoveEvent event)
{ {

View File

@ -0,0 +1,15 @@
package me.totalfreedom.base;
import me.totalfreedom.provider.ModuleProvider;
import org.bukkit.plugin.java.JavaPlugin;
public final class Shortcuts
{
private Shortcuts() {
throw new AssertionError();
}
public static <T extends JavaPlugin> ModuleProvider<T> provideModule(final Class<T> pluginClass) {
return CommonsBase.getInstance().getRegistrations().getModuleRegistry().getProvider(pluginClass);
}
}

View File

@ -1,12 +1,12 @@
package me.totalfreedom.command; package me.totalfreedom.command;
import me.totalfreedom.api.Context;
import me.totalfreedom.command.annotation.Completion; import me.totalfreedom.command.annotation.Completion;
import me.totalfreedom.command.annotation.Subcommand; import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.provider.ContextProvider; import me.totalfreedom.provider.ContextProvider;
import me.totalfreedom.utils.logging.FreedomLogger; import me.totalfreedom.utils.logging.FreedomLogger;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
@ -120,7 +120,7 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
final Subcommand node) final Subcommand node)
{ {
final Class<?>[] argTypes = node.args(); final Class<?>[] argTypes = node.args();
if (argTypes.length != args.length) if (argTypes.length > args.length)
return; return;
final Object[] objects = new Object[argTypes.length + 1]; final Object[] objects = new Object[argTypes.length + 1];
@ -130,11 +130,27 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
final Class<?> argType = argTypes[i]; final Class<?> argType = argTypes[i];
final String arg = args[i]; final String arg = args[i];
if (argType == String.class) if (argType.equals(String.class))
continue; {
if (i == argTypes.length - 1)
{
final String[] reasonArgs = Arrays.copyOfRange(args, i, args.length - 1);
final String reason = String.join(" ", reasonArgs);
objects[i] = reason;
} else
{
continue;
}
}
final Context<?> context = () -> provider.fromString(arg, argType); if (argType.equals(Location.class)) {
objects[i] = context.get(); final String[] locationArgs = Arrays.copyOfRange(args, i, i + 3);
final String location = String.join(" ", locationArgs);
objects[i] = location;
}
final Object obj = provider.fromString(arg, argType);
objects[i] = obj;
} }
try try
{ {
@ -183,7 +199,7 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
"7", "7",
"8", "8",
"9")); "9"));
case "%location%" -> results.add("world,x,y,z"); case "%location%" -> results.add("world x y z");
default -> results.add(p); default -> results.add(p);
} }
} }

View File

@ -10,19 +10,26 @@ import java.lang.annotation.Target;
/** /**
* This annotation should be used to mark methods as subcommand methods. Subcommand methods can have custom arguments * This annotation should be used to mark methods as subcommand methods. Subcommand methods can have custom arguments
* (current supported arguments can be found in the {@link ContextProvider}), and can also have a custom permission. * <i>(current supported arguments can be found in the {@link ContextProvider})</i>, and can also have a custom
* These subcommands can also be annotated with {@link Completions} to provide tab completions for the subcommand. The * permission. These subcommands can also be annotated with {@link Completions} to provide tab completions for the
* subcommand method must be public, and must be in a class that is registered with the {@link CommandHandler}. * subcommand. The subcommand method must be public, and must be in a class that is registered with the
* <br> * {@link CommandHandler}.
* <p>
* Tab completions with the {@link Completions} annotation are only supported for subcommands. When registering * Tab completions with the {@link Completions} annotation are only supported for subcommands. When registering
* completions, you only need to define the completion arguments a single time. If there are other methods which * completions, you only need to define the completion arguments a single time. If there are other methods which
* function as optional additional arguments for the subcommand, the previously registered arguments will still be * function as optional additional arguments for the subcommand, the previously registered arguments will still be
* present when the user does their tab completion. * present when the user does their tab completion.
* <br> * <p>
* For example, if you have a subcommand method with the arguments {@code (Player, String)}, and another method which * For example, if you have a subcommand method with the arguments {@code (Player, String)}, and another method which
* has the arguments {@code (Player, String, String)}, the tab completions for the second method will still have the * has the arguments {@code (Player, String, String)}, the tab completions for the second method will still have the
* {@code Player} and {@code String} arguments registered from the first method. You will only need to provide a * {@code Player} and {@code String} arguments registered from the first method. You will only need to provide a
* {@link Completion} for the additional 3rd argument. * {@link Completion} for the additional 3rd argument.
* <p>
* Additionally, if the final argument is a String object, the BukkitDelegate will automatically append any additional
* arguments to the end of the String. For example, if you have a subcommand method with the arguments
* {@code (Player, String)}, and the user executes the command with the arguments {@code /command playerName arg2 arg3},
* the {@code String} argument will be {@code "arg2 arg3"}. This allows for us to use a String at the end of our
* subcommand arguments to allow for the user to input a reason.
*/ */
@Target(ElementType.METHOD) @Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)

View File

@ -1,5 +1,8 @@
package me.totalfreedom.provider; package me.totalfreedom.provider;
import me.totalfreedom.api.Context;
import me.totalfreedom.command.BukkitDelegate;
import me.totalfreedom.command.annotation.Subcommand;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location; import org.bukkit.Location;
@ -13,6 +16,26 @@ import org.jetbrains.annotations.Nullable;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
/**
* This class is used to provide context to subcommand methods. This class is used by the BukkitDelegate to parse
* arguments for subcommands. The following types are supported:
* <ul>
* <li>Boolean</li>
* <li>Double</li>
* <li>Integer</li>
* <li>Long</li>
* <li>Float</li>
* <li>Material</li>
* <li>Player</li>
* <li>World</li>
* <li>Location</li>
* <li>CommandSender</li>
* <li>Component</li>
* </ul>
* All of these types can be parsed from a String input. If the String cannot be parsed into any of
* these types, then null will be returned.
* @see #fromString(String, Class)
*/
public class ContextProvider public class ContextProvider
{ {
public <T> T fromString(final String string, final Class<T> clazz) public <T> T fromString(final String string, final Class<T> clazz)
@ -104,25 +127,29 @@ public class ContextProvider
} }
/** /**
* When using this method, the input string must be formatted as * When using this method, the next four arguments must be world, x, y, z.
* <br> * The world must be a valid world name, and x, y, and z must be valid doubles.
* <code>worldName,x,y,z</code> * If any of these are invalid, this will return null.
* <br>
* *
* @param string The string to parse * @param string The string to parse
* @return A location object if xyz is valid * @return A location object if xyz is valid
* @see BukkitDelegate#processSubCommands(String[], CommandSender, ContextProvider, Subcommand)
*/ */
private @Nullable Location toLocation(final String string) private @Nullable Location toLocation(final String string)
{ {
final String[] split = string.split(","); final String[] split = string.split(" ");
if (split.length != 4 || toWorld(split[0]) == null) return null; if (split.length != 4 || toWorld(split[0]) == null) return null;
final double x = Double.parseDouble(split[1]); try {
final double y = Double.parseDouble(split[2]); final double x = Double.parseDouble(split[1]);
final double z = Double.parseDouble(split[3]); final double y = Double.parseDouble(split[2]);
final double z = Double.parseDouble(split[3]);
return new Location(toWorld(split[0]), x, y, z); return new Location(toWorld(split[0]), x, y, z);
} catch (NumberFormatException ex) {
return null;
}
} }
private @Nullable CommandSender toCommandSender(final String string) private @Nullable CommandSender toCommandSender(final String string)