Add support for named potion types and enchantments.
In this commit, the ItemParser's behavior changes from one that requires or encourages numeric IDs for everything to one that discourages it by logging a warning that suggests using a string instead of a numeric value. While this doesn't actually make things that much better for updating to Minecraft 1.13, the "ID nagging" hopefully increases awareness about the upcoming breaking changes. Fixes #382
This commit is contained in:
@@ -7,6 +7,9 @@ import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.material.Dye;
|
||||
import org.bukkit.material.MaterialData;
|
||||
import org.bukkit.material.Wool;
|
||||
import org.bukkit.potion.PotionData;
|
||||
import org.bukkit.potion.PotionType;
|
||||
|
||||
@@ -14,12 +17,10 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ItemParser
|
||||
{
|
||||
private static final int WOOL_ID = Material.WOOL.getId();
|
||||
private static final int DYE_ID = Material.INK_SACK.getId();
|
||||
|
||||
private static final Map<Short, PotionType> POTION_TYPE_MAP = new HashMap<>();
|
||||
static {
|
||||
POTION_TYPE_MAP.put((short) 8193, PotionType.REGEN);
|
||||
@@ -80,7 +81,7 @@ public class ItemParser
|
||||
result = withDataAndAmount(parts[0], parts[1], parts[2]);
|
||||
break;
|
||||
}
|
||||
if (result == null || result.getTypeId() == 0) {
|
||||
if (result == null || result.getType() == Material.AIR) {
|
||||
if (logFailure) {
|
||||
Bukkit.getLogger().warning("[MobArena] Failed to parse item: " + item);
|
||||
}
|
||||
@@ -95,70 +96,136 @@ public class ItemParser
|
||||
}
|
||||
|
||||
private static ItemStack singleItem(String item) {
|
||||
int id = getTypeId(item);
|
||||
return new ItemStack(id);
|
||||
return getType(item)
|
||||
.map(ItemStack::new)
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private static ItemStack withAmount(String item, String amount) {
|
||||
int id = getTypeId(item);
|
||||
int a = getAmount(amount);
|
||||
return new ItemStack(id,a);
|
||||
return getType(item)
|
||||
.map(type -> new ItemStack(type, getAmount(amount)))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
private static ItemStack withDataAndAmount(String item, String data, String amount) {
|
||||
int id = getTypeId(item);
|
||||
short d = getData(data, id);
|
||||
int a = getAmount(amount);
|
||||
|
||||
if (id == Material.LINGERING_POTION.getId() || id == Material.TIPPED_ARROW.getId() || id == Material.SPLASH_POTION.getId()) {
|
||||
return withPotionMeta(id, d, a);
|
||||
ItemStack stack = withAmount(item, amount);
|
||||
if (stack == null) {
|
||||
return null;
|
||||
}
|
||||
return new ItemStack(id,a,d);
|
||||
|
||||
Material type = stack.getType();
|
||||
if (type == Material.POTION || type == Material.LINGERING_POTION || type == Material.SPLASH_POTION|| type == Material.TIPPED_ARROW) {
|
||||
return withPotionMeta(stack, data);
|
||||
}
|
||||
|
||||
MaterialData md = getData(data, type);
|
||||
if (md == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return md.toItemStack(stack.getAmount());
|
||||
}
|
||||
|
||||
private static ItemStack withPotionMeta(int id, short d, int a) {
|
||||
ItemStack result = new ItemStack(id, a);
|
||||
PotionMeta meta = (PotionMeta) result.getItemMeta();
|
||||
|
||||
boolean extended = (d & 64) > 0;
|
||||
boolean upgraded = (d & 32) > 0;
|
||||
if (extended) {
|
||||
d -= 64;
|
||||
}
|
||||
if (upgraded) {
|
||||
d -= 32;
|
||||
private static ItemStack withPotionMeta(ItemStack stack, String data) {
|
||||
PotionType type = getPotionType(data);
|
||||
if (type == null) {
|
||||
return null;
|
||||
}
|
||||
PotionMeta meta = (PotionMeta) stack.getItemMeta();
|
||||
meta.setBasePotionData(new PotionData(type));
|
||||
stack.setItemMeta(meta);
|
||||
return stack;
|
||||
}
|
||||
|
||||
PotionType type = POTION_TYPE_MAP.get(d);
|
||||
if (type != null) {
|
||||
PotionData pData = new PotionData(type, extended, upgraded);
|
||||
meta.setBasePotionData(pData);
|
||||
result.setItemMeta(meta);
|
||||
return result;
|
||||
private static PotionType getPotionType(String data) {
|
||||
if (data.matches("[0-9]+")) {
|
||||
short d = Short.parseShort(data);
|
||||
|
||||
// Compensate for splash potions
|
||||
if (d > (2 * 8192)) {
|
||||
d -= 8192;
|
||||
}
|
||||
|
||||
boolean extended = (d & 64) > 0;
|
||||
boolean upgraded = (d & 32) > 0;
|
||||
if (extended) {
|
||||
d -= 64;
|
||||
}
|
||||
if (upgraded) {
|
||||
d -= 32;
|
||||
}
|
||||
|
||||
PotionType type = POTION_TYPE_MAP.get(d);
|
||||
if (type != null) {
|
||||
warn(type.name(), data);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
try {
|
||||
return PotionType.valueOf(data.toUpperCase());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Optional<Material> getType(String item) {
|
||||
if (item.matches("(-)?[1-9][0-9]*")) {
|
||||
Material type = Material.getMaterial(Integer.parseInt(item));
|
||||
if (type == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
warn(type.name(), item);
|
||||
|
||||
return Optional.of(type);
|
||||
}
|
||||
return Optional.ofNullable(Material.getMaterial(item.toUpperCase()));
|
||||
}
|
||||
|
||||
private static MaterialData getData(String data, Material type) {
|
||||
if (type == Material.INK_SACK) {
|
||||
return getDyeData(data);
|
||||
}
|
||||
if (type == Material.WOOL) {
|
||||
return getWoolData(data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static int getTypeId(String item) {
|
||||
if (item.matches("(-)?[0-9]*")) {
|
||||
return Integer.parseInt(item);
|
||||
private static Wool getWoolData(String data) {
|
||||
if (data.matches("(-)?[1-9][0-9]*")) {
|
||||
DyeColor color = DyeColor.getByWoolData(Byte.parseByte(data));
|
||||
if (color == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
warn(color.name(), data);
|
||||
|
||||
return new Wool(color);
|
||||
}
|
||||
try {
|
||||
return new Wool(DyeColor.valueOf(data.toUpperCase()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
Material m = Enums.getEnumFromString(Material.class, item);
|
||||
return (m != null ? m.getId() : 0);
|
||||
}
|
||||
|
||||
private static short getData(String data, int id) {
|
||||
// Wool and ink are special
|
||||
if (id == WOOL_ID) {
|
||||
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data);
|
||||
if (dye == null) dye = DyeColor.getByWoolData(Byte.parseByte(data));
|
||||
return dye.getWoolData();
|
||||
} else if (id == DYE_ID) {
|
||||
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data);
|
||||
if (dye == null) dye = DyeColor.getByDyeData(Byte.parseByte(data));
|
||||
return dye.getDyeData();
|
||||
private static Dye getDyeData(String data) {
|
||||
if (data.matches("(-)?[1-9][0-9]*")) {
|
||||
DyeColor color = DyeColor.getByDyeData(Byte.parseByte(data));
|
||||
if (color == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
warn(color.name(), data);
|
||||
|
||||
return new Dye(color);
|
||||
}
|
||||
try {
|
||||
return new Dye(DyeColor.valueOf(data.toUpperCase()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return null;
|
||||
}
|
||||
return (data.matches("(-)?[0-9]+") ? Short.parseShort(data) : 0);
|
||||
}
|
||||
|
||||
private static int getAmount(String amount) {
|
||||
@@ -179,24 +246,45 @@ public class ItemParser
|
||||
|
||||
private static void addEnchantment(ItemStack stack, String ench) {
|
||||
String[] parts = ench.split(":");
|
||||
if (parts.length != 2 || !(parts[0].matches("[0-9]*") && parts[1].matches("[0-9]*"))) {
|
||||
if (parts.length != 2 || !parts[1].matches("[0-9]*")) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id = Integer.parseInt(parts[0]);
|
||||
Enchantment enchantment = getEnchantment(parts[0]);
|
||||
if (enchantment == null) {
|
||||
return;
|
||||
}
|
||||
int lvl = Integer.parseInt(parts[1]);
|
||||
|
||||
Enchantment e = Enchantment.getById(id);
|
||||
if (e == null) {// || !e.canEnchantItem(stack) || lvl > e.getMaxLevel() || lvl < e.getStartLevel()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stack.getType() == Material.ENCHANTED_BOOK) {
|
||||
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) stack.getItemMeta();
|
||||
esm.addStoredEnchant(e, lvl, true);
|
||||
esm.addStoredEnchant(enchantment, lvl, true);
|
||||
stack.setItemMeta(esm);
|
||||
} else {
|
||||
stack.addUnsafeEnchantment(e, lvl);
|
||||
stack.addUnsafeEnchantment(enchantment, lvl);
|
||||
}
|
||||
}
|
||||
|
||||
private static Enchantment getEnchantment(String ench) {
|
||||
if (ench.matches("[1-9][0-9]*")) {
|
||||
Enchantment enchantment = Enchantment.getById(Integer.parseInt(ench));
|
||||
if (enchantment == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
warn(enchantment.getName(), ench);
|
||||
|
||||
return enchantment;
|
||||
}
|
||||
return Enchantment.getByName(ench.toUpperCase());
|
||||
}
|
||||
|
||||
private static void warn(String name, String value) {
|
||||
String msg = String.format(
|
||||
"Consider using '%s' instead of '%s'",
|
||||
name.toLowerCase(),
|
||||
value
|
||||
);
|
||||
Bukkit.getLogger().warning("[MobArena] " + msg);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user