4.4.0: Add generic type to ListTag

This commit is contained in:
Nassim Jahnke 2024-03-07 11:02:11 +01:00
parent 9f71f9b978
commit 45506291a3
No known key found for this signature in database
GPG Key ID: EF6771C01F6EF02F
16 changed files with 111 additions and 61 deletions

View File

@ -5,7 +5,7 @@
<groupId>com.viaversion</groupId>
<artifactId>nbt</artifactId>
<version>4.3.0</version>
<version>4.4.0</version>
<packaging>jar</packaging>
<name>ViaNBT</name>

View File

@ -76,7 +76,7 @@ final class TagStringReader {
throw this.buffer.makeError("Unterminated compound tag!");
}
public ListTag list() throws StringifiedTagParseException {
public ListTag<?> list() throws StringifiedTagParseException {
final ListTag listTag = new ListTag();
this.buffer.expect(Tokens.ARRAY_BEGIN);
final boolean prefixedIndex = this.acceptLegacy && this.buffer.peek() == '0' && this.buffer.peek(1) == ':';

View File

@ -102,7 +102,7 @@ final class TagStringWriter {
return this;
}
private TagStringWriter writeList(final ListTag tag) {
private TagStringWriter writeList(final ListTag<?> tag) {
this.beginList();
for (final Tag el : tag) {
this.printAndResetSeparator();

View File

@ -9,7 +9,7 @@ import java.util.Arrays;
/**
* A tag containing a byte array.
*/
public class ByteArrayTag extends NumberArrayTag {
public final class ByteArrayTag extends NumberArrayTag {
public static final int ID = 7;
private static final byte[] EMPTY_ARRAY = new byte[0];
private byte[] value;
@ -90,8 +90,8 @@ public class ByteArrayTag extends NumberArrayTag {
}
@Override
public ListTag toListTag() {
final ListTag list = new ListTag(ByteTag.class);
public ListTag<ByteTag> toListTag() {
final ListTag<ByteTag> list = new ListTag<>(ByteTag.class);
for (final byte b : this.value) {
list.add(new ByteTag(b));
}

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing a byte.
*/
public class ByteTag extends NumberTag {
public final class ByteTag extends NumberTag {
public static final int ID = 1;
private byte value;

View File

@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable;
/**
* A compound tag containing other tags.
*/
public class CompoundTag extends Tag implements Iterable<Entry<String, Tag>> {
public final class CompoundTag extends Tag implements Iterable<Entry<String, Tag>> {
public static final int ID = 10;
private Map<String, Tag> value;
@ -152,9 +152,31 @@ public class CompoundTag extends Tag implements Iterable<Entry<String, Tag>> {
return tag instanceof CompoundTag ? (CompoundTag) tag : null;
}
public @Nullable ListTag getListTag(String tagName) {
public @Nullable ListTag<?> getListTag(String tagName) {
final Tag tag = this.value.get(tagName);
return tag instanceof ListTag ? (ListTag) tag : null;
return tag instanceof ListTag<?> ? (ListTag<?>) tag : null;
}
public <T extends Tag> @Nullable ListTag<T> getListTag(String tagName, Class<T> type) {
final Tag tag = this.value.get(tagName);
if (!(tag instanceof ListTag<?>)) {
return null;
}
final Class<? extends Tag> elementType = ((ListTag<?>) tag).getElementType();
//noinspection unchecked
return elementType == type || elementType == null ? (ListTag<T>) tag : null;
}
public @Nullable ListTag<? extends NumberTag> getNumberListTag(String tagName) {
final Tag tag = this.value.get(tagName);
if (!(tag instanceof ListTag<?>)) {
return null;
}
final Class<? extends Tag> elementType = ((ListTag<?>) tag).getElementType();
//noinspection unchecked
return elementType == null || NumberTag.class.isAssignableFrom(elementType) ? (ListTag<? extends NumberTag>) tag : null;
}
public @Nullable NumberTag getNumberTag(String tagName) {

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing a double.
*/
public class DoubleTag extends NumberTag {
public final class DoubleTag extends NumberTag {
public static final int ID = 6;
private double value;

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing a float.
*/
public class FloatTag extends NumberTag {
public final class FloatTag extends NumberTag {
public static final int ID = 5;
private float value;

View File

@ -9,7 +9,7 @@ import java.util.Arrays;
/**
* A tag containing an integer array.
*/
public class IntArrayTag extends NumberArrayTag {
public final class IntArrayTag extends NumberArrayTag {
public static final int ID = 11;
private static final int[] EMPTY_ARRAY = new int[0];
private int[] value;
@ -91,8 +91,8 @@ public class IntArrayTag extends NumberArrayTag {
}
@Override
public ListTag toListTag() {
final ListTag list = new ListTag();
public ListTag<IntTag> toListTag() {
final ListTag<IntTag> list = new ListTag<>(IntTag.class);
for (final int i : this.value) {
list.add(new IntTag(i));
}

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing an integer.
*/
public class IntTag extends NumberTag {
public final class IntTag extends NumberTag {
public static final int ID = 3;
private int value;

View File

@ -14,14 +14,15 @@ import org.jetbrains.annotations.Nullable;
/**
* A tag containing a list of tags.
*/
public class ListTag extends Tag implements Iterable<Tag> {
public final class ListTag<T extends Tag> extends Tag implements Iterable<T> {
public static final int ID = 9;
private List<Tag> value;
private Class<? extends Tag> type;
private Class<T> type;
private List<T> value;
/**
* Creates an empty list tag and no defined type.
*/
@Deprecated
public ListTag() {
this.value = new ArrayList<>();
}
@ -31,7 +32,7 @@ public class ListTag extends Tag implements Iterable<Tag> {
*
* @param type Tag type of the list.
*/
public ListTag(@Nullable Class<? extends Tag> type) {
public ListTag(Class<T> type) {
this.type = type;
this.value = new ArrayList<>();
}
@ -43,11 +44,11 @@ public class ListTag extends Tag implements Iterable<Tag> {
* @param value The value of the tag.
* @throws IllegalArgumentException If all tags in the list are not of the same type.
*/
public ListTag(List<Tag> value) throws IllegalArgumentException {
public ListTag(List<T> value) {
this.setValue(value);
}
public static ListTag read(DataInput in, TagLimiter tagLimiter, int nestingLevel) throws IOException {
public static ListTag<?> read(DataInput in, TagLimiter tagLimiter, int nestingLevel) throws IOException {
tagLimiter.checkLevel(nestingLevel);
tagLimiter.countBytes(Byte.BYTES + Integer.BYTES);
@ -59,14 +60,18 @@ public class ListTag extends Tag implements Iterable<Tag> {
throw new IOException("Unknown tag ID in ListTag: " + id);
}
}
return read(in, id, type, tagLimiter, nestingLevel);
}
ListTag listTag = new ListTag(type);
private static <T extends Tag> ListTag<T> read(DataInput in, int id, Class<T> type, TagLimiter tagLimiter, int nestingLevel) throws IOException {
ListTag<T> listTag = new ListTag<>(type);
int count = in.readInt();
int newNestingLevel = nestingLevel + 1;
for (int index = 0; index < count; index++) {
Tag tag;
T tag;
try {
tag = TagRegistry.read(id, in, tagLimiter, newNestingLevel);
//noinspection unchecked
tag = (T) TagRegistry.read(id, in, tagLimiter, newNestingLevel);
} catch (IllegalArgumentException e) {
throw new IOException("Failed to create tag.", e);
}
@ -76,7 +81,7 @@ public class ListTag extends Tag implements Iterable<Tag> {
}
@Override
public List<Tag> getValue() {
public List<T> getValue() {
return this.value;
}
@ -92,15 +97,15 @@ public class ListTag extends Tag implements Iterable<Tag> {
* @param value New value of this tag.
* @throws IllegalArgumentException If all tags in the list are not of the same type.
*/
public void setValue(List<Tag> value) throws IllegalArgumentException {
public void setValue(List<T> value) {
this.value = new ArrayList<>(value);
if (!value.isEmpty()) {
this.type = value.get(0).getClass();
for (int i = 1; i < value.size(); i++) {
this.checkType(value.get(i));
if (this.type == null) {
this.type = (Class<T>) value.get(0).getClass();
}
for (T t : value) {
this.checkType(t);
}
} else {
this.type = null;
}
}
@ -121,18 +126,20 @@ public class ListTag extends Tag implements Iterable<Tag> {
* @return If the list was changed as a result.
* @throws IllegalArgumentException If the tag's type differs from the list tag's type.
*/
public boolean add(Tag tag) throws IllegalArgumentException {
// If currently empty, use this as the tag type
if (this.type == null) {
this.type = tag.getClass();
} else if (tag.getClass() != this.type) {
this.checkType(tag);
}
public boolean add(T tag) throws IllegalArgumentException {
this.checkAddedTag(tag);
return this.value.add(tag);
}
private void checkType(Tag tag) throws IllegalArgumentException {
private void checkAddedTag(T tag) {
if (this.type == null) {
this.type = (Class<T>) tag.getClass();
} else {
this.checkType(tag);
}
}
private void checkType(Tag tag) {
if (tag.getClass() != this.type) {
throw new IllegalArgumentException("Tag type " + tag.getClass().getSimpleName() + " differs from list type " + this.type.getSimpleName());
}
@ -144,19 +151,40 @@ public class ListTag extends Tag implements Iterable<Tag> {
* @param tag Tag to remove.
* @return If the list contained the tag.
*/
public boolean remove(Tag tag) {
public boolean remove(T tag) {
return this.value.remove(tag);
}
/**
* Gets the tag at the given index of this list tag.
*
* @param <T> Type of tag to get
* @param index Index of the tag.
* @return The tag at the given index.
*/
public <T extends Tag> T get(int index) {
return (T) this.value.get(index);
public T get(int index) {
return this.value.get(index);
}
/**
* Sets the tag at the given index of this list tag.
*
* @param index Index of the tag.
* @param tag New tag to set.
* @return The old tag at the given index.
*/
public T set(int index, T tag) {
this.checkAddedTag(tag);
return this.value.set(index, tag);
}
/**
* Removes the tag at the given index of this list tag.
*
* @param index Index of the tag.
* @return The removed tag at the given index.
*/
public T remove(int index) {
return this.value.remove(index);
}
/**
@ -173,13 +201,13 @@ public class ListTag extends Tag implements Iterable<Tag> {
}
@Override
public Iterator<Tag> iterator() {
public Iterator<T> iterator() {
return this.value.iterator();
}
@Override
public void write(DataOutput out) throws IOException {
if (this.type == null) {
if (this.value.isEmpty()) {
out.writeByte(TagRegistry.END);
} else {
int id = TagRegistry.getIdFor(this.type);
@ -197,20 +225,20 @@ public class ListTag extends Tag implements Iterable<Tag> {
}
@Override
public ListTag copy() {
List<Tag> newList = new ArrayList<>();
for (Tag value : this.value) {
newList.add(value.copy());
public ListTag<T> copy() {
ListTag<T> copy = new ListTag<>(this.type);
copy.value = new ArrayList<>(this.value.size());
for (T value : this.value) {
copy.add((T) value.copy());
}
return new ListTag(newList);
return copy;
}
@Override
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ListTag tags = (ListTag) o;
ListTag<?> tags = (ListTag<?>) o;
if (!Objects.equals(this.type, tags.type)) return false;
return this.value.equals(tags.value);
}

View File

@ -9,7 +9,7 @@ import java.util.Arrays;
/**
* A tag containing a long array.
*/
public class LongArrayTag extends NumberArrayTag {
public final class LongArrayTag extends NumberArrayTag {
public static final int ID = 12;
private static final long[] EMPTY_ARRAY = new long[0];
private long[] value;
@ -91,8 +91,8 @@ public class LongArrayTag extends NumberArrayTag {
}
@Override
public ListTag toListTag() {
final ListTag list = new ListTag(LongTag.class);
public ListTag<LongTag> toListTag() {
final ListTag<LongTag> list = new ListTag<>(LongTag.class);
for (final long l : this.value) {
list.add(new LongTag(l));
}

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing a long.
*/
public class LongTag extends NumberTag {
public final class LongTag extends NumberTag {
public static final int ID = 4;
private long value;

View File

@ -14,5 +14,5 @@ public abstract class NumberArrayTag extends Tag {
*
* @return a new list tag
*/
public abstract ListTag toListTag();
public abstract ListTag<? extends NumberTag> toListTag();
}

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing a short.
*/
public class ShortTag extends NumberTag {
public final class ShortTag extends NumberTag {
public static final int ID = 2;
private short value;

View File

@ -8,7 +8,7 @@ import java.io.IOException;
/**
* A tag containing a string.
*/
public class StringTag extends Tag {
public final class StringTag extends Tag {
public static final int ID = 8;
private String value;