This commit is contained in:
Paul Reilly 2023-06-25 21:46:01 -05:00
parent d0e8d6e361
commit 2b12f4eebb
10 changed files with 151 additions and 74 deletions

View File

@ -19,7 +19,7 @@ import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@Info(name = "cleardrops", description = "Clears all item drops in the world" + ".", usage = "/<command>", aliases = @Info(name = "cleardrops", description = "Clears all item drops in the world" + ".", usage = "/<command>", aliases =
{"cd", "clearitems", "ci", "wipeitems", "wi"}) {"cd", "clearitems", "ci", "wipeitems", "wi", "removedrops", "rd"})
@Permissive(perm = "datura.cleardrops") @Permissive(perm = "datura.cleardrops")
public class ClearDropsCommand extends Commander public class ClearDropsCommand extends Commander
{ {

View File

@ -3,6 +3,8 @@ package me.totalfreedom.datura.cmd;
import me.totalfreedom.command.Commander; import me.totalfreedom.command.Commander;
import me.totalfreedom.command.annotation.Base; import me.totalfreedom.command.annotation.Base;
import me.totalfreedom.command.annotation.Completion; import me.totalfreedom.command.annotation.Completion;
import me.totalfreedom.command.annotation.Info;
import me.totalfreedom.command.annotation.Permissive;
import me.totalfreedom.command.annotation.Subcommand; import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.utils.Tagged; import me.totalfreedom.utils.Tagged;
import org.bukkit.World; import org.bukkit.World;
@ -12,6 +14,9 @@ import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@Info(name = "clearentities", description = "Clears all entities in the world.", usage = "/<command> [world]",
aliases = {"ew", "ce", "entitywipe", "entityclear", "ec"})
@Permissive(perm = "datura.clearentities")
public class ClearEntitiesCommand extends Commander public class ClearEntitiesCommand extends Commander
{ {
/** /**

View File

@ -0,0 +1,93 @@
package me.totalfreedom.datura.cmd;
import java.time.Duration;
import me.totalfreedom.base.Shortcuts;
import me.totalfreedom.command.Commander;
import me.totalfreedom.command.annotation.Completion;
import me.totalfreedom.command.annotation.Info;
import me.totalfreedom.command.annotation.Permissive;
import me.totalfreedom.command.annotation.Subcommand;
import me.totalfreedom.datura.perms.PermissionNodeBuilder;
import me.totalfreedom.security.Node;
import me.totalfreedom.security.NodeType;
import me.totalfreedom.security.PermissionHolder;
import me.totalfreedom.user.User;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
@Info(name = "manageuser", description = "Manage a user's permissions", usage = "/manageuser <username> <info | (add "
+ "| remove <permission>)>", aliases = {"mu", "userdata", "ud", "usermanager", "um"})
@Permissive(perm = "datura.manageuser")
public class ManageUserCommand extends Commander
{
/**
* 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 ManageUserCommand(final @NotNull JavaPlugin plugin)
{
super(plugin);
}
@Subcommand(permission = "datura.manageuser", args = {Player.class, String.class, String.class, Long.class})
@Completion(index = 0, args = {"%player%"})
@Completion(index = 1, args = {"info", "add", "remove"})
@Completion(index = 2, args = {"<permission>"})
public void manageUser(final CommandSender sender, final Player player, final String addOrRemove,
final String permission, final long duration)
{
final PermissionHolder user = Shortcuts.getUser(player);
final Node node = new PermissionNodeBuilder().key(permission)
.type(NodeType.PERMISSION)
.expiry(Duration.ofMinutes(duration)
.getSeconds() + System.currentTimeMillis())
.build();
ifElse(addOrRemove, user, node);
}
@Subcommand(permission = "datura.manageuser", args = {Player.class, String.class, String.class})
public void manageUser(final CommandSender sender, final Player player, final String addOrRemove,
final String permission)
{
final PermissionHolder user = Shortcuts.getUser(player);
final Node node = new PermissionNodeBuilder().key(permission).type(NodeType.PERMISSION).build();
ifElse(addOrRemove, user, node);
}
@Subcommand(permission = "datura.manageuser", args = {Player.class, String.class})
public void userInfo(final CommandSender sender, final Player player, final String info)
{
final User user = Shortcuts.getUser(player);
if (info.equalsIgnoreCase("info"))
{
final StringBuilder permissions = new StringBuilder();
user.getEffectivePermissions().forEach(node -> permissions.append(node.getPermission()));
final String text = """
User: %s
Group: %s
Permissions: %s""".formatted(user.getName(), user.getUserData().getGroup(),
permissions.toString());
sender.sendPlainMessage(text);
}
}
private void ifElse(final String addOrRemove, final PermissionHolder user, final Node node)
{
if (addOrRemove.equalsIgnoreCase("add"))
{
user.addPermission(node);
}
else if (addOrRemove.equalsIgnoreCase("remove"))
{
user.removePermission(node);
}
}
}

View File

@ -114,7 +114,7 @@ public class FreedomGroup implements Group
.findFirst() .findFirst()
.orElse(null); .orElse(null);
return node != null && node.value(); return node != null;
} }
@Override @Override
@ -127,7 +127,7 @@ public class FreedomGroup implements Group
.findFirst() .findFirst()
.orElse(null); .orElse(null);
return node != null && node.value(); return node != null;
} }
@Override @Override
@ -139,7 +139,7 @@ public class FreedomGroup implements Group
.findFirst() .findFirst()
.orElse(null); .orElse(null);
return node != null && node.value(); return node != null;
} }
@Override @Override
@ -152,7 +152,7 @@ public class FreedomGroup implements Group
.findFirst() .findFirst()
.orElse(null); .orElse(null);
return node != null && node.value(); return node != null;
} }
/** /**
@ -214,8 +214,7 @@ public class FreedomGroup implements Group
.map(n -> new PermissionAttachmentInfo( .map(n -> new PermissionAttachmentInfo(
this, this,
n.key(), n.key(),
attachment, attachment, true))
n.value()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }
@ -228,7 +227,7 @@ public class FreedomGroup implements Group
.findFirst() .findFirst()
.orElse(null); .orElse(null);
return node != null && node.value(); return node != null;
} }
@Override @Override

View File

@ -5,29 +5,19 @@ import me.totalfreedom.security.NodeType;
import org.bukkit.permissions.Permission; import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionDefault; import org.bukkit.permissions.PermissionDefault;
record PermissionNode(String key, record PermissionNode(String key, long expiry, NodeType type, boolean wildcard) implements Node
boolean value,
long expiry,
NodeType type,
boolean wildcard) implements Node
{ {
@Override @Override
public Permission bukkit() public Permission bukkit()
{ {
return new Permission(key(), return new Permission(key(), PermissionDefault.FALSE);
value()
? PermissionDefault.TRUE
: PermissionDefault.FALSE);
} }
@Override @Override
public boolean compare(final Node node) public boolean compare(final Node node)
{ {
return node.key() return node.key().equalsIgnoreCase(key()) && node.type().equals(type()) && !node.isExpired();
.equalsIgnoreCase(key())
&& node.value() == value()
&& node.type() == type();
} }
@Override @Override

View File

@ -7,11 +7,9 @@ import me.totalfreedom.security.NodeType;
public class PermissionNodeBuilder implements NodeBuilder public class PermissionNodeBuilder implements NodeBuilder
{ {
private String key = "freedom.default"; private String key = "freedom.default";
private boolean value = true;
private long expiry = -1; private long expiry = -1;
private NodeType type = NodeType.PERMISSION; private NodeType type = NodeType.PERMISSION;
private boolean wildcard = false; private boolean wildcard = false;
private boolean negated = false;
@Override @Override
public NodeBuilder key(final String key) public NodeBuilder key(final String key)
@ -20,13 +18,6 @@ public class PermissionNodeBuilder implements NodeBuilder
return this; return this;
} }
@Override
public NodeBuilder value(final boolean value)
{
this.value = value;
return this;
}
@Override @Override
public NodeBuilder expiry(final long expiry) public NodeBuilder expiry(final long expiry)
{ {
@ -48,16 +39,9 @@ public class PermissionNodeBuilder implements NodeBuilder
return this; return this;
} }
@Override
public NodeBuilder negated(final boolean negated)
{
this.negated = negated;
return this;
}
@Override @Override
public Node build() public Node build()
{ {
return new PermissionNode(key, value, expiry, type, wildcard, negated); return new PermissionNode(key, expiry, type, wildcard);
} }
} }

View File

@ -155,6 +155,10 @@ public final class BukkitDelegate extends Command implements PluginIdentifiableC
} }
final Object obj = provider.fromString(arg, argType); final Object obj = provider.fromString(arg, argType);
if (obj == null) {
FreedomLogger.getLogger("Datura").error("Failed to parse argument " + arg + " for type " + argType.getName());
return;
}
objects[i] = obj; objects[i] = obj;
} }
try try

View File

@ -40,25 +40,26 @@ 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)
{ {
return Stream.of(toBoolean(string), return Stream.of(toBoolean(string, clazz),
toDouble(string), toDouble(string, clazz),
toInt(string), toInt(string, clazz),
toLong(string), toLong(string, clazz),
toFloat(string), toFloat(string, clazz),
toMaterial(string), toMaterial(string, clazz),
toPlayer(string), toPlayer(string, clazz),
toWorld(string), toWorld(string, clazz),
toLocation(string), toLocation(string, clazz),
toCommandSender(string), toComponent(string, clazz))
toComponent(string))
.filter(Objects::nonNull) .filter(Objects::nonNull)
.findFirst() .findFirst()
.map(clazz::cast) .map(clazz::cast)
.orElse(null); .orElse(null);
} }
private @Nullable Boolean toBoolean(final String string) private @Nullable Boolean toBoolean(final String string, final Class<?> clazz)
{ {
if (clazz != Boolean.class) return null;
// Previously we used Boolean#parseBoolean, but that will always return a value and does not throw // Previously we used Boolean#parseBoolean, but that will always return a value and does not throw
// an exception. This means that if the string is not "true" or "false", it will return false. // an exception. This means that if the string is not "true" or "false", it will return false.
if (string.equalsIgnoreCase("true")) return true; if (string.equalsIgnoreCase("true")) return true;
@ -67,8 +68,10 @@ public class ContextProvider
return null; return null;
} }
private @Nullable Double toDouble(final String string) private @Nullable Double toDouble(final String string, final Class<?> clazz)
{ {
if (clazz != Double.class) return null;
try try
{ {
return Double.parseDouble(string); return Double.parseDouble(string);
@ -78,8 +81,10 @@ public class ContextProvider
} }
} }
private @Nullable Integer toInt(final String string) private @Nullable Integer toInt(final String string, final Class<?> clazz)
{ {
if (clazz != Integer.class) return null;
try try
{ {
return Integer.parseInt(string); return Integer.parseInt(string);
@ -89,8 +94,10 @@ public class ContextProvider
} }
} }
private @Nullable Long toLong(final String string) private @Nullable Long toLong(final String string, final Class<?> clazz)
{ {
if (clazz != Long.class) return null;
try try
{ {
return Long.parseLong(string); return Long.parseLong(string);
@ -100,8 +107,10 @@ public class ContextProvider
} }
} }
private @Nullable Float toFloat(final String string) private @Nullable Float toFloat(final String string, final Class<?> clazz)
{ {
if (clazz != Float.class) return null;
try try
{ {
return Float.parseFloat(string); return Float.parseFloat(string);
@ -111,18 +120,21 @@ public class ContextProvider
} }
} }
private @Nullable Material toMaterial(final String string) private @Nullable Material toMaterial(final String string, final Class<?> clazz)
{ {
if (clazz != Material.class) return null;
return Material.matchMaterial(string); return Material.matchMaterial(string);
} }
private @Nullable Player toPlayer(final String string) private @Nullable Player toPlayer(final String string, final Class<?> clazz)
{ {
if (clazz != Player.class) return null;
return Bukkit.getPlayer(string); return Bukkit.getPlayer(string);
} }
private @Nullable World toWorld(final String string) private @Nullable World toWorld(final String string, final Class<?> clazz)
{ {
if (clazz != World.class) return null;
return Bukkit.getWorld(string); return Bukkit.getWorld(string);
} }
@ -135,32 +147,28 @@ public class ContextProvider
* @return A location object if xyz is valid * @return A location object if xyz is valid
* @see BukkitDelegate#processSubCommands(String[], CommandSender, ContextProvider, Subcommand) * @see BukkitDelegate#processSubCommands(String[], CommandSender, ContextProvider, Subcommand)
*/ */
private @Nullable Location toLocation(final String string) private @Nullable Location toLocation(final String string, final Class<?> clazz)
{ {
if (clazz != Location.class) return null;
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], World.class) == null) return null;
try { try {
final double x = Double.parseDouble(split[1]); final double x = Double.parseDouble(split[1]);
final double y = Double.parseDouble(split[2]); final double y = Double.parseDouble(split[2]);
final double z = Double.parseDouble(split[3]); final double z = Double.parseDouble(split[3]);
return new Location(toWorld(split[0]), x, y, z); return new Location(toWorld(split[0], World.class), x, y, z);
} catch (NumberFormatException ex) { } catch (NumberFormatException ex) {
return null; return null;
} }
} }
private @Nullable CommandSender toCommandSender(final String string) private @Nullable Component toComponent(final String string, final Class<?> clazz)
{
if (toPlayer(string) == null) return null;
return toPlayer(string);
}
private @NotNull Component toComponent(final String string)
{ {
if (clazz != Component.class) return null;
return Component.text(string); return Component.text(string);
} }
} }

View File

@ -9,8 +9,6 @@ public interface Node
{ {
String key(); String key();
boolean value();
Permission bukkit(); Permission bukkit();
NodeType type(); NodeType type();

View File

@ -4,15 +4,11 @@ public interface NodeBuilder
{ {
NodeBuilder key(String key); NodeBuilder key(String key);
NodeBuilder value(boolean value);
NodeBuilder expiry(long expiry); NodeBuilder expiry(long expiry);
NodeBuilder type(NodeType type); NodeBuilder type(NodeType type);
NodeBuilder wildcard(boolean wildcard); NodeBuilder wildcard(boolean wildcard);
NodeBuilder negated(boolean negated);
Node build(); Node build();
} }