From 512b30e9dfa3291d2f1c2273c942cccf8e6379f0 Mon Sep 17 00:00:00 2001 From: themode Date: Fri, 16 Oct 2020 14:31:15 +0200 Subject: [PATCH] Added ArgumentItemStack --- .../net/minestom/server/chat/ChatParser.java | 70 +++++++++++++----- .../server/command/CommandManager.java | 3 + .../server/command/builder/Arguments.java | 5 ++ .../builder/arguments/ArgumentType.java | 4 + .../minecraft/ArgumentItemStack.java | 73 +++++++++++++++++++ .../net/minestom/server/utils/NBTUtils.java | 10 ++- src/test/java/demo/PlayerInit.java | 15 ---- src/test/java/demo/commands/TestCommand.java | 28 ++----- 8 files changed, 149 insertions(+), 59 deletions(-) create mode 100644 src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentItemStack.java diff --git a/src/main/java/net/minestom/server/chat/ChatParser.java b/src/main/java/net/minestom/server/chat/ChatParser.java index c7d7c15d7..e2a60bc12 100644 --- a/src/main/java/net/minestom/server/chat/ChatParser.java +++ b/src/main/java/net/minestom/server/chat/ChatParser.java @@ -1,10 +1,7 @@ package net.minestom.server.chat; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; +import com.google.gson.*; /** * Class used to convert JSON string to proper chat message representation. @@ -20,22 +17,42 @@ public final class ChatParser { * @return a {@link ColoredText} representing the text */ public static ColoredText toColoredText(String json) { + json = json.replace("\\\"", "\""); + StringBuilder builder = new StringBuilder(); - final JsonObject object = JsonParser.parseString(json).getAsJsonObject(); + try { + final JsonElement element = JsonParser.parseString(json); + if (element instanceof JsonObject) { + final JsonObject object = element.getAsJsonObject(); + appendBuilder(builder, object); + } else if (element instanceof JsonArray) { + final JsonArray array = element.getAsJsonArray(); + for (JsonElement e : array) { + JsonObject object = e.getAsJsonObject(); + appendBuilder(builder, object); + } + } + + return ColoredText.of(builder.toString()); + } catch (JsonSyntaxException e) { + // Not a json text + return ColoredText.of(json); + } + } + + private static void appendBuilder(StringBuilder builder, JsonObject object) { builder.append(parseText(object)); final boolean hasExtra = object.has("extra"); if (hasExtra) { JsonArray extraArray = object.get("extra").getAsJsonArray(); - for (JsonElement element : extraArray) { - JsonObject extraObject = element.getAsJsonObject(); + for (JsonElement extraElement : extraArray) { + JsonObject extraObject = extraElement.getAsJsonObject(); builder.append(parseText(extraObject)); } } - - return ColoredText.of(builder.toString()); } /** @@ -49,13 +66,25 @@ public final class ChatParser { if (!hasText) return ""; - final boolean hasColor = textObject.has("color"); - StringBuilder builder = new StringBuilder(); - // Add color - if (hasColor) { - String colorString = textObject.get("color").getAsString(); + appendColor(textObject, builder); + appendExtra(textObject, builder, "bold"); + appendExtra(textObject, builder, "italic"); + appendExtra(textObject, builder, "underlined"); + appendExtra(textObject, builder, "strikethrough"); + appendExtra(textObject, builder, "obfuscated"); + + // Add text + final String text = textObject.get("text").getAsString(); + builder.append(text); + + return builder.toString(); + } + + private static void appendColor(JsonObject textObject, StringBuilder builder) { + if (textObject.has("color")) { + final String colorString = textObject.get("color").getAsString(); if (colorString.startsWith("#")) { // RGB format builder.append("{").append(colorString).append("}"); @@ -65,11 +94,14 @@ public final class ChatParser { builder.append(color); } } + } - // Add text - String text = textObject.get("text").getAsString(); - builder.append(text); - - return builder.toString(); + private static void appendExtra(JsonObject textObject, StringBuilder builder, String name) { + if (textObject.has(name)) { + final boolean value = textObject.get(name).getAsBoolean(); + if (value) { + builder.append("{#").append(name).append("}"); + } + } } } diff --git a/src/main/java/net/minestom/server/command/CommandManager.java b/src/main/java/net/minestom/server/command/CommandManager.java index ba733815e..6a5abd485 100644 --- a/src/main/java/net/minestom/server/command/CommandManager.java +++ b/src/main/java/net/minestom/server/command/CommandManager.java @@ -512,6 +512,9 @@ public final class CommandManager { } packetWriter.writeByte(mask); }; + } else if (argument instanceof ArgumentItemStack) { + DeclareCommandsPacket.Node argumentNode = simpleArgumentNode(nodes, argument, executable, false); + argumentNode.parser = "minecraft:item_stack"; } return nodes; diff --git a/src/main/java/net/minestom/server/command/builder/Arguments.java b/src/main/java/net/minestom/server/command/builder/Arguments.java index f9735d65b..e643b2312 100644 --- a/src/main/java/net/minestom/server/command/builder/Arguments.java +++ b/src/main/java/net/minestom/server/command/builder/Arguments.java @@ -4,6 +4,7 @@ import net.minestom.server.chat.ChatColor; import net.minestom.server.entity.Entity; import net.minestom.server.entity.EntityType; import net.minestom.server.item.Enchantment; +import net.minestom.server.item.ItemStack; import net.minestom.server.particle.Particle; import net.minestom.server.potion.PotionEffect; import net.minestom.server.utils.math.FloatRange; @@ -89,6 +90,10 @@ public class Arguments { return (List) getObject(id); } + public ItemStack getItemStack(String id) { + return (ItemStack) getObject(id); + } + public Object getObject(String id) { return args.getOrDefault(id, null); } diff --git a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentType.java b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentType.java index a72c2f14d..6f63da487 100644 --- a/src/main/java/net/minestom/server/command/builder/arguments/ArgumentType.java +++ b/src/main/java/net/minestom/server/command/builder/arguments/ArgumentType.java @@ -94,4 +94,8 @@ public class ArgumentType { return new ArgumentEntities(id); } + public static ArgumentItemStack ItemStack(String id) { + return new ArgumentItemStack(id); + } + } diff --git a/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentItemStack.java b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentItemStack.java new file mode 100644 index 000000000..99c0c5670 --- /dev/null +++ b/src/main/java/net/minestom/server/command/builder/arguments/minecraft/ArgumentItemStack.java @@ -0,0 +1,73 @@ +package net.minestom.server.command.builder.arguments.minecraft; + +import net.minestom.server.command.builder.arguments.Argument; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NBTUtils; +import org.jglrxavpok.hephaistos.nbt.NBT; +import org.jglrxavpok.hephaistos.nbt.NBTCompound; +import org.jglrxavpok.hephaistos.nbt.SNBTParser; + +import java.io.StringReader; + +public class ArgumentItemStack extends Argument { + + public static final int NO_MATERIAL = 1; + public static final int INVALID_NBT = 2; + + public ArgumentItemStack(String id) { + super(id, true); + } + + @Override + public int getCorrectionResult(String value) { + if (value.startsWith("{")) { + return NO_MATERIAL; + } + + final int nbtIndex = value.indexOf("{"); + + if (nbtIndex == -1 && !value.contains(" ")) { + // Only item name + return SUCCESS; + } else { + // has nbt + final String sNBT = value.substring(nbtIndex); + try { + NBT nbt = new SNBTParser(new StringReader(sNBT)).parse(); + return nbt instanceof NBTCompound ? SUCCESS : INVALID_NBT; + } catch (Exception e) { + return INVALID_NBT; + } + } + } + + @Override + public ItemStack parse(String value) { + final int nbtIndex = value.indexOf("{"); + + if (nbtIndex == -1) { + // Only item name + final Material material = Registries.getMaterial(value); + return new ItemStack(material, (byte) 1); + } else { + final String materialName = value.substring(0, nbtIndex); + final Material material = Registries.getMaterial(materialName); + + ItemStack itemStack = new ItemStack(material, (byte) 1); + + final String sNBT = value.substring(nbtIndex); + final NBTCompound compound = (NBTCompound) new SNBTParser(new StringReader(sNBT)).parse(); + + NBTUtils.loadDataIntoItem(itemStack, compound); + + return itemStack; + } + } + + @Override + public int getConditionResult(ItemStack value) { + return SUCCESS; + } +} diff --git a/src/main/java/net/minestom/server/utils/NBTUtils.java b/src/main/java/net/minestom/server/utils/NBTUtils.java index b38500716..245d85482 100644 --- a/src/main/java/net/minestom/server/utils/NBTUtils.java +++ b/src/main/java/net/minestom/server/utils/NBTUtils.java @@ -121,8 +121,12 @@ public final class NBTUtils { if (nbt.containsKey("Unbreakable")) item.setUnbreakable(nbt.getInt("Unbreakable") == 1); if (nbt.containsKey("HideFlags")) item.setHideFlag(nbt.getInt("HideFlags")); if (nbt.containsKey("display")) { - NBTCompound display = nbt.getCompound("display"); - if (display.containsKey("Name")) item.setDisplayName(ChatParser.toColoredText(display.getString("Name"))); + final NBTCompound display = nbt.getCompound("display"); + if (display.containsKey("Name")) { + final String rawName = display.getString("Name"); + final ColoredText displayName = ChatParser.toColoredText(rawName); + item.setDisplayName(displayName); + } if (display.containsKey("Lore")) { NBTList loreList = display.getList("Lore"); ArrayList lore = new ArrayList<>(); @@ -182,7 +186,7 @@ public final class NBTUtils { public static void loadEnchantments(NBTList enchantments, EnchantmentSetter setter) { for (NBTCompound enchantment : enchantments) { - final short level = enchantment.getShort("lvl"); + final short level = enchantment.getAsShort("lvl"); final String id = enchantment.getString("id"); final Enchantment enchant = Registries.getEnchantment(id); if (enchant != null) { diff --git a/src/test/java/demo/PlayerInit.java b/src/test/java/demo/PlayerInit.java index 38267af08..a846c591c 100644 --- a/src/test/java/demo/PlayerInit.java +++ b/src/test/java/demo/PlayerInit.java @@ -7,10 +7,7 @@ import net.minestom.server.MinecraftServer; import net.minestom.server.attribute.Attribute; import net.minestom.server.attribute.AttributeOperation; import net.minestom.server.benchmark.BenchmarkManager; -import net.minestom.server.chat.ChatColor; -import net.minestom.server.chat.ChatHoverEvent; import net.minestom.server.chat.ColoredText; -import net.minestom.server.chat.RichMessage; import net.minestom.server.data.Data; import net.minestom.server.entity.*; import net.minestom.server.entity.damage.DamageType; @@ -254,18 +251,6 @@ public class PlayerInit { player.setGameMode(GameMode.CREATIVE); player.teleport(new Position(0, 73f, 0)); - //player.setHeldItemSlot((byte) 5); - - ColoredText coloredText = ColoredText.of(ChatColor.RED + "" + ChatColor.BOLD + " test" + ChatColor.BRIGHT_GREEN + " lol"); - coloredText.append("test"); - player.sendMessage(coloredText); - System.out.println(coloredText.toString()); - { - RichMessage richMessage = RichMessage.of(ColoredText.of(ChatColor.RED + " HEY MESSAGE")); - richMessage.setHoverEvent(ChatHoverEvent.showItem(new ItemStack(Material.STONE, (byte) 5))); - //player.sendMessage(richMessage); - } - player.getInventory().addItemStack(new ItemStack(Material.STONE, (byte) 1)); player.setGlowing(true); diff --git a/src/test/java/demo/commands/TestCommand.java b/src/test/java/demo/commands/TestCommand.java index 615658003..fb1d39abe 100644 --- a/src/test/java/demo/commands/TestCommand.java +++ b/src/test/java/demo/commands/TestCommand.java @@ -5,7 +5,7 @@ import net.minestom.server.command.builder.Arguments; import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.arguments.Argument; import net.minestom.server.command.builder.arguments.ArgumentType; -import net.minestom.server.entity.Player; +import net.minestom.server.item.ItemStack; public class TestCommand extends Command { @@ -18,32 +18,16 @@ public class TestCommand extends Command { //addSyntax(this::execute, dynamicWord); } - Argument test = ArgumentType.Word("test").from("hey"); - Argument num = ArgumentType.Integer("num"); - Argument test2 = ArgumentType.Word("test2").from("oh"); - Argument num2 = ArgumentType.Float("num2"); + Argument test = ArgumentType.ItemStack("test"); addSyntax((source, args) -> { - }, test, num); - addSyntax((source, args) -> { - }, test2, num2); + System.out.println("SUCCESS"); + ItemStack itemStack = args.getItemStack("test"); + source.asPlayer().getInventory().addItemStack(itemStack); + }, test); } private void usage(CommandSender sender, Arguments arguments) { sender.sendMessage("Incorrect usage"); } - - private void execute(CommandSender sender, Arguments arguments) { - final String word = arguments.getWord("test"); - sender.sendMessage("word: " + word); - } - - private boolean isAllowed(Player player) { - return true; // TODO: permissions - } - - @Override - public String[] onDynamicWrite(String text) { - return new String[]{"test1", "test2"}; - } }