Improve tag API

This commit is contained in:
TheMode 2021-06-22 02:51:04 +02:00
parent 1f2dc0cd9f
commit a9086e83f2
6 changed files with 41 additions and 32 deletions

View File

@ -117,11 +117,6 @@ public class ItemMeta implements TagReadable, Writeable {
return tag.read(nbt); return tag.read(nbt);
} }
@Override
public boolean hasTag(@NotNull Tag<?> tag) {
return nbt.containsKey(tag.getKey());
}
public @NotNull NBTCompound toNBT() { public @NotNull NBTCompound toNBT() {
return nbt.deepClone(); return nbt.deepClone();
} }

View File

@ -203,11 +203,6 @@ public final class ItemStack implements TagReadable, HoverEventSource<HoverEvent
return meta.getTag(tag); return meta.getTag(tag);
} }
@Override
public boolean hasTag(@NotNull Tag<?> tag) {
return meta.hasTag(tag);
}
@Override @Override
public @NotNull HoverEvent<HoverEvent.ShowItem> asHoverEvent(@NotNull UnaryOperator<HoverEvent.ShowItem> op) { public @NotNull HoverEvent<HoverEvent.ShowItem> asHoverEvent(@NotNull UnaryOperator<HoverEvent.ShowItem> op) {
return HoverEvent.showItem(op.apply(HoverEvent.ShowItem.of(this.material, return HoverEvent.showItem(op.apply(HoverEvent.ShowItem.of(this.material,

View File

@ -21,6 +21,8 @@ import java.util.function.Supplier;
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
public class Tag<T> { public class Tag<T> {
private static final String EMPTY_KEY = "";
private final String key; private final String key;
private final Function<NBTCompound, T> readFunction; private final Function<NBTCompound, T> readFunction;
private final BiConsumer<NBTCompound, T> writeConsumer; private final BiConsumer<NBTCompound, T> writeConsumer;
@ -60,7 +62,7 @@ public class Tag<T> {
@Contract(value = "_, _ -> new", pure = true) @Contract(value = "_, _ -> new", pure = true)
public <R> Tag<R> map(@NotNull Function<T, R> readMap, public <R> Tag<R> map(@NotNull Function<T, R> readMap,
@NotNull Function<R, T> writeMap) { @NotNull Function<R, T> writeMap) {
return new Tag<R>(key, return new Tag<>(key,
// Read // Read
nbtCompound -> { nbtCompound -> {
final var old = readFunction.apply(nbtCompound); final var old = readFunction.apply(nbtCompound);
@ -85,22 +87,26 @@ public class Tag<T> {
} }
public @Nullable T read(@NotNull NBTCompound nbtCompound) { public @Nullable T read(@NotNull NBTCompound nbtCompound) {
if (nbtCompound.containsKey(key)) { T result = readFunction.apply(nbtCompound);
return readFunction.apply(nbtCompound); if (result == null) {
} else {
final var supplier = defaultValue; final var supplier = defaultValue;
return supplier != null ? supplier.get() : null; result = supplier != null ? supplier.get() : null;
} }
return result;
} }
public void write(@NotNull NBTCompound nbtCompound, @Nullable T value) { public void write(@NotNull NBTCompound nbtCompound, @Nullable T value) {
if (value != null) { if (value != null || key.equals(EMPTY_KEY)) {
this.writeConsumer.accept(nbtCompound, value); this.writeConsumer.accept(nbtCompound, value);
} else { } else {
nbtCompound.removeTag(key); nbtCompound.removeTag(key);
} }
} }
public void writeUnsafe(@NotNull NBTCompound nbtCompound, @Nullable Object value) {
write(nbtCompound, (T) value);
}
public static @NotNull Tag<Byte> Byte(@NotNull String key) { public static @NotNull Tag<Byte> Byte(@NotNull String key) {
return new Tag<>(key, return new Tag<>(key,
nbtCompound -> nbtCompound.getByte(key), nbtCompound -> nbtCompound.getByte(key),
@ -149,17 +155,15 @@ public class Tag<T> {
(nbtCompound, value) -> nbtCompound.setString(key, value)); (nbtCompound, value) -> nbtCompound.setString(key, value));
} }
public static @NotNull Tag<NBT> NBT(@NotNull String key) { public static <T extends NBT> @NotNull Tag<T> NBT(@NotNull String key) {
return new Tag<>(key, return new Tag<>(key,
nbt -> { nbt -> {
var currentNBT = nbt.get(key); final var currentNBT = nbt.get(key);
// Avoid a NPE when cloning a null variable. // Avoid a NPE when cloning a null variable.
if (currentNBT == null) { if (currentNBT == null) {
return null; return null;
} }
return (T) currentNBT.deepClone();
return currentNBT.deepClone();
}, },
((nbt, value) -> nbt.set(key, value.deepClone()))); ((nbt, value) -> nbt.set(key, value.deepClone())));
} }
@ -176,7 +180,15 @@ public class Tag<T> {
(nbtCompound, value) -> nbtCompound.setLongArray(key, value)); (nbtCompound, value) -> nbtCompound.setLongArray(key, value));
} }
public static <T> @NotNull Tag<T> Custom(@NotNull String key, @NotNull TagSerializer<T> serializer) { /**
* Create a wrapper around a compound.
*
* @param key the tag key
* @param serializer the tag serializer
* @param <T> the tag type
* @return the created tag
*/
public static <T> @NotNull Tag<T> Structure(@NotNull String key, @NotNull TagSerializer<T> serializer) {
return new Tag<>(key, return new Tag<>(key,
nbtCompound -> { nbtCompound -> {
final var compound = nbtCompound.getCompound(key); final var compound = nbtCompound.getCompound(key);
@ -194,4 +206,10 @@ public class Tag<T> {
serializer.write(TagWritable.fromCompound(compound), value); serializer.write(TagWritable.fromCompound(compound), value);
}); });
} }
public static <T> @NotNull Tag<T> View(@NotNull TagSerializer<T> serializer) {
return new Tag<>(EMPTY_KEY,
nbtCompound -> serializer.read(TagReadable.fromCompound(nbtCompound)),
(nbtCompound, value) -> serializer.write(TagWritable.fromCompound(nbtCompound), value));
}
} }

View File

@ -24,7 +24,9 @@ public interface TagReadable {
* @param tag the tag to check * @param tag the tag to check
* @return true if the tag is present, false otherwise * @return true if the tag is present, false otherwise
*/ */
boolean hasTag(@NotNull Tag<?> tag); default boolean hasTag(@NotNull Tag<?> tag) {
return getTag(tag) != null;
}
/** /**
* Converts an nbt compound to a tag reader. * Converts an nbt compound to a tag reader.
@ -38,11 +40,6 @@ public interface TagReadable {
public <T> @Nullable T getTag(@NotNull Tag<T> tag) { public <T> @Nullable T getTag(@NotNull Tag<T> tag) {
return tag.read(compound); return tag.read(compound);
} }
@Override
public boolean hasTag(@NotNull Tag<?> tag) {
return compound.containsKey(tag.getKey());
}
}; };
} }
} }

View File

@ -4,7 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
* Interface used to create custom types compatible with {@link Tag#Custom(String, TagSerializer)}. * Interface used to create custom {@link Tag tags}.
* *
* @param <T> the type to serialize * @param <T> the type to serialize
*/ */
@ -14,7 +14,7 @@ public interface TagSerializer<T> {
* Reads the custom tag from a {@link TagReadable}. * Reads the custom tag from a {@link TagReadable}.
* *
* @param reader the reader * @param reader the reader
* @return the deserialized value * @return the deserialized value, null if invalid
*/ */
@Nullable T read(@NotNull TagReadable reader); @Nullable T read(@NotNull TagReadable reader);
@ -22,7 +22,7 @@ public interface TagSerializer<T> {
* Writes the custom tag to a {@link TagWritable}. * Writes the custom tag to a {@link TagWritable}.
* *
* @param writer the writer * @param writer the writer
* @param value the value to serialize * @param value the value to serialize, null to remove
*/ */
void write(@NotNull TagWritable writer, @NotNull T value); void write(@NotNull TagWritable writer, @Nullable T value);
} }

View File

@ -18,6 +18,10 @@ public interface TagWritable {
*/ */
<T> void setTag(@NotNull Tag<T> tag, @Nullable T value); <T> void setTag(@NotNull Tag<T> tag, @Nullable T value);
default void removeTag(@NotNull Tag<?> tag) {
setTag(tag, null);
}
/** /**
* Converts an nbt compound to a tag writer. * Converts an nbt compound to a tag writer.
* *