diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/NbtComponentSerializer.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/NbtComponentSerializer.java index a7867ad63..9fd6818fa 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/NbtComponentSerializer.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/NbtComponentSerializer.java @@ -6,6 +6,7 @@ import com.google.gson.JsonPrimitive; import com.google.gson.internal.LazilyParsedNumber; import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.checkerframework.checker.nullness.qual.Nullable; import org.cloudburstmc.nbt.NbtList; import org.cloudburstmc.nbt.NbtMap; @@ -13,6 +14,7 @@ import org.cloudburstmc.nbt.NbtType; import org.jetbrains.annotations.Contract; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; @@ -101,41 +103,33 @@ private static Object convertToTag(final @Nullable JsonElement element) { throw new IllegalArgumentException("Unhandled json type " + element.getClass().getSimpleName() + " with value " + element.getAsString()); } - private static void addToListOrFail(final NbtList list, final Object tag) { - Class listClass = list.getType().getTagClass(); - - if (listClass.isInstance(tag)) { - list.add(listClass.cast(tag)); - } else { - throw new IllegalArgumentException("Cannot add " + tag.getClass().getSimpleName() + " to list of " + listClass.getSimpleName()); - } - } - private static NbtList convertJsonArray(final JsonArray array) { // TODO Number arrays? - NbtList listTag = null; - boolean singleType = true; + NbtListBuilder listBuilder = null; for (final JsonElement entry : array) { final Object convertedEntryTag = convertToTag(entry); - if (listTag == null) { - listTag = new NbtList<>(NbtType.byClass(convertedEntryTag.getClass())); + NbtType convertedTagType = NbtType.byClass(convertedEntryTag.getClass()); + + if (listBuilder == null) { + listBuilder = new NbtListBuilder<>(convertedTagType); } - if (listTag.getType() != NbtType.byClass(convertedEntryTag.getClass())) { - singleType = false; + // If we have different types mixed, fallback to compounds below. + if (listBuilder.type != convertedTagType) { + listBuilder = null; break; } - addToListOrFail(listTag, convertedEntryTag); + listBuilder.addUnsafe(convertedEntryTag); } - if (singleType) { - return listTag; + if (listBuilder != null) { + return listBuilder.build(); } // Generally, vanilla-esque serializers should not produce this format, so it should be rare // Lists are only used for lists of components ("extra" and "with") - final NbtList processedListTag = new NbtList<>(NbtType.COMPOUND); + final NbtListBuilder processedListTag = new NbtListBuilder<>(NbtType.COMPOUND); for (final JsonElement entry : array) { final Object convertedTag = convertToTag(entry); if (convertedTag instanceof NbtMap nbtMap) { @@ -154,7 +148,8 @@ private static NbtList convertJsonArray(final JsonArray array) { } processedListTag.add(compoundTag.build()); } - return processedListTag; + + return processedListTag.build(); } /** @@ -336,4 +331,22 @@ private static class Pair { private final K key; private final V value; } + + @RequiredArgsConstructor + private static class NbtListBuilder { + private final NbtType type; + private final List list = new ArrayList<>(); + + public void add(T value) { + list.add(value); + } + + public void addUnsafe(Object value) { + add(type.getTagClass().cast(value)); + } + + public NbtList build() { + return new NbtList<>(type, list); + } + } }