diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java
index be98094..b5c883e 100644
--- a/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java
+++ b/src/main/java/me/unurled/sacredrealms/sr/commands/CommandManager.java
@@ -7,6 +7,7 @@ import me.unurled.sacredrealms.sr.SR;
import me.unurled.sacredrealms.sr.commands.admin.AttributeCommand;
import me.unurled.sacredrealms.sr.commands.admin.ClientBuildCommand;
import me.unurled.sacredrealms.sr.commands.admin.EntityTypeCommand;
+import me.unurled.sacredrealms.sr.commands.admin.ItemCommand;
import me.unurled.sacredrealms.sr.commands.admin.LevelCommand;
import me.unurled.sacredrealms.sr.commands.player.ResetAdventureCommand;
import me.unurled.sacredrealms.sr.managers.Manager;
@@ -40,6 +41,7 @@ public class CommandManager extends Manager {
registerCommand("clientbuild", ClientBuildCommand.class);
registerCommand("level", LevelCommand.class);
registerCommand("entitytype", EntityTypeCommand.class);
+ registerCommand("item", ItemCommand.class);
registerCommand("resetadventure", ResetAdventureCommand.class);
}
diff --git a/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java
new file mode 100644
index 0000000..31aa33d
--- /dev/null
+++ b/src/main/java/me/unurled/sacredrealms/sr/commands/admin/ItemCommand.java
@@ -0,0 +1,435 @@
+package me.unurled.sacredrealms.sr.commands.admin;
+
+import static me.unurled.sacredrealms.sr.utils.Component.comp;
+import static me.unurled.sacredrealms.sr.utils.Logger.error;
+
+import java.util.Arrays;
+import java.util.List;
+import me.unurled.sacredrealms.sr.components.attributes.Attribute;
+import me.unurled.sacredrealms.sr.components.item.Item;
+import me.unurled.sacredrealms.sr.components.item.ItemManager;
+import me.unurled.sacredrealms.sr.components.item.ItemType;
+import me.unurled.sacredrealms.sr.components.item.Rarity;
+import org.bukkit.Bukkit;
+import org.bukkit.Material;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.TabExecutor;
+import org.bukkit.entity.Player;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class ItemCommand implements TabExecutor {
+
+ /**
+ * Executes the given command, returning its success.
+ * If false is returned, then the "usage" plugin.yml entry for this command (if defined) will be
+ * sent to the player.
+ *
+ * @param sender Source of the command
+ * @param command Command which was executed
+ * @param label Alias of the command which was used
+ * @param args Passed command arguments
+ * @return true if a valid command, otherwise false
+ */
+ @Override
+ public boolean onCommand(
+ @NotNull CommandSender sender,
+ @NotNull Command command,
+ @NotNull String label,
+ @NotNull String[] args) {
+ if (!(sender instanceof Player p)) {
+ sender.sendMessage("You must be a player to use this command.");
+ return true;
+ }
+
+ if (!p.hasPermission("sr.admin.item")) {
+ p.sendMessage("You do not have permission to use this command.");
+ return true;
+ }
+
+ if (args.length == 0) {
+ p.sendMessage("Usage: /item ");
+ return true;
+ }
+
+ if (args[0].equalsIgnoreCase("list")) {
+ ItemManager im = ItemManager.getInstance(ItemManager.class);
+ if (im.getItemIDs().isEmpty()) {
+ p.sendMessage(comp("There are no items."));
+ return true;
+ }
+ p.sendMessage("Items:");
+ im.getItemIDs().forEach(p::sendMessage);
+ return true;
+ }
+
+ if (args[0].equalsIgnoreCase("create")) {
+ if (args.length < 2) {
+ p.sendMessage("Usage: /item create ");
+ return true;
+ }
+ ItemManager im = ItemManager.getInstance(ItemManager.class);
+ if (im.getItemIDs().contains(args[1])) {
+ p.sendMessage(comp("An item with that ID already exists."));
+ return true;
+ }
+ Item item = new Item();
+ item.setID(args[1]);
+ im.addItem(item);
+ p.sendMessage(
+ comp(
+ "Item created. You can now modify it using "
+ + " /item modify "
+ + args[1]
+ + ""));
+ return true;
+ }
+
+ if (args[0].equalsIgnoreCase("delete")) {
+ if (args.length < 2) {
+ p.sendMessage("Usage: /item delete ");
+ return true;
+ }
+ ItemManager im = ItemManager.getInstance(ItemManager.class);
+ if (!im.getItemIDs().contains(args[1])) {
+ p.sendMessage(comp("An item with that ID does not exist."));
+ return true;
+ }
+ im.removeItem(args[1]);
+ p.sendMessage(comp("Item deleted."));
+ return true;
+ }
+
+ if (args[0].equalsIgnoreCase("give")) {
+ if (args.length < 2) {
+ p.sendMessage("Usage: /item give ");
+ return true;
+ }
+
+ ItemManager im = ItemManager.getInstance(ItemManager.class);
+ if (!im.getItemIDs().contains(args[1])) {
+ p.sendMessage(comp("An item with that ID does not exist."));
+ return true;
+ }
+
+ Item item = im.getItem(args[1]);
+
+ if (args.length == 2) {
+ p.getInventory().addItem(item.toItemStack());
+ p.sendMessage(comp("Item given."));
+ return true;
+ }
+
+ Player target = Bukkit.getPlayer(args[2]);
+ if (target == null) {
+ p.sendMessage(comp("Player not found."));
+ return true;
+ }
+
+ target.getInventory().addItem(item.toItemStack());
+ p.sendMessage(comp("Item given."));
+
+ return true;
+ }
+
+ if (args[0].equalsIgnoreCase("modify")) {
+ if (args.length < 2) {
+ p.sendMessage(
+ "Usage: /item modify [value]");
+ return true;
+ }
+
+ ItemManager im = ItemManager.getInstance(ItemManager.class);
+ if (!im.getItemIDs().contains(args[1])) {
+ p.sendMessage(comp("An item with that ID does not exist."));
+ return true;
+ }
+
+ Item item = im.getItem(args[1]);
+
+ if (args.length == 2) {
+ p.sendMessage(
+ "Usage: /item modify [value]");
+ return true;
+ }
+
+ switch (args[2].toLowerCase()) {
+ case "name" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify name ");
+ return true;
+ }
+ String name = String.join(" ", Arrays.copyOfRange(args, 3, args.length));
+ item.setName(name);
+ p.sendMessage(comp("Item name set."));
+ // TODO: update item in player inventory
+ return true;
+ }
+ case "material" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify material ");
+ return true;
+ }
+ Material material = Material.matchMaterial(args[3]);
+ if (material == null) {
+ p.sendMessage(comp("Material not found."));
+ return true;
+ }
+ item.setMaterial(material);
+ p.sendMessage(comp("Item material set."));
+ }
+ case "enchantments" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify enchantments [enchantment]");
+ return true;
+ }
+ if (args[3].equalsIgnoreCase("add")) {
+ if (args.length < 5) {
+ p.sendMessage("Usage: /item modify enchantments add ");
+ return true;
+ }
+ // TODO: add enchantment
+ p.sendMessage("Enchantments not working for now.");
+ return true;
+ }
+ if (args[3].equalsIgnoreCase("remove")) {
+ if (args.length < 5) {
+ p.sendMessage("Usage: /item modify enchantments remove ");
+ return true;
+ }
+ // TODO: remove enchantment
+ p.sendMessage("Enchantments not working for now.");
+ return true;
+ }
+ }
+ case "attributes" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify attributes [attribute] [value]");
+ return true;
+ }
+ if (args[3].equalsIgnoreCase("add")) {
+ if (args.length < 6) {
+ p.sendMessage("Usage: /item modify attributes add ");
+ return true;
+ }
+ Attribute attribute = null;
+ try {
+ attribute = Attribute.valueOf(args[4]);
+ } catch (Exception e) {
+ p.sendMessage(comp("Attribute not found."));
+ error("Error on attribute affectation on item: " + args[1] + "\n" + e);
+ return true;
+ }
+ double value;
+ try {
+ value = Double.parseDouble(args[5]);
+ } catch (NumberFormatException e) {
+ p.sendMessage(comp("Invalid value."));
+ return true;
+ }
+ item.addAttribute(attribute, value);
+ p.sendMessage(comp("Attribute added."));
+ return true;
+ }
+ if (args[3].equalsIgnoreCase("remove")) {
+ if (args.length < 5) {
+ p.sendMessage("Usage: /item modify attributes remove ");
+ return true;
+ }
+ Attribute attribute = null;
+ try {
+ attribute = Attribute.valueOf(args[4]);
+ } catch (Exception e) {
+ p.sendMessage(comp("Attribute not found."));
+ error("Error on attribute affectation on item: " + args[1] + "\n" + e);
+ return true;
+ }
+ item.removeAttribute(attribute);
+ p.sendMessage(comp("Attribute removed."));
+ return true;
+ }
+ return true;
+ }
+ case "abilities" -> {
+ if (args.length < 5) {
+ p.sendMessage("Usage: /item modify abilities add ");
+ return true;
+ }
+ if (args[3].equalsIgnoreCase("add")) {
+ p.sendMessage("Abilities not working for now.");
+ // TODO: add ability
+ } else if (args[3].equalsIgnoreCase("remove")) {
+ p.sendMessage("Abilities not working for now.");
+ // TODO: remove ability
+ }
+ return true;
+ }
+ case "custommodeldata" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify custommodeldata ");
+ return true;
+ }
+ int customModelData;
+ try {
+ customModelData = Integer.parseInt(args[3]);
+ } catch (NumberFormatException e) {
+ p.sendMessage(comp("Invalid value."));
+ return true;
+ }
+ item.setCustomModelData(customModelData);
+ p.sendMessage(comp("Custom model data set."));
+ return true;
+ }
+ case "rarity" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify rarity ");
+ return true;
+ }
+ Rarity rarity;
+ try {
+ rarity = Rarity.valueOf(args[3]);
+ } catch (Exception e) {
+ p.sendMessage(comp("Rarity not found."));
+ return true;
+ }
+ item.setRarity(rarity);
+ p.sendMessage(comp("Rarity set."));
+ return true;
+ }
+ case "type" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify type ");
+ return true;
+ }
+ ItemType type;
+ try {
+ type = ItemType.valueOf(args[3]);
+ } catch (Exception e) {
+ p.sendMessage(comp("Type not found."));
+ return true;
+ }
+ item.setType(type);
+ p.sendMessage(comp("Type set."));
+ return true;
+ }
+ case "description" -> {
+ if (args.length < 4) {
+ p.sendMessage("Usage: /item modify description ");
+ return true;
+ }
+ String description = String.join(" ", Arrays.copyOfRange(args, 3, args.length));
+ item.setDescription(description);
+ p.sendMessage(comp("Description set."));
+ return true;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Requests a list of possible completions for a command argument.
+ *
+ * @param sender Source of the command. For players tab-completing a command inside of a command
+ * block, this will be the player, not the command block.
+ * @param command Command which was executed
+ * @param label Alias of the command which was used
+ * @param args The arguments passed to the command, including final partial argument to be
+ * completed
+ * @return A List of possible completions for the final argument, or null to default to the
+ * command executor
+ */
+ @Override
+ public @Nullable List onTabComplete(
+ @NotNull CommandSender sender,
+ @NotNull Command command,
+ @NotNull String label,
+ @NotNull String[] args) {
+ if (!(sender instanceof Player) || !sender.hasPermission("sr.admin.item")) {
+ return List.of("");
+ }
+
+ if (args.length == 1) {
+ return List.of("list", "create", "delete", "give", "modify");
+ }
+
+ if (args.length == 2) {
+ if (args[0].equalsIgnoreCase("delete")
+ || args[0].equalsIgnoreCase("give")
+ || args[0].equalsIgnoreCase("modify")) {
+ ItemManager im = ItemManager.getInstance(ItemManager.class);
+ return im.getItemIDs();
+ }
+ }
+
+ if (args.length == 3) {
+ if (args[0].equalsIgnoreCase("modify")) {
+ return List.of(
+ "name",
+ "material",
+ "enchantments",
+ "attributes",
+ "abilities",
+ "custommodeldata",
+ "rarity",
+ "type",
+ "description");
+ } else if (args[0].equalsIgnoreCase("give")) {
+ return Bukkit.getOnlinePlayers().stream().map(Player::getName).toList();
+ }
+ }
+
+ if (args.length == 4) {
+ if (args[0].equalsIgnoreCase("modify")) {
+ if (args[2].equalsIgnoreCase("rarity")) {
+ return Arrays.stream(Rarity.values()).map(Enum::name).toList();
+ } else if (args[2].equalsIgnoreCase("type")) {
+ return Arrays.stream(ItemType.values()).map(Enum::name).toList();
+ } else if (args[2].equalsIgnoreCase("material")) {
+ return Arrays.stream(Material.values()).map(Enum::name).toList();
+ } else if (args[2].equalsIgnoreCase("enchantments")) {
+ return List.of("add", "remove");
+ } else if (args[2].equalsIgnoreCase("abilities")) {
+ return List.of("add", "remove");
+ } else if (args[2].equalsIgnoreCase("attributes")) {
+ return List.of("add", "remove");
+ } else if (args[2].equalsIgnoreCase("custommodeldata")) {
+ try {
+ Integer.parseInt(args[3]);
+ } catch (NumberFormatException e) {
+ return List.of("1");
+ }
+ }
+ }
+ }
+
+ if (args.length == 5) {
+ if (args[0].equalsIgnoreCase("modify")) {
+ /*if (args[2].equalsIgnoreCase("enchantments")) { // TODO: Enchantments in completion
+ return Arrays.stream(Enchantment.values()).map(Enum::name).toList();
+ } else*/ if (args[2].equalsIgnoreCase("attributes")) {
+ return Arrays.stream(Attribute.values()).map(Enum::name).toList();
+ }
+ }
+ }
+
+ if (args.length == 6) {
+ if (args[0].equalsIgnoreCase("modify")) {
+ if (args[2].equalsIgnoreCase("attributes")) {
+ try {
+ Double.parseDouble(args[5]);
+ } catch (NumberFormatException e) {
+ return List.of("1.0");
+ }
+ }
+ }
+ }
+
+ return List.of("");
+ }
+}
diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java b/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java
index 72d4ab2..470549e 100644
--- a/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java
+++ b/src/main/java/me/unurled/sacredrealms/sr/components/item/Item.java
@@ -127,6 +127,14 @@ public class Item {
this.rarity = rarity;
}
+ public ItemType getType() {
+ return type;
+ }
+
+ public void setType(ItemType type) {
+ this.type = type;
+ }
+
public HashMap getAttributes() {
return attributes;
}
@@ -263,4 +271,8 @@ public class Item {
error("Failed to parse item from string: " + item + "\n" + e.getMessage());
}
}
+
+ public void setID(String arg) {
+ this.ID = arg;
+ }
}
diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/item/ItemManager.java b/src/main/java/me/unurled/sacredrealms/sr/components/item/ItemManager.java
index 15814e9..4798298 100644
--- a/src/main/java/me/unurled/sacredrealms/sr/components/item/ItemManager.java
+++ b/src/main/java/me/unurled/sacredrealms/sr/components/item/ItemManager.java
@@ -3,6 +3,7 @@ package me.unurled.sacredrealms.sr.components.item;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.HashMap;
+import java.util.List;
import me.unurled.sacredrealms.sr.data.DataHandler;
import me.unurled.sacredrealms.sr.data.DataManager;
import me.unurled.sacredrealms.sr.data.gson.ItemDeserializer;
@@ -12,7 +13,6 @@ import org.bukkit.NamespacedKey;
import org.bukkit.inventory.ItemStack;
import org.bukkit.persistence.PersistentDataType;
-@SuppressWarnings("EmptyMethod")
public class ItemManager extends Manager {
public static final NamespacedKey ID = new NamespacedKey("sr", "id");
@@ -85,4 +85,8 @@ public class ItemManager extends Manager {
public boolean isItem(String id) {
return items.containsKey(id);
}
+
+ public List getItemIDs() {
+ return List.copyOf(items.keySet());
+ }
}
diff --git a/src/main/java/me/unurled/sacredrealms/sr/components/item/enchantments/Enchantment.java b/src/main/java/me/unurled/sacredrealms/sr/components/item/enchantments/Enchantment.java
index 367838d..fde513e 100644
--- a/src/main/java/me/unurled/sacredrealms/sr/components/item/enchantments/Enchantment.java
+++ b/src/main/java/me/unurled/sacredrealms/sr/components/item/enchantments/Enchantment.java
@@ -1,25 +1,3 @@
package me.unurled.sacredrealms.sr.components.item.enchantments;
-public class Enchantment {
- private final String name;
- private final String ID;
- private final Integer maxLevel;
-
- public Enchantment(String name, String ID, Integer maxLevel) {
- this.name = name;
- this.ID = ID;
- this.maxLevel = maxLevel;
- }
-
- public String getName() {
- return name;
- }
-
- public String getID() {
- return ID;
- }
-
- public Integer getMaxLevel() {
- return maxLevel;
- }
-}
+public record Enchantment(String name, String ID, Integer maxLevel) {}
diff --git a/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java b/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java
index f25c378..bbe857b 100644
--- a/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java
+++ b/src/main/java/me/unurled/sacredrealms/sr/utils/Items.java
@@ -112,8 +112,7 @@ public class Items {
lore.add(comp("Enchantments:"));
item.getEnchantments()
.forEach(
- (k, v) ->
- lore.add(comp(" ➤ " + k.getName() + " " + v)));
+ (k, v) -> lore.add(comp(" ➤ " + k.name() + " " + v)));
}
stack.lore(lore);
diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml
index dbd04a4..8efb3c4 100644
--- a/src/main/resources/plugin.yml
+++ b/src/main/resources/plugin.yml
@@ -26,6 +26,9 @@ permissions:
sr.entitytype:
default: op
description: When the player has permission for the command /entitytype
+ sr.admin.item:
+ default: op
+ description: When the player has permission for the command /item
sr.resetadventure:
default: op
description: When the player has permission for the command /resetadventure
@@ -39,5 +42,7 @@ commands:
description: Set the level of the player.
entitytype:
description: Create a new entity type.
+ item:
+ description: Create/modify an item.
resetadventure:
description: Reset the adventure of the player
\ No newline at end of file