Skip to content

Commit

Permalink
Added "give" command
Browse files Browse the repository at this point in the history
- Created OnlinePlayerArgument
- Updated ImageCommand and ImageCommandBridge
- Updated README.md

> Related to #10
  • Loading branch information
josemmo committed Dec 5, 2021
1 parent 981ee0c commit 55547c9
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 10 deletions.
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -62,6 +62,7 @@ This plugin adds the following commands:
- `/image clear <x z world> <r> [<placed-by>]`: Remove all placed images in a radius of `r` blocks around an origin.
- `/image describe`: Show detailed information about a placed image.
- `/image download <url> <filename>`: Download an image from a URL and place it in the images directory.
- `/image give <player> <filename> <amount> <width> [<height>]`: Give image items that can be placed later to a player.
- `/image list [<page>]`: List all available files in the images directory.
- `/image place <filename> <width> [<height>]`: Place an image of size `width`x`height` blocks.
- `/image remove`: Remove a placed image from the world without deleting the image file.
Expand All @@ -73,6 +74,8 @@ This plugin adds the following commands:
`/image`
- Download an image from a URL and save it with another name\
`/image download "https://www.example.com/a/b/c/1234.jpg" imagename.jpg`
- Give 10 image items to "TestPlayer" for the "test.jpg" image (3x5 blocks)\
`/image give TestPlayer test.jpg 10 3 5`
- Start the dialog to place an image with a width of 3 blocks and auto height\
`/image place imagename.jpg 3`
- Start the dialog to place a 3-blocks wide and 2-blocks high image\
Expand All @@ -94,6 +97,7 @@ Yamipa defines the following permissions, each one corresponding to the command
- `yamipa.clear`
- `yamipa.describe`
- `yamipa.download`
- `yamipa.give`
- `yamipa.list`
- `yamipa.place`
- `yamipa.remove`
Expand Down
59 changes: 49 additions & 10 deletions src/main/java/io/josemmo/bukkit/plugin/commands/ImageCommand.java
Expand Up @@ -9,6 +9,10 @@
import org.bukkit.*;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataContainer;
import org.bukkit.persistence.PersistentDataType;
import org.bukkit.plugin.PluginDescriptionFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand All @@ -21,10 +25,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.*;

public class ImageCommand {
public static final int ITEMS_PER_PAGE = 9;
Expand All @@ -42,6 +43,9 @@ public static void showHelp(@NotNull CommandSender s, @NotNull String commandNam
if (s.hasPermission("yamipa.download")) {
s.sendMessage(ChatColor.AQUA + cmd + " download <url> <filename>" + ChatColor.RESET + " - Download image");
}
if (s.hasPermission("yamipa.give")) {
s.sendMessage(ChatColor.AQUA + cmd + " give <p> <filename> <#> <w> [<h>]" + ChatColor.RESET + " - Give image items");
}
if (s.hasPermission("yamipa.list")) {
s.sendMessage(ChatColor.AQUA + cmd + " list [<page>]" + ChatColor.RESET + " - List all images");
}
Expand Down Expand Up @@ -130,12 +134,7 @@ public static void placeImage(
player.sendMessage(ChatColor.RED + "The requested file is not a valid image");
return;
}
if (height == 0) {
float imageRatio = (float) sizeInPixels.height / sizeInPixels.width;
height = Math.round(width * imageRatio);
height = Math.min(height, FakeImage.MAX_DIMENSION);
}
final int finalHeight = height;
final int finalHeight = (height == 0) ? FakeImage.getProportionalHeight(sizeInPixels, width) : height;

// Ask player where to place image
SelectBlockTask task = new SelectBlockTask(player);
Expand Down Expand Up @@ -297,4 +296,44 @@ public static void showTopPlayers(@NotNull CommandSender sender) {
++printedLines;
}
}

public static void giveImageItems(
@NotNull CommandSender sender,
@NotNull Player player,
@NotNull ImageFile image,
int amount,
int width,
int height
) {
YamipaPlugin plugin = YamipaPlugin.getInstance();

// Get image size in blocks
Dimension sizeInPixels = image.getSize();
if (sizeInPixels == null) {
sender.sendMessage(ChatColor.RED + "The requested file is not a valid image");
return;
}
if (height == 0) {
height = FakeImage.getProportionalHeight(sizeInPixels, width);
}

// Create item stack
ItemStack itemStack = new ItemStack(Material.PAPER, amount);
ItemMeta itemMeta = Objects.requireNonNull(itemStack.getItemMeta());
PersistentDataContainer itemData = itemMeta.getPersistentDataContainer();
itemMeta.setDisplayName(image.getName() + ChatColor.AQUA + " (" + width + "x" + height + ")");

This comment has been minimized.

Copy link
@wtlgo

wtlgo Dec 7, 2021

Sorry for putting my 5 cents again, but maybe it would be better to also add the ability to set a custom name for the item and fallback to this if it isn't set? Just thinking.

This comment has been minimized.

Copy link
@josemmo

josemmo Dec 7, 2021

Author Owner

Well, allowing a custom item name will remove essential information to the player (width and height) and the "give" command will need to have an additional argument (5 arguments looks like more than plenty to me).

At first I wouldn't add that feature, players can always rename image items like any other in-game item using an anvil and it would retain its metadata.

This comment has been minimized.

Copy link
@wtlgo

wtlgo Dec 7, 2021

Okay, you know better.

itemMeta.setLore(Collections.singletonList("Yamipa image"));
itemData.set(new NamespacedKey(plugin, "filename"), PersistentDataType.STRING, image.getName());
itemData.set(new NamespacedKey(plugin, "width"), PersistentDataType.INTEGER, width);
itemData.set(new NamespacedKey(plugin, "height"), PersistentDataType.INTEGER, height);
itemStack.setItemMeta(itemMeta);

// Add item stack to player's inventory
player.getInventory().addItem(itemStack);
sender.sendMessage(
ChatColor.ITALIC + "Added " + amount + " " +
(amount == 1 ? "image item" : "image items") +
" to " + player.getName() + "'s inventory"
);
}
}
Expand Up @@ -63,6 +63,7 @@ public static void register(@NotNull YamipaPlugin plugin) {
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") ||
Expand Down Expand Up @@ -110,6 +111,29 @@ public static void register(@NotNull YamipaPlugin plugin) {
ImageCommand.downloadImage(sender, (String) args[1], (String) args[2]);
});

