Skip to content

Commit

Permalink
Merge pull request #63 from josemmo/develop
Browse files Browse the repository at this point in the history
v1.2.6
  • Loading branch information
josemmo authored Oct 29, 2022
2 parents 0abaec8 + 2ae0dc3 commit 705926f
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 71 deletions.
35 changes: 22 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,20 +97,29 @@ This plugin adds the following commands:
## Permissions
If you want more granular control over the players who can use a particular set of commands, permissions are the way to go!

Yamipa defines the following permissions, each one corresponding to the command with the same name:

- `yamipa.clear`
- `yamipa.describe`
- `yamipa.download`
- `yamipa.give`
- `yamipa.list`
- `yamipa.place`
- `yamipa.remove`
- `yamipa.top`

By default, only server OPs have all permissions granted. You can change this by using a permission plugin,
Yamipa defines the following permissions:

| Command | Default | Description |
|:----------------------------|:-----------:|:----------------------------------------------------------------|
| `yamipa.command.clear` | OPs | To use the `/image clear` command |
| `yamipa.command.describe` | OPs | To use the `/image describe` command |
| `yamipa.command.download` | OPs | To use the `/image download` command |
| `yamipa.command.give` | OPs | To use the `/image give` download |
| `yamipa.command.list` | OPs | To use the `/image list` command |
| `yamipa.command.place` | OPs | To use the `/image place` command |
| `yamipa.command.remove` | OPs | To use the `/image remove` command |
| `yamipa.command.remove.own` | OPs | Same as previous, but only for images placed by the same player |
| `yamipa.command.top` | OPs | To use the `/image top` command |
| `yamipa.item.place` | All players | To place image items |
| `yamipa.item.remove` | All players | To remove image items (that have the `REMO` flag) |
| `yamipa.item.remove.own` | All players | Same as previous, but only for images placed by the same player |

Note that permissions work **as a tree**. This means that if you grant a permission, by default its children will also
be granted. For instance, you can grant access to all commands with `yamipa.command.*`.
Similarly, if you grant the `yamipa.command.remove`, the permission `yamipa.command.remove.own` will also be granted.

