Added ItemMeta + MapDataPacket

This commit is contained in:
Felix Cravic 2020-07-23 05:36:15 +02:00
parent f75c3870a3
commit f8453b4906
10 changed files with 400 additions and 163 deletions

View File

@ -26,7 +26,9 @@ import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.metadata.MapMeta;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.server.play.MapDataPacket;
import net.minestom.server.ping.ResponseDataConsumer;
import net.minestom.server.timer.TaskRunnable;
import net.minestom.server.utils.MathUtils;
@ -36,6 +38,7 @@ import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.utils.time.UpdateOption;
import net.minestom.server.world.DimensionType;
import java.util.Arrays;
import java.util.Map;
import java.util.UUID;
@ -53,7 +56,6 @@ public class PlayerInit {
instanceContainer = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.OVERWORLD);
instanceContainer.enableAutoChunkLoad(true);
instanceContainer.setChunkGenerator(noiseTestGenerator);
instanceContainer.setTimeRate(150);
netherTest = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.NETHER);
netherTest.enableAutoChunkLoad(true);
@ -238,16 +240,45 @@ public class PlayerInit {
player.setGameMode(GameMode.SURVIVAL);
player.teleport(new Position(0, 41f, 0));
player.setHeldItemSlot((byte) 5);
//player.setHeldItemSlot((byte) 5);
player.setGlowing(true);
for (int i = 0; i < 9; i++) {
/*for (int i = 0; i < 9; i++) {
player.getInventory().setItemStack(i, new ItemStack(Material.STONE, (byte) 127));
}*/
ItemStack map = new ItemStack(Material.FILLED_MAP, (byte) 1);
MapMeta mapMeta = (MapMeta) map.getItemMeta();
mapMeta.setMapId(1);
player.getInventory().setItemStack(0, map);
{
// Map test
MapDataPacket mapDataPacket = new MapDataPacket();
mapDataPacket.mapId = 1;
mapDataPacket.scale = 1;
mapDataPacket.trackingPosition = false;
mapDataPacket.locked = false;
mapDataPacket.icons = null;
mapDataPacket.columns = (byte) 127;
mapDataPacket.rows = (byte) 127;
mapDataPacket.x = 0;
mapDataPacket.z = 0;
final byte[] data = new byte[127 * 127];
Arrays.fill(data, (byte) 10);
mapDataPacket.data = data;
player.getPlayerConnection().sendPacket(mapDataPacket);
}
ItemStack item = new ItemStack(Material.STONE_SWORD, (byte) 1);
item.setDisplayName(ColoredText.of("Item name"));
item.setDamage(5);
//item.getLore().add(ColoredText.of(ChatColor.RED + "a lore line " + ChatColor.BLACK + " BLACK"));
//item.addItemFlags(ItemFlag.HIDE_ENCHANTS);
//item.setEnchantment(Enchantment.SHARPNESS, (short) 50);

View File

@ -1837,16 +1837,16 @@ public class Player extends LivingEntity implements CommandSender {
* null if there is no item to update the state
*/
public ItemUpdateStateEvent callItemUpdateStateEvent(boolean allowFood) {
Material mainHandMat = Material.fromId(getItemInMainHand().getMaterialId());
Material offHandMat = Material.fromId(getItemInOffHand().getMaterialId());
boolean isOffhand = offHandMat.hasState();
final Material mainHandMat = getItemInMainHand().getMaterial();
final Material offHandMat = getItemInOffHand().getMaterial();
final boolean isOffhand = offHandMat.hasState();
ItemStack updatedItem = isOffhand ? getItemInOffHand() :
final ItemStack updatedItem = isOffhand ? getItemInOffHand() :
mainHandMat.hasState() ? getItemInMainHand() : null;
if (updatedItem == null) // No item with state, cancel
return null;
boolean isFood = updatedItem.getMaterial().isFood();
final boolean isFood = updatedItem.getMaterial().isFood();
if (isFood && !allowFood)
return null;
@ -1921,8 +1921,8 @@ public class Player extends LivingEntity implements CommandSender {
* based on which one is the lowest
*/
public int getChunkRange() {
int serverRange = MinecraftServer.CHUNK_VIEW_DISTANCE;
int playerRange = getSettings().viewDistance;
final int serverRange = MinecraftServer.CHUNK_VIEW_DISTANCE;
final int playerRange = getSettings().viewDistance;
if (playerRange == 0) {
return serverRange; // Didn't receive settings packet yet (is the case on login)
} else {

View File

@ -5,8 +5,10 @@ import net.minestom.server.chat.ColoredText;
import net.minestom.server.data.Data;
import net.minestom.server.data.DataContainer;
import net.minestom.server.item.attribute.ItemAttribute;
import net.minestom.server.item.metadata.ItemMeta;
import net.minestom.server.item.metadata.MapMeta;
import net.minestom.server.item.metadata.PotionMeta;
import net.minestom.server.item.rule.VanillaStackingRule;
import net.minestom.server.potion.PotionType;
import net.minestom.server.registry.Registries;
import net.minestom.server.utils.NBTUtils;
import net.minestom.server.utils.validate.Check;
@ -18,17 +20,27 @@ public class ItemStack implements DataContainer {
private static final StackingRule DEFAULT_STACKING_RULE = new VanillaStackingRule(127);
public static ItemStack getAirItem() {
return new ItemStack((short) 0, (byte) 0);
}
private Material material;
private static StackingRule defaultStackingRule;
private short materialId;
private ItemMeta itemMeta;
private byte amount;
private int damage;
public ItemStack(Material material, byte amount, int damage) {
this.material = material;
this.amount = amount;
this.damage = damage;
this.lore = new ArrayList<>();
this.enchantmentMap = new HashMap<>();
this.storedEnchantmentMap = new HashMap<>();
this.attributes = new ArrayList<>();
this.itemMeta = findMeta();
}
private ColoredText displayName;
private boolean unbreakable;
private ArrayList<ColoredText> lore;
@ -36,7 +48,6 @@ public class ItemStack implements DataContainer {
private Map<Enchantment, Short> enchantmentMap;
private Map<Enchantment, Short> storedEnchantmentMap;
private List<ItemAttribute> attributes;
private Set<PotionType> potionTypes;
private int hideFlag;
private int customModelData;
@ -53,24 +64,12 @@ public class ItemStack implements DataContainer {
this.stackingRule = defaultStackingRule;
}
public ItemStack(short materialId, byte amount, int damage) {
this.materialId = materialId;
this.amount = amount;
this.damage = damage;
this.lore = new ArrayList<>();
this.enchantmentMap = new HashMap<>();
this.storedEnchantmentMap = new HashMap<>();
this.attributes = new ArrayList<>();
this.potionTypes = new HashSet<>();
}
public ItemStack(short materialId, byte amount) {
this(materialId, amount, (short) 0);
}
public ItemStack(Material material, byte amount) {
this(material.getId(), amount);
this(material, amount, (short) 0);
}
public static ItemStack getAirItem() {
return new ItemStack(Material.AIR, (byte) 0);
}
/**
@ -93,13 +92,28 @@ public class ItemStack implements DataContainer {
ItemStack.defaultStackingRule = defaultStackingRule;
}
public static ItemStack fromNBT(NBTCompound nbt) {
if (!nbt.containsKey("id") || !nbt.containsKey("Count"))
throw new IllegalArgumentException("Invalid item NBT, must at least contain 'id' and 'Count' tags");
final Material material = Registries.getMaterial(nbt.getString("id"));
final byte count = nbt.getByte("Count");
ItemStack s = new ItemStack(material, count);
NBTCompound tag = nbt.getCompound("tag");
if (tag != null) {
NBTUtils.loadDataIntoItem(s, tag);
}
return s;
}
/**
* Get if the item is air
*
* @return true if the material is air, false otherwise
*/
public boolean isAir() {
return materialId == Material.AIR.getId();
return material == Material.AIR;
}
/**
@ -119,15 +133,18 @@ public class ItemStack implements DataContainer {
final boolean dataCheck = (data == null && itemData == null) ||
(data != null && itemData != null && data.equals(itemData));
return itemStack.getMaterialId() == materialId &&
final boolean sameMeta = (itemStack.itemMeta == null && itemMeta == null) ||
(itemStack.itemMeta != null && itemMeta != null && (itemStack.itemMeta.isSimilar(itemMeta)));
return itemStack.getMaterial() == material &&
displayNameCheck &&
itemStack.isUnbreakable() == unbreakable &&
itemStack.getDamage() == damage &&
itemStack.enchantmentMap.equals(enchantmentMap) &&
itemStack.storedEnchantmentMap.equals(storedEnchantmentMap) &&
itemStack.attributes.equals(attributes) &&
itemStack.potionTypes.equals(potionTypes) &&
itemStack.hideFlag == hideFlag &&
sameMeta &&
dataCheck;
}
}
@ -165,21 +182,14 @@ public class ItemStack implements DataContainer {
}
/**
* Get the item internal material id
* Get the special meta object for this item
* <p>
* Can be null if not any
*
* @return the item material id
* @return the item meta
*/
public short getMaterialId() {
return materialId;
}
/**
* Get the item material
*
* @return the item material
*/
public Material getMaterial() {
return Material.fromId(getMaterialId());
public ItemMeta getItemMeta() {
return itemMeta;
}
/**
@ -350,33 +360,6 @@ public class ItemStack implements DataContainer {
this.attributes.remove(itemAttribute);
}
/**
* Get the item potion types
*
* @return an unmodifiable {@link Set} containing the item potion types
*/
public Set<PotionType> getPotionTypes() {
return Collections.unmodifiableSet(potionTypes);
}
/**
* Add a potion type to the item
*
* @param potionType the potion type to add
*/
public void addPotionType(PotionType potionType) {
this.potionTypes.add(potionType);
}
/**
* Remove a potion type to the item
*
* @param potionType the potion type to remove
*/
public void removePotionType(PotionType potionType) {
this.potionTypes.remove(potionType);
}
/**
* Get the item hide flag
*
@ -481,16 +464,25 @@ public class ItemStack implements DataContainer {
this.unbreakable = unbreakable;
}
/**
* Get the item material
*
* @return the item material
*/
public Material getMaterial() {
return material;
}
/**
* Get if the item has any nbt tag
*
* @return true if the item has nbt tag, false otherwise
*/
public boolean hasNbtTag() {
return hasDisplayName() || hasLore() || isUnbreakable() ||
return hasDisplayName() || hasLore() || damage != 0 || isUnbreakable() ||
!enchantmentMap.isEmpty() || !storedEnchantmentMap.isEmpty() ||
!attributes.isEmpty() || !potionTypes.isEmpty() ||
hideFlag != 0 || customModelData != 0;
!attributes.isEmpty() ||
hideFlag != 0 || customModelData != 0 || (itemMeta != null && itemMeta.hasNbt());
}
/**
@ -499,7 +491,7 @@ public class ItemStack implements DataContainer {
* @return a cloned item stack
*/
public synchronized ItemStack clone() {
ItemStack itemStack = new ItemStack(materialId, amount, damage);
ItemStack itemStack = new ItemStack(material, amount, damage);
itemStack.setDisplayName(displayName);
itemStack.setUnbreakable(unbreakable);
itemStack.setLore(new ArrayList<>(getLore()));
@ -508,40 +500,19 @@ public class ItemStack implements DataContainer {
itemStack.enchantmentMap = new HashMap<>(enchantmentMap);
itemStack.storedEnchantmentMap = new HashMap<>(storedEnchantmentMap);
itemStack.attributes = new ArrayList<>(attributes);
itemStack.potionTypes = new HashSet<>(potionTypes);
itemStack.hideFlag = hideFlag;
itemStack.customModelData = customModelData;
Data data = getData();
if (itemMeta != null)
itemStack.itemMeta = itemMeta.clone();
final Data data = getData();
if (data != null)
itemStack.setData(data.clone());
return itemStack;
}
/**
* Convert the item into a readable Json object
* <p>
* Mainly used to show an item in a message hover
*
* @return a {@link JsonObject} containing the item data
*/
public synchronized JsonObject toJsonObject() {
JsonObject object = new JsonObject();
object.addProperty("id", getMaterialId());
object.addProperty("Damage", getDamage());
object.addProperty("Count", getAmount());
if (hasDisplayName() || hasLore()) {
JsonObject tagObject = new JsonObject();
if (hasDisplayName()) {
tagObject.addProperty("display", getDisplayName().toString());
}
}
return object;
}
@Override
public Data getData() {
return data;
@ -594,30 +565,53 @@ public class ItemStack implements DataContainer {
return (byte) (1 << hideFlag.ordinal());
}
/**
* Convert the item into a readable Json object
* <p>
* Mainly used to show an item in a message hover
*
* @return a {@link JsonObject} containing the item data
*/
public synchronized JsonObject toJsonObject() {
JsonObject object = new JsonObject();
object.addProperty("id", material.getId());
object.addProperty("Damage", getDamage());
object.addProperty("Count", getAmount());
if (hasDisplayName() || hasLore()) {
JsonObject tagObject = new JsonObject();
if (hasDisplayName()) {
tagObject.addProperty("display", getDisplayName().toString());
}
}
return object;
}
/**
* Find the item meta based on the material type
*
* @return the item meta
*/
private ItemMeta findMeta() {
if (material == Material.POTION)
return new PotionMeta();
if (material == Material.FILLED_MAP)
return new MapMeta();
return null;
}
public NBTCompound toNBT() {
NBTCompound compound = new NBTCompound()
.setByte("Count", amount)
.setString("id", Material.fromId(materialId).getName());
if(hasNbtTag()) {
.setString("id", material.getName());
if (hasNbtTag()) {
NBTCompound additionalTag = new NBTCompound();
NBTUtils.saveDataIntoNBT(this, additionalTag);
compound.set("tag", additionalTag);
}
return compound;
}
public static ItemStack fromNBT(NBTCompound nbt) {
if(!nbt.containsKey("id") || !nbt.containsKey("Count"))
throw new IllegalArgumentException("Invalid item NBT, must at least contain 'id' and 'Count' tags");
short materialID = Registries.getMaterial(nbt.getString("id")).getId();
byte count = nbt.getByte("Count");
ItemStack s = new ItemStack(materialID, count);
NBTCompound tag = nbt.getCompound("tag");
if(tag != null) {
NBTUtils.loadDataIntoItem(s, tag);
}
return s;
}
}

View File

@ -0,0 +1,11 @@
package net.minestom.server.item.metadata;
public abstract class ItemMeta {
public abstract boolean hasNbt();
public abstract boolean isSimilar(ItemMeta itemMeta);
public abstract ItemMeta clone();
}

View File

@ -0,0 +1,31 @@
package net.minestom.server.item.metadata;
public class MapMeta extends ItemMeta {
private int mapId;
public int getMapId() {
return mapId;
}
public void setMapId(int mapId) {
this.mapId = mapId;
}
@Override
public boolean hasNbt() {
return mapId != 0;
}
@Override
public boolean isSimilar(ItemMeta itemMeta) {
return itemMeta instanceof MapMeta && ((MapMeta) itemMeta).getMapId() == mapId;
}
@Override
public ItemMeta clone() {
MapMeta mapMeta = new MapMeta();
mapMeta.setMapId(mapId);
return mapMeta;
}
}

View File

@ -0,0 +1,57 @@
package net.minestom.server.item.metadata;
import net.minestom.server.potion.PotionType;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class PotionMeta extends ItemMeta {
private Set<PotionType> potionTypes = new HashSet<>();
/**
* Get the item potion types
*
* @return an unmodifiable {@link Set} containing the item potion types
*/
public Set<PotionType> getPotionTypes() {
return Collections.unmodifiableSet(potionTypes);
}
/**
* Add a potion type to the item
*
* @param potionType the potion type to add
*/
public void addPotionType(PotionType potionType) {
this.potionTypes.add(potionType);
}
/**
* Remove a potion type to the item
*
* @param potionType the potion type to remove
*/
public void removePotionType(PotionType potionType) {
this.potionTypes.remove(potionType);
}
@Override
public boolean hasNbt() {
return !potionTypes.isEmpty();
}
@Override
public boolean isSimilar(ItemMeta itemMeta) {
return itemMeta instanceof PotionMeta && ((PotionMeta) itemMeta).potionTypes.equals(potionTypes);
}
@Override
public ItemMeta clone() {
PotionMeta potionMeta = new PotionMeta();
potionMeta.potionTypes = new HashSet<>(potionTypes);
return potionMeta;
}
}

View File

@ -28,23 +28,23 @@ import java.util.Set;
public class BlockPlacementListener {
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
PlayerInventory playerInventory = player.getInventory();
Player.Hand hand = packet.hand;
BlockFace blockFace = packet.blockFace;
BlockPosition blockPosition = packet.blockPosition;
final PlayerInventory playerInventory = player.getInventory();
final Player.Hand hand = packet.hand;
final BlockFace blockFace = packet.blockFace;
final BlockPosition blockPosition = packet.blockPosition;
Instance instance = player.getInstance();
final Instance instance = player.getInstance();
if (instance == null)
return;
// Interact at block
PlayerBlockInteractEvent playerBlockInteractEvent = new PlayerBlockInteractEvent(blockPosition, hand, blockFace);
player.callCancellableEvent(PlayerBlockInteractEvent.class, playerBlockInteractEvent, () -> {
CustomBlock customBlock = instance.getCustomBlock(blockPosition);
final CustomBlock customBlock = instance.getCustomBlock(blockPosition);
if (customBlock != null) {
Data data = instance.getBlockData(blockPosition);
boolean blocksItem = customBlock.onInteract(player, hand, blockPosition, data);
if(blocksItem) {
final Data data = instance.getBlockData(blockPosition);
final boolean blocksItem = customBlock.onInteract(player, hand, blockPosition, data);
if (blocksItem) {
playerBlockInteractEvent.setBlockingItemUse(true);
}
}
@ -56,7 +56,7 @@ public class BlockPlacementListener {
// Check if item at hand is a block
final ItemStack usedItem = hand == Player.Hand.MAIN ? playerInventory.getItemInMainHand() : playerInventory.getItemInOffHand();
final Material material = Material.fromId(usedItem.getMaterialId());
final Material material = usedItem.getMaterial();
if (material == Material.AIR) {
return;
}
@ -104,7 +104,7 @@ public class BlockPlacementListener {
player.callEvent(PlayerBlockPlaceEvent.class, playerBlockPlaceEvent);
if (!playerBlockPlaceEvent.isCancelled() && canPlace) {
short customBlockId = playerBlockPlaceEvent.getCustomBlockId();
if(customBlockId != 0) {
if (customBlockId != 0) {
instance.setSeparateBlocks(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockId(), playerBlockPlaceEvent.getCustomBlockId());
} else {
instance.setBlock(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ(), playerBlockPlaceEvent.getBlockId());

View File

@ -19,7 +19,7 @@ public class UseItemListener {
PlayerUseItemEvent useItemEvent = new PlayerUseItemEvent(player, hand, itemStack);
player.callEvent(PlayerUseItemEvent.class, useItemEvent);
final Material material = Material.fromId(itemStack.getMaterialId());
final Material material = itemStack.getMaterial();
// Equip armor with right click
if (material.isArmor()) {

View File

@ -0,0 +1,81 @@
package net.minestom.server.network.packet.server.play;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
public class MapDataPacket implements ServerPacket {
public int mapId;
public byte scale;
public boolean trackingPosition;
public boolean locked;
public Icon[] icons;
public byte columns;
public byte rows;
public byte x;
public byte z;
public byte[] data;
@Override
public void write(PacketWriter writer) {
writer.writeVarInt(mapId);
writer.writeByte(scale);
writer.writeBoolean(trackingPosition);
writer.writeBoolean(locked);
if (icons != null && icons.length > 0) {
writer.writeVarInt(icons.length);
for (Icon icon : icons) {
icon.write(writer);
}
} else {
writer.writeVarInt(0);
}
writer.writeByte(columns);
if (columns <= 0)
return;
writer.writeByte(rows);
writer.writeByte(x);
writer.writeByte(z);
if (data != null && data.length > 0) {
writer.writeVarInt(data.length);
writer.writeBytes(data);
} else {
writer.writeVarInt(0);
}
}
@Override
public int getId() {
return ServerPacketIdentifier.MAP_DATA;
}
public static class Icon {
public int type;
public byte x, z;
public byte direction;
public ColoredText displayName;
private void write(PacketWriter writer) {
writer.writeVarInt(type);
writer.writeByte(x);
writer.writeByte(z);
writer.writeByte(direction);
final boolean hasDisplayName = displayName != null;
writer.writeBoolean(hasDisplayName);
if (hasDisplayName) {
writer.writeSizedString(displayName.toString());
}
}
}
}

View File

@ -11,6 +11,9 @@ import net.minestom.server.item.Material;
import net.minestom.server.item.NBTConsumer;
import net.minestom.server.item.attribute.AttributeSlot;
import net.minestom.server.item.attribute.ItemAttribute;
import net.minestom.server.item.metadata.ItemMeta;
import net.minestom.server.item.metadata.MapMeta;
import net.minestom.server.item.metadata.PotionMeta;
import net.minestom.server.network.packet.PacketReader;
import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.potion.PotionType;
@ -80,24 +83,24 @@ public class NBTUtils {
}
public static ItemStack readItemStack(PacketReader reader) {
boolean present = reader.readBoolean();
final boolean present = reader.readBoolean();
if (!present) {
return ItemStack.getAirItem();
}
int id = reader.readVarInt();
final int id = reader.readVarInt();
if (id == -1) {
// Drop mode
return ItemStack.getAirItem();
}
byte count = reader.readByte();
ItemStack item = new ItemStack((short) id, count);
final Material material = Material.fromId((short) id);
final byte count = reader.readByte();
ItemStack item = new ItemStack(material, count);
try {
NBT itemNBT = reader.readTag();
final NBT itemNBT = reader.readTag();
if (itemNBT instanceof NBTCompound) { // can also be a TAG_End if no data
NBTCompound nbt = (NBTCompound) itemNBT;
loadDataIntoItem(item, nbt);
@ -113,7 +116,6 @@ public class NBTUtils {
if (nbt.containsKey("Damage")) item.setDamage(nbt.getInt("Damage"));
if (nbt.containsKey("Unbreakable")) item.setUnbreakable(nbt.getInt("Unbreakable") == 1);
if (nbt.containsKey("HideFlags")) item.setHideFlag(nbt.getInt("HideFlags"));
if (nbt.containsKey("Potion")) item.addPotionType(Registries.getPotionType(nbt.getString("Potion")));
if (nbt.containsKey("display")) {
NBTCompound display = nbt.getCompound("display");
if (display.containsKey("Name")) item.setDisplayName(ChatParser.toColoredText(display.getString("Name")));
@ -165,6 +167,24 @@ public class NBTUtils {
item.addAttribute(itemAttribute);
}
}
// Meta specific field
final ItemMeta itemMeta = item.getItemMeta();
if (itemMeta == null)
return;
final Class metaType = itemMeta.getClass();
if (metaType == PotionMeta.class) {
final PotionMeta potionMeta = (PotionMeta) itemMeta;
if (nbt.containsKey("Potion")) {
potionMeta.addPotionType(Registries.getPotionType(nbt.getString("Potion")));
}
} else if (metaType == MapMeta.class) {
final MapMeta mapMeta = (MapMeta) itemMeta;
if (nbt.containsKey("map")) {
mapMeta.setMapId(nbt.getInt("map"));
}
}
}
private static void loadEnchantments(NBTList<NBTCompound> enchantments, EnchantmentSetter setter) {
@ -185,7 +205,7 @@ public class NBTUtils {
packet.writeBoolean(false);
} else {
packet.writeBoolean(true);
packet.writeVarInt(itemStack.getMaterialId());
packet.writeVarInt(itemStack.getMaterial().getId());
packet.writeByte(itemStack.getAmount());
if (!itemStack.hasNbtTag()) {
@ -217,13 +237,16 @@ public class NBTUtils {
// Start damage
{
itemNBT.setInt("Damage", itemStack.getDamage());
final int damage = itemStack.getDamage();
if (damage > 0) {
itemNBT.setInt("Damage", damage);
}
}
// End damage
// Display
boolean hasDisplayName = itemStack.hasDisplayName();
boolean hasLore = itemStack.hasLore();
final boolean hasDisplayName = itemStack.hasDisplayName();
final boolean hasLore = itemStack.hasLore();
if (hasDisplayName || hasLore) {
NBTCompound displayNBT = new NBTCompound();
@ -248,12 +271,12 @@ public class NBTUtils {
// Start enchantment
{
Map<Enchantment, Short> enchantmentMap = itemStack.getEnchantmentMap();
final Map<Enchantment, Short> enchantmentMap = itemStack.getEnchantmentMap();
if (!enchantmentMap.isEmpty()) {
writeEnchant(itemNBT, "Enchantments", enchantmentMap);
}
Map<Enchantment, Short> storedEnchantmentMap = itemStack.getStoredEnchantmentMap();
final Map<Enchantment, Short> storedEnchantmentMap = itemStack.getStoredEnchantmentMap();
if (!storedEnchantmentMap.isEmpty()) {
writeEnchant(itemNBT, "StoredEnchantments", storedEnchantmentMap);
}
@ -262,12 +285,12 @@ public class NBTUtils {
// Start attribute
{
List<ItemAttribute> itemAttributes = itemStack.getAttributes();
final List<ItemAttribute> itemAttributes = itemStack.getAttributes();
if (!itemAttributes.isEmpty()) {
NBTList<NBTCompound> attributesNBT = new NBTList<>(NBTTypes.TAG_Compound);
for (ItemAttribute itemAttribute : itemAttributes) {
UUID uuid = itemAttribute.getUuid();
final UUID uuid = itemAttribute.getUuid();
attributesNBT.add(
new NBTCompound()
@ -285,20 +308,9 @@ public class NBTUtils {
}
// End attribute
// Start potion
{
Set<PotionType> potionTypes = itemStack.getPotionTypes();
if (!potionTypes.isEmpty()) {
for (PotionType potionType : potionTypes) {
itemNBT.setString("Potion", potionType.getNamespaceID());
}
}
}
// End potion
// Start hide flags
{
int hideFlag = itemStack.getHideFlag();
final int hideFlag = itemStack.getHideFlag();
if (hideFlag != 0) {
itemNBT.setInt("HideFlags", hideFlag);
}
@ -307,11 +319,31 @@ public class NBTUtils {
// Start custom model data
{
int customModelData = itemStack.getCustomModelData();
final int customModelData = itemStack.getCustomModelData();
if (customModelData != 0) {
itemNBT.setInt("CustomModelData", customModelData);
}
}
// Start custom meta
final ItemMeta itemMeta = itemStack.getItemMeta();
if (itemMeta != null) {
final Class metaType = itemMeta.getClass();
if (metaType == PotionMeta.class) {
final Set<PotionType> potionTypes = ((PotionMeta) itemMeta).getPotionTypes();
if (!potionTypes.isEmpty()) {
for (PotionType potionType : potionTypes) {
itemNBT.setString("Potion", potionType.getNamespaceID());
}
}
} else if (metaType == MapMeta.class) {
final int mapId = ((MapMeta) itemMeta).getMapId();
if (mapId != 0) {
itemNBT.setInt("map", mapId);
}
}
}
}
@FunctionalInterface