// Give subcommand
root.addSubcommand("give")
.withPermission("yamipa.give")
.withArgument(new OnlinePlayerArgument("player"))
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("amount", 1, 64))
.withArgument(new IntegerArgument("width", 1, FakeImage.MAX_DIMENSION))
.withArgument(new IntegerArgument("height", 1, FakeImage.MAX_DIMENSION))
.executes((sender, args) -> {
ImageCommand.giveImageItems(sender, (Player) args[1], (ImageFile) args[2], (int) args[3],
(int) args[4], (int) args[5]);
});
root.addSubcommand("give")
.withPermission("yamipa.give")
.withArgument(new OnlinePlayerArgument("player"))
.withArgument(new ImageFileArgument("filename"))
.withArgument(new IntegerArgument("amount", 1, 64))
.withArgument(new IntegerArgument("width", 1, FakeImage.MAX_DIMENSION))
.executes((sender, args) -> {
ImageCommand.giveImageItems(sender, (Player) args[1], (ImageFile) args[2], (int) args[3],
(int) args[4], 0);
});

// List subcommand
root.addSubcommand("list")
.withPermission("yamipa.list")
Expand Down
@@ -0,0 +1,55 @@
package io.josemmo.bukkit.plugin.commands.arguments;

import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

public class OnlinePlayerArgument extends StringArgument {
/**
* Online player argument constructor
* @param name Argument name
*/
public OnlinePlayerArgument(@NotNull String name) {
super(name);
}

@Override
public @NotNull RequiredArgumentBuilder<?, ?> build() {
return super.build().suggests(this::getSuggestions);
}

@Override
public @NotNull Object parse(@NotNull CommandSender sender, @NotNull Object rawValue) throws CommandSyntaxException {
Player player = getAllowedValues().get((String) rawValue);
if (player == null) {
throw newException("Expected online player (name or UUID)");
}
return player;
}

private @NotNull CompletableFuture<Suggestions> getSuggestions(
@NotNull CommandContext<?> ctx,
@NotNull SuggestionsBuilder builder
) {
getAllowedValues().keySet().forEach(builder::suggest);
return builder.buildFuture();
}

private @NotNull Map<String, Player> getAllowedValues() {
Map<String, Player> values = new HashMap<>();
for (Player player : Bukkit.getOnlinePlayers()) {
values.put(player.getUniqueId().toString(), player);
values.put(player.getName(), player);
}
return values;
}
}
14 changes: 14 additions & 0 deletions src/main/java/io/josemmo/bukkit/plugin/renderer/FakeImage.java
Expand Up @@ -10,6 +10,7 @@
import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.*;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -84,6 +85,19 @@ public static boolean isAnimationEnabled() {
}
}

/**
* Get proportional height
* @param sizeInPixels Image file dimension in pixels
* @param width Desired width in blocks
* @return Height in blocks (capped at <code>FakeImage.MAX_DIMENSION</code>)
*/
public static int getProportionalHeight(@NotNull Dimension sizeInPixels, int width) {
float imageRatio = (float) sizeInPixels.height / sizeInPixels.width;
int height = Math.round(width * imageRatio);
height = Math.min(height, MAX_DIMENSION);
return height;
}

/**
* Class constructor
* @param filename Image filename
Expand Down
3 changes: 3 additions & 0 deletions src/main/resources/plugin.yml
Expand Up @@ -12,6 +12,7 @@ permissions:
yamipa.clear: true
yamipa.describe: true
yamipa.download: true
yamipa.give: true
yamipa.list: true
yamipa.place: true
yamipa.remove: true
Expand All @@ -22,6 +23,8 @@ permissions:
default: op
yamipa.download:
default: op
yamipa.give:
default: op
yamipa.list:
default: op
yamipa.place:
Expand Down

0 comments on commit 55547c9

Please sign in to comment.