diff --git a/src/main/java/com/comphenix/protocol/events/AbstractStructure.java b/src/main/java/com/comphenix/protocol/events/AbstractStructure.java index e7ebb6a22..43746ebd2 100644 --- a/src/main/java/com/comphenix/protocol/events/AbstractStructure.java +++ b/src/main/java/com/comphenix/protocol/events/AbstractStructure.java @@ -1,10 +1,5 @@ package com.comphenix.protocol.events; -import javax.annotation.Nonnull; -import java.lang.reflect.Array; -import java.time.Instant; -import java.util.*; - import com.comphenix.protocol.PacketType; import com.comphenix.protocol.reflect.EquivalentConverter; import com.comphenix.protocol.reflect.StructureModifier; @@ -17,7 +12,6 @@ import com.comphenix.protocol.wrappers.nbt.NbtCompound; import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.google.common.base.Preconditions; - import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.Sound; @@ -31,6 +25,11 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import javax.annotation.Nonnull; +import java.lang.reflect.Array; +import java.time.Instant; +import java.util.*; + public abstract class AbstractStructure { protected transient Object handle; protected transient StructureModifier structureModifier; @@ -410,7 +409,7 @@ public StructureModifier> getBlockPositionCollectionModifier } /** - * Retrieves a read/write structure for collections of watchable objects. + * Retrieves a read/write structure for collections of watchable objects before Minecraft 1.19.3. *

* This modifier will automatically marshal between the visible WrappedWatchableObject and the * internal Minecraft WatchableObject. @@ -424,7 +423,7 @@ public StructureModifier> getWatchableCollectionMod } /** - * Retrieves a read/write structure for collections of data values. + * Retrieves a read/write structure for collections of data values for Minecraft 1.19.3 or later. * @return A modifier for data values. */ public StructureModifier> getDataValueCollectionModifier() { diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedDataValue.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedDataValue.java index f87c9010c..a4421be2a 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/WrappedDataValue.java +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedDataValue.java @@ -9,6 +9,7 @@ /** * Represents a DataValue in 1.19.3+. + * Use {@link WrappedWatchableObject} before 1.19.3. */ public class WrappedDataValue extends AbstractWrapper { @@ -29,10 +30,28 @@ public WrappedDataValue(Object handle) { this.modifier = new StructureModifier<>(this.handleType).withTarget(handle); } + /** + * Creates a new WrappedDataValue from a NMS value. + * ProtocolLib wrappers are not supported as arguments. + * If implicit unwrapping of wrappers is required, use {@link WrappedDataValue#fromWrappedValue(int, Serializer, Object)}. + * @param index the index of the metadata value + * @param serializer the serializer corresponding for serializing. Can be null. + * @param value The raw value for the DataValue. Can be null. + */ public WrappedDataValue(int index, Serializer serializer, Object value) { this(newHandle(index, serializer, value)); } + /** + * Creates a new WrappedDataValue from a possibly wrapped value and implicitly unwrap value if possible. + * @param index the index of the metadata value + * @param serializer the serializer corresponding for serializing. Can be null. + * @param value The value for the DataValue. Can be null. + */ + public static WrappedDataValue fromWrappedValue(int index, Serializer serializer, Object value) { + return new WrappedDataValue(index, serializer, value == null ? null : WrappedWatchableObject.getUnwrapped(value)); + } + private static Object newHandle(int index, Serializer serializer, Object value) { if (constructor == null) { constructor = Accessors.getConstructorAccessor(HANDLE_TYPE.getConstructors()[0]); @@ -41,14 +60,26 @@ private static Object newHandle(int index, Serializer serializer, Object value) return constructor.invoke(index, serializer.getHandle(), value); } + /** + * Returns the entity-type specific index of this DataValue + * @return index of the DataValue + */ public int getIndex() { return this.modifier.withType(int.class).read(0); } + /** + * Sets the entity-type specific index of this DataValue + * @param index New index of the DataValue + */ public void setIndex(int index) { this.modifier.withType(int.class).write(0, index); } + /** + * Returns the current serializer for this DataValue. + * @return serializer + */ public Serializer getSerializer() { Object serializer = this.modifier.readSafely(1); if (serializer != null) { @@ -63,22 +94,42 @@ public Serializer getSerializer() { } } + /** + * Changes the serializer for this DataValue + * @param serializer serializer + */ public void setSerializer(Serializer serializer) { this.modifier.writeSafely(1, serializer == null ? null : serializer.getHandle()); } + /** + * Returns the current value associated and implicitly wraps it to corresponding ProtocolLib wrappers if possible. + * @return Current value + */ public Object getValue() { return WrappedWatchableObject.getWrapped(getRawValue()); } + /** + * Sets the current value associated and implicitly unwraps it to NMS types if a ProtocolLib wrapper is provided. + * @param value New value for this DataValue + */ public void setValue(Object value) { setRawValue(WrappedWatchableObject.getUnwrapped(value)); } + /** + * Returns the current, raw value. + * @return Raw value (not wrapped) + */ public Object getRawValue() { return this.modifier.readSafely(2); } + /** + * Updates the raw value for this DataValue. No unwrapping will be applied. + * @param value NMS value + */ public void setRawValue(Object value) { this.modifier.writeSafely(2, value); } diff --git a/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java b/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java index d4f662774..bc42bda3c 100644 --- a/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java +++ b/src/main/java/com/comphenix/protocol/wrappers/WrappedWatchableObject.java @@ -14,8 +14,6 @@ */ package com.comphenix.protocol.wrappers; -import static com.comphenix.protocol.utility.MinecraftReflection.is; - import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.reflect.accessors.Accessors; import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; @@ -25,12 +23,15 @@ import com.comphenix.protocol.wrappers.WrappedDataWatcher.WrappedDataWatcherObject; import com.comphenix.protocol.wrappers.nbt.NbtCompound; import com.comphenix.protocol.wrappers.nbt.NbtFactory; -import java.util.Optional; import org.bukkit.inventory.ItemStack; +import java.util.Optional; + +import static com.comphenix.protocol.utility.MinecraftReflection.is; + /** - * Represents a DataWatcher Item in 1.8 to 1.10. - * + * Represents a DataWatcher Item in 1.8 to 1.19.2. + * Use {@link WrappedDataValue} for 1.19.3 or later. * @author dmulloy2 */ public class WrappedWatchableObject extends AbstractWrapper { @@ -97,6 +98,9 @@ private static Object newHandle(WrappedDataWatcherObject watcherObject, Object v * @return The wrapped object. */ static Object getWrapped(Object value) { + if(value == null) { + return null; + } // Handle watcher items first if (is(MinecraftReflection.getDataWatcherItemClass(), value)) { return getWrapped(new WrappedWatchableObject(value).getRawValue()); @@ -135,6 +139,9 @@ static Object getWrapped(Object value) { */ // Must be kept in sync with getWrapped! static Object getUnwrapped(Object wrapped) { + if(wrapped == null) { + return null; + } if (wrapped instanceof Optional) { return ((Optional) wrapped).map(WrappedWatchableObject::getUnwrapped); }