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:
Andreas Troelsen
2018-07-03 14:51:54 +02:00
parent fe35964b93
commit b5b4fdd30a
@@ -7,6 +7,9 @@ import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.EnchantmentStorageMeta; import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.inventory.meta.PotionMeta; 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.PotionData;
import org.bukkit.potion.PotionType; import org.bukkit.potion.PotionType;
@@ -14,12 +17,10 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
public class ItemParser 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<>(); private static final Map<Short, PotionType> POTION_TYPE_MAP = new HashMap<>();
static { static {
POTION_TYPE_MAP.put((short) 8193, PotionType.REGEN); POTION_TYPE_MAP.put((short) 8193, PotionType.REGEN);
@@ -80,7 +81,7 @@ public class ItemParser
result = withDataAndAmount(parts[0], parts[1], parts[2]); result = withDataAndAmount(parts[0], parts[1], parts[2]);
break; break;
} }
if (result == null || result.getTypeId() == 0) { if (result == null || result.getType() == Material.AIR) {
if (logFailure) { if (logFailure) {
Bukkit.getLogger().warning("[MobArena] Failed to parse item: " + item); Bukkit.getLogger().warning("[MobArena] Failed to parse item: " + item);
} }
@@ -95,70 +96,136 @@ public class ItemParser
} }
private static ItemStack singleItem(String item) { private static ItemStack singleItem(String item) {
int id = getTypeId(item); return getType(item)
return new ItemStack(id); .map(ItemStack::new)
.orElse(null);
} }
private static ItemStack withAmount(String item, String amount) { private static ItemStack withAmount(String item, String amount) {
int id = getTypeId(item); return getType(item)
int a = getAmount(amount); .map(type -> new ItemStack(type, getAmount(amount)))
return new ItemStack(id,a); .orElse(null);
} }
private static ItemStack withDataAndAmount(String item, String data, String amount) { private static ItemStack withDataAndAmount(String item, String data, String amount) {
int id = getTypeId(item); ItemStack stack = withAmount(item, amount);
short d = getData(data, id); if (stack == null) {
int a = getAmount(amount); return null;
if (id == Material.LINGERING_POTION.getId() || id == Material.TIPPED_ARROW.getId() || id == Material.SPLASH_POTION.getId()) {
return withPotionMeta(id, d, a);
} }
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) { private static ItemStack withPotionMeta(ItemStack stack, String data) {
ItemStack result = new ItemStack(id, a); PotionType type = getPotionType(data);
PotionMeta meta = (PotionMeta) result.getItemMeta(); if (type == null) {
return null;
boolean extended = (d & 64) > 0;
boolean upgraded = (d & 32) > 0;
if (extended) {
d -= 64;
}
if (upgraded) {
d -= 32;
} }
PotionMeta meta = (PotionMeta) stack.getItemMeta();
meta.setBasePotionData(new PotionData(type));
stack.setItemMeta(meta);
return stack;
}
PotionType type = POTION_TYPE_MAP.get(d); private static PotionType getPotionType(String data) {
if (type != null) { if (data.matches("[0-9]+")) {
PotionData pData = new PotionData(type, extended, upgraded); short d = Short.parseShort(data);
meta.setBasePotionData(pData);
result.setItemMeta(meta); // Compensate for splash potions
return result; 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; return null;
} }
private static int getTypeId(String item) { private static Wool getWoolData(String data) {
if (item.matches("(-)?[0-9]*")) { if (data.matches("(-)?[1-9][0-9]*")) {
return Integer.parseInt(item); 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) { private static Dye getDyeData(String data) {
// Wool and ink are special if (data.matches("(-)?[1-9][0-9]*")) {
if (id == WOOL_ID) { DyeColor color = DyeColor.getByDyeData(Byte.parseByte(data));
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data); if (color == null) {
if (dye == null) dye = DyeColor.getByWoolData(Byte.parseByte(data)); return null;
return dye.getWoolData(); }
} else if (id == DYE_ID) {
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data); warn(color.name(), data);
if (dye == null) dye = DyeColor.getByDyeData(Byte.parseByte(data));
return dye.getDyeData(); 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) { private static int getAmount(String amount) {
@@ -179,24 +246,45 @@ public class ItemParser
private static void addEnchantment(ItemStack stack, String ench) { private static void addEnchantment(ItemStack stack, String ench) {
String[] parts = ench.split(":"); 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;
}
Enchantment enchantment = getEnchantment(parts[0]);
if (enchantment == null) {
return; return;
} }
int id = Integer.parseInt(parts[0]);
int lvl = Integer.parseInt(parts[1]); 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) { if (stack.getType() == Material.ENCHANTED_BOOK) {
EnchantmentStorageMeta esm = (EnchantmentStorageMeta) stack.getItemMeta(); EnchantmentStorageMeta esm = (EnchantmentStorageMeta) stack.getItemMeta();
esm.addStoredEnchant(e, lvl, true); esm.addStoredEnchant(enchantment, lvl, true);
stack.setItemMeta(esm); stack.setItemMeta(esm);
} else { } 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);
}
} }