package com.intellectualcrafters.jnbt; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; /** * The {@code TAG_List} tag. */ public final class ListTag extends Tag { private final Class<? extends Tag> type; private final List<Tag> value; /** * Creates the tag with an empty name. * * @param type the type of tag * @param value the value of the tag */ public ListTag(Class<? extends Tag> type, List<? extends Tag> value) { checkNotNull(value); this.type = type; this.value = Collections.unmodifiableList(value); } /** * Creates the tag. * * @param name the name of the tag * @param type the type of tag * @param value the value of the tag */ public ListTag(String name, Class<? extends Tag> type, List<? extends Tag> value) { super(name); checkNotNull(value); this.type = type; this.value = Collections.unmodifiableList(value); } /** * Gets the type of item in this list. * * @return The type of item in this list. */ public Class<? extends Tag> getType() { return this.type; } @Override public List<Tag> getValue() { return this.value; } /** * Create a new list tag with this tag's name and type. * * @param list the new list * * @return a new list tag */ public ListTag setValue(List<Tag> list) { return new ListTag(getName(), getType(), list); } /** * Get the tag if it exists at the given index. * * @param index the index * * @return the tag or null */ public Tag getIfExists(int index) { try { return this.value.get(index); } catch (NoSuchElementException ignored) { return null; } } /** * Get a byte array named with the given index. <p> If the index does not exist or its value is not a byte * array tag, then an empty byte array will be returned. </p> * * @param index the index * * @return a byte array */ public byte[] getByteArray(int index) { Tag tag = getIfExists(index); if (tag instanceof ByteArrayTag) { return ((ByteArrayTag) tag).getValue(); } else { return new byte[0]; } } /** * Get a byte named with the given index. <p> If the index does not exist or its value is not a byte tag, then * {@code 0} will be returned. </p> * * @param index the index * * @return a byte */ public byte getByte(int index) { Tag tag = getIfExists(index); if (tag instanceof ByteTag) { return ((ByteTag) tag).getValue(); } else { return (byte) 0; } } /** * Get a double named with the given index. <p> If the index does not exist or its value is not a double tag, * then {@code 0} will be returned. </p> * * @param index the index * * @return a double */ public double getDouble(int index) { Tag tag = getIfExists(index); if (tag instanceof DoubleTag) { return ((DoubleTag) tag).getValue(); } else { return 0; } } /** * Get a double named with the given index, even if it's another type of number. <p> If the index does not * exist or its value is not a number, then {@code 0} will be returned. </p> * * @param index the index * * @return a double */ public double asDouble(int index) { Tag tag = getIfExists(index); if (tag instanceof ByteTag) { return ((ByteTag) tag).getValue(); } else if (tag instanceof ShortTag) { return ((ShortTag) tag).getValue(); } else if (tag instanceof IntTag) { return ((IntTag) tag).getValue(); } else if (tag instanceof LongTag) { return ((LongTag) tag).getValue(); } else if (tag instanceof FloatTag) { return ((FloatTag) tag).getValue(); } else if (tag instanceof DoubleTag) { return ((DoubleTag) tag).getValue(); } else { return 0; } } /** * Get a float named with the given index. <p> If the index does not exist or its value is not a float tag, * then {@code 0} will be returned. </p> * * @param index the index * * @return a float */ public float getFloat(int index) { Tag tag = getIfExists(index); if (tag instanceof FloatTag) { return ((FloatTag) tag).getValue(); } else { return 0; } } /** * Get a {@code int[]} named with the given index. <p> If the index does not exist or its value is not an int * array tag, then an empty array will be returned. </p> * * @param index the index * * @return an int array */ public int[] getIntArray(int index) { Tag tag = getIfExists(index); if (tag instanceof IntArrayTag) { return ((IntArrayTag) tag).getValue(); } else { return new int[0]; } } /** * Get an int named with the given index. <p> If the index does not exist or its value is not an int tag, then * {@code 0} will be returned. </p> * * @param index the index * * @return an int */ public int getInt(int index) { Tag tag = getIfExists(index); if (tag instanceof IntTag) { return ((IntTag) tag).getValue(); } else { return 0; } } /** * Get an int named with the given index, even if it's another type of number. <p> If the index does not exist * or its value is not a number, then {@code 0} will be returned. </p> * * @param index the index * * @return an int */ public int asInt(int index) { Tag tag = getIfExists(index); if (tag instanceof ByteTag) { return ((ByteTag) tag).getValue(); } else if (tag instanceof ShortTag) { return ((ShortTag) tag).getValue(); } else if (tag instanceof IntTag) { return ((IntTag) tag).getValue(); } else if (tag instanceof LongTag) { return ((LongTag) tag).getValue().intValue(); } else if (tag instanceof FloatTag) { return ((FloatTag) tag).getValue().intValue(); } else if (tag instanceof DoubleTag) { return ((DoubleTag) tag).getValue().intValue(); } else { return 0; } } /** * Get a list of tags named with the given index. <p> If the index does not exist or its value is not a list * tag, then an empty list will be returned. </p> * * @param index the index * * @return a list of tags */ public List<Tag> getList(int index) { Tag tag = getIfExists(index); if (tag instanceof ListTag) { return ((ListTag) tag).getValue(); } else { return Collections.emptyList(); } } /** * Get a {@code TagList} named with the given index. <p> If the index does not exist or its value is not a list * tag, then an empty tag list will be returned. </p> * * @param index the index * * @return a tag list instance */ public ListTag getListTag(int index) { Tag tag = getIfExists(index); if (tag instanceof ListTag) { return (ListTag) tag; } else { return new ListTag(StringTag.class, Collections.<Tag>emptyList()); } } /** * Get a list of tags named with the given index. <p> If the index does not exist or its value is not a list * tag, then an empty list will be returned. If the given index references a list but the list of of a different * type, then an empty list will also be returned. </p> * * @param index the index * @param listType the class of the contained type * @param <T> the NBT type * * @return a list of tags */ @SuppressWarnings("unchecked") public <T extends Tag> List<T> getList(int index, Class<T> listType) { Tag tag = getIfExists(index); if (tag instanceof ListTag) { ListTag listTag = (ListTag) tag; if (listTag.getType().equals(listType)) { return (List<T>) listTag.getValue(); } else { return Collections.emptyList(); } } else { return Collections.emptyList(); } } /** * Get a long named with the given index. <p> If the index does not exist or its value is not a long tag, then * {@code 0} will be returned. </p> * * @param index the index * * @return a long */ public long getLong(int index) { Tag tag = getIfExists(index); if (tag instanceof LongTag) { return ((LongTag) tag).getValue(); } else { return 0L; } } /** * Get a long named with the given index, even if it's another type of number. <p> If the index does not exist * or its value is not a number, then {@code 0} will be returned. </p> * * @param index the index * * @return a long */ public long asLong(int index) { Tag tag = getIfExists(index); if (tag instanceof ByteTag) { return ((ByteTag) tag).getValue(); } else if (tag instanceof ShortTag) { return ((ShortTag) tag).getValue(); } else if (tag instanceof IntTag) { return ((IntTag) tag).getValue(); } else if (tag instanceof LongTag) { return ((LongTag) tag).getValue(); } else if (tag instanceof FloatTag) { return ((FloatTag) tag).getValue().longValue(); } else if (tag instanceof DoubleTag) { return ((DoubleTag) tag).getValue().longValue(); } else { return 0; } } /** * Get a short named with the given index. <p> If the index does not exist or its value is not a short tag, * then {@code 0} will be returned. </p> * * @param index the index * * @return a short */ public short getShort(int index) { Tag tag = getIfExists(index); if (tag instanceof ShortTag) { return ((ShortTag) tag).getValue(); } else { return 0; } } /** * Get a string named with the given index. <p> If the index does not exist or its value is not a string tag, * then {@code ""} will be returned. </p> * * @param index the index * * @return a string */ public String getString(int index) { Tag tag = getIfExists(index); if (tag instanceof StringTag) { return ((StringTag) tag).getValue(); } else { return ""; } } @Override public String toString() { String name = getName(); String append = ""; if (name != null && !name.isEmpty()) { append = "(\"" + getName() + "\")"; } StringBuilder bldr = new StringBuilder(); bldr.append("TAG_List").append(append).append(": ").append(this.value.size()).append(" entries of type ") .append(NBTUtils.getTypeName(this.type)) .append("\r\n{\r\n"); for (Tag t : this.value) { bldr.append(" ").append(t.toString().replaceAll("\r\n", "\r\n ")).append("\r\n"); } bldr.append("}"); return bldr.toString(); } }