diff --git a/eco-api/src/main/java/com/willfp/eco/core/items/Items.java b/eco-api/src/main/java/com/willfp/eco/core/items/Items.java
index bc9cbdd0..1ec570fe 100644
--- a/eco-api/src/main/java/com/willfp/eco/core/items/Items.java
+++ b/eco-api/src/main/java/com/willfp/eco/core/items/Items.java
@@ -115,6 +115,48 @@ public final class Items {
REGISTRY.remove(key);
}
+ /**
+ * Turn an ItemStack back into a lookup string.
+ *
+ * @param itemStack The ItemStack.
+ * @return The lookup string.
+ */
+ @NotNull
+ public static String toLookupString(@Nullable final ItemStack itemStack) {
+ if (itemStack == null) {
+ return "";
+ }
+
+ StringBuilder builder = new StringBuilder();
+
+ CustomItem customItem = getCustomItem(itemStack);
+
+ if (customItem != null) {
+ builder.append(customItem.getKey());
+ } else {
+ builder.append(itemStack.getType().name().toLowerCase());
+ }
+
+ if (itemStack.getAmount() > 1) {
+ builder.append(" ")
+ .append(itemStack.getAmount());
+ }
+
+ ItemMeta meta = itemStack.getItemMeta();
+
+ if (meta != null) {
+ for (LookupArgParser parser : ARG_PARSERS) {
+ String parsed = parser.serializeBack(meta);
+ if (parsed != null) {
+ builder.append(" ")
+ .append(parsed);
+ }
+ }
+ }
+
+ return builder.toString();
+ }
+
/**
* This is the backbone of the entire eco item system.
*
diff --git a/eco-api/src/main/java/com/willfp/eco/core/items/args/LookupArgParser.java b/eco-api/src/main/java/com/willfp/eco/core/items/args/LookupArgParser.java
index 2027d384..30b286ec 100644
--- a/eco-api/src/main/java/com/willfp/eco/core/items/args/LookupArgParser.java
+++ b/eco-api/src/main/java/com/willfp/eco/core/items/args/LookupArgParser.java
@@ -22,4 +22,14 @@ public interface LookupArgParser {
*/
@Nullable Predicate parseArguments(@NotNull String[] args,
@NotNull ItemMeta meta);
+
+ /**
+ * Serialize the item back to a string.
+ *
+ * @param meta The ItemMeta.
+ * @return The string, or null if not required.
+ */
+ default @Nullable String serializeBack(@NotNull final ItemMeta meta) {
+ return null;
+ }
}
diff --git a/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt b/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt
new file mode 100644
index 00000000..5eb01d89
--- /dev/null
+++ b/eco-api/src/main/kotlin/com/willfp/eco/core/items/Items.kt
@@ -0,0 +1,11 @@
+@file:JvmName("ItemsExtensions")
+
+package com.willfp.eco.core.items
+
+import org.bukkit.inventory.ItemStack
+
+/**
+ * @see Items.toLookupString
+ */
+fun ItemStack?.toLookupString(): String =
+ Items.toLookupString(this)
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserColor.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserColor.kt
index 1feaac4e..e3f8abd0 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserColor.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserColor.kt
@@ -41,4 +41,12 @@ class ArgParserColor : LookupArgParser {
)
}
}
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ if (meta !is LeatherArmorMeta) {
+ return null
+ }
+
+ return "color:#${Integer.toHexString(meta.color.asRGB())}"
+ }
}
\ No newline at end of file
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserCustomModelData.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserCustomModelData.kt
index e2b0b6e3..b4d0faf1 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserCustomModelData.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserCustomModelData.kt
@@ -30,4 +30,12 @@ class ArgParserCustomModelData : LookupArgParser {
testMeta.customModelData == modelData
}
}
-}
\ No newline at end of file
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ if (!meta.hasCustomModelData()) {
+ return null
+ }
+
+ return "custom-model-data:${meta.customModelData}"
+ }
+}
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEnchantment.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEnchantment.kt
index 22a61fe6..18791c07 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEnchantment.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserEnchantment.kt
@@ -52,4 +52,26 @@ class ArgParserEnchantment : LookupArgParser {
true
}
}
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ val enchants = mutableMapOf()
+
+ if (meta is EnchantmentStorageMeta) {
+ enchants.putAll(meta.storedEnchants)
+ } else {
+ enchants.putAll(meta.enchants)
+ }
+
+ if (enchants.isEmpty()) {
+ return null
+ }
+
+ val builder = StringBuilder()
+
+ for ((enchant, level) in enchants) {
+ builder.append("${enchant.key.key}:$level ")
+ }
+
+ return builder.toString().trimEnd()
+ }
}
\ No newline at end of file
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserFlag.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserFlag.kt
index 19ec043b..49560696 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserFlag.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserFlag.kt
@@ -27,4 +27,14 @@ class ArgParserFlag : LookupArgParser {
testMeta.itemFlags.containsAll(flags)
}
}
-}
\ No newline at end of file
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ val flags = meta.itemFlags
+
+ if (flags.isEmpty()) {
+ return null
+ }
+
+ return flags.joinToString(" ") { it.name.lowercase() }
+ }
+}
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserName.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserName.kt
index a77b0b19..19852e9f 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserName.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserName.kt
@@ -30,4 +30,12 @@ class ArgParserName : LookupArgParser {
testMeta.displayName == formatted
}
}
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ if (!meta.hasDisplayName()) {
+ return null
+ }
+
+ return "name:${meta.displayName}"
+ }
}
\ No newline at end of file
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTexture.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTexture.kt
index 49c9e1a7..70bea9cd 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTexture.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserTexture.kt
@@ -36,4 +36,12 @@ class ArgParserTexture : LookupArgParser {
texture == SkullUtils.getSkullTexture(testMeta)
}
}
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ if (meta !is SkullMeta) {
+ return null
+ }
+
+ return "texture:${SkullUtils.getSkullTexture(meta)}"
+ }
}
\ No newline at end of file
diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserUnbreakable.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserUnbreakable.kt
index 87dbf86a..f2f5f523 100644
--- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserUnbreakable.kt
+++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/items/ArgParserUnbreakable.kt
@@ -27,4 +27,12 @@ class ArgParserUnbreakable : LookupArgParser {
testMeta.isUnbreakable
}
}
+
+ override fun serializeBack(meta: ItemMeta): String? {
+ if (!meta.isUnbreakable) {
+ return null
+ }
+
+ return "unbreakable"
+ }
}
\ No newline at end of file