You can change which roles or players are granted these commands by using a permission plugin,
such as [LuckPerms](https://luckperms.net/) or [GroupManager](https://elgarl.github.io/GroupManager/).

Both these plugins have been tested to work with Yamipa, although any similar one should work just fine.

## Protecting areas
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>io.josemmo.bukkit.plugin</groupId>
<artifactId>YamipaPlugin</artifactId>
<version>1.2.5</version>
<version>1.2.6</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
Expand Down
27 changes: 17 additions & 10 deletions src/main/java/io/josemmo/bukkit/plugin/commands/Command.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,18 @@ public Command(@NotNull String name) {

/**
* Add permission requirement to this command
* @param permission Permission name
* @return This instance
* @param permissions Permission names (match as least one)
* @return This instance
*/
public @NotNull Command withPermission(@NotNull String permission) {
return withRequirement(sender -> sender.hasPermission(permission));
public @NotNull Command withPermission(@NotNull String ...permissions) {
return withRequirement(sender -> {
for (String permission : permissions) {
if (sender.hasPermission(permission)) {
return true;
}
}
return false;
});
}

/**
Expand Down Expand Up @@ -112,6 +119,12 @@ public Command(@NotNull String name) {

@SuppressWarnings({"rawtypes", "unchecked"})
private @NotNull ArgumentBuilder buildElement(@NotNull ArgumentBuilder parent, int argIndex) {
// Attach requirement handler to each command element
parent.requires(source -> {
CommandSender sender = Internals.getBukkitSender(source);
return requirementHandler.test(sender);
});

// Chain command elements from the bottom-up
if (argIndex < arguments.size()) {
parent.then(buildElement(arguments.get(argIndex).build(), argIndex+1)).executes(ctx -> {
Expand All @@ -122,12 +135,6 @@ public Command(@NotNull String name) {
return parent;
}

// Attach requirement handler to last command element
parent.requires(source -> {
CommandSender sender = Internals.getBukkitSender(source);
return requirementHandler.test(sender);
});

// Attach execution handler to last command element
if (executesPlayerHandler != null) {
parent.executes(ctx -> {
Expand Down
53 changes: 33 additions & 20 deletions src/main/java/io/josemmo/bukkit/plugin/commands/ImageCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,28 +35,28 @@ public static void showHelp(@NotNull CommandSender s, @NotNull String commandNam
String cmd = "/" + commandName;
s.sendMessage(ChatColor.BOLD + "=== Yamipa Plugin Help ===");
s.sendMessage(ChatColor.AQUA + cmd + ChatColor.RESET + " - Show this help");
if (s.hasPermission("yamipa.clear")) {
if (s.hasPermission("yamipa.command.clear") || s.hasPermission("yamipa.clear")) {
s.sendMessage(ChatColor.AQUA + cmd + " clear <x z w> <r> [<player>]" + ChatColor.RESET + " - Remove placed images");
}
if (s.hasPermission("yamipa.describe")) {
if (s.hasPermission("yamipa.command.describe") || s.hasPermission("yamipa.describe")) {
s.sendMessage(ChatColor.AQUA + cmd + " describe" + ChatColor.RESET + " - Describe placed image");
}
if (s.hasPermission("yamipa.download")) {
if (s.hasPermission("yamipa.command.download") || s.hasPermission("yamipa.download")) {
s.sendMessage(ChatColor.AQUA + cmd + " download <url> <filename>" + ChatColor.RESET + " - Download image");
}
if (s.hasPermission("yamipa.give")) {
if (s.hasPermission("yamipa.command.give") || s.hasPermission("yamipa.give")) {
s.sendMessage(ChatColor.AQUA + cmd + " give <p> <filename> <#> <w> [<h>] [<f>]" + ChatColor.RESET + " - Give items");
}
if (s.hasPermission("yamipa.list")) {
if (s.hasPermission("yamipa.command.list") || s.hasPermission("yamipa.list")) {
s.sendMessage(ChatColor.AQUA + cmd + " list [<page>]" + ChatColor.RESET + " - List all images");
}
if (s.hasPermission("yamipa.place")) {
if (s.hasPermission("yamipa.command.place") || s.hasPermission("yamipa.place")) {
s.sendMessage(ChatColor.AQUA + cmd + " place <filename> <w> [<h>] [<f>]" + ChatColor.RESET + " - Place image");
}
if (s.hasPermission("yamipa.remove")) {
if (s.hasPermission("yamipa.command.remove.own") || s.hasPermission("yamipa.remove")) {
s.sendMessage(ChatColor.AQUA + cmd + " remove" + ChatColor.RESET + " - Remove a single placed image");
}
if (s.hasPermission("yamipa.top")) {
if (s.hasPermission("yamipa.command.top") || s.hasPermission("yamipa.top")) {
s.sendMessage(ChatColor.AQUA + cmd + " top" + ChatColor.RESET + " - List players with the most images");
}
}
Expand Down Expand Up @@ -232,32 +232,45 @@ public static boolean placeImage(
}

public static void removeImage(@NotNull Player player) {
ImageRenderer renderer = YamipaPlugin.getInstance().getRenderer();

// Ask user to select fake image
SelectBlockTask task = new SelectBlockTask(player);
task.onSuccess((location, face) -> {
FakeImage image = renderer.getImage(location, face);
FakeImage image = YamipaPlugin.getInstance().getRenderer().getImage(location, face);
if (image == null) {
ActionBar.send(player, ChatColor.RED + "That is not a valid image!");
return;
}

// Check player permissions
for (Location loc : image.getAllLocations()) {
if (!Permissions.canEditBlock(player, loc)) {
ActionBar.send(player, ChatColor.RED + "You're not allowed to remove this image!");
return;
}
// Check player's command permissions
if (
!player.getUniqueId().equals(image.getPlacedBy().getUniqueId()) &&
!player.hasPermission("yamipa.command.remove") &&
!player.hasPermission("yamipa.remove")
) {
ActionBar.send(player, ChatColor.RED + "You cannot remove images from other players!");
return;
}

// Trigger image removal
renderer.removeImage(image);
// Attempt to remove image
removeImage(player, image);
});
task.onFailure(() -> ActionBar.send(player, ChatColor.RED + "Image removing canceled"));
task.run("Right click an image to continue");
}

public static boolean removeImage(@NotNull Player player, @NotNull FakeImage image) {
// Check block permissions
for (Location loc : image.getAllLocations()) {
if (!Permissions.canEditBlock(player, loc)) {
ActionBar.send(player, ChatColor.RED + "You're not allowed to remove this image!");
return false;
}
}

// Trigger image removal
YamipaPlugin.getInstance().getRenderer().removeImage(image);
return true;
}

public static void clearImages(
@NotNull CommandSender sender,
@NotNull Location origin,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,23 +58,23 @@ public static void register(@NotNull YamipaPlugin plugin) {
Command root = new Command(COMMAND_NAME);

// Help command
root.withRequirement(sender ->
sender.hasPermission("yamipa.*") ||
sender.hasPermission("yamipa.clear") ||
sender.hasPermission("yamipa.describe") ||
sender.hasPermission("yamipa.download") ||
sender.hasPermission("yamipa.give") ||
sender.hasPermission("yamipa.list") ||
sender.hasPermission("yamipa.place") ||
sender.hasPermission("yamipa.remove") ||
sender.hasPermission("yamipa.top"))
root.withPermission(
"yamipa.command.clear", "yamipa.clear",
"yamipa.command.describe", "yamipa.describe",
"yamipa.command.download", "yamipa.download",
"yamipa.command.give", "yamipa.give",
"yamipa.command.list", "yamipa.list",
"yamipa.command.place", "yamipa.place",
"yamipa.command.remove.own", "yamipa.remove",
"yamipa.command.top", "yamipa.top"
)
.executes((sender, args) -> {
ImageCommand.showHelp(sender, (String) args[0]);
});

// Clear command
root.addSubcommand("clear")
.withPermission("yamipa.clear")
.withPermission("yamipa.command.clear", "yamipa.clear")
.withArgument(new IntegerArgument("x"))
.withArgument(new IntegerArgument("z"))
.withArgument(new WorldArgument("world"))
Expand All @@ -85,7 +85,7 @@ public static void register(@NotNull YamipaPlugin plugin) {
ImageCommand.clearImages(sender, origin, (int) args[4], (OfflinePlayer) args[5]);
});
root.addSubcommand("clear")
.withPermission("yamipa.clear")
.withPermission("yamipa.command.clear", "yamipa.clear")
.withArgument(new IntegerArgument("x"))
.withArgument(new IntegerArgument("z"))
.withArgument(new WorldArgument("world"))
Expand All @@ -97,14 +97,14 @@ public static void register(@NotNull YamipaPlugin plugin) {

// Describe command
root.addSubcommand("describe")
.withPermission("yamipa.describe")
.withPermission("yamipa.command.describe", "yamipa.describe")
.executesPlayer((player, __) -> {
ImageCommand.describeImage(player);
});

// Download command
root.addSubcommand("download")
.withPermission("yamipa.download")
.withPermission("yamipa.command.download", "yamipa.download")
.withArgument(new StringArgument("url"))
.withArgument(new StringArgument("filename"))
.executes((sender, args) -> {
Expand All @@ -113,7 +113,7 @@ public static void register(@NotNull YamipaPlugin plugin) {

// Give subcommand
root.addSubcommand("give")
.withPermission("yamipa.give")
.withPermission("yamipa.command.give", "yamipa.give")
.withArgument(new OnlinePlayerArgument("player"))
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("amount", 1, 64))
Expand All @@ -125,7 +125,7 @@ public static void register(@NotNull YamipaPlugin plugin) {
(int) args[4], (int) args[5], (int) args[6]);
});
root.addSubcommand("give")
.withPermission("yamipa.give")
.withPermission("yamipa.command.give", "yamipa.give")
.withArgument(new OnlinePlayerArgument("player"))
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("amount", 1, 64))
Expand All @@ -136,7 +136,7 @@ public static void register(@NotNull YamipaPlugin plugin) {
(int) args[4], (int) args[5], FakeImage.DEFAULT_GIVE_FLAGS);
});
root.addSubcommand("give")
.withPermission("yamipa.give")
.withPermission("yamipa.command.give", "yamipa.give")
.withArgument(new OnlinePlayerArgument("player"))
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("amount", 1, 64))
Expand All @@ -148,21 +148,21 @@ public static void register(@NotNull YamipaPlugin plugin) {

// List subcommand
root.addSubcommand("list")
.withPermission("yamipa.list")
.withPermission("yamipa.command.list", "yamipa.list")
.withArgument(new IntegerArgument("page", 1))
.executes((sender, args) -> {
ImageCommand.listImages(sender, (int) args[1]);
});
root.addSubcommand("list")
.withPermission("yamipa.list")
.withPermission("yamipa.command.list", "yamipa.list")
.executes((sender, __) -> {
boolean isPlayer = (sender instanceof Player);
ImageCommand.listImages(sender, isPlayer ? 1 : 0);
});

// Place subcommand
root.addSubcommand("place")
.withPermission("yamipa.place")
.withPermission("yamipa.command.place", "yamipa.place")
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("width", 1, FakeImage.MAX_DIMENSION))
.withArgument(new IntegerArgument("height", 1, FakeImage.MAX_DIMENSION))
Expand All @@ -171,7 +171,7 @@ public static void register(@NotNull YamipaPlugin plugin) {
ImageCommand.placeImage(player, (ImageFile) args[1], (int) args[2], (int) args[3], (int) args[4]);
});
root.addSubcommand("place")
.withPermission("yamipa.place")
.withPermission("yamipa.command.place", "yamipa.place")
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("width", 1, FakeImage.MAX_DIMENSION))
.withArgument(new IntegerArgument("height", 1, FakeImage.MAX_DIMENSION))
Expand All @@ -180,7 +180,7 @@ public static void register(@NotNull YamipaPlugin plugin) {
FakeImage.DEFAULT_PLACE_FLAGS);
});
root.addSubcommand("place")
.withPermission("yamipa.place")
.withPermission("yamipa.command.place", "yamipa.place")
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("width", 1, FakeImage.MAX_DIMENSION))
.executesPlayer((player, args) -> {
Expand All @@ -190,14 +190,14 @@ public static void register(@NotNull YamipaPlugin plugin) {

// Remove subcommand
root.addSubcommand("remove")
.withPermission("yamipa.remove")
.withPermission("yamipa.command.remove.own", "yamipa.remove")
.executesPlayer((player, __) -> {
ImageCommand.removeImage(player);
});

// Top subcommand
root.addSubcommand("top")
.withPermission("yamipa.top")
.withPermission("yamipa.command.top", "yamipa.top")
.executes((sender, __) -> {
ImageCommand.showTopPlayers(sender);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ private void load() {
* @param player Player instance
*/
public void spawn(@NotNull Player player) {
plugin.fine("Received request to spawn FakeImage#(" + location + "," + face + ") for Player#" + player.getName());

// Send pixels if instance is already loaded
if (frames != null) {
spawnOnceLoaded(player);
Expand Down Expand Up @@ -447,6 +449,11 @@ public void destroy() {
* @param player Player instance or NULL for all observing players
*/
public void destroy(@Nullable Player player) {
plugin.fine(
"Received request to destroy FakeImage#(" + location + "," + face + ") for " +
(player == null ? "all players" : "Player#" + player.getName())
);

// Send packets to destroy item frames
if (frames != null) {
Set<Player> targets = (player == null) ? observingPlayers : Collections.singleton(player);
Expand Down
Loading

0 comments on commit 705926f

Please sign in to comment.