Implement ability to create ItemStacks with Custom Model Data. (#1981)

This commit is contained in:
BONNe 2022-05-23 20:46:02 +03:00 committed by GitHub
parent 0f815d8175
commit 3ab7ac8484
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 9 deletions

View File

@ -1,7 +1,9 @@
package world.bentobox.bentobox.util;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.MissingFormatArgumentException;
import java.util.Optional;
import java.util.UUID;
import org.bukkit.Bukkit;
@ -56,38 +58,78 @@ public class ItemParser {
return defaultItemStack;
}
ItemStack returnValue = defaultItemStack;
String[] part = text.split(":");
try {
// Because I am lazy, and do not want to rewrite every parser, I will just add custom data as
// parameter and remove that array part form input data.
Optional<String> first = Arrays.stream(part).filter(field -> field.matches("(CMD-[0-9]*)")).findFirst();
Integer customModelData = null;
if (first.isPresent()) {
// Ugly and fast way how to get rid of customData field.
String[] copyParts = new String[part.length - 1];
int j = 0;
for (String field : part) {
if (!field.matches("(CMD-[0-9]*)")) {
copyParts[j++] = field;
}
}
// Replace original parts with the copy parts that does not have any CMD values.
part = copyParts;
// Now use value from Custom Data Model and parse it as integer.
customModelData = Integer.valueOf(first.get().replaceFirst("CMD-", ""));
}
// Check if there are more properties for the item stack
if (part.length == 1) {
// Parse material directly. It does not have any extra properties.
return new ItemStack(Material.valueOf(text.toUpperCase()));
returnValue = new ItemStack(Material.valueOf(text.toUpperCase()));
}
// Material-specific handling
else if (part[0].contains("POTION") || part[0].equalsIgnoreCase("TIPPED_ARROW")) {
// Parse Potions and Tipped Arrows
return parsePotion(part);
returnValue = parsePotion(part);
} else if (part[0].contains("BANNER")) {
// Parse Banners
return parseBanner(part);
returnValue = parseBanner(part);
} else if (part[0].equalsIgnoreCase("PLAYER_HEAD")) {
// Parse Player Heads
return parsePlayerHead(part);
returnValue = parsePlayerHead(part);
}
// Generic handling
else if (part.length == 2) {
// Material:Qty
return parseItemQuantity(part);
returnValue = parseItemQuantity(part);
} else if (part.length == 3) {
// Material:Durability:Qty
return parseItemDurabilityAndQuantity(part);
returnValue = parseItemDurabilityAndQuantity(part);
}
if (returnValue != null) {
// If wrapper is just for code-style null-pointer checks.
if (customModelData != null) {
// We have custom data model. Now assign it to the item-stack.
ItemMeta itemMeta = returnValue.getItemMeta();
// Another null-pointer check for materials that does not have item meta.
if (itemMeta != null) {
itemMeta.setCustomModelData(customModelData);
// Update meta to the return item.
returnValue.setItemMeta(itemMeta);
}
}
}
} catch (Exception exception) {
BentoBox.getInstance().logError("Could not parse item " + text + " " + exception.getLocalizedMessage());
returnValue = defaultItemStack;
}
return defaultItemStack;
return returnValue;
}

View File

@ -1,7 +1,6 @@
package world.bentobox.bentobox.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -281,4 +280,13 @@ public class ItemParserTest {
assertEquals(defaultItem, ItemParser.parse("STNE:AA:5", defaultItem));
assertEquals(defaultItem, ItemParser.parse("WOODEN_SWORD:4:AA", defaultItem));
}
@Test
public void parseCustomModelData() {
ItemStack result = ItemParser.parse("WOODEN_SWORD:CMD-23151212:2");
assertEquals(Material.WOODEN_SWORD, result.getType());
assertEquals(2, result.getAmount());
assertNull(ItemParser.parse("WOODEN_SWORD:CMD-23151212:2:CMD-23151212"));
}
}