EpicHeads/main/java/com/songoda/epicheads/menu/ui/item/Item.java

367 lines
10 KiB
Java

package com.songoda.epicheads.menu.ui.item;
import com.songoda.epicheads.EpicHeads;
import com.songoda.epicheads.config.lang.Placeholder;
import com.songoda.epicheads.menu.ui.MenuResponse;
import com.songoda.epicheads.util.Checks;
import com.songoda.epicheads.util.Methods;
import com.songoda.epicheads.util.Stringify;
import com.songoda.epicheads.volatilecode.ItemNBT;
import com.songoda.epicheads.volatilecode.reflection.Version;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.MaterialData;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
public final class Item {
private final Material type;
private final int amount;
private final short damage;
private final String name;
private final String[] lore;
private final boolean enchanted;
private Item(Material type) {
this(type, 1, (short) 0, null, null, false);
}
private Item(Material type, int amount, short damage, String name, String[] lore, boolean enchanted) {
Checks.ensureNonNull(type, "type");
Checks.ensureTrue(amount > 0, "amount must be greater than 0");
Checks.ensureTrue(damage >= 0, "damage must be greater than or equal to 0");
if (lore != null) {
Checks.ensureArrayNonNull(lore, "lore");
}
this.type = type;
this.amount = amount;
this.damage = damage;
this.name = name;
this.lore = (lore == null || lore.length == 0 ? null : lore);
this.enchanted = enchanted;
}
public Item amount(int amount) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item damage(short damage) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item name(String name) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item lore(String... lore) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Item enchanted(boolean enchanted) {
return new Item(type, amount, damage, name, lore, enchanted);
}
public Button buildButton(Placeholder... placeholders) {
return new Button(build(placeholders));
}
public Button buildButton(Callable<MenuResponse> callable, Placeholder... placeholders) {
return new Button(build(placeholders), callable);
}
public ItemStack build(Placeholder... placeholders) {
return build(null, placeholders);
}
public ItemStack build(Function<String, Boolean> loreFilter, Placeholder... placeholders) {
Checks.ensureNonNull(placeholders, "placeholders");
ItemStack item = new ItemStack(type, amount, damage);
ItemMeta meta = item.getItemMeta();
if (meta == null)
return item;
if (name != null) {
String displayName = ChatColor.translateAlternateColorCodes('&', name);
displayName = Placeholder.applyAll(displayName, placeholders);
meta.setDisplayName(displayName);
}
if (lore != null) {
String[] itemLore = Placeholder.colourAll(lore);
itemLore = Placeholder.filterAndApplyAll(itemLore, loreFilter, placeholders);
meta.setLore(Arrays.asList(itemLore));
}
item.setItemMeta(meta);
if (enchanted) {
item = ItemNBT.addGlow(item);
}
return item;
}
public void save(ConfigurationSection section, String key) {
section.set(key, null);
save(section.createSection(key));
}
public void save(ConfigurationSection section) {
section.set("type", getTypeName(type));
if (amount != 1) {
section.set("amount", amount);
}
if (damage != 0) {
section.set("damage", damage);
}
if (name != null) {
section.set("name", name);
}
if (lore != null) {
section.set("lore", Arrays.asList(lore));
}
if (enchanted) {
section.set("enchanted", true);
}
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Item))
return false;
Item other = (Item) obj;
return other.type == type && other.amount == amount && Objects.equals(other.name, name) && (other.lore == null ? lore == null : Arrays.equals(other.lore, lore)) && other.enchanted == enchanted;
}
@Override
public String toString() {
Stringify.Builder properties = Stringify.builder();
{
properties.entry("type", getTypeName(type));
if (amount != 1) {
properties.entry("amount", amount);
}
if (name != null) {
properties.entry("name", name);
}
if (Version.isBelow(Version.v1_13)) {
if (damage != 0) {
properties.entry("data", damage);
}
} else {
if (damage != 0) {
properties.entry("damage", damage);
}
}
if (lore != null) {
properties.entry("lore", lore);
}
if (enchanted) {
properties.entry("enchanted", true);
}
}
return properties.toString();
}
public static Item create(Material type) {
return new Item(type);
}
public static Item create(Material type, byte data) {
if (Version.isBelow(Version.v1_13)) {
return new Item(type, 1, data, null, null, false);
}
return new Item(type, 1, (short) 0, null, null, false);
}
public static Item create(ItemStack itemStack) {
Item item = create(itemStack.getType()).amount(itemStack.getAmount()).damage(itemStack.getDurability());
ItemMeta meta = itemStack.getItemMeta();
if (meta == null)
return item;
if (meta.hasDisplayName()) {
String name = meta.getDisplayName().replace(ChatColor.COLOR_CHAR, '&');
item = item.name(name);
}
if (meta.hasLore()) {
List<String> rawLore = meta.getLore();
String[] lore = new String[rawLore.size()];
for (int index = 0; index < lore.length; ++index) {
lore[index] = rawLore.get(index).replace(ChatColor.COLOR_CHAR, '&');
}
item = item.lore(lore);
}
if (meta.hasEnchants()) {
item = item.enchanted(true);
}
return item;
}
private static void updateLegacyTypes(String filename, ConfigurationSection section, AtomicBoolean shouldSave) {
if (!section.isSet("type"))
return;
if (Version.isBelow(Version.v1_13) && section.isSet("data")) {
section.set("damage", section.get("data"));
section.set("data", null);
shouldSave.set(true);
}
String typeName = section.getString("type");
String typeData = section.getString("damage", null);
Material type = Material.matchMaterial(typeName);
if (type != null && !section.isInt("type"))
return;
if (section.isInt("type")) {
int typeId = section.getInt("type");
String convertedType = EpicHeads.getInstance().getLegacyIDs().fromId(typeId);
if (convertedType == null || convertedType.isEmpty()) {
Methods.formatText("Invalid type of item " + section.getCurrentPath() + ", " + "unknown type id " + typeId);
return;
}
if (Version.isBelow(Version.v1_13)) {
type = Material.matchMaterial(convertedType);
} else {
type = null;
}
section.set("type", convertedType.toLowerCase());
}
boolean legacy = false;
if (type == null && !Version.isBelow(Version.v1_13)) {
type = Material.valueOf("LEGACY_" + section.getString("type").toUpperCase().replace(' ', '_'));
legacy = true;
}
if (type == null) {
Methods.formatText("Invalid type of item " + section.getCurrentPath() + ", could not find type " + typeName);
return;
}
if (legacy && !Version.isBelow(Version.v1_13)) {
Material legacyType = type;
int data = section.getInt("damage");
byte byteData = (byte) (data >= 0 && data < 16 ? data : 0);
// Get a type to begin with, to check if the data is a damage value
Material withoutData = fromLegacyType(legacyType, (byte) 0);
type = fromLegacyType(legacyType, byteData);
if (type == null) {
Methods.formatText("Invalid legacy type of item " + section.getCurrentPath() + ": " + "Could not convert " + legacyType + ":" + data + " to non-legacy format");
return;
}
if (withoutData != type) {
section.set("damage", null);
}
}
section.set("type", type.name().toLowerCase());
String from = typeName + (typeData != null ? ":" + typeData : "");
String to = type.name().toLowerCase() + (section.isSet("damage") ? ":" + section.get("damage") : "");
Methods.formatText("1.13 Update - " + from + " converted to " + to + " for " + filename + " -> " + section.getCurrentPath());
shouldSave.set(true);
}
public static Item load(String filename, ConfigurationSection section, AtomicBoolean shouldSave) {
// Convert from legacy type ids to type names
updateLegacyTypes(filename, section, shouldSave);
if (!section.isSet("type") || !section.isString("type")) {
Methods.formatText("Invalid type of item " + section.getCurrentPath() + " in " + filename + ", " + "expected a type name");
return null;
}
String typeName = section.getString("type");
Material type = Material.matchMaterial(typeName);
if (type == null) {
Methods.formatText("Invalid type of item " + section.getCurrentPath() + ", " + "unknown material for type name " + typeName);
return null;
}
short damage = (short) section.getInt("damage", 0);
if (damage < 0) {
Methods.formatText("Invalid damage of item " + section.getCurrentPath() + ", " + "damage must be at least 0");
return null;
}
int amount = section.getInt("amount", 1);
if (amount < 1) {
Methods.formatText("Invalid amount of item " + section.getCurrentPath() + ", " + "amount must be at least 1");
return null;
}
String name = section.getString("name", null);
String[] lore = section.getStringList("lore").toArray(new String[0]);
boolean enchanted = section.getBoolean("enchanted", false);
return new Item(type, amount, damage, name, lore, enchanted);
}
private static String getTypeName(Material type) {
return type.name().toLowerCase();
}
public static Material getType(String typeName) {
Material type = Material.matchMaterial(typeName);
if (type != null || Version.isBelow(Version.v1_13))
return type;
return Material.matchMaterial(typeName, true);
}
// Need to be kept, will look for an alternative in the future.
private static Material fromLegacyType(Material legacyType, byte data) {
return Bukkit.getUnsafe().fromLegacy(new MaterialData(legacyType, data));
}
}