Add ArmorStand Item Meta

This is adds basic item meta for armor stands. It does not add all
possible metadata however.

There are armor, hand, and equipment types, as well as position data
that can also be added here. This initial addition should serve a
starting point for future additions in this area.

Fixes GH-559
This commit is contained in:
Zach Brown 2018-01-27 17:04:14 -05:00
parent ec3ae43c82
commit e3dd06b7c1
3 changed files with 133 additions and 5 deletions

View File

@ -1,5 +1,6 @@
package org.bukkit.craftbukkit.inventory;
import com.destroystokyo.paper.inventory.meta.ArmorStandMeta;
import java.util.function.BiFunction;
import java.util.function.Function;
import net.minecraft.world.item.BannerItem;
@ -103,7 +104,7 @@ public final class CraftItemMetas {
item -> new CraftMetaSpawnEgg(item.getComponentsPatch()),
(type, meta) -> meta instanceof CraftMetaSpawnEgg spawnEgg ? spawnEgg : new CraftMetaSpawnEgg(meta));
private static final ItemMetaData<ItemMeta> ARMOR_STAND_META_DATA = new ItemMetaData<>(ItemMeta.class,
private static final ItemMetaData<ArmorStandMeta> ARMOR_STAND_META_DATA = new ItemMetaData<>(ArmorStandMeta.class, // paper
item -> new CraftMetaArmorStand(item.getComponentsPatch()),
(type, meta) -> meta instanceof CraftMetaArmorStand armorStand ? armorStand : new CraftMetaArmorStand(meta));

View File

@ -11,9 +11,17 @@ import org.bukkit.Material;
import org.bukkit.configuration.serialization.DelegateDeserialization;
@DelegateDeserialization(SerializableMeta.class)
public class CraftMetaArmorStand extends CraftMetaItem {
public class CraftMetaArmorStand extends CraftMetaItem implements com.destroystokyo.paper.inventory.meta.ArmorStandMeta { // Paper
static final ItemMetaKeyType<CustomData> ENTITY_TAG = new ItemMetaKeyType<>(DataComponents.ENTITY_DATA, "entity-tag");
// Paper start
static final ItemMetaKey ENTITY_ID = new ItemMetaKey("id", "entity-id");
static final ItemMetaKey INVISIBLE = new ItemMetaKey("Invisible", "invisible");
static final ItemMetaKey NO_BASE_PLATE = new ItemMetaKey("NoBasePlate", "no-base-plate");
static final ItemMetaKey SHOW_ARMS = new ItemMetaKey("ShowArms", "show-arms");
static final ItemMetaKey SMALL = new ItemMetaKey("Small", "small");
static final ItemMetaKey MARKER = new ItemMetaKey("Marker", "marker");
// Paper end
CompoundTag entityTag;
CraftMetaArmorStand(CraftMetaItem meta) {
@ -37,6 +45,42 @@ public class CraftMetaArmorStand extends CraftMetaItem {
CraftMetaArmorStand(Map<String, Object> map) {
super(map);
// Paper start
String entityTag = SerializableMeta.getString(map, ENTITY_TAG.BUKKIT, true);
if (entityTag != null) {
java.io.ByteArrayInputStream buf = new java.io.ByteArrayInputStream(java.util.Base64.getDecoder().decode(entityTag));
try {
this.entityTag = net.minecraft.nbt.NbtIo.readCompressed(buf, net.minecraft.nbt.NbtAccounter.unlimitedHeap());
} catch (java.io.IOException ex) {
java.util.logging.Logger.getLogger(CraftMetaItem.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
return;
}
SerializableMeta.getObjectOptionally(Boolean.class, map, INVISIBLE.BUKKIT, true).ifPresent((value) -> {
populateTagIfNull();
this.entityTag.putBoolean(INVISIBLE.NBT, value);
});
SerializableMeta.getObjectOptionally(Boolean.class, map, NO_BASE_PLATE.BUKKIT, true).ifPresent((value) -> {
populateTagIfNull();
this.entityTag.putBoolean(NO_BASE_PLATE.NBT, value);
});
SerializableMeta.getObjectOptionally(Boolean.class, map, SHOW_ARMS.BUKKIT, true).ifPresent((value) -> {
populateTagIfNull();
this.entityTag.putBoolean(SHOW_ARMS.NBT, value);
});
SerializableMeta.getObjectOptionally(Boolean.class, map, SMALL.BUKKIT, true).ifPresent((value) -> {
populateTagIfNull();
this.entityTag.putBoolean(SMALL.NBT, value);
});
SerializableMeta.getObjectOptionally(Boolean.class, map, MARKER.BUKKIT, true).ifPresent((value) -> {
populateTagIfNull();
this.entityTag.putBoolean(MARKER.NBT, value);
});
SerializableMeta.getObjectOptionally(String.class, map, ENTITY_ID, true).ifPresent((value) -> {
populateTagIfNull();
this.entityTag.putString(ENTITY_ID.NBT, value);
});
// Paper end
}
@Override
@ -45,12 +89,13 @@ public class CraftMetaArmorStand extends CraftMetaItem {
if (tag.contains(CraftMetaArmorStand.ENTITY_TAG.NBT)) {
this.entityTag = tag.getCompound(CraftMetaArmorStand.ENTITY_TAG.NBT);
if (!this.entityTag.contains(ENTITY_ID.NBT)) entityTag.putString(ENTITY_ID.NBT, "minecraft:armor_stand"); // Paper - fixup legacy armorstand metas that did not include this.
}
}
@Override
void serializeInternal(Map<String, Tag> internalTags) {
if (this.entityTag != null && !this.entityTag.isEmpty()) {
if (false && this.entityTag != null && !this.entityTag.isEmpty()) { // Paper - now correctly serialised as entity tag
internalTags.put(CraftMetaArmorStand.ENTITY_TAG.NBT, this.entityTag);
}
}
@ -75,7 +120,7 @@ public class CraftMetaArmorStand extends CraftMetaItem {
}
boolean isArmorStandEmpty() {
return !(this.entityTag != null);
return entityTag == null || entityTag.isEmpty(); // Paper - consider armor stand empty if tag is empty.
}
@Override
@ -86,7 +131,9 @@ public class CraftMetaArmorStand extends CraftMetaItem {
if (meta instanceof CraftMetaArmorStand) {
CraftMetaArmorStand that = (CraftMetaArmorStand) meta;
return this.entityTag != null ? that.entityTag != null && this.entityTag.equals(that.entityTag) : this.entityTag == null;
// Paper start
return java.util.Objects.equals(this.entityTag, that.entityTag);
// Paper end
}
return true;
}
@ -112,6 +159,21 @@ public class CraftMetaArmorStand extends CraftMetaItem {
Builder<String, Object> serialize(Builder<String, Object> builder) {
super.serialize(builder);
// Paper start
if (entityTag == null) {
return builder;
} else if (true) {
java.io.ByteArrayOutputStream buf = new java.io.ByteArrayOutputStream();
try {
net.minecraft.nbt.NbtIo.writeCompressed(entityTag, buf);
} catch (java.io.IOException ex) {
java.util.logging.Logger.getLogger(CraftMetaItem.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
builder.put(ENTITY_TAG.BUKKIT, java.util.Base64.getEncoder().encodeToString(buf.toByteArray()));
return builder;
}
// Paper end
return builder;
}
@ -125,4 +187,68 @@ public class CraftMetaArmorStand extends CraftMetaItem {
return clone;
}
// Paper start
private void populateTagIfNull() {
if (this.entityTag == null) {
this.entityTag = new CompoundTag();
this.entityTag.putString(ENTITY_ID.NBT, "minecraft:armor_stand");
}
}
@Override
public boolean isInvisible() {
return entityTag != null && entityTag.contains(INVISIBLE.NBT) && entityTag.getBoolean(INVISIBLE.NBT);
}
@Override
public boolean hasNoBasePlate() {
return entityTag != null && entityTag.contains(NO_BASE_PLATE.NBT) && entityTag.getBoolean(NO_BASE_PLATE.NBT);
}
@Override
public boolean shouldShowArms() {
return entityTag != null && entityTag.contains(SHOW_ARMS.NBT) && entityTag.getBoolean(SHOW_ARMS.NBT);
}
@Override
public boolean isSmall() {
return entityTag != null && entityTag.contains(SMALL.NBT) && entityTag.getBoolean(SMALL.NBT);
}
@Override
public boolean isMarker() {
return entityTag != null && entityTag.contains(MARKER.NBT) && entityTag.getBoolean(MARKER.NBT);
}
@Override
public void setInvisible(boolean invisible) {
populateTagIfNull();
entityTag.putBoolean(INVISIBLE.NBT, invisible);
}
@Override
public void setNoBasePlate(boolean noBasePlate) {
populateTagIfNull();
entityTag.putBoolean(NO_BASE_PLATE.NBT, noBasePlate);
}
@Override
public void setShowArms(boolean showArms) {
populateTagIfNull();
entityTag.putBoolean(SHOW_ARMS.NBT, showArms);
}
@Override
public void setSmall(boolean small) {
populateTagIfNull();
entityTag.putBoolean(SMALL.NBT, small);
}
@Override
public void setMarker(boolean marker) {
populateTagIfNull();
entityTag.putBoolean(MARKER.NBT, marker);
}
// Paper end
}

View File

@ -365,6 +365,7 @@ public class ItemMetaTest {
final CraftMetaArmorStand meta = (CraftMetaArmorStand) cleanStack.getItemMeta();
meta.entityTag = new CompoundTag();
meta.entityTag.putBoolean("Small", true);
meta.setInvisible(true); // Paper
cleanStack.setItemMeta(meta);
return cleanStack;
}