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,30 +96,55 @@ 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);
} }
private static ItemStack withPotionMeta(int id, short d, int a) { Material type = stack.getType();
ItemStack result = new ItemStack(id, a); if (type == Material.POTION || type == Material.LINGERING_POTION || type == Material.SPLASH_POTION|| type == Material.TIPPED_ARROW) {
PotionMeta meta = (PotionMeta) result.getItemMeta(); return withPotionMeta(stack, data);
}
MaterialData md = getData(data, type);
if (md == null) {
return null;
}
return md.toItemStack(stack.getAmount());
}
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;
}
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 extended = (d & 64) > 0;
boolean upgraded = (d & 32) > 0; boolean upgraded = (d & 32) > 0;
@@ -131,34 +157,75 @@ public class ItemParser
PotionType type = POTION_TYPE_MAP.get(d); PotionType type = POTION_TYPE_MAP.get(d);
if (type != null) { if (type != null) {
PotionData pData = new PotionData(type, extended, upgraded); warn(type.name(), data);
meta.setBasePotionData(pData); }
result.setItemMeta(meta); return type;
return result; }
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) {
Material m = Enums.getEnumFromString(Material.class, item); return null;
return (m != null ? m.getId() : 0);
} }
private static short getData(String data, int id) { warn(color.name(), data);
// Wool and ink are special
if (id == WOOL_ID) { return new Wool(color);
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data); }
if (dye == null) dye = DyeColor.getByWoolData(Byte.parseByte(data)); try {
return dye.getWoolData(); return new Wool(DyeColor.valueOf(data.toUpperCase()));
} else if (id == DYE_ID) { } catch (IllegalArgumentException e) {
DyeColor dye = Enums.getEnumFromString(DyeColor.class, data); return null;
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) { 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; return;
} }
int id = Integer.parseInt(parts[0]); Enchantment enchantment = getEnchantment(parts[0]);
if (enchantment == null) {
return;
}
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);
}
} }