mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-04 14:04:49 +01:00
Replace ItemTag API with new API that also expands to Tiles and Entities
This commit is contained in:
parent
724ec10f33
commit
42f88f72b5
16 changed files with 797 additions and 221 deletions
|
@ -319,7 +319,19 @@
|
|||
IChatBaseComponent ichatbasecomponent = this.getCustomName();
|
||||
|
||||
if (ichatbasecomponent != null) {
|
||||
@@ -1414,6 +1595,42 @@
|
||||
@@ -1331,6 +1512,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ // CraftBukkit start - stores eventually existing bukkit values
|
||||
+ if (this.bukkitEntity != null) {
|
||||
+ this.bukkitEntity.storeBukkitValues(nbttagcompound);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return nbttagcompound;
|
||||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.a(throwable, "Saving entity NBT");
|
||||
@@ -1414,6 +1600,42 @@
|
||||
} else {
|
||||
throw new IllegalStateException("Entity has invalid position");
|
||||
}
|
||||
|
@ -362,7 +374,7 @@
|
|||
} catch (Throwable throwable) {
|
||||
CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT");
|
||||
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded");
|
||||
@@ -1489,9 +1706,22 @@
|
||||
@@ -1489,9 +1711,22 @@
|
||||
} else if (this.world.isClientSide) {
|
||||
return null;
|
||||
} else {
|
||||
|
@ -385,7 +397,7 @@
|
|||
this.world.addEntity(entityitem);
|
||||
return entityitem;
|
||||
}
|
||||
@@ -1595,7 +1825,7 @@
|
||||
@@ -1595,7 +1830,7 @@
|
||||
}
|
||||
|
||||
this.vehicle = entity;
|
||||
|
@ -394,7 +406,7 @@
|
|||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1620,15 +1850,36 @@
|
||||
@@ -1620,15 +1855,36 @@
|
||||
Entity entity = this.vehicle;
|
||||
|
||||
this.vehicle = null;
|
||||
|
@ -433,7 +445,7 @@
|
|||
if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.getRidingPassenger() instanceof EntityHuman)) {
|
||||
this.passengers.add(0, entity);
|
||||
} else {
|
||||
@@ -1636,15 +1887,33 @@
|
||||
@@ -1636,15 +1892,33 @@
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -468,7 +480,7 @@
|
|||
}
|
||||
|
||||
protected boolean q(Entity entity) {
|
||||
@@ -1687,7 +1956,7 @@
|
||||
@@ -1687,7 +1961,7 @@
|
||||
int i = this.ab();
|
||||
|
||||
if (this.ai) {
|
||||
|
@ -477,7 +489,7 @@
|
|||
this.world.getMethodProfiler().enter("portal");
|
||||
this.aj = i;
|
||||
this.portalCooldown = this.aW();
|
||||
@@ -1771,6 +2040,13 @@
|
||||
@@ -1771,6 +2045,13 @@
|
||||
}
|
||||
|
||||
public void setSwimming(boolean flag) {
|
||||
|
@ -491,7 +503,7 @@
|
|||
this.setFlag(4, flag);
|
||||
}
|
||||
|
||||
@@ -1831,16 +2107,56 @@
|
||||
@@ -1831,16 +2112,56 @@
|
||||
}
|
||||
|
||||
public void setAirTicks(int i) {
|
||||
|
@ -551,7 +563,7 @@
|
|||
}
|
||||
|
||||
public void j(boolean flag) {
|
||||
@@ -1988,20 +2304,33 @@
|
||||
@@ -1988,20 +2309,33 @@
|
||||
|
||||
@Nullable
|
||||
public Entity a(DimensionManager dimensionmanager) {
|
||||
|
@ -588,7 +600,7 @@
|
|||
if (dimensionmanager1 == DimensionManager.THE_END && dimensionmanager == DimensionManager.OVERWORLD) {
|
||||
blockposition = worldserver1.getHighestBlockYAt(HeightMap.Type.MOTION_BLOCKING_NO_LEAVES, worldserver1.getSpawn());
|
||||
} else if (dimensionmanager == DimensionManager.THE_END) {
|
||||
@@ -2039,6 +2368,25 @@
|
||||
@@ -2039,6 +2373,25 @@
|
||||
vec3d = shapedetector_c.b;
|
||||
f = (float) shapedetector_c.c;
|
||||
}
|
||||
|
@ -614,7 +626,7 @@
|
|||
|
||||
this.world.getMethodProfiler().exitEnter("reloading");
|
||||
Entity entity = this.getEntityType().a((World) worldserver1);
|
||||
@@ -2048,6 +2396,14 @@
|
||||
@@ -2048,6 +2401,14 @@
|
||||
entity.setPositionRotation(blockposition, entity.yaw + f, entity.pitch);
|
||||
entity.setMot(vec3d);
|
||||
worldserver1.addEntityTeleport(entity);
|
||||
|
@ -629,7 +641,7 @@
|
|||
}
|
||||
|
||||
this.dead = true;
|
||||
@@ -2239,7 +2595,26 @@
|
||||
@@ -2239,7 +2600,26 @@
|
||||
}
|
||||
|
||||
public void a(AxisAlignedBB axisalignedbb) {
|
||||
|
|
|
@ -1,15 +1,47 @@
|
|||
--- a/net/minecraft/server/TileEntity.java
|
||||
+++ b/net/minecraft/server/TileEntity.java
|
||||
@@ -4,6 +4,8 @@
|
||||
@@ -3,9 +3,18 @@
|
||||
import javax.annotation.Nullable;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
+// CraftBukkit start
|
||||
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
|
||||
+import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
|
||||
+import org.bukkit.inventory.InventoryHolder;
|
||||
+// CraftBukkit end
|
||||
|
||||
+import org.bukkit.inventory.InventoryHolder; // CraftBukkit
|
||||
+
|
||||
public abstract class TileEntity {
|
||||
|
||||
+ // CraftBukkit start - data containers
|
||||
+ private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||
+ public final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
|
||||
+ // CraftBukkit end
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -55,8 +57,15 @@
|
||||
private final TileEntityTypes<?> b;
|
||||
@Nullable
|
||||
@@ -35,6 +44,12 @@
|
||||
|
||||
public void load(NBTTagCompound nbttagcompound) {
|
||||
this.position = new BlockPosition(nbttagcompound.getInt("x"), nbttagcompound.getInt("y"), nbttagcompound.getInt("z"));
|
||||
+ // CraftBukkit start - read container
|
||||
+ NBTTagCompound persistentDataTag = nbttagcompound.getCompound("PublicBukkitValues");
|
||||
+ if (persistentDataTag != null) {
|
||||
+ this.persistentDataContainer.putAll(persistentDataTag);
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
}
|
||||
|
||||
public NBTTagCompound save(NBTTagCompound nbttagcompound) {
|
||||
@@ -51,12 +66,24 @@
|
||||
nbttagcompound.setInt("x", this.position.getX());
|
||||
nbttagcompound.setInt("y", this.position.getY());
|
||||
nbttagcompound.setInt("z", this.position.getZ());
|
||||
+ // CraftBukkit start - store container
|
||||
+ if (!this.persistentDataContainer.isEmpty()) {
|
||||
+ nbttagcompound.set("PublicBukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
return nbttagcompound;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +57,7 @@
|
|||
String s = nbttagcompound.getString("id");
|
||||
|
||||
return (TileEntity) IRegistry.BLOCK_ENTITY_TYPE.getOptional(new MinecraftKey(s)).map((tileentitytypes) -> {
|
||||
@@ -68,6 +77,7 @@
|
||||
@@ -68,6 +95,7 @@
|
||||
}
|
||||
}).map((tileentity) -> {
|
||||
try {
|
||||
|
@ -33,7 +65,7 @@
|
|||
tileentity.load(nbttagcompound);
|
||||
return tileentity;
|
||||
} catch (Throwable throwable) {
|
||||
@@ -157,4 +167,13 @@
|
||||
@@ -157,4 +185,13 @@
|
||||
public TileEntityTypes<?> q() {
|
||||
return this.b;
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@ import net.minecraft.server.TileEntity;
|
|||
import net.minecraft.server.World;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.TileState;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
|
||||
public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState {
|
||||
public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState implements TileState {
|
||||
|
||||
private final Class<T> tileEntityClass;
|
||||
private final T tileEntity;
|
||||
|
@ -118,4 +120,9 @@ public class CraftBlockEntityState<T extends TileEntity> extends CraftBlockState
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentDataContainer getPersistentDataContainer() {
|
||||
return this.getSnapshot().persistentDataContainer;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -146,6 +146,8 @@ import org.bukkit.block.PistonMoveReaction;
|
|||
import org.bukkit.craftbukkit.CraftServer;
|
||||
import org.bukkit.craftbukkit.CraftWorld;
|
||||
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
|
||||
import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
|
||||
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
import org.bukkit.craftbukkit.util.CraftVector;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
@ -163,10 +165,12 @@ import org.bukkit.util.Vector;
|
|||
|
||||
public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
||||
private static PermissibleBase perm;
|
||||
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||
|
||||
protected final CraftServer server;
|
||||
protected Entity entity;
|
||||
private EntityDamageEvent lastDamageEvent;
|
||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
|
||||
|
||||
public CraftEntity(final CraftServer server, final Entity entity) {
|
||||
this.server = server;
|
||||
|
@ -884,6 +888,24 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
|
|||
return CraftBlock.notchToBlockFace(getHandle().getAdjustedDirection());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CraftPersistentDataContainer getPersistentDataContainer() {
|
||||
return persistentDataContainer;
|
||||
}
|
||||
|
||||
public void storeBukkitValues(NBTTagCompound c) {
|
||||
if (!this.persistentDataContainer.isEmpty()) {
|
||||
c.set("BukkitValues", this.persistentDataContainer.toTagCompound());
|
||||
}
|
||||
}
|
||||
|
||||
public void readBukkitValues(NBTTagCompound c) {
|
||||
NBTTagCompound base = c.getCompound("BukkitValues");
|
||||
if (base != null) {
|
||||
this.persistentDataContainer.putAll(base);
|
||||
}
|
||||
}
|
||||
|
||||
protected NBTTagCompound save() {
|
||||
NBTTagCompound nbttagcompound = new NBTTagCompound();
|
||||
|
||||
|
|
|
@ -62,7 +62,9 @@ import org.bukkit.craftbukkit.attribute.CraftAttributeInstance;
|
|||
import org.bukkit.craftbukkit.attribute.CraftAttributeMap;
|
||||
import org.bukkit.craftbukkit.block.data.CraftBlockData;
|
||||
import org.bukkit.craftbukkit.inventory.CraftMetaItem.ItemMetaKey.Specific;
|
||||
import org.bukkit.craftbukkit.inventory.tags.CraftCustomItemTagContainer;
|
||||
import org.bukkit.craftbukkit.inventory.tags.DeprecatedCustomTagContainer;
|
||||
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
|
||||
import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry;
|
||||
import org.bukkit.craftbukkit.util.CraftChatMessage;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.craftbukkit.util.CraftNBTTagConfigSerializer;
|
||||
|
@ -75,6 +77,7 @@ import org.bukkit.inventory.meta.Damageable;
|
|||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.Repairable;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
|
||||
/**
|
||||
* Children must include the following:
|
||||
|
@ -267,11 +270,11 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
private int damage;
|
||||
|
||||
private static final Set<String> HANDLED_TAGS = Sets.newHashSet();
|
||||
private static final CraftCustomTagTypeRegistry TAG_TYPE_REGISTRY = new CraftCustomTagTypeRegistry();
|
||||
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
|
||||
|
||||
private NBTTagCompound internalTag;
|
||||
private final Map<String, NBTBase> unhandledTags = new HashMap<String, NBTBase>();
|
||||
private final CraftCustomItemTagContainer publicItemTagContainer = new CraftCustomItemTagContainer(TAG_TYPE_REGISTRY);
|
||||
private final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
|
||||
|
||||
private int version = CraftMagicNumbers.INSTANCE.getDataVersion(); // Internal use only
|
||||
|
||||
|
@ -303,7 +306,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
this.unbreakable = meta.unbreakable;
|
||||
this.damage = meta.damage;
|
||||
this.unhandledTags.putAll(meta.unhandledTags);
|
||||
this.publicItemTagContainer.putAll(meta.publicItemTagContainer.getRaw());
|
||||
this.persistentDataContainer.putAll(meta.persistentDataContainer.getRaw());
|
||||
|
||||
this.internalTag = meta.internalTag;
|
||||
if (this.internalTag != null) {
|
||||
|
@ -375,7 +378,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
NBTTagCompound compound = tag.getCompound(BUKKIT_CUSTOM_TAG.NBT);
|
||||
Set<String> keys = compound.getKeys();
|
||||
for (String key : keys) {
|
||||
publicItemTagContainer.put(key, compound.get(key));
|
||||
persistentDataContainer.put(key, compound.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,7 +537,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
|
||||
Map nbtMap = SerializableMeta.getObject(Map.class, map, BUKKIT_CUSTOM_TAG.BUKKIT, true);
|
||||
if (nbtMap != null) {
|
||||
this.publicItemTagContainer.putAll((NBTTagCompound) CraftNBTTagConfigSerializer.deserialize(nbtMap));
|
||||
this.persistentDataContainer.putAll((NBTTagCompound) CraftNBTTagConfigSerializer.deserialize(nbtMap));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -648,9 +651,9 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
itemTag.set(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
if (!publicItemTagContainer.isEmpty()) {
|
||||
if (!persistentDataContainer.isEmpty()) {
|
||||
NBTTagCompound bukkitCustomCompound = new NBTTagCompound();
|
||||
Map<String, NBTBase> rawPublicMap = publicItemTagContainer.getRaw();
|
||||
Map<String, NBTBase> rawPublicMap = persistentDataContainer.getRaw();
|
||||
|
||||
for (Map.Entry<String, NBTBase> nbtBaseEntry : rawPublicMap.entrySet()) {
|
||||
bukkitCustomCompound.set(nbtBaseEntry.getKey(), nbtBaseEntry.getValue());
|
||||
|
@ -741,7 +744,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
|
||||
@Overridden
|
||||
boolean isEmpty() {
|
||||
return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || hasLore() || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !publicItemTagContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers());
|
||||
return !(hasDisplayName() || hasLocalizedName() || hasEnchants() || hasLore() || hasCustomModelData() || hasBlockData() || hasRepairCost() || !unhandledTags.isEmpty() || !persistentDataContainer.isEmpty() || hideFlag != 0 || isUnbreakable() || hasDamage() || hasAttributeModifiers());
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
|
@ -1041,7 +1044,12 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
|
||||
@Override
|
||||
public CustomItemTagContainer getCustomTagContainer() {
|
||||
return this.publicItemTagContainer;
|
||||
return new DeprecatedCustomTagContainer(this.getPersistentDataContainer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentDataContainer getPersistentDataContainer() {
|
||||
return this.persistentDataContainer;
|
||||
}
|
||||
|
||||
private static boolean compareModifiers(Multimap<Attribute, AttributeModifier> first, Multimap<Attribute, AttributeModifier> second) {
|
||||
|
@ -1106,7 +1114,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
&& (this.hasRepairCost() ? that.hasRepairCost() && this.repairCost == that.repairCost : !that.hasRepairCost())
|
||||
&& (this.hasAttributeModifiers() ? that.hasAttributeModifiers() && compareModifiers(this.attributeModifiers, that.attributeModifiers) : !that.hasAttributeModifiers())
|
||||
&& (this.unhandledTags.equals(that.unhandledTags))
|
||||
&& (this.publicItemTagContainer.equals(that.publicItemTagContainer))
|
||||
&& (this.persistentDataContainer.equals(that.persistentDataContainer))
|
||||
&& (this.hideFlag == that.hideFlag)
|
||||
&& (this.isUnbreakable() == that.isUnbreakable())
|
||||
&& (this.hasDamage() ? that.hasDamage() && this.damage == that.damage : !that.hasDamage())
|
||||
|
@ -1139,7 +1147,7 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
hash = 61 * hash + (hasEnchants() ? this.enchantments.hashCode() : 0);
|
||||
hash = 61 * hash + (hasRepairCost() ? this.repairCost : 0);
|
||||
hash = 61 * hash + unhandledTags.hashCode();
|
||||
hash = 61 * hash + (!publicItemTagContainer.isEmpty() ? publicItemTagContainer.hashCode() : 0);
|
||||
hash = 61 * hash + (!persistentDataContainer.isEmpty() ? persistentDataContainer.hashCode() : 0);
|
||||
hash = 61 * hash + hideFlag;
|
||||
hash = 61 * hash + (isUnbreakable() ? 1231 : 1237);
|
||||
hash = 61 * hash + (hasDamage() ? this.damage : 0);
|
||||
|
@ -1240,8 +1248,8 @@ class CraftMetaItem implements ItemMeta, Damageable, Repairable, BlockDataMeta {
|
|||
}
|
||||
}
|
||||
|
||||
if (!publicItemTagContainer.isEmpty()) { // Store custom tags, wrapped in their compound
|
||||
builder.put(BUKKIT_CUSTOM_TAG.BUKKIT, publicItemTagContainer.serialize());
|
||||
if (!persistentDataContainer.isEmpty()) { // Store custom tags, wrapped in their compound
|
||||
builder.put(BUKKIT_CUSTOM_TAG.BUKKIT, persistentDataContainer.serialize());
|
||||
}
|
||||
|
||||
return builder;
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
package org.bukkit.craftbukkit.inventory.tags;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import net.minecraft.server.NBTBase;
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.inventory.CraftCustomTagTypeRegistry;
|
||||
import org.bukkit.craftbukkit.util.CraftNBTTagConfigSerializer;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagAdapterContext;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagType;
|
||||
|
||||
public final class CraftCustomItemTagContainer implements CustomItemTagContainer {
|
||||
|
||||
private final Map<String, NBTBase> customTags = new HashMap<>();
|
||||
private final CraftCustomTagTypeRegistry tagTypeRegistry;
|
||||
private final CraftItemTagAdapterContext adapterContext;
|
||||
|
||||
public CraftCustomItemTagContainer(Map<String, NBTBase> customTags, CraftCustomTagTypeRegistry tagTypeRegistry) {
|
||||
this(tagTypeRegistry);
|
||||
this.customTags.putAll(customTags);
|
||||
}
|
||||
|
||||
public CraftCustomItemTagContainer(CraftCustomTagTypeRegistry tagTypeRegistry) {
|
||||
this.tagTypeRegistry = tagTypeRegistry;
|
||||
this.adapterContext = new CraftItemTagAdapterContext(this.tagTypeRegistry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> void setCustomTag(NamespacedKey key, ItemTagType<T, Z> type, Z value) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
Validate.notNull(type, "The provided type for the custom value was null");
|
||||
Validate.notNull(value, "The provided value for the custom value was null");
|
||||
|
||||
this.customTags.put(key.toString(), tagTypeRegistry.wrap(type.getPrimitiveType(), type.toPrimitive(value, adapterContext)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> boolean hasCustomTag(NamespacedKey key, ItemTagType<T, Z> type) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
Validate.notNull(type, "The provided type for the custom value was null");
|
||||
|
||||
NBTBase value = this.customTags.get(key.toString());
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return tagTypeRegistry.isInstanceOf(type.getPrimitiveType(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> Z getCustomTag(NamespacedKey key, ItemTagType<T, Z> type) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
Validate.notNull(type, "The provided type for the custom value was null");
|
||||
|
||||
NBTBase value = this.customTags.get(key.toString());
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return type.fromPrimitive(tagTypeRegistry.extract(type.getPrimitiveType(), value), adapterContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomTag(NamespacedKey key) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
|
||||
this.customTags.remove(key.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.customTags.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemTagAdapterContext getAdapterContext() {
|
||||
return this.adapterContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof CraftCustomItemTagContainer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, NBTBase> myRawMap = getRaw();
|
||||
Map<String, NBTBase> theirRawMap = ((CraftCustomItemTagContainer) obj).getRaw();
|
||||
|
||||
return Objects.equals(myRawMap, theirRawMap);
|
||||
}
|
||||
|
||||
public NBTTagCompound toTagCompound() {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
for (Entry<String, NBTBase> entry : this.customTags.entrySet()) {
|
||||
tag.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void put(String key, NBTBase base) {
|
||||
this.customTags.put(key, base);
|
||||
}
|
||||
|
||||
public void putAll(Map<String, NBTBase> map) {
|
||||
this.customTags.putAll(map);
|
||||
}
|
||||
|
||||
public void putAll(NBTTagCompound compound) {
|
||||
for (String key : compound.getKeys()) {
|
||||
this.customTags.put(key, compound.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, NBTBase> getRaw() {
|
||||
return this.customTags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 3;
|
||||
hashCode += this.customTags.hashCode(); // We will simply add the maps hashcode
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public Map<String, Object> serialize() {
|
||||
return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(toTagCompound());
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
package org.bukkit.craftbukkit.inventory.tags;
|
||||
|
||||
import org.bukkit.craftbukkit.inventory.CraftCustomTagTypeRegistry;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagAdapterContext;
|
||||
|
||||
public final class CraftItemTagAdapterContext implements ItemTagAdapterContext {
|
||||
|
||||
private final CraftCustomTagTypeRegistry registry;
|
||||
|
||||
public CraftItemTagAdapterContext(CraftCustomTagTypeRegistry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new and empty tag container instance
|
||||
*
|
||||
* @return the fresh container instance
|
||||
*/
|
||||
@Override
|
||||
public CustomItemTagContainer newTagContainer() {
|
||||
return new CraftCustomItemTagContainer(this.registry);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.bukkit.craftbukkit.inventory.tags;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagType;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
public final class DeprecatedContainerTagType<Z> implements PersistentDataType<PersistentDataContainer, Z> {
|
||||
|
||||
private final ItemTagType<CustomItemTagContainer, Z> deprecated;
|
||||
|
||||
DeprecatedContainerTagType(ItemTagType<CustomItemTagContainer, Z> deprecated) {
|
||||
this.deprecated = deprecated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<PersistentDataContainer> getPrimitiveType() {
|
||||
return PersistentDataContainer.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Z> getComplexType() {
|
||||
return deprecated.getComplexType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentDataContainer toPrimitive(Z complex, PersistentDataAdapterContext context) {
|
||||
CustomItemTagContainer deprecated = this.deprecated.toPrimitive(complex, new DeprecatedItemAdapterContext(context));
|
||||
Validate.isInstanceOf(DeprecatedCustomTagContainer.class, deprecated, "Could not wrap deprecated API due to foreign CustomItemTagContainer implementation %s", deprecated.getClass().getSimpleName());
|
||||
|
||||
DeprecatedCustomTagContainer tagContainer = (DeprecatedCustomTagContainer) deprecated;
|
||||
PersistentDataContainer wrapped = tagContainer.getWrapped();
|
||||
Validate.isInstanceOf(CraftPersistentDataContainer.class, wrapped, "Could not wrap deprecated API due to wrong deprecation wrapper %s", deprecated.getClass().getSimpleName());
|
||||
|
||||
CraftPersistentDataContainer craftTagContainer = (CraftPersistentDataContainer) wrapped;
|
||||
return new CraftPersistentDataContainer(craftTagContainer.getRaw(), craftTagContainer.getDataTagTypeRegistry());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Z fromPrimitive(PersistentDataContainer primitive, PersistentDataAdapterContext context) {
|
||||
Validate.isInstanceOf(CraftPersistentDataContainer.class, primitive, "Could not wrap deprecated API due to foreign PersistentMetadataContainer implementation %s", primitive.getClass().getSimpleName());
|
||||
|
||||
return this.deprecated.fromPrimitive(new DeprecatedCustomTagContainer(primitive), new DeprecatedItemAdapterContext(context));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package org.bukkit.craftbukkit.inventory.tags;
|
||||
|
||||
import java.util.Objects;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagAdapterContext;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagType;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
|
||||
/**
|
||||
* The {@link DeprecatedCustomTagContainer} is a simply wrapper implementation
|
||||
* that wraps the new api to still be usable with the old api parts.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public final class DeprecatedCustomTagContainer implements CustomItemTagContainer {
|
||||
|
||||
private final PersistentDataContainer wrapped;
|
||||
|
||||
public DeprecatedCustomTagContainer(PersistentDataContainer wrapped) {
|
||||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> void setCustomTag(NamespacedKey key, ItemTagType<T, Z> type, Z value) {
|
||||
if (Objects.equals(CustomItemTagContainer.class, type.getPrimitiveType())) {
|
||||
wrapped.set(key, new DeprecatedContainerTagType<>((ItemTagType<CustomItemTagContainer, Z>) type), value);
|
||||
} else {
|
||||
wrapped.set(key, new DeprecatedItemTagType<>(type), value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> boolean hasCustomTag(NamespacedKey key, ItemTagType<T, Z> type) {
|
||||
if (Objects.equals(CustomItemTagContainer.class, type.getPrimitiveType())) {
|
||||
return wrapped.has(key, new DeprecatedContainerTagType<>((ItemTagType<CustomItemTagContainer, Z>) type));
|
||||
} else {
|
||||
return wrapped.has(key, new DeprecatedItemTagType<>(type));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> Z getCustomTag(NamespacedKey key, ItemTagType<T, Z> type) {
|
||||
if (Objects.equals(CustomItemTagContainer.class, type.getPrimitiveType())) {
|
||||
return wrapped.get(key, new DeprecatedContainerTagType<>((ItemTagType<CustomItemTagContainer, Z>) type));
|
||||
} else {
|
||||
return wrapped.get(key, new DeprecatedItemTagType<>(type));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeCustomTag(NamespacedKey key) {
|
||||
wrapped.remove(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return wrapped.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemTagAdapterContext getAdapterContext() {
|
||||
return new DeprecatedItemAdapterContext(this.wrapped.getAdapterContext());
|
||||
}
|
||||
|
||||
public PersistentDataContainer getWrapped() {
|
||||
return wrapped;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.bukkit.craftbukkit.inventory.tags;
|
||||
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
|
||||
public final class DeprecatedItemAdapterContext implements ItemTagAdapterContext {
|
||||
|
||||
private final PersistentDataAdapterContext context;
|
||||
|
||||
public DeprecatedItemAdapterContext(PersistentDataAdapterContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new and empty tag container instance.
|
||||
*
|
||||
* @return the fresh container instance
|
||||
*/
|
||||
@Override
|
||||
public CustomItemTagContainer newTagContainer() {
|
||||
return new DeprecatedCustomTagContainer(context.newPersistentDataContainer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.bukkit.craftbukkit.inventory.tags;
|
||||
|
||||
import org.bukkit.inventory.meta.tags.ItemTagType;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
public final class DeprecatedItemTagType<T, Z> implements PersistentDataType<T, Z> {
|
||||
|
||||
private final ItemTagType<T, Z> deprecated;
|
||||
|
||||
public DeprecatedItemTagType(ItemTagType<T, Z> deprecated) {
|
||||
this.deprecated = deprecated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getPrimitiveType() {
|
||||
return deprecated.getPrimitiveType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<Z> getComplexType() {
|
||||
return deprecated.getComplexType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T toPrimitive(Z complex, PersistentDataAdapterContext context) {
|
||||
return this.deprecated.toPrimitive(complex, new DeprecatedItemAdapterContext(context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Z fromPrimitive(T primitive, PersistentDataAdapterContext context) {
|
||||
return this.deprecated.fromPrimitive(primitive, new DeprecatedItemAdapterContext(context));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.bukkit.craftbukkit.persistence;
|
||||
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
|
||||
public final class CraftPersistentDataAdapterContext implements PersistentDataAdapterContext {
|
||||
|
||||
private final CraftPersistentDataTypeRegistry registry;
|
||||
|
||||
public CraftPersistentDataAdapterContext(CraftPersistentDataTypeRegistry registry) {
|
||||
this.registry = registry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new and empty tag container instance
|
||||
*
|
||||
* @return the fresh container instance
|
||||
*/
|
||||
@Override
|
||||
public CraftPersistentDataContainer newPersistentDataContainer() {
|
||||
return new CraftPersistentDataContainer(this.registry);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
package org.bukkit.craftbukkit.persistence;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import net.minecraft.server.NBTBase;
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.craftbukkit.util.CraftNBTTagConfigSerializer;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
|
||||
public final class CraftPersistentDataContainer implements PersistentDataContainer {
|
||||
|
||||
private final Map<String, NBTBase> customDataTags = new HashMap<>();
|
||||
private final CraftPersistentDataTypeRegistry registry;
|
||||
private final CraftPersistentDataAdapterContext adapterContext;
|
||||
|
||||
public CraftPersistentDataContainer(Map<String, NBTBase> customTags, CraftPersistentDataTypeRegistry registry) {
|
||||
this(registry);
|
||||
this.customDataTags.putAll(customTags);
|
||||
}
|
||||
|
||||
public CraftPersistentDataContainer(CraftPersistentDataTypeRegistry registry) {
|
||||
this.registry = registry;
|
||||
this.adapterContext = new CraftPersistentDataAdapterContext(this.registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> void set(NamespacedKey key, PersistentDataType<T, Z> type, Z value) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
Validate.notNull(type, "The provided type for the custom value was null");
|
||||
Validate.notNull(value, "The provided value for the custom value was null");
|
||||
|
||||
this.customDataTags.put(key.toString(), registry.wrap(type.getPrimitiveType(), type.toPrimitive(value, adapterContext)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> boolean has(NamespacedKey key, PersistentDataType<T, Z> type) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
Validate.notNull(type, "The provided type for the custom value was null");
|
||||
|
||||
NBTBase value = this.customDataTags.get(key.toString());
|
||||
if (value == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return registry.isInstanceOf(type.getPrimitiveType(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> Z get(NamespacedKey key, PersistentDataType<T, Z> type) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
Validate.notNull(type, "The provided type for the custom value was null");
|
||||
|
||||
NBTBase value = this.customDataTags.get(key.toString());
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return type.fromPrimitive(registry.extract(type.getPrimitiveType(), value), adapterContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, Z> Z getOrDefault(NamespacedKey key, PersistentDataType<T, Z> type, Z defaultValue) {
|
||||
Z z = get(key, type);
|
||||
return z != null ? z : defaultValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(NamespacedKey key) {
|
||||
Validate.notNull(key, "The provided key for the custom value was null");
|
||||
|
||||
this.customDataTags.remove(key.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.customDataTags.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistentDataAdapterContext getAdapterContext() {
|
||||
return this.adapterContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof CraftPersistentDataContainer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<String, NBTBase> myRawMap = getRaw();
|
||||
Map<String, NBTBase> theirRawMap = ((CraftPersistentDataContainer) obj).getRaw();
|
||||
|
||||
return Objects.equals(myRawMap, theirRawMap);
|
||||
}
|
||||
|
||||
public NBTTagCompound toTagCompound() {
|
||||
NBTTagCompound tag = new NBTTagCompound();
|
||||
for (Entry<String, NBTBase> entry : this.customDataTags.entrySet()) {
|
||||
tag.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void put(String key, NBTBase base) {
|
||||
this.customDataTags.put(key, base);
|
||||
}
|
||||
|
||||
public void putAll(Map<String, NBTBase> map) {
|
||||
this.customDataTags.putAll(map);
|
||||
}
|
||||
|
||||
public void putAll(NBTTagCompound compound) {
|
||||
for (String key : compound.getKeys()) {
|
||||
this.customDataTags.put(key, compound.get(key));
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, NBTBase> getRaw() {
|
||||
return this.customDataTags;
|
||||
}
|
||||
|
||||
public CraftPersistentDataTypeRegistry getDataTagTypeRegistry() {
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 3;
|
||||
hashCode += this.customDataTags.hashCode(); // We will simply add the maps hashcode
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public Map<String, Object> serialize() {
|
||||
return (Map<String, Object>) CraftNBTTagConfigSerializer.serialize(toTagCompound());
|
||||
}
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
package org.bukkit.craftbukkit.inventory;
|
||||
package org.bukkit.craftbukkit.persistence;
|
||||
|
||||
import com.google.common.primitives.Primitives;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import com.google.common.primitives.Primitives;
|
||||
import net.minecraft.server.NBTBase;
|
||||
import net.minecraft.server.NBTTagByte;
|
||||
import net.minecraft.server.NBTTagByteArray;
|
||||
|
@ -19,17 +19,16 @@ import net.minecraft.server.NBTTagLongArray;
|
|||
import net.minecraft.server.NBTTagShort;
|
||||
import net.minecraft.server.NBTTagString;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.craftbukkit.inventory.tags.CraftCustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
|
||||
/**
|
||||
* This class represents a registry that contains the used adapters for.
|
||||
*/
|
||||
public final class CraftCustomTagTypeRegistry {
|
||||
public final class CraftPersistentDataTypeRegistry {
|
||||
|
||||
private final Function<Class, CustomTagAdapter> CREATE_ADAPTER = this::createAdapter;
|
||||
private final Function<Class, TagAdapter> CREATE_ADAPTER = this::createAdapter;
|
||||
|
||||
private class CustomTagAdapter<T, Z extends NBTBase> {
|
||||
private class TagAdapter<T, Z extends NBTBase> {
|
||||
|
||||
private final Function<T, Z> builder;
|
||||
private final Function<Z, T> extractor;
|
||||
|
@ -37,7 +36,7 @@ public final class CraftCustomTagTypeRegistry {
|
|||
private final Class<T> primitiveType;
|
||||
private final Class<Z> nbtBaseType;
|
||||
|
||||
public CustomTagAdapter(Class<T> primitiveType, Class<Z> nbtBaseType, Function<T, Z> builder, Function<Z, T> extractor) {
|
||||
public TagAdapter(Class<T> primitiveType, Class<Z> nbtBaseType, Function<T, Z> builder, Function<Z, T> extractor) {
|
||||
this.primitiveType = primitiveType;
|
||||
this.nbtBaseType = nbtBaseType;
|
||||
this.builder = builder;
|
||||
|
@ -49,7 +48,9 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* the expected primitive type.
|
||||
*
|
||||
* @param base the base to extract from
|
||||
*
|
||||
* @return the value stored inside of the tag
|
||||
*
|
||||
* @throws ClassCastException if the passed base is not an instanced of
|
||||
* the defined base type and therefore is not applicable to the
|
||||
* extractor function
|
||||
|
@ -63,7 +64,9 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* Builds a tag instance wrapping around the provided value object.
|
||||
*
|
||||
* @param value the value to store inside the created tag
|
||||
*
|
||||
* @return the new tag instance
|
||||
*
|
||||
* @throws ClassCastException if the passed value object is not of the
|
||||
* defined primitive type and therefore is not applicable to the builder
|
||||
* function
|
||||
|
@ -77,6 +80,7 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* Returns if the tag instance matches the adapters one.
|
||||
*
|
||||
* @param base the base to check
|
||||
*
|
||||
* @return if the tag was an instance of the set type
|
||||
*/
|
||||
boolean isInstance(NBTBase base) {
|
||||
|
@ -84,18 +88,20 @@ public final class CraftCustomTagTypeRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
private final Map<Class, CustomTagAdapter> adapters = new HashMap<>();
|
||||
private final Map<Class, TagAdapter> adapters = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a suitable adapter instance for the primitive class type
|
||||
*
|
||||
* @param type the type to create an adapter for
|
||||
* @param <T> the generic type of that class
|
||||
*
|
||||
* @return the created adapter instance
|
||||
*
|
||||
* @throws IllegalArgumentException if no suitable tag type adapter for this
|
||||
* type was found
|
||||
*/
|
||||
private <T> CustomTagAdapter createAdapter(Class<T> type) {
|
||||
private <T> TagAdapter createAdapter(Class<T> type) {
|
||||
if (!Primitives.isWrapperType(type)) {
|
||||
type = Primitives.wrap(type); //Make sure we will always "switch" over the wrapper types
|
||||
}
|
||||
|
@ -143,12 +149,12 @@ public final class CraftCustomTagTypeRegistry {
|
|||
}
|
||||
|
||||
/*
|
||||
Note that this will map the interface CustomItemTagContainer directly to the CraftBukkit implementation
|
||||
Passing any other instance of this form to the tag type registry will throw a ClassCastException as defined in CustomTagAdapter#build
|
||||
Note that this will map the interface PersistentMetadataContainer directly to the CraftBukkit implementation
|
||||
Passing any other instance of this form to the tag type registry will throw a ClassCastException as defined in TagAdapter#build
|
||||
*/
|
||||
if (Objects.equals(CustomItemTagContainer.class, type)) {
|
||||
return createAdapter(CraftCustomItemTagContainer.class, NBTTagCompound.class, CraftCustomItemTagContainer::toTagCompound, tag -> {
|
||||
CraftCustomItemTagContainer container = new CraftCustomItemTagContainer(this);
|
||||
if (Objects.equals(PersistentDataContainer.class, type)) {
|
||||
return createAdapter(CraftPersistentDataContainer.class, NBTTagCompound.class, CraftPersistentDataContainer::toTagCompound, tag -> {
|
||||
CraftPersistentDataContainer container = new CraftPersistentDataContainer(this);
|
||||
for (String key : tag.getKeys()) {
|
||||
container.put(key, tag.get(key));
|
||||
}
|
||||
|
@ -156,11 +162,11 @@ public final class CraftCustomTagTypeRegistry {
|
|||
});
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Could not find a valid CustomTagAdapter implementation for the requested type " + type.getSimpleName());
|
||||
throw new IllegalArgumentException("Could not find a valid TagAdapter implementation for the requested type " + type.getSimpleName());
|
||||
}
|
||||
|
||||
private <T, Z extends NBTBase> CustomTagAdapter<T, Z> createAdapter(Class<T> primitiveType, Class<Z> nbtBaseType, Function<T, Z> builder, Function<Z, T> extractor) {
|
||||
return new CustomTagAdapter<>(primitiveType, nbtBaseType, builder, extractor);
|
||||
private <T, Z extends NBTBase> TagAdapter<T, Z> createAdapter(Class<T> primitiveType, Class<Z> nbtBaseType, Function<T, Z> builder, Function<Z, T> extractor) {
|
||||
return new TagAdapter<>(primitiveType, nbtBaseType, builder, extractor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,7 +175,9 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* @param type the type of the passed value
|
||||
* @param value the value to be stored in the tag
|
||||
* @param <T> the generic type of the value
|
||||
*
|
||||
* @return the created tag instance
|
||||
*
|
||||
* @throws IllegalArgumentException if no suitable tag type adapter for this
|
||||
* type was found
|
||||
*/
|
||||
|
@ -183,7 +191,9 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* @param type the type of the primitive value
|
||||
* @param base the base instance to check
|
||||
* @param <T> the generic type of the type
|
||||
*
|
||||
* @return if the base stores values of the primitive type passed
|
||||
*
|
||||
* @throws IllegalArgumentException if no suitable tag type adapter for this
|
||||
* type was found
|
||||
*/
|
||||
|
@ -197,7 +207,9 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* @param type the type of the value to extract
|
||||
* @param tag the tag to extract the value from
|
||||
* @param <T> the generic type of the value stored inside the tag
|
||||
*
|
||||
* @return the extracted value
|
||||
*
|
||||
* @throws IllegalArgumentException if the passed base is not an instanced
|
||||
* of the defined base type and therefore is not applicable to the extractor
|
||||
* function
|
||||
|
@ -207,7 +219,7 @@ public final class CraftCustomTagTypeRegistry {
|
|||
* type was found
|
||||
*/
|
||||
public <T> T extract(Class<T> type, NBTBase tag) throws ClassCastException, IllegalArgumentException {
|
||||
CustomTagAdapter adapter = this.adapters.computeIfAbsent(type, CREATE_ADAPTER);
|
||||
TagAdapter adapter = this.adapters.computeIfAbsent(type, CREATE_ADAPTER);
|
||||
Validate.isTrue(adapter.isInstance(tag), "`The found tag instance cannot store %s as it is a %s", type.getSimpleName(), tag.getClass().getSimpleName());
|
||||
|
||||
Object foundValue = adapter.extract(tag);
|
|
@ -4,18 +4,13 @@ import static org.junit.Assert.*;
|
|||
import java.io.StringReader;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.NBTBase;
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
import net.minecraft.server.NBTTagIntArray;
|
||||
import net.minecraft.server.NBTTagList;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.craftbukkit.inventory.tags.CraftCustomItemTagContainer;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
|
@ -25,7 +20,7 @@ import org.bukkit.support.AbstractTestingBase;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ItemMetaCustomValueTest extends AbstractTestingBase {
|
||||
public class DeprecatedItemMetaCustomValueTest extends AbstractTestingBase {
|
||||
|
||||
private static NamespacedKey VALID_KEY;
|
||||
|
||||
|
@ -166,12 +161,6 @@ public class ItemMetaCustomValueTest extends AbstractTestingBase {
|
|||
CustomItemTagContainer innerContainer = itemMeta.getCustomTagContainer().getAdapterContext().newTagContainer(); //Add a inner container
|
||||
innerContainer.setCustomTag(VALID_KEY, ItemTagType.LONG, 5L);
|
||||
itemMeta.getCustomTagContainer().setCustomTag(requestKey("custom-inner-compound"), ItemTagType.TAG_CONTAINER, innerContainer);
|
||||
|
||||
Map<String, NBTBase> rawMap = ((CraftCustomItemTagContainer) itemMeta.getCustomTagContainer()).getRaw(); //Adds a tag list as well (even tho is has no API yet)
|
||||
NBTTagList nbtList = new NBTTagList();
|
||||
nbtList.add(new NBTTagIntArray(Arrays.asList(1, 5, 3)));
|
||||
nbtList.add(new NBTTagIntArray(Arrays.asList(42, 51)));
|
||||
rawMap.put("nbttaglist", nbtList);
|
||||
return itemMeta;
|
||||
}
|
||||
|
|
@ -0,0 +1,313 @@
|
|||
package org.bukkit.craftbukkit.inventory;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Array;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.server.NBTTagCompound;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.persistence.PersistentDataAdapterContext;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.support.AbstractTestingBase;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PersistentDataContainerTest extends AbstractTestingBase {
|
||||
|
||||
private static NamespacedKey VALID_KEY;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
VALID_KEY = new NamespacedKey("test", "validkey");
|
||||
}
|
||||
|
||||
/*
|
||||
Sets a test
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testSetNoAdapter() {
|
||||
ItemMeta itemMeta = createNewItemMeta();
|
||||
itemMeta.getPersistentDataContainer().set(VALID_KEY, new PrimitiveTagType<>(boolean.class), true);
|
||||
}
|
||||
|
||||
/*
|
||||
Contains a tag
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testHasNoAdapter() {
|
||||
ItemMeta itemMeta = createNewItemMeta();
|
||||
itemMeta.getPersistentDataContainer().set(VALID_KEY, PersistentDataType.INTEGER, 1); // We gotta set this so we at least try to compare it
|
||||
itemMeta.getPersistentDataContainer().has(VALID_KEY, new PrimitiveTagType<>(boolean.class));
|
||||
}
|
||||
|
||||
/*
|
||||
Getting a tag
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetNoAdapter() {
|
||||
ItemMeta itemMeta = createNewItemMeta();
|
||||
itemMeta.getPersistentDataContainer().set(VALID_KEY, PersistentDataType.INTEGER, 1); //We gotta set this so we at least try to compare it
|
||||
itemMeta.getPersistentDataContainer().get(VALID_KEY, new PrimitiveTagType<>(boolean.class));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void testGetWrongType() {
|
||||
ItemMeta itemMeta = createNewItemMeta();
|
||||
itemMeta.getPersistentDataContainer().set(VALID_KEY, PersistentDataType.INTEGER, 1);
|
||||
itemMeta.getPersistentDataContainer().get(VALID_KEY, PersistentDataType.STRING);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifferentNamespace() {
|
||||
NamespacedKey namespacedKeyA = new NamespacedKey("plugin-a", "damage");
|
||||
NamespacedKey namespacedKeyB = new NamespacedKey("plugin-b", "damage");
|
||||
|
||||
ItemMeta meta = createNewItemMeta();
|
||||
meta.getPersistentDataContainer().set(namespacedKeyA, PersistentDataType.LONG, 15L);
|
||||
meta.getPersistentDataContainer().set(namespacedKeyB, PersistentDataType.LONG, 160L);
|
||||
|
||||
assertEquals(15L, (long) meta.getPersistentDataContainer().get(namespacedKeyA, PersistentDataType.LONG));
|
||||
assertEquals(160L, (long) meta.getPersistentDataContainer().get(namespacedKeyB, PersistentDataType.LONG));
|
||||
}
|
||||
|
||||
private ItemMeta createNewItemMeta() {
|
||||
return Bukkit.getItemFactory().getItemMeta(Material.DIAMOND_PICKAXE);
|
||||
}
|
||||
|
||||
private NamespacedKey requestKey(String keyName) {
|
||||
return new NamespacedKey("test-plugin", keyName.toLowerCase());
|
||||
}
|
||||
|
||||
/*
|
||||
Removing a tag
|
||||
*/
|
||||
@Test
|
||||
public void testNBTTagStoring() {
|
||||
CraftMetaItem itemMeta = createComplexItemMeta();
|
||||
|
||||
NBTTagCompound compound = new NBTTagCompound();
|
||||
itemMeta.applyToItem(compound);
|
||||
|
||||
assertEquals(itemMeta, new CraftMetaItem(compound));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMapStoring() {
|
||||
CraftMetaItem itemMeta = createComplexItemMeta();
|
||||
|
||||
Map<String, Object> serialize = itemMeta.serialize();
|
||||
assertEquals(itemMeta, new CraftMetaItem(serialize));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testYAMLStoring() {
|
||||
ItemStack stack = new ItemStack(Material.DIAMOND);
|
||||
CraftMetaItem meta = createComplexItemMeta();
|
||||
stack.setItemMeta(meta);
|
||||
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
configuration.set("testpath", stack);
|
||||
|
||||
String configValue = configuration.saveToString();
|
||||
YamlConfiguration loadedConfig = YamlConfiguration.loadConfiguration(new StringReader(configValue));
|
||||
|
||||
assertEquals(stack, loadedConfig.getSerializable("testpath", ItemStack.class));
|
||||
assertNotEquals(new ItemStack(Material.DIAMOND), loadedConfig.getSerializable("testpath", ItemStack.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectType() {
|
||||
ItemStack stack = new ItemStack(Material.DIAMOND);
|
||||
CraftMetaItem meta = createComplexItemMeta();
|
||||
|
||||
meta.getPersistentDataContainer().set(requestKey("int"), PersistentDataType.STRING, "1");
|
||||
meta.getPersistentDataContainer().set(requestKey("double"), PersistentDataType.STRING, "1.33");
|
||||
stack.setItemMeta(meta);
|
||||
|
||||
YamlConfiguration configuration = new YamlConfiguration();
|
||||
configuration.set("testpath", stack);
|
||||
|
||||
String configValue = configuration.saveToString();
|
||||
YamlConfiguration loadedConfig = YamlConfiguration.loadConfiguration(new StringReader(configValue));
|
||||
ItemStack newStack = loadedConfig.getSerializable("testpath", ItemStack.class);
|
||||
|
||||
assertTrue(newStack.getItemMeta().getPersistentDataContainer().has(requestKey("int"), PersistentDataType.STRING));
|
||||
assertEquals(newStack.getItemMeta().getPersistentDataContainer().get(requestKey("int"), PersistentDataType.STRING), "1");
|
||||
|
||||
assertTrue(newStack.getItemMeta().getPersistentDataContainer().has(requestKey("double"), PersistentDataType.STRING));
|
||||
assertEquals(newStack.getItemMeta().getPersistentDataContainer().get(requestKey("double"), PersistentDataType.STRING), "1.33");
|
||||
}
|
||||
|
||||
private CraftMetaItem createComplexItemMeta() {
|
||||
CraftMetaItem itemMeta = (CraftMetaItem) createNewItemMeta();
|
||||
itemMeta.setDisplayName("Item Display Name");
|
||||
|
||||
itemMeta.getPersistentDataContainer().set(requestKey("custom-long"), PersistentDataType.LONG, 4L); //Add random primitive values
|
||||
itemMeta.getPersistentDataContainer().set(requestKey("custom-byte-array"), PersistentDataType.BYTE_ARRAY, new byte[]{
|
||||
0, 1, 2, 10
|
||||
});
|
||||
itemMeta.getPersistentDataContainer().set(requestKey("custom-string"), PersistentDataType.STRING, "Hello there world");
|
||||
itemMeta.getPersistentDataContainer().set(requestKey("custom-int"), PersistentDataType.INTEGER, 3);
|
||||
itemMeta.getPersistentDataContainer().set(requestKey("custom-double"), PersistentDataType.DOUBLE, 3.123);
|
||||
|
||||
PersistentDataContainer innerContainer = itemMeta.getPersistentDataContainer().getAdapterContext().newPersistentDataContainer(); //Add a inner container
|
||||
innerContainer.set(VALID_KEY, PersistentDataType.LONG, 5L);
|
||||
itemMeta.getPersistentDataContainer().set(requestKey("custom-inner-compound"), PersistentDataType.TAG_CONTAINER, innerContainer);
|
||||
return itemMeta;
|
||||
}
|
||||
|
||||
/*
|
||||
Test complex object storage
|
||||
*/
|
||||
@Test
|
||||
public void storeUUIDOnItemTest() {
|
||||
ItemMeta itemMeta = createNewItemMeta();
|
||||
UUIDPersistentDataType uuidPersistentDataType = new UUIDPersistentDataType();
|
||||
UUID uuid = UUID.fromString("434eea72-22a6-4c61-b5ef-945874a5c478");
|
||||
|
||||
itemMeta.getPersistentDataContainer().set(VALID_KEY, uuidPersistentDataType, uuid);
|
||||
assertTrue(itemMeta.getPersistentDataContainer().has(VALID_KEY, uuidPersistentDataType));
|
||||
assertEquals(uuid, itemMeta.getPersistentDataContainer().get(VALID_KEY, uuidPersistentDataType));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encapsulatedContainers() {
|
||||
NamespacedKey innerKey = new NamespacedKey("plugin-a", "inner");
|
||||
|
||||
ItemMeta meta = createNewItemMeta();
|
||||
PersistentDataAdapterContext context = meta.getPersistentDataContainer().getAdapterContext();
|
||||
|
||||
PersistentDataContainer thirdContainer = context.newPersistentDataContainer();
|
||||
thirdContainer.set(VALID_KEY, PersistentDataType.LONG, 3L);
|
||||
|
||||
PersistentDataContainer secondContainer = context.newPersistentDataContainer();
|
||||
secondContainer.set(VALID_KEY, PersistentDataType.LONG, 2L);
|
||||
secondContainer.set(innerKey, PersistentDataType.TAG_CONTAINER, thirdContainer);
|
||||
|
||||
meta.getPersistentDataContainer().set(VALID_KEY, PersistentDataType.LONG, 1L);
|
||||
meta.getPersistentDataContainer().set(innerKey, PersistentDataType.TAG_CONTAINER, secondContainer);
|
||||
|
||||
assertEquals(3L, meta.getPersistentDataContainer()
|
||||
.get(innerKey, PersistentDataType.TAG_CONTAINER)
|
||||
.get(innerKey, PersistentDataType.TAG_CONTAINER)
|
||||
.get(VALID_KEY, PersistentDataType.LONG).longValue());
|
||||
|
||||
assertEquals(2L, meta.getPersistentDataContainer()
|
||||
.get(innerKey, PersistentDataType.TAG_CONTAINER)
|
||||
.get(VALID_KEY, PersistentDataType.LONG).longValue());
|
||||
|
||||
assertEquals(1L, meta.getPersistentDataContainer()
|
||||
.get(VALID_KEY, PersistentDataType.LONG).longValue());
|
||||
}
|
||||
|
||||
class UUIDPersistentDataType implements PersistentDataType<byte[], UUID> {
|
||||
|
||||
@Override
|
||||
public Class<byte[]> getPrimitiveType() {
|
||||
return byte[].class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<UUID> getComplexType() {
|
||||
return UUID.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toPrimitive(UUID complex, PersistentDataAdapterContext context) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
bb.putLong(complex.getMostSignificantBits());
|
||||
bb.putLong(complex.getLeastSignificantBits());
|
||||
return bb.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID fromPrimitive(byte[] primitive, PersistentDataAdapterContext context) {
|
||||
ByteBuffer bb = ByteBuffer.wrap(primitive);
|
||||
long firstLong = bb.getLong();
|
||||
long secondLong = bb.getLong();
|
||||
return new UUID(firstLong, secondLong);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveCustomTags() {
|
||||
ItemMeta itemMeta = createNewItemMeta();
|
||||
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.BYTE, (byte) 1);
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.SHORT, (short) 1);
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.INTEGER, 1);
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.LONG, 1L);
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.FLOAT, 1.34F);
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.DOUBLE, 151.123);
|
||||
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.STRING, "test");
|
||||
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.BYTE_ARRAY, new byte[]{
|
||||
1, 4, 2, Byte.MAX_VALUE
|
||||
});
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.INTEGER_ARRAY, new int[]{
|
||||
1, 4, 2, Integer.MAX_VALUE
|
||||
});
|
||||
testPrimitiveCustomTag(itemMeta, PersistentDataType.LONG_ARRAY, new long[]{
|
||||
1L, 4L, 2L, Long.MAX_VALUE
|
||||
});
|
||||
}
|
||||
|
||||
private <T, Z> void testPrimitiveCustomTag(ItemMeta meta, PersistentDataType<T, Z> type, Z value) {
|
||||
NamespacedKey tagKey = new NamespacedKey("test", String.valueOf(type.hashCode()));
|
||||
|
||||
meta.getPersistentDataContainer().set(tagKey, type, value);
|
||||
assertTrue(meta.getPersistentDataContainer().has(tagKey, type));
|
||||
|
||||
Z foundValue = meta.getPersistentDataContainer().get(tagKey, type);
|
||||
if (foundValue.getClass().isArray()) { // Compare arrays using reflection access
|
||||
int length = Array.getLength(foundValue);
|
||||
int originalLength = Array.getLength(value);
|
||||
for (int i = 0; i < length && i < originalLength; i++) {
|
||||
assertEquals(Array.get(value, i), Array.get(foundValue, i));
|
||||
}
|
||||
} else {
|
||||
assertEquals(foundValue, value);
|
||||
}
|
||||
|
||||
meta.getPersistentDataContainer().remove(tagKey);
|
||||
assertFalse(meta.getPersistentDataContainer().has(tagKey, type));
|
||||
}
|
||||
|
||||
class PrimitiveTagType<T> implements PersistentDataType<T, T> {
|
||||
|
||||
private final Class<T> primitiveType;
|
||||
|
||||
PrimitiveTagType(Class<T> primitiveType) {
|
||||
this.primitiveType = primitiveType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getPrimitiveType() {
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<T> getComplexType() {
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T toPrimitive(T complex, PersistentDataAdapterContext context) {
|
||||
return complex;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T fromPrimitive(T primitive, PersistentDataAdapterContext context) {
|
||||
return primitive;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue