Initial Commit

This commit is contained in:
richard committed 2026-11-13 22:25:04 +01:00
1 parent 377b32db6e
commit 2d9a5eecba
14134 files changed
+1160982

No files matched your search

@@ -0,0 +1,166 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
public class ByteArrayTag extends CollectionTag<ByteTag> {
private static final int SELF_SIZE_IN_BYTES = 24;
public static final TagType<ByteArrayTag> TYPE = new TagType.VariableSize<ByteArrayTag>() {
public ByteArrayTag load(DataInput p_128247_, int p_128248_, NbtAccounter p_128249_) throws IOException {
p_128249_.accountBytes(24L);
int i = p_128247_.readInt();
p_128249_.accountBytes(1L * (long)i);
byte[] abyte = new byte[i];
p_128247_.readFully(abyte);
return new ByteArrayTag(abyte);
}
public StreamTagVisitor.ValueResult parse(DataInput p_197433_, StreamTagVisitor p_197434_) throws IOException {
int i = p_197433_.readInt();
byte[] abyte = new byte[i];
p_197433_.readFully(abyte);
return p_197434_.visit(abyte);
}
public void skip(DataInput p_197431_) throws IOException {
p_197431_.skipBytes(p_197431_.readInt() * 1);
}
public String getName() {
return "BYTE[]";
}
public String getPrettyName() {
return "TAG_Byte_Array";
}
};
private byte[] data;
public ByteArrayTag(byte[] pData) {
this.data = pData;
}
public ByteArrayTag(List<Byte> pDataList) {
this(toArray(pDataList));
}
private static byte[] toArray(List<Byte> pDataList) {
byte[] abyte = new byte[pDataList.size()];
for(int i = 0; i < pDataList.size(); ++i) {
Byte obyte = pDataList.get(i);
abyte[i] = obyte == null ? 0 : obyte;
}
return abyte;
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeInt(this.data.length);
pOutput.write(this.data);
}
public int sizeInBytes() {
return 24 + 1 * this.data.length;
}
public byte getId() {
return 7;
}
public TagType<ByteArrayTag> getType() {
return TYPE;
}
public String toString() {
return this.getAsString();
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public Tag copy() {
byte[] abyte = new byte[this.data.length];
System.arraycopy(this.data, 0, abyte, 0, this.data.length);
return new ByteArrayTag(abyte);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof ByteArrayTag && Arrays.equals(this.data, ((ByteArrayTag)pOther).data);
}
}
public int hashCode() {
return Arrays.hashCode(this.data);
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitByteArray(this);
}
public byte[] getAsByteArray() {
return this.data;
}
public int size() {
return this.data.length;
}
public ByteTag get(int p_128194_) {
return ByteTag.valueOf(this.data[p_128194_]);
}
public ByteTag set(int p_128196_, ByteTag p_128197_) {
byte b0 = this.data[p_128196_];
this.data[p_128196_] = p_128197_.getAsByte();
return ByteTag.valueOf(b0);
}
public void add(int p_128215_, ByteTag p_128216_) {
this.data = ArrayUtils.add(this.data, p_128215_, p_128216_.getAsByte());
}
public boolean setTag(int pIndex, Tag pNbt) {
if (pNbt instanceof NumericTag) {
this.data[pIndex] = ((NumericTag)pNbt).getAsByte();
return true;
} else {
return false;
}
}
public boolean addTag(int pIndex, Tag pNbt) {
if (pNbt instanceof NumericTag) {
this.data = ArrayUtils.add(this.data, pIndex, ((NumericTag)pNbt).getAsByte());
return true;
} else {
return false;
}
}
public ByteTag remove(int p_128213_) {
byte b0 = this.data[p_128213_];
this.data = ArrayUtils.remove(this.data, p_128213_);
return ByteTag.valueOf(b0);
}
public byte getElementType() {
return 1;
}
public void clear() {
this.data = new byte[0];
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
}
@@ -0,0 +1,136 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class ByteTag extends NumericTag {
private static final int SELF_SIZE_IN_BYTES = 9;
public static final TagType<ByteTag> TYPE = new TagType.StaticSize<ByteTag>() {
public ByteTag load(DataInput p_128292_, int p_128293_, NbtAccounter p_128294_) throws IOException {
p_128294_.accountBytes(9L);
return ByteTag.valueOf(p_128292_.readByte());
}
public StreamTagVisitor.ValueResult parse(DataInput p_197438_, StreamTagVisitor p_197439_) throws IOException {
return p_197439_.visit(p_197438_.readByte());
}
public int size() {
return 1;
}
public String getName() {
return "BYTE";
}
public String getPrettyName() {
return "TAG_Byte";
}
public boolean isValue() {
return true;
}
};
public static final ByteTag ZERO = valueOf((byte)0);
public static final ByteTag ONE = valueOf((byte)1);
private final byte data;
ByteTag(byte pData) {
this.data = pData;
}
public static ByteTag valueOf(byte pData) {
return ByteTag.Cache.cache[128 + pData];
}
public static ByteTag valueOf(boolean pData) {
return pData ? ONE : ZERO;
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeByte(this.data);
}
public int sizeInBytes() {
return 9;
}
public byte getId() {
return 1;
}
public TagType<ByteTag> getType() {
return TYPE;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public ByteTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof ByteTag && this.data == ((ByteTag)pOther).data;
}
}
public int hashCode() {
return this.data;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitByte(this);
}
public long getAsLong() {
return (long)this.data;
}
public int getAsInt() {
return this.data;
}
public short getAsShort() {
return (short)this.data;
}
public byte getAsByte() {
return this.data;
}
public double getAsDouble() {
return (double)this.data;
}
public float getAsFloat() {
return (float)this.data;
}
public Number getAsNumber() {
return this.data;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
static class Cache {
static final ByteTag[] cache = new ByteTag[256];
private Cache() {
}
static {
for(int i = 0; i < cache.length; ++i) {
cache[i] = new ByteTag((byte)(i - 128));
}
}
}
}
@@ -0,0 +1,17 @@
package net.minecraft.nbt;
import java.util.AbstractList;
public abstract class CollectionTag<T extends Tag> extends AbstractList<T> implements Tag {
public abstract T set(int p_128318_, T p_128319_);
public abstract void add(int p_128315_, T p_128316_);
public abstract T remove(int p_128313_);
public abstract boolean setTag(int pIndex, Tag pTag);
public abstract boolean addTag(int pIndex, Tag pTag);
public abstract byte getElementType();
}
@@ -0,0 +1,561 @@
package net.minecraft.nbt;
import com.google.common.collect.Maps;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.Dynamic;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
public class CompoundTag implements Tag {
public static final Codec<CompoundTag> CODEC = Codec.PASSTHROUGH.comapFlatMap((p_274781_) -> {
Tag tag = p_274781_.convert(NbtOps.INSTANCE).getValue();
return tag instanceof CompoundTag ? DataResult.success((CompoundTag)tag) : DataResult.error(() -> {
return "Not a compound tag: " + tag;
});
}, (p_128412_) -> {
return new Dynamic<>(NbtOps.INSTANCE, p_128412_);
});
private static final int SELF_SIZE_IN_BYTES = 48;
private static final int MAP_ENTRY_SIZE_IN_BYTES = 32;
public static final TagType<CompoundTag> TYPE = new TagType.VariableSize<CompoundTag>() {
public CompoundTag load(DataInput p_128485_, int p_128486_, NbtAccounter p_128487_) throws IOException {
p_128487_.accountBytes(48L);
if (p_128486_ > 512) {
throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512");
} else {
Map<String, Tag> map = Maps.newHashMap();
byte b0;
while((b0 = CompoundTag.readNamedTagType(p_128485_, p_128487_)) != 0) {
String s = CompoundTag.readNamedTagName(p_128485_, p_128487_);
p_128487_.accountBytes((long)(28 + 2 * s.length()));
p_128487_.accountBytes(4); //Forge: 4 extra bytes for the object allocation.
Tag tag = CompoundTag.readNamedTagData(TagTypes.getType(b0), s, p_128485_, p_128486_ + 1, p_128487_);
if (map.put(s, tag) == null) {
p_128487_.accountBytes(36L);
}
}
return new CompoundTag(map);
}
}
public StreamTagVisitor.ValueResult parse(DataInput p_197446_, StreamTagVisitor p_197447_) throws IOException {
while(true) {
byte b0;
if ((b0 = p_197446_.readByte()) != 0) {
TagType<?> tagtype = TagTypes.getType(b0);
switch (p_197447_.visitEntry(tagtype)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
StringTag.skipString(p_197446_);
tagtype.skip(p_197446_);
break;
case SKIP:
StringTag.skipString(p_197446_);
tagtype.skip(p_197446_);
continue;
default:
String s = p_197446_.readUTF();
switch (p_197447_.visitEntry(tagtype, s)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
tagtype.skip(p_197446_);
break;
case SKIP:
tagtype.skip(p_197446_);
continue;
default:
switch (tagtype.parse(p_197446_, p_197447_)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
default:
continue;
}
}
}
}
if (b0 != 0) {
while((b0 = p_197446_.readByte()) != 0) {
StringTag.skipString(p_197446_);
TagTypes.getType(b0).skip(p_197446_);
}
}
return p_197447_.visitContainerEnd();
}
}
public void skip(DataInput p_197444_) throws IOException {
byte b0;
while((b0 = p_197444_.readByte()) != 0) {
StringTag.skipString(p_197444_);
TagTypes.getType(b0).skip(p_197444_);
}
}
public String getName() {
return "COMPOUND";
}
public String getPrettyName() {
return "TAG_Compound";
}
};
private final Map<String, Tag> tags;
protected CompoundTag(Map<String, Tag> pTags) {
this.tags = pTags;
}
public CompoundTag() {
this(Maps.newHashMap());
}
public void write(DataOutput pOutput) throws IOException {
for(String s : this.tags.keySet()) {
Tag tag = this.tags.get(s);
writeNamedTag(s, tag, pOutput);
}
pOutput.writeByte(0);
}
public int sizeInBytes() {
int i = 48;
for(Map.Entry<String, Tag> entry : this.tags.entrySet()) {
i += 28 + 2 * entry.getKey().length();
i += 36;
i += entry.getValue().sizeInBytes();
}
return i;
}
public Set<String> getAllKeys() {
return this.tags.keySet();
}
public byte getId() {
return 10;
}
public TagType<CompoundTag> getType() {
return TYPE;
}
public int size() {
return this.tags.size();
}
@Nullable
public Tag put(String pKey, Tag pValue) {
if (pValue == null) throw new IllegalArgumentException("Invalid null NBT value with key " + pKey);
return this.tags.put(pKey, pValue);
}
public void putByte(String pKey, byte pValue) {
this.tags.put(pKey, ByteTag.valueOf(pValue));
}
public void putShort(String pKey, short pValue) {
this.tags.put(pKey, ShortTag.valueOf(pValue));
}
public void putInt(String pKey, int pValue) {
this.tags.put(pKey, IntTag.valueOf(pValue));
}
public void putLong(String pKey, long pValue) {
this.tags.put(pKey, LongTag.valueOf(pValue));
}
public void putUUID(String pKey, UUID pValue) {
this.tags.put(pKey, NbtUtils.createUUID(pValue));
}
public UUID getUUID(String pKey) {
return NbtUtils.loadUUID(this.get(pKey));
}
public boolean hasUUID(String pKey) {
Tag tag = this.get(pKey);
return tag != null && tag.getType() == IntArrayTag.TYPE && ((IntArrayTag)tag).getAsIntArray().length == 4;
}
public void putFloat(String pKey, float pValue) {
this.tags.put(pKey, FloatTag.valueOf(pValue));
}
public void putDouble(String pKey, double pValue) {
this.tags.put(pKey, DoubleTag.valueOf(pValue));
}
public void putString(String pKey, String pValue) {
this.tags.put(pKey, StringTag.valueOf(pValue));
}
public void putByteArray(String pKey, byte[] pValue) {
this.tags.put(pKey, new ByteArrayTag(pValue));
}
public void putByteArray(String pKey, List<Byte> pValue) {
this.tags.put(pKey, new ByteArrayTag(pValue));
}
public void putIntArray(String pKey, int[] pValue) {
this.tags.put(pKey, new IntArrayTag(pValue));
}
public void putIntArray(String pKey, List<Integer> pValue) {
this.tags.put(pKey, new IntArrayTag(pValue));
}
public void putLongArray(String pKey, long[] pValue) {
this.tags.put(pKey, new LongArrayTag(pValue));
}
public void putLongArray(String pKey, List<Long> pValue) {
this.tags.put(pKey, new LongArrayTag(pValue));
}
public void putBoolean(String pKey, boolean pValue) {
this.tags.put(pKey, ByteTag.valueOf(pValue));
}
@Nullable
public Tag get(String pKey) {
return this.tags.get(pKey);
}
/**
* Gets the byte identifier of the tag of the specified {@code key}, or {@code 0} if no tag exists for the {@code
* key}.
*/
public byte getTagType(String pKey) {
Tag tag = this.tags.get(pKey);
return tag == null ? 0 : tag.getId();
}
public boolean contains(String pKey) {
return this.tags.containsKey(pKey);
}
/**
* Returns whether the tag of the specified {@code key} is a particular {@code tagType}. If the {@code tagType} is
* {@code 99}, all numeric tags will be checked against the type of the stored tag.
*/
public boolean contains(String pKey, int pTagType) {
int i = this.getTagType(pKey);
if (i == pTagType) {
return true;
} else if (pTagType != 99) {
return false;
} else {
return i == 1 || i == 2 || i == 3 || i == 4 || i == 5 || i == 6;
}
}
public byte getByte(String pKey) {
try {
if (this.contains(pKey, 99)) {
return ((NumericTag)this.tags.get(pKey)).getAsByte();
}
} catch (ClassCastException classcastexception) {
}
return 0;
}
public short getShort(String pKey) {
try {
if (this.contains(pKey, 99)) {
return ((NumericTag)this.tags.get(pKey)).getAsShort();
}
} catch (ClassCastException classcastexception) {
}
return 0;
}
public int getInt(String pKey) {
try {
if (this.contains(pKey, 99)) {
return ((NumericTag)this.tags.get(pKey)).getAsInt();
}
} catch (ClassCastException classcastexception) {
}
return 0;
}
public long getLong(String pKey) {
try {
if (this.contains(pKey, 99)) {
return ((NumericTag)this.tags.get(pKey)).getAsLong();
}
} catch (ClassCastException classcastexception) {
}
return 0L;
}
public float getFloat(String pKey) {
try {
if (this.contains(pKey, 99)) {
return ((NumericTag)this.tags.get(pKey)).getAsFloat();
}
} catch (ClassCastException classcastexception) {
}
return 0.0F;
}
public double getDouble(String pKey) {
try {
if (this.contains(pKey, 99)) {
return ((NumericTag)this.tags.get(pKey)).getAsDouble();
}
} catch (ClassCastException classcastexception) {
}
return 0.0D;
}
public String getString(String pKey) {
try {
if (this.contains(pKey, 8)) {
return this.tags.get(pKey).getAsString();
}
} catch (ClassCastException classcastexception) {
}
return "";
}
public byte[] getByteArray(String pKey) {
try {
if (this.contains(pKey, 7)) {
return ((ByteArrayTag)this.tags.get(pKey)).getAsByteArray();
}
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.createReport(pKey, ByteArrayTag.TYPE, classcastexception));
}
return new byte[0];
}
public int[] getIntArray(String pKey) {
try {
if (this.contains(pKey, 11)) {
return ((IntArrayTag)this.tags.get(pKey)).getAsIntArray();
}
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.createReport(pKey, IntArrayTag.TYPE, classcastexception));
}
return new int[0];
}
public long[] getLongArray(String pKey) {
try {
if (this.contains(pKey, 12)) {
return ((LongArrayTag)this.tags.get(pKey)).getAsLongArray();
}
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.createReport(pKey, LongArrayTag.TYPE, classcastexception));
}
return new long[0];
}
public CompoundTag getCompound(String pKey) {
try {
if (this.contains(pKey, 10)) {
return (CompoundTag)this.tags.get(pKey);
}
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.createReport(pKey, TYPE, classcastexception));
}
return new CompoundTag();
}
public ListTag getList(String pKey, int pTagType) {
try {
if (this.getTagType(pKey) == 9) {
ListTag listtag = (ListTag)this.tags.get(pKey);
if (!listtag.isEmpty() && listtag.getElementType() != pTagType) {
return new ListTag();
}
return listtag;
}
} catch (ClassCastException classcastexception) {
throw new ReportedException(this.createReport(pKey, ListTag.TYPE, classcastexception));
}
return new ListTag();
}
public boolean getBoolean(String pKey) {
return this.getByte(pKey) != 0;
}
public void remove(String pKey) {
this.tags.remove(pKey);
}
public String toString() {
return this.getAsString();
}
public boolean isEmpty() {
return this.tags.isEmpty();
}
private CrashReport createReport(String pTagName, TagType<?> pType, ClassCastException pException) {
CrashReport crashreport = CrashReport.forThrowable(pException, "Reading NBT data");
CrashReportCategory crashreportcategory = crashreport.addCategory("Corrupt NBT tag", 1);
crashreportcategory.setDetail("Tag type found", () -> {
return this.tags.get(pTagName).getType().getName();
});
crashreportcategory.setDetail("Tag type expected", pType::getName);
crashreportcategory.setDetail("Tag name", pTagName);
return crashreport;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public CompoundTag copy() {
Map<String, Tag> map = Maps.newHashMap(Maps.transformValues(this.tags, Tag::copy));
return new CompoundTag(map);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof CompoundTag && Objects.equals(this.tags, ((CompoundTag)pOther).tags);
}
}
public int hashCode() {
return this.tags.hashCode();
}
private static void writeNamedTag(String pName, Tag pTag, DataOutput pOutput) throws IOException {
pOutput.writeByte(pTag.getId());
if (pTag.getId() != 0) {
pOutput.writeUTF(pName);
pTag.write(pOutput);
}
}
static byte readNamedTagType(DataInput pInput, NbtAccounter pAccounter) throws IOException {
pAccounter.accountBytes(2);
return pInput.readByte();
}
static String readNamedTagName(DataInput pInput, NbtAccounter pAccounter) throws IOException {
return pAccounter.readUTF(pInput.readUTF());
}
static Tag readNamedTagData(TagType<?> pType, String pName, DataInput pInput, int pDepth, NbtAccounter pAccounter) {
try {
return pType.load(pInput, pDepth, pAccounter);
} catch (IOException ioexception) {
CrashReport crashreport = CrashReport.forThrowable(ioexception, "Loading NBT data");
CrashReportCategory crashreportcategory = crashreport.addCategory("NBT Tag");
crashreportcategory.setDetail("Tag name", pName);
crashreportcategory.setDetail("Tag type", pType.getName());
throw new ReportedException(crashreport);
}
}
/**
* Copies all the tags of {@code other} into this tag, then returns itself.
* @see #copy()
*/
public CompoundTag merge(CompoundTag pOther) {
for(String s : pOther.tags.keySet()) {
Tag tag = pOther.tags.get(s);
if (tag.getId() == 10) {
if (this.contains(s, 10)) {
CompoundTag compoundtag = this.getCompound(s);
compoundtag.merge((CompoundTag)tag);
} else {
this.put(s, tag.copy());
}
} else {
this.put(s, tag.copy());
}
}
return this;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitCompound(this);
}
protected Map<String, Tag> entries() {
return Collections.unmodifiableMap(this.tags);
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
for(Map.Entry<String, Tag> entry : this.tags.entrySet()) {
Tag tag = entry.getValue();
TagType<?> tagtype = tag.getType();
StreamTagVisitor.EntryResult streamtagvisitor$entryresult = pVisitor.visitEntry(tagtype);
switch (streamtagvisitor$entryresult) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
return pVisitor.visitContainerEnd();
case SKIP:
break;
default:
streamtagvisitor$entryresult = pVisitor.visitEntry(tagtype, entry.getKey());
switch (streamtagvisitor$entryresult) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
return pVisitor.visitContainerEnd();
case SKIP:
break;
default:
StreamTagVisitor.ValueResult streamtagvisitor$valueresult = tag.accept(pVisitor);
switch (streamtagvisitor$valueresult) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
return pVisitor.visitContainerEnd();
}
}
}
}
return pVisitor.visitContainerEnd();
}
}
@@ -0,0 +1,119 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import net.minecraft.util.Mth;
public class DoubleTag extends NumericTag {
private static final int SELF_SIZE_IN_BYTES = 16;
public static final DoubleTag ZERO = new DoubleTag(0.0D);
public static final TagType<DoubleTag> TYPE = new TagType.StaticSize<DoubleTag>() {
public DoubleTag load(DataInput p_128524_, int p_128525_, NbtAccounter p_128526_) throws IOException {
p_128526_.accountBytes(16L);
return DoubleTag.valueOf(p_128524_.readDouble());
}
public StreamTagVisitor.ValueResult parse(DataInput p_197454_, StreamTagVisitor p_197455_) throws IOException {
return p_197455_.visit(p_197454_.readDouble());
}
public int size() {
return 8;
}
public String getName() {
return "DOUBLE";
}
public String getPrettyName() {
return "TAG_Double";
}
public boolean isValue() {
return true;
}
};
private final double data;
private DoubleTag(double pData) {
this.data = pData;
}
public static DoubleTag valueOf(double pData) {
return pData == 0.0D ? ZERO : new DoubleTag(pData);
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeDouble(this.data);
}
public int sizeInBytes() {
return 16;
}
public byte getId() {
return 6;
}
public TagType<DoubleTag> getType() {
return TYPE;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public DoubleTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof DoubleTag && this.data == ((DoubleTag)pOther).data;
}
}
public int hashCode() {
long i = Double.doubleToLongBits(this.data);
return (int)(i ^ i >>> 32);
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitDouble(this);
}
public long getAsLong() {
return (long)Math.floor(this.data);
}
public int getAsInt() {
return Mth.floor(this.data);
}
public short getAsShort() {
return (short)(Mth.floor(this.data) & '\uffff');
}
public byte getAsByte() {
return (byte)(Mth.floor(this.data) & 255);
}
public double getAsDouble() {
return this.data;
}
public float getAsFloat() {
return (float)this.data;
}
public Number getAsNumber() {
return this.data;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
}
@@ -0,0 +1,76 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class EndTag implements Tag {
private static final int SELF_SIZE_IN_BYTES = 8;
public static final TagType<EndTag> TYPE = new TagType<EndTag>() {
public EndTag load(DataInput p_128550_, int p_128551_, NbtAccounter p_128552_) {
p_128552_.accountBytes(8L);
return EndTag.INSTANCE;
}
public StreamTagVisitor.ValueResult parse(DataInput p_197465_, StreamTagVisitor p_197466_) {
return p_197466_.visitEnd();
}
public void skip(DataInput p_197462_, int p_197463_) {
}
public void skip(DataInput p_197460_) {
}
public String getName() {
return "END";
}
public String getPrettyName() {
return "TAG_End";
}
public boolean isValue() {
return true;
}
};
public static final EndTag INSTANCE = new EndTag();
private EndTag() {
}
public void write(DataOutput pOutput) throws IOException {
}
public int sizeInBytes() {
return 8;
}
public byte getId() {
return 0;
}
public TagType<EndTag> getType() {
return TYPE;
}
public String toString() {
return this.getAsString();
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public EndTag copy() {
return this;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitEnd(this);
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visitEnd();
}
}
@@ -0,0 +1,118 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import net.minecraft.util.Mth;
public class FloatTag extends NumericTag {
private static final int SELF_SIZE_IN_BYTES = 12;
public static final FloatTag ZERO = new FloatTag(0.0F);
public static final TagType<FloatTag> TYPE = new TagType.StaticSize<FloatTag>() {
public FloatTag load(DataInput p_128590_, int p_128591_, NbtAccounter p_128592_) throws IOException {
p_128592_.accountBytes(12L);
return FloatTag.valueOf(p_128590_.readFloat());
}
public StreamTagVisitor.ValueResult parse(DataInput p_197470_, StreamTagVisitor p_197471_) throws IOException {
return p_197471_.visit(p_197470_.readFloat());
}
public int size() {
return 4;
}
public String getName() {
return "FLOAT";
}
public String getPrettyName() {
return "TAG_Float";
}
public boolean isValue() {
return true;
}
};
private final float data;
private FloatTag(float pData) {
this.data = pData;
}
public static FloatTag valueOf(float pData) {
return pData == 0.0F ? ZERO : new FloatTag(pData);
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeFloat(this.data);
}
public int sizeInBytes() {
return 12;
}
public byte getId() {
return 5;
}
public TagType<FloatTag> getType() {
return TYPE;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public FloatTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof FloatTag && this.data == ((FloatTag)pOther).data;
}
}
public int hashCode() {
return Float.floatToIntBits(this.data);
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitFloat(this);
}
public long getAsLong() {
return (long)this.data;
}
public int getAsInt() {
return Mth.floor(this.data);
}
public short getAsShort() {
return (short)(Mth.floor(this.data) & '\uffff');
}
public byte getAsByte() {
return (byte)(Mth.floor(this.data) & 255);
}
public double getAsDouble() {
return (double)this.data;
}
public float getAsFloat() {
return this.data;
}
public Number getAsNumber() {
return this.data;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
}
@@ -0,0 +1,178 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
public class IntArrayTag extends CollectionTag<IntTag> {
private static final int SELF_SIZE_IN_BYTES = 24;
public static final TagType<IntArrayTag> TYPE = new TagType.VariableSize<IntArrayTag>() {
public IntArrayTag load(DataInput p_128662_, int p_128663_, NbtAccounter p_128664_) throws IOException {
p_128664_.accountBytes(24L);
int i = p_128662_.readInt();
p_128664_.accountBytes(4L * (long)i);
int[] aint = new int[i];
for(int j = 0; j < i; ++j) {
aint[j] = p_128662_.readInt();
}
return new IntArrayTag(aint);
}
public StreamTagVisitor.ValueResult parse(DataInput p_197478_, StreamTagVisitor p_197479_) throws IOException {
int i = p_197478_.readInt();
int[] aint = new int[i];
for(int j = 0; j < i; ++j) {
aint[j] = p_197478_.readInt();
}
return p_197479_.visit(aint);
}
public void skip(DataInput p_197476_) throws IOException {
p_197476_.skipBytes(p_197476_.readInt() * 4);
}
public String getName() {
return "INT[]";
}
public String getPrettyName() {
return "TAG_Int_Array";
}
};
private int[] data;
public IntArrayTag(int[] pData) {
this.data = pData;
}
public IntArrayTag(List<Integer> pDataList) {
this(toArray(pDataList));
}
private static int[] toArray(List<Integer> pDataList) {
int[] aint = new int[pDataList.size()];
for(int i = 0; i < pDataList.size(); ++i) {
Integer integer = pDataList.get(i);
aint[i] = integer == null ? 0 : integer;
}
return aint;
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeInt(this.data.length);
for(int i : this.data) {
pOutput.writeInt(i);
}
}
public int sizeInBytes() {
return 24 + 4 * this.data.length;
}
public byte getId() {
return 11;
}
public TagType<IntArrayTag> getType() {
return TYPE;
}
public String toString() {
return this.getAsString();
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public IntArrayTag copy() {
int[] aint = new int[this.data.length];
System.arraycopy(this.data, 0, aint, 0, this.data.length);
return new IntArrayTag(aint);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof IntArrayTag && Arrays.equals(this.data, ((IntArrayTag)pOther).data);
}
}
public int hashCode() {
return Arrays.hashCode(this.data);
}
public int[] getAsIntArray() {
return this.data;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitIntArray(this);
}
public int size() {
return this.data.length;
}
public IntTag get(int p_128608_) {
return IntTag.valueOf(this.data[p_128608_]);
}
public IntTag set(int p_128610_, IntTag p_128611_) {
int i = this.data[p_128610_];
this.data[p_128610_] = p_128611_.getAsInt();
return IntTag.valueOf(i);
}
public void add(int p_128629_, IntTag p_128630_) {
this.data = ArrayUtils.add(this.data, p_128629_, p_128630_.getAsInt());
}
public boolean setTag(int pIndex, Tag pNbt) {
if (pNbt instanceof NumericTag) {
this.data[pIndex] = ((NumericTag)pNbt).getAsInt();
return true;
} else {
return false;
}
}
public boolean addTag(int pIndex, Tag pNbt) {
if (pNbt instanceof NumericTag) {
this.data = ArrayUtils.add(this.data, pIndex, ((NumericTag)pNbt).getAsInt());
return true;
} else {
return false;
}
}
public IntTag remove(int p_128627_) {
int i = this.data[p_128627_];
this.data = ArrayUtils.remove(this.data, p_128627_);
return IntTag.valueOf(i);
}
public byte getElementType() {
return 3;
}
public void clear() {
this.data = new int[0];
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
}
@@ -0,0 +1,132 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class IntTag extends NumericTag {
private static final int SELF_SIZE_IN_BYTES = 12;
public static final TagType<IntTag> TYPE = new TagType.StaticSize<IntTag>() {
public IntTag load(DataInput p_128703_, int p_128704_, NbtAccounter p_128705_) throws IOException {
p_128705_.accountBytes(12L);
return IntTag.valueOf(p_128703_.readInt());
}
public StreamTagVisitor.ValueResult parse(DataInput p_197483_, StreamTagVisitor p_197484_) throws IOException {
return p_197484_.visit(p_197483_.readInt());
}
public int size() {
return 4;
}
public String getName() {
return "INT";
}
public String getPrettyName() {
return "TAG_Int";
}
public boolean isValue() {
return true;
}
};
private final int data;
IntTag(int pData) {
this.data = pData;
}
public static IntTag valueOf(int pData) {
return pData >= -128 && pData <= 1024 ? IntTag.Cache.cache[pData - -128] : new IntTag(pData);
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeInt(this.data);
}
public int sizeInBytes() {
return 12;
}
public byte getId() {
return 3;
}
public TagType<IntTag> getType() {
return TYPE;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public IntTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof IntTag && this.data == ((IntTag)pOther).data;
}
}
public int hashCode() {
return this.data;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitInt(this);
}
public long getAsLong() {
return (long)this.data;
}
public int getAsInt() {
return this.data;
}
public short getAsShort() {
return (short)(this.data & '\uffff');
}
public byte getAsByte() {
return (byte)(this.data & 255);
}
public double getAsDouble() {
return (double)this.data;
}
public float getAsFloat() {
return (float)this.data;
}
public Number getAsNumber() {
return this.data;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
static class Cache {
private static final int HIGH = 1024;
private static final int LOW = -128;
static final IntTag[] cache = new IntTag[1153];
private Cache() {
}
static {
for(int i = 0; i < cache.length; ++i) {
cache[i] = new IntTag(-128 + i);
}
}
}
}
@@ -0,0 +1,384 @@
package net.minecraft.nbt;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
public class ListTag extends CollectionTag<Tag> {
private static final int SELF_SIZE_IN_BYTES = 37;
public static final TagType<ListTag> TYPE = new TagType.VariableSize<ListTag>() {
public ListTag load(DataInput p_128792_, int p_128793_, NbtAccounter p_128794_) throws IOException {
p_128794_.accountBytes(37L);
if (p_128793_ > 512) {
throw new RuntimeException("Tried to read NBT tag with too high complexity, depth > 512");
} else {
byte b0 = p_128792_.readByte();
int i = p_128792_.readInt();
if (b0 == 0 && i > 0) {
throw new RuntimeException("Missing type on ListTag");
} else {
p_128794_.accountBytes(4L * (long)i);
TagType<?> tagtype = TagTypes.getType(b0);
List<Tag> list = Lists.newArrayListWithCapacity(i);
for(int j = 0; j < i; ++j) {
list.add(tagtype.load(p_128792_, p_128793_ + 1, p_128794_));
}
return new ListTag(list, b0);
}
}
}
public StreamTagVisitor.ValueResult parse(DataInput p_197491_, StreamTagVisitor p_197492_) throws IOException {
TagType<?> tagtype = TagTypes.getType(p_197491_.readByte());
int i = p_197491_.readInt();
switch (p_197492_.visitList(tagtype, i)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
tagtype.skip(p_197491_, i);
return p_197492_.visitContainerEnd();
default:
int j = 0;
while(true) {
label45: {
if (j < i) {
switch (p_197492_.visitElement(tagtype, j)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
tagtype.skip(p_197491_);
break;
case SKIP:
tagtype.skip(p_197491_);
break label45;
default:
switch (tagtype.parse(p_197491_, p_197492_)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
break;
default:
break label45;
}
}
}
int k = i - 1 - j;
if (k > 0) {
tagtype.skip(p_197491_, k);
}
return p_197492_.visitContainerEnd();
}
++j;
}
}
}
public void skip(DataInput p_197489_) throws IOException {
TagType<?> tagtype = TagTypes.getType(p_197489_.readByte());
int i = p_197489_.readInt();
tagtype.skip(p_197489_, i);
}
public String getName() {
return "LIST";
}
public String getPrettyName() {
return "TAG_List";
}
};
private final List<Tag> list;
private byte type;
ListTag(List<Tag> pList, byte pType) {
this.list = pList;
this.type = pType;
}
public ListTag() {
this(Lists.newArrayList(), (byte)0);
}
public void write(DataOutput pOutput) throws IOException {
if (this.list.isEmpty()) {
this.type = 0;
} else {
this.type = this.list.get(0).getId();
}
pOutput.writeByte(this.type);
pOutput.writeInt(this.list.size());
for(Tag tag : this.list) {
tag.write(pOutput);
}
}
public int sizeInBytes() {
int i = 37;
i += 4 * this.list.size();
for(Tag tag : this.list) {
i += tag.sizeInBytes();
}
return i;
}
public byte getId() {
return 9;
}
public TagType<ListTag> getType() {
return TYPE;
}
public String toString() {
return this.getAsString();
}
private void updateTypeAfterRemove() {
if (this.list.isEmpty()) {
this.type = 0;
}
}
public Tag remove(int p_128751_) {
Tag tag = this.list.remove(p_128751_);
this.updateTypeAfterRemove();
return tag;
}
public boolean isEmpty() {
return this.list.isEmpty();
}
public CompoundTag getCompound(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 10) {
return (CompoundTag)tag;
}
}
return new CompoundTag();
}
public ListTag getList(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 9) {
return (ListTag)tag;
}
}
return new ListTag();
}
public short getShort(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 2) {
return ((ShortTag)tag).getAsShort();
}
}
return 0;
}
public int getInt(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 3) {
return ((IntTag)tag).getAsInt();
}
}
return 0;
}
public int[] getIntArray(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 11) {
return ((IntArrayTag)tag).getAsIntArray();
}
}
return new int[0];
}
public long[] getLongArray(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 12) {
return ((LongArrayTag)tag).getAsLongArray();
}
}
return new long[0];
}
public double getDouble(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 6) {
return ((DoubleTag)tag).getAsDouble();
}
}
return 0.0D;
}
public float getFloat(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
if (tag.getId() == 5) {
return ((FloatTag)tag).getAsFloat();
}
}
return 0.0F;
}
public String getString(int pIndex) {
if (pIndex >= 0 && pIndex < this.list.size()) {
Tag tag = this.list.get(pIndex);
return tag.getId() == 8 ? tag.getAsString() : tag.toString();
} else {
return "";
}
}
public int size() {
return this.list.size();
}
public Tag get(int p_128781_) {
return this.list.get(p_128781_);
}
public Tag set(int p_128760_, Tag p_128761_) {
Tag tag = this.get(p_128760_);
if (!this.setTag(p_128760_, p_128761_)) {
throw new UnsupportedOperationException(String.format(Locale.ROOT, "Trying to add tag of type %d to list of %d", p_128761_.getId(), this.type));
} else {
return tag;
}
}
public void add(int p_128753_, Tag p_128754_) {
if (!this.addTag(p_128753_, p_128754_)) {
throw new UnsupportedOperationException(String.format(Locale.ROOT, "Trying to add tag of type %d to list of %d", p_128754_.getId(), this.type));
}
}
public boolean setTag(int pIndex, Tag pNbt) {
if (this.updateType(pNbt)) {
this.list.set(pIndex, pNbt);
return true;
} else {
return false;
}
}
public boolean addTag(int pIndex, Tag pNbt) {
if (this.updateType(pNbt)) {
this.list.add(pIndex, pNbt);
return true;
} else {
return false;
}
}
private boolean updateType(Tag pTag) {
if (pTag.getId() == 0) {
return false;
} else if (this.type == 0) {
this.type = pTag.getId();
return true;
} else {
return this.type == pTag.getId();
}
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public ListTag copy() {
Iterable<Tag> iterable = (Iterable<Tag>)(TagTypes.getType(this.type).isValue() ? this.list : Iterables.transform(this.list, Tag::copy));
List<Tag> list = Lists.newArrayList(iterable);
return new ListTag(list, this.type);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof ListTag && Objects.equals(this.list, ((ListTag)pOther).list);
}
}
public int hashCode() {
return this.list.hashCode();
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitList(this);
}
public byte getElementType() {
return this.type;
}
public void clear() {
this.list.clear();
this.type = 0;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
switch (pVisitor.visitList(TagTypes.getType(this.type), this.list.size())) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
return pVisitor.visitContainerEnd();
default:
int i = 0;
while(i < this.list.size()) {
Tag tag = this.list.get(i);
switch (pVisitor.visitElement(tag.getType(), i)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
return pVisitor.visitContainerEnd();
default:
switch (tag.accept(pVisitor)) {
case HALT:
return StreamTagVisitor.ValueResult.HALT;
case BREAK:
return pVisitor.visitContainerEnd();
}
case SKIP:
++i;
}
}
return pVisitor.visitContainerEnd();
}
}
}
@@ -0,0 +1,183 @@
package net.minecraft.nbt;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.ArrayUtils;
public class LongArrayTag extends CollectionTag<LongTag> {
private static final int SELF_SIZE_IN_BYTES = 24;
public static final TagType<LongArrayTag> TYPE = new TagType.VariableSize<LongArrayTag>() {
public LongArrayTag load(DataInput p_128865_, int p_128866_, NbtAccounter p_128867_) throws IOException {
p_128867_.accountBytes(24L);
int i = p_128865_.readInt();
p_128867_.accountBytes(8L * (long)i);
long[] along = new long[i];
for(int j = 0; j < i; ++j) {
along[j] = p_128865_.readLong();
}
return new LongArrayTag(along);
}
public StreamTagVisitor.ValueResult parse(DataInput p_197501_, StreamTagVisitor p_197502_) throws IOException {
int i = p_197501_.readInt();
long[] along = new long[i];
for(int j = 0; j < i; ++j) {
along[j] = p_197501_.readLong();
}
return p_197502_.visit(along);
}
public void skip(DataInput p_197499_) throws IOException {
p_197499_.skipBytes(p_197499_.readInt() * 8);
}
public String getName() {
return "LONG[]";
}
public String getPrettyName() {
return "TAG_Long_Array";
}
};
private long[] data;
public LongArrayTag(long[] pData) {
this.data = pData;
}
public LongArrayTag(LongSet pDataSet) {
this.data = pDataSet.toLongArray();
}
public LongArrayTag(List<Long> pDataList) {
this(toArray(pDataList));
}
private static long[] toArray(List<Long> pDataList) {
long[] along = new long[pDataList.size()];
for(int i = 0; i < pDataList.size(); ++i) {
Long olong = pDataList.get(i);
along[i] = olong == null ? 0L : olong;
}
return along;
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeInt(this.data.length);
for(long i : this.data) {
pOutput.writeLong(i);
}
}
public int sizeInBytes() {
return 24 + 8 * this.data.length;
}
public byte getId() {
return 12;
}
public TagType<LongArrayTag> getType() {
return TYPE;
}
public String toString() {
return this.getAsString();
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public LongArrayTag copy() {
long[] along = new long[this.data.length];
System.arraycopy(this.data, 0, along, 0, this.data.length);
return new LongArrayTag(along);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof LongArrayTag && Arrays.equals(this.data, ((LongArrayTag)pOther).data);
}
}
public int hashCode() {
return Arrays.hashCode(this.data);
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitLongArray(this);
}
public long[] getAsLongArray() {
return this.data;
}
public int size() {
return this.data.length;
}
public LongTag get(int p_128811_) {
return LongTag.valueOf(this.data[p_128811_]);
}
public LongTag set(int p_128813_, LongTag p_128814_) {
long i = this.data[p_128813_];
this.data[p_128813_] = p_128814_.getAsLong();
return LongTag.valueOf(i);
}
public void add(int p_128832_, LongTag p_128833_) {
this.data = ArrayUtils.add(this.data, p_128832_, p_128833_.getAsLong());
}
public boolean setTag(int pIndex, Tag pNbt) {
if (pNbt instanceof NumericTag) {
this.data[pIndex] = ((NumericTag)pNbt).getAsLong();
return true;
} else {
return false;
}
}
public boolean addTag(int pIndex, Tag pNbt) {
if (pNbt instanceof NumericTag) {
this.data = ArrayUtils.add(this.data, pIndex, ((NumericTag)pNbt).getAsLong());
return true;
} else {
return false;
}
}
public LongTag remove(int p_128830_) {
long i = this.data[p_128830_];
this.data = ArrayUtils.remove(this.data, p_128830_);
return LongTag.valueOf(i);
}
public byte getElementType() {
return 4;
}
public void clear() {
this.data = new long[0];
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
}
@@ -0,0 +1,132 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class LongTag extends NumericTag {
private static final int SELF_SIZE_IN_BYTES = 16;
public static final TagType<LongTag> TYPE = new TagType.StaticSize<LongTag>() {
public LongTag load(DataInput p_128906_, int p_128907_, NbtAccounter p_128908_) throws IOException {
p_128908_.accountBytes(16L);
return LongTag.valueOf(p_128906_.readLong());
}
public StreamTagVisitor.ValueResult parse(DataInput p_197506_, StreamTagVisitor p_197507_) throws IOException {
return p_197507_.visit(p_197506_.readLong());
}
public int size() {
return 8;
}
public String getName() {
return "LONG";
}
public String getPrettyName() {
return "TAG_Long";
}
public boolean isValue() {
return true;
}
};
private final long data;
LongTag(long pData) {
this.data = pData;
}
public static LongTag valueOf(long pData) {
return pData >= -128L && pData <= 1024L ? LongTag.Cache.cache[(int)pData - -128] : new LongTag(pData);
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeLong(this.data);
}
public int sizeInBytes() {
return 16;
}
public byte getId() {
return 4;
}
public TagType<LongTag> getType() {
return TYPE;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public LongTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof LongTag && this.data == ((LongTag)pOther).data;
}
}
public int hashCode() {
return (int)(this.data ^ this.data >>> 32);
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitLong(this);
}
public long getAsLong() {
return this.data;
}
public int getAsInt() {
return (int)(this.data & -1L);
}
public short getAsShort() {
return (short)((int)(this.data & 65535L));
}
public byte getAsByte() {
return (byte)((int)(this.data & 255L));
}
public double getAsDouble() {
return (double)this.data;
}
public float getAsFloat() {
return (float)this.data;
}
public Number getAsNumber() {
return this.data;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
static class Cache {
private static final int HIGH = 1024;
private static final int LOW = -128;
static final LongTag[] cache = new LongTag[1153];
private Cache() {
}
static {
for(int i = 0; i < cache.length; ++i) {
cache[i] = new LongTag((long)(-128 + i));
}
}
}
}
@@ -0,0 +1,68 @@
package net.minecraft.nbt;
import com.google.common.annotations.VisibleForTesting;
public class NbtAccounter {
public static final NbtAccounter UNLIMITED = new NbtAccounter(0L) {
/**
* Adds the bytes to the current number of read bytes. If the number of bytes is greater than the stored quota, an
* exception will occur.
* @throws RuntimeException if the number of {@code usage} bytes exceed the number of {@code quota} bytes
*/
public void accountBytes(long p_128927_) {
}
};
private final long quota;
private long usage;
public NbtAccounter(long pQuota) {
this.quota = pQuota;
}
/**
* Adds the bytes to the current number of read bytes. If the number of bytes is greater than the stored quota, an
* exception will occur.
* @throws RuntimeException if the number of {@code usage} bytes exceed the number of {@code quota} bytes
*/
public void accountBytes(long pBytes) {
this.usage += pBytes;
if (this.usage > this.quota) {
throw new RuntimeException("Tried to read NBT tag that was too big; tried to allocate: " + this.usage + "bytes where max allowed: " + this.quota);
}
}
/*
* UTF8 is not a simple encoding system, each character can be either
* 1, 2, or 3 bytes. Depending on where it's numerical value falls.
* We have to count up each character individually to see the true
* length of the data.
*
* Basic concept is that it uses the MSB of each byte as a 'read more' signal.
* So it has to shift each 7-bit segment.
*
* This will accurately count the correct byte length to encode this string, plus the 2 bytes for it's length prefix.
*/
public String readUTF(String data) {
accountBytes(2); //Header length
if (data == null)
return data;
int len = data.length();
int utflen = 0;
for (int i = 0; i < len; i++) {
int c = data.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) utflen += 1;
else if (c > 0x07FF) utflen += 3;
else utflen += 2;
}
accountBytes(utflen);
return data;
}
@VisibleForTesting
public long getUsage() {
return this.usage;
}
}
@@ -0,0 +1,178 @@
package net.minecraft.nbt;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.annotation.Nullable;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.util.FastBufferedInputStream;
public class NbtIo {
public static CompoundTag readCompressed(File pFile) throws IOException {
try (InputStream inputstream = new FileInputStream(pFile)) {
return readCompressed(inputstream);
}
}
private static DataInputStream createDecompressorStream(InputStream pZippedStream) throws IOException {
return new DataInputStream(new FastBufferedInputStream(new GZIPInputStream(pZippedStream)));
}
/**
* Reads a compressed compound tag from a GNU zipped file.
* @see #readCompressed(File)
*/
public static CompoundTag readCompressed(InputStream pZippedStream) throws IOException {
try (DataInputStream datainputstream = createDecompressorStream(pZippedStream)) {
return read(datainputstream, NbtAccounter.UNLIMITED);
}
}
public static void parseCompressed(File pFile, StreamTagVisitor pVisitor) throws IOException {
try (InputStream inputstream = new FileInputStream(pFile)) {
parseCompressed(inputstream, pVisitor);
}
}
public static void parseCompressed(InputStream pZippedStream, StreamTagVisitor pVisitor) throws IOException {
try (DataInputStream datainputstream = createDecompressorStream(pZippedStream)) {
parse(datainputstream, pVisitor);
}
}
public static void writeCompressed(CompoundTag pCompoundTag, File pFile) throws IOException {
try (OutputStream outputstream = new FileOutputStream(pFile)) {
writeCompressed(pCompoundTag, outputstream);
}
}
/**
* Writes and compresses a compound tag to a GNU zipped file.
* @see #writeCompressed(CompoundTag, File)
*/
public static void writeCompressed(CompoundTag pCompoundTag, OutputStream pOutputStream) throws IOException {
try (DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(pOutputStream)))) {
write(pCompoundTag, dataoutputstream);
}
}
public static void write(CompoundTag pCompoundTag, File pFile) throws IOException {
try (
FileOutputStream fileoutputstream = new FileOutputStream(pFile);
DataOutputStream dataoutputstream = new DataOutputStream(fileoutputstream);
) {
write(pCompoundTag, dataoutputstream);
}
}
@Nullable
public static CompoundTag read(File pFile) throws IOException {
if (!pFile.exists()) {
return null;
} else {
CompoundTag compoundtag;
try (
FileInputStream fileinputstream = new FileInputStream(pFile);
DataInputStream datainputstream = new DataInputStream(fileinputstream);
) {
compoundtag = read(datainputstream, NbtAccounter.UNLIMITED);
}
return compoundtag;
}
}
/**
* Reads a compound tag from a file. The size of the file can be infinite.
*/
public static CompoundTag read(DataInput pInput) throws IOException {
return read(pInput, NbtAccounter.UNLIMITED);
}
/**
* Reads a compound tag from a file. The size of the file is limited by the {@code accounter}.
* @throws RuntimeException if the size of the file is larger than the maximum amount of bytes specified by the
* {@code accounter}
*/
public static CompoundTag read(DataInput pInput, NbtAccounter pAccounter) throws IOException {
Tag tag = readUnnamedTag(pInput, 0, pAccounter);
if (tag instanceof CompoundTag) {
return (CompoundTag)tag;
} else {
throw new IOException("Root tag must be a named compound tag");
}
}
public static void write(CompoundTag pCompoundTag, DataOutput pOutput) throws IOException {
writeUnnamedTag(pCompoundTag, pOutput);
}
public static void parse(DataInput pInput, StreamTagVisitor pVisitor) throws IOException {
TagType<?> tagtype = TagTypes.getType(pInput.readByte());
if (tagtype == EndTag.TYPE) {
if (pVisitor.visitRootEntry(EndTag.TYPE) == StreamTagVisitor.ValueResult.CONTINUE) {
pVisitor.visitEnd();
}
} else {
switch (pVisitor.visitRootEntry(tagtype)) {
case HALT:
default:
break;
case BREAK:
StringTag.skipString(pInput);
tagtype.skip(pInput);
break;
case CONTINUE:
StringTag.skipString(pInput);
tagtype.parse(pInput, pVisitor);
}
}
}
public static void writeUnnamedTag(Tag pTag, DataOutput pOutput) throws IOException {
pOutput.writeByte(pTag.getId());
if (pTag.getId() != 0) {
pOutput.writeUTF("");
pTag.write(pOutput);
}
}
private static Tag readUnnamedTag(DataInput pInput, int pDepth, NbtAccounter pAccounter) throws IOException {
byte b0 = pInput.readByte();
pAccounter.accountBytes(1); // Forge: Count everything!
if (b0 == 0) {
return EndTag.INSTANCE;
} else {
pAccounter.readUTF(pInput.readUTF()); //Forge: Count this string.
pAccounter.accountBytes(4); //Forge: 4 extra bytes for the object allocation.
try {
return TagTypes.getType(b0).load(pInput, pDepth, pAccounter);
} catch (IOException ioexception) {
CrashReport crashreport = CrashReport.forThrowable(ioexception, "Loading NBT data");
CrashReportCategory crashreportcategory = crashreport.addCategory("NBT Tag");
crashreportcategory.setDetail("Tag type", b0);
throw new ReportedException(crashreport);
}
}
}
}
@@ -0,0 +1,654 @@
package net.minecraft.nbt;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mojang.datafixers.DataFixUtils;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.MapLike;
import com.mojang.serialization.RecordBuilder;
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import java.util.stream.LongStream;
import java.util.stream.Stream;
import javax.annotation.Nullable;
public class NbtOps implements DynamicOps<Tag> {
public static final NbtOps INSTANCE = new NbtOps();
private static final String WRAPPER_MARKER = "";
protected NbtOps() {
}
public Tag empty() {
return EndTag.INSTANCE;
}
public <U> U convertTo(DynamicOps<U> pOps, Tag pTag) {
switch (pTag.getId()) {
case 0:
return pOps.empty();
case 1:
return pOps.createByte(((NumericTag)pTag).getAsByte());
case 2:
return pOps.createShort(((NumericTag)pTag).getAsShort());
case 3:
return pOps.createInt(((NumericTag)pTag).getAsInt());
case 4:
return pOps.createLong(((NumericTag)pTag).getAsLong());
case 5:
return pOps.createFloat(((NumericTag)pTag).getAsFloat());
case 6:
return pOps.createDouble(((NumericTag)pTag).getAsDouble());
case 7:
return pOps.createByteList(ByteBuffer.wrap(((ByteArrayTag)pTag).getAsByteArray()));
case 8:
return pOps.createString(pTag.getAsString());
case 9:
return this.convertList(pOps, pTag);
case 10:
return this.convertMap(pOps, pTag);
case 11:
return pOps.createIntList(Arrays.stream(((IntArrayTag)pTag).getAsIntArray()));
case 12:
return pOps.createLongList(Arrays.stream(((LongArrayTag)pTag).getAsLongArray()));
default:
throw new IllegalStateException("Unknown tag type: " + pTag);
}
}
public DataResult<Number> getNumberValue(Tag pTag) {
if (pTag instanceof NumericTag numerictag) {
return DataResult.success(numerictag.getAsNumber());
} else {
return DataResult.error(() -> {
return "Not a number";
});
}
}
public Tag createNumeric(Number pData) {
return DoubleTag.valueOf(pData.doubleValue());
}
public Tag createByte(byte pData) {
return ByteTag.valueOf(pData);
}
public Tag createShort(short pData) {
return ShortTag.valueOf(pData);
}
public Tag createInt(int pData) {
return IntTag.valueOf(pData);
}
public Tag createLong(long pData) {
return LongTag.valueOf(pData);
}
public Tag createFloat(float pData) {
return FloatTag.valueOf(pData);
}
public Tag createDouble(double pData) {
return DoubleTag.valueOf(pData);
}
public Tag createBoolean(boolean pData) {
return ByteTag.valueOf(pData);
}
public DataResult<String> getStringValue(Tag pTag) {
if (pTag instanceof StringTag stringtag) {
return DataResult.success(stringtag.getAsString());
} else {
return DataResult.error(() -> {
return "Not a string";
});
}
}
public Tag createString(String pData) {
return StringTag.valueOf(pData);
}
public DataResult<Tag> mergeToList(Tag pList, Tag pTag) {
return createCollector(pList).map((p_248053_) -> {
return DataResult.success(p_248053_.accept(pTag).result());
}).orElseGet(() -> {
return DataResult.error(() -> {
return "mergeToList called with not a list: " + pList;
}, pList);
});
}
public DataResult<Tag> mergeToList(Tag pList, List<Tag> pTags) {
return createCollector(pList).map((p_248048_) -> {
return DataResult.success(p_248048_.acceptAll(pTags).result());
}).orElseGet(() -> {
return DataResult.error(() -> {
return "mergeToList called with not a list: " + pList;
}, pList);
});
}
public DataResult<Tag> mergeToMap(Tag pMap, Tag pKey, Tag pValue) {
if (!(pMap instanceof CompoundTag) && !(pMap instanceof EndTag)) {
return DataResult.error(() -> {
return "mergeToMap called with not a map: " + pMap;
}, pMap);
} else if (!(pKey instanceof StringTag)) {
return DataResult.error(() -> {
return "key is not a string: " + pKey;
}, pMap);
} else {
CompoundTag compoundtag = new CompoundTag();
if (pMap instanceof CompoundTag) {
CompoundTag compoundtag1 = (CompoundTag)pMap;
compoundtag1.getAllKeys().forEach((p_129068_) -> {
compoundtag.put(p_129068_, compoundtag1.get(p_129068_));
});
}
compoundtag.put(pKey.getAsString(), pValue);
return DataResult.success(compoundtag);
}
}
public DataResult<Tag> mergeToMap(Tag pMap, MapLike<Tag> pOtherMap) {
if (!(pMap instanceof CompoundTag) && !(pMap instanceof EndTag)) {
return DataResult.error(() -> {
return "mergeToMap called with not a map: " + pMap;
}, pMap);
} else {
CompoundTag compoundtag = new CompoundTag();
if (pMap instanceof CompoundTag) {
CompoundTag compoundtag1 = (CompoundTag)pMap;
compoundtag1.getAllKeys().forEach((p_129059_) -> {
compoundtag.put(p_129059_, compoundtag1.get(p_129059_));
});
}
List<Tag> list = Lists.newArrayList();
pOtherMap.entries().forEach((p_128994_) -> {
Tag tag = p_128994_.getFirst();
if (!(tag instanceof StringTag)) {
list.add(tag);
} else {
compoundtag.put(tag.getAsString(), p_128994_.getSecond());
}
});
return !list.isEmpty() ? DataResult.error(() -> {
return "some keys are not strings: " + list;
}, compoundtag) : DataResult.success(compoundtag);
}
}
public DataResult<Stream<Pair<Tag, Tag>>> getMapValues(Tag pMap) {
if (pMap instanceof CompoundTag compoundtag) {
return DataResult.success(compoundtag.getAllKeys().stream().map((p_129021_) -> {
return Pair.of(this.createString(p_129021_), compoundtag.get(p_129021_));
}));
} else {
return DataResult.error(() -> {
return "Not a map: " + pMap;
});
}
}
public DataResult<Consumer<BiConsumer<Tag, Tag>>> getMapEntries(Tag pMap) {
if (pMap instanceof CompoundTag compoundtag) {
return DataResult.success((p_129024_) -> {
compoundtag.getAllKeys().forEach((p_178006_) -> {
p_129024_.accept(this.createString(p_178006_), compoundtag.get(p_178006_));
});
});
} else {
return DataResult.error(() -> {
return "Not a map: " + pMap;
});
}
}
public DataResult<MapLike<Tag>> getMap(Tag pMap) {
if (pMap instanceof final CompoundTag compoundtag) {
return DataResult.success(new MapLike<Tag>() {
@Nullable
public Tag get(Tag p_129174_) {
return compoundtag.get(p_129174_.getAsString());
}
@Nullable
public Tag get(String p_129169_) {
return compoundtag.get(p_129169_);
}
public Stream<Pair<Tag, Tag>> entries() {
return compoundtag.getAllKeys().stream().map((p_129172_) -> {
return Pair.of(NbtOps.this.createString(p_129172_), compoundtag.get(p_129172_));
});
}
public String toString() {
return "MapLike[" + compoundtag + "]";
}
});
} else {
return DataResult.error(() -> {
return "Not a map: " + pMap;
});
}
}
public Tag createMap(Stream<Pair<Tag, Tag>> pData) {
CompoundTag compoundtag = new CompoundTag();
pData.forEach((p_129018_) -> {
compoundtag.put(p_129018_.getFirst().getAsString(), p_129018_.getSecond());
});
return compoundtag;
}
private static Tag tryUnwrap(CompoundTag pTag) {
if (pTag.size() == 1) {
Tag tag = pTag.get("");
if (tag != null) {
return tag;
}
}
return pTag;
}
public DataResult<Stream<Tag>> getStream(Tag pTag) {
if (pTag instanceof ListTag listtag) {
return listtag.getElementType() == 10 ? DataResult.success(listtag.stream().map((p_248049_) -> {
return tryUnwrap((CompoundTag)p_248049_);
})) : DataResult.success(listtag.stream());
} else if (pTag instanceof CollectionTag<?> collectiontag) {
return DataResult.success(collectiontag.stream().map((p_129158_) -> {
return p_129158_;
}));
} else {
return DataResult.error(() -> {
return "Not a list";
});
}
}
public DataResult<Consumer<Consumer<Tag>>> getList(Tag pTag) {
if (pTag instanceof ListTag listtag) {
return listtag.getElementType() == 10 ? DataResult.success((p_248055_) -> {
listtag.forEach((p_248051_) -> {
p_248055_.accept(tryUnwrap((CompoundTag)p_248051_));
});
}) : DataResult.success(listtag::forEach);
} else if (pTag instanceof CollectionTag<?> collectiontag) {
return DataResult.success(collectiontag::forEach);
} else {
return DataResult.error(() -> {
return "Not a list: " + pTag;
});
}
}
public DataResult<ByteBuffer> getByteBuffer(Tag pTag) {
if (pTag instanceof ByteArrayTag bytearraytag) {
return DataResult.success(ByteBuffer.wrap(bytearraytag.getAsByteArray()));
} else {
return DynamicOps.super.getByteBuffer(pTag);
}
}
public Tag createByteList(ByteBuffer pData) {
return new ByteArrayTag(DataFixUtils.toArray(pData));
}
public DataResult<IntStream> getIntStream(Tag pTag) {
if (pTag instanceof IntArrayTag intarraytag) {
return DataResult.success(Arrays.stream(intarraytag.getAsIntArray()));
} else {
return DynamicOps.super.getIntStream(pTag);
}
}
public Tag createIntList(IntStream pData) {
return new IntArrayTag(pData.toArray());
}
public DataResult<LongStream> getLongStream(Tag pTag) {
if (pTag instanceof LongArrayTag longarraytag) {
return DataResult.success(Arrays.stream(longarraytag.getAsLongArray()));
} else {
return DynamicOps.super.getLongStream(pTag);
}
}
public Tag createLongList(LongStream pData) {
return new LongArrayTag(pData.toArray());
}
public Tag createList(Stream<Tag> pData) {
return NbtOps.InitialListCollector.INSTANCE.acceptAll(pData).result();
}
public Tag remove(Tag pMap, String pRemoveKey) {
if (pMap instanceof CompoundTag compoundtag) {
CompoundTag compoundtag1 = new CompoundTag();
compoundtag.getAllKeys().stream().filter((p_128988_) -> {
return !Objects.equals(p_128988_, pRemoveKey);
}).forEach((p_129028_) -> {
compoundtag1.put(p_129028_, compoundtag.get(p_129028_));
});
return compoundtag1;
} else {
return pMap;
}
}
public String toString() {
return "NBT";
}
public RecordBuilder<Tag> mapBuilder() {
return new NbtOps.NbtRecordBuilder();
}
private static Optional<NbtOps.ListCollector> createCollector(Tag pTag) {
if (pTag instanceof EndTag) {
return Optional.of(NbtOps.InitialListCollector.INSTANCE);
} else {
if (pTag instanceof CollectionTag) {
CollectionTag<?> collectiontag = (CollectionTag)pTag;
if (collectiontag.isEmpty()) {
return Optional.of(NbtOps.InitialListCollector.INSTANCE);
}
if (collectiontag instanceof ListTag) {
ListTag listtag = (ListTag)collectiontag;
Optional optional;
switch (listtag.getElementType()) {
case 0:
optional = Optional.of(NbtOps.InitialListCollector.INSTANCE);
break;
case 10:
optional = Optional.of(new NbtOps.HeterogenousListCollector(listtag));
break;
default:
optional = Optional.of(new NbtOps.HomogenousListCollector(listtag));
}
return optional;
}
if (collectiontag instanceof ByteArrayTag) {
ByteArrayTag bytearraytag = (ByteArrayTag)collectiontag;
return Optional.of(new NbtOps.ByteListCollector(bytearraytag.getAsByteArray()));
}
if (collectiontag instanceof IntArrayTag) {
IntArrayTag intarraytag = (IntArrayTag)collectiontag;
return Optional.of(new NbtOps.IntListCollector(intarraytag.getAsIntArray()));
}
if (collectiontag instanceof LongArrayTag) {
LongArrayTag longarraytag = (LongArrayTag)collectiontag;
return Optional.of(new NbtOps.LongListCollector(longarraytag.getAsLongArray()));
}
}
return Optional.empty();
}
}
static class ByteListCollector implements NbtOps.ListCollector {
private final ByteArrayList values = new ByteArrayList();
public ByteListCollector(byte pValue) {
this.values.add(pValue);
}
public ByteListCollector(byte[] pValues) {
this.values.addElements(0, pValues);
}
public NbtOps.ListCollector accept(Tag pTag) {
if (pTag instanceof ByteTag bytetag) {
this.values.add(bytetag.getAsByte());
return this;
} else {
return (new NbtOps.HeterogenousListCollector(this.values)).accept(pTag);
}
}
public Tag result() {
return new ByteArrayTag(this.values.toByteArray());
}
}
static class HeterogenousListCollector implements NbtOps.ListCollector {
private final ListTag result = new ListTag();
public HeterogenousListCollector() {
}
public HeterogenousListCollector(Collection<Tag> p_249606_) {
this.result.addAll(p_249606_);
}
public HeterogenousListCollector(IntArrayList p_250270_) {
p_250270_.forEach((p_249166_) -> {
this.result.add(wrapElement(IntTag.valueOf(p_249166_)));
});
}
public HeterogenousListCollector(ByteArrayList p_248575_) {
p_248575_.forEach((p_249160_) -> {
this.result.add(wrapElement(ByteTag.valueOf(p_249160_)));
});
}
public HeterogenousListCollector(LongArrayList p_249410_) {
p_249410_.forEach((p_249754_) -> {
this.result.add(wrapElement(LongTag.valueOf(p_249754_)));
});
}
private static boolean isWrapper(CompoundTag p_252073_) {
return p_252073_.size() == 1 && p_252073_.contains("");
}
private static Tag wrapIfNeeded(Tag p_252042_) {
if (p_252042_ instanceof CompoundTag compoundtag) {
if (!isWrapper(compoundtag)) {
return compoundtag;
}
}
return wrapElement(p_252042_);
}
private static CompoundTag wrapElement(Tag p_251263_) {
CompoundTag compoundtag = new CompoundTag();
compoundtag.put("", p_251263_);
return compoundtag;
}
public NbtOps.ListCollector accept(Tag p_249045_) {
this.result.add(wrapIfNeeded(p_249045_));
return this;
}
public Tag result() {
return this.result;
}
}
static class HomogenousListCollector implements NbtOps.ListCollector {
private final ListTag result = new ListTag();
HomogenousListCollector(Tag pValue) {
this.result.add(pValue);
}
HomogenousListCollector(ListTag pValues) {
this.result.addAll(pValues);
}
public NbtOps.ListCollector accept(Tag pTag) {
if (pTag.getId() != this.result.getElementType()) {
return (new NbtOps.HeterogenousListCollector()).acceptAll(this.result).accept(pTag);
} else {
this.result.add(pTag);
return this;
}
}
public Tag result() {
return this.result;
}
}
static class InitialListCollector implements NbtOps.ListCollector {
public static final NbtOps.InitialListCollector INSTANCE = new NbtOps.InitialListCollector();
private InitialListCollector() {
}
public NbtOps.ListCollector accept(Tag p_251635_) {
if (p_251635_ instanceof CompoundTag compoundtag) {
return (new NbtOps.HeterogenousListCollector()).accept(compoundtag);
} else if (p_251635_ instanceof ByteTag bytetag) {
return new NbtOps.ByteListCollector(bytetag.getAsByte());
} else if (p_251635_ instanceof IntTag inttag) {
return new NbtOps.IntListCollector(inttag.getAsInt());
} else if (p_251635_ instanceof LongTag longtag) {
return new NbtOps.LongListCollector(longtag.getAsLong());
} else {
return new NbtOps.HomogenousListCollector(p_251635_);
}
}
public Tag result() {
return new ListTag();
}
}
static class IntListCollector implements NbtOps.ListCollector {
private final IntArrayList values = new IntArrayList();
public IntListCollector(int pValue) {
this.values.add(pValue);
}
public IntListCollector(int[] pValues) {
this.values.addElements(0, pValues);
}
public NbtOps.ListCollector accept(Tag pTag) {
if (pTag instanceof IntTag inttag) {
this.values.add(inttag.getAsInt());
return this;
} else {
return (new NbtOps.HeterogenousListCollector(this.values)).accept(pTag);
}
}
public Tag result() {
return new IntArrayTag(this.values.toIntArray());
}
}
interface ListCollector {
NbtOps.ListCollector accept(Tag pTag);
default NbtOps.ListCollector acceptAll(Iterable<Tag> p_249781_) {
NbtOps.ListCollector nbtops$listcollector = this;
for(Tag tag : p_249781_) {
nbtops$listcollector = nbtops$listcollector.accept(tag);
}
return nbtops$listcollector;
}
default NbtOps.ListCollector acceptAll(Stream<Tag> p_249876_) {
return this.acceptAll(p_249876_::iterator);
}
Tag result();
}
static class LongListCollector implements NbtOps.ListCollector {
private final LongArrayList values = new LongArrayList();
public LongListCollector(long pValue) {
this.values.add(pValue);
}
public LongListCollector(long[] pValues) {
this.values.addElements(0, pValues);
}
public NbtOps.ListCollector accept(Tag pTag) {
if (pTag instanceof LongTag longtag) {
this.values.add(longtag.getAsLong());
return this;
} else {
return (new NbtOps.HeterogenousListCollector(this.values)).accept(pTag);
}
}
public Tag result() {
return new LongArrayTag(this.values.toLongArray());
}
}
class NbtRecordBuilder extends RecordBuilder.AbstractStringBuilder<Tag, CompoundTag> {
protected NbtRecordBuilder() {
super(NbtOps.this);
}
protected CompoundTag initBuilder() {
return new CompoundTag();
}
protected CompoundTag append(String pKey, Tag pValue, CompoundTag pTag) {
pTag.put(pKey, pValue);
return pTag;
}
protected DataResult<Tag> build(CompoundTag p_129190_, Tag p_129191_) {
if (p_129191_ != null && p_129191_ != EndTag.INSTANCE) {
if (!(p_129191_ instanceof CompoundTag)) {
return DataResult.error(() -> {
return "mergeToMap called with not a map: " + p_129191_;
}, p_129191_);
} else {
CompoundTag compoundtag = (CompoundTag)p_129191_;
CompoundTag compoundtag1 = new CompoundTag(Maps.newHashMap(compoundtag.entries()));
for(Map.Entry<String, Tag> entry : p_129190_.entries().entrySet()) {
compoundtag1.put(entry.getKey(), entry.getValue());
}
return DataResult.success(compoundtag1);
}
} else {
return DataResult.success(p_129190_);
}
}
}
}
@@ -0,0 +1,657 @@
package net.minecraft.nbt;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderGetter;
import net.minecraft.core.UUIDUtil;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringUtil;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.StateHolder;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.FluidState;
import org.slf4j.Logger;
public final class NbtUtils {
private static final Comparator<ListTag> YXZ_LISTTAG_INT_COMPARATOR = Comparator.<ListTag>comparingInt((p_178074_) -> {
return p_178074_.getInt(1);
}).thenComparingInt((p_178070_) -> {
return p_178070_.getInt(0);
}).thenComparingInt((p_178066_) -> {
return p_178066_.getInt(2);
});
private static final Comparator<ListTag> YXZ_LISTTAG_DOUBLE_COMPARATOR = Comparator.<ListTag>comparingDouble((p_178060_) -> {
return p_178060_.getDouble(1);
}).thenComparingDouble((p_178056_) -> {
return p_178056_.getDouble(0);
}).thenComparingDouble((p_178042_) -> {
return p_178042_.getDouble(2);
});
public static final String SNBT_DATA_TAG = "data";
private static final char PROPERTIES_START = '{';
private static final char PROPERTIES_END = '}';
private static final String ELEMENT_SEPARATOR = ",";
private static final char KEY_VALUE_SEPARATOR = ':';
private static final Splitter COMMA_SPLITTER = Splitter.on(",");
private static final Splitter COLON_SPLITTER = Splitter.on(':').limit(2);
private static final Logger LOGGER = LogUtils.getLogger();
private static final int INDENT = 2;
private static final int NOT_FOUND = -1;
private NbtUtils() {
}
@Nullable
public static GameProfile readGameProfile(CompoundTag pTag) {
String s = null;
UUID uuid = null;
if (pTag.contains("Name", 8)) {
s = pTag.getString("Name");
}
if (pTag.hasUUID("Id")) {
uuid = pTag.getUUID("Id");
}
try {
GameProfile gameprofile = new GameProfile(uuid, s);
if (pTag.contains("Properties", 10)) {
CompoundTag compoundtag = pTag.getCompound("Properties");
for(String s1 : compoundtag.getAllKeys()) {
ListTag listtag = compoundtag.getList(s1, 10);
for(int i = 0; i < listtag.size(); ++i) {
CompoundTag compoundtag1 = listtag.getCompound(i);
String s2 = compoundtag1.getString("Value");
if (compoundtag1.contains("Signature", 8)) {
gameprofile.getProperties().put(s1, new com.mojang.authlib.properties.Property(s1, s2, compoundtag1.getString("Signature")));
} else {
gameprofile.getProperties().put(s1, new com.mojang.authlib.properties.Property(s1, s2));
}
}
}
}
return gameprofile;
} catch (Throwable throwable) {
return null;
}
}
/**
* Writes a {@code profile} to the given {@code tag}.
*/
public static CompoundTag writeGameProfile(CompoundTag pTag, GameProfile pProfile) {
if (!StringUtil.isNullOrEmpty(pProfile.getName())) {
pTag.putString("Name", pProfile.getName());
}
if (pProfile.getId() != null) {
pTag.putUUID("Id", pProfile.getId());
}
if (!pProfile.getProperties().isEmpty()) {
CompoundTag compoundtag = new CompoundTag();
for(String s : pProfile.getProperties().keySet()) {
ListTag listtag = new ListTag();
for(com.mojang.authlib.properties.Property property : pProfile.getProperties().get(s)) {
CompoundTag compoundtag1 = new CompoundTag();
compoundtag1.putString("Value", property.getValue());
if (property.hasSignature()) {
compoundtag1.putString("Signature", property.getSignature());
}
listtag.add(compoundtag1);
}
compoundtag.put(s, listtag);
}
pTag.put("Properties", compoundtag);
}
return pTag;
}
@VisibleForTesting
public static boolean compareNbt(@Nullable Tag pTag, @Nullable Tag pOther, boolean pCompareListTag) {
if (pTag == pOther) {
return true;
} else if (pTag == null) {
return true;
} else if (pOther == null) {
return false;
} else if (!pTag.getClass().equals(pOther.getClass())) {
return false;
} else if (pTag instanceof CompoundTag) {
CompoundTag compoundtag = (CompoundTag)pTag;
CompoundTag compoundtag1 = (CompoundTag)pOther;
for(String s : compoundtag.getAllKeys()) {
Tag tag1 = compoundtag.get(s);
if (!compareNbt(tag1, compoundtag1.get(s), pCompareListTag)) {
return false;
}
}
return true;
} else if (pTag instanceof ListTag && pCompareListTag) {
ListTag listtag = (ListTag)pTag;
ListTag listtag1 = (ListTag)pOther;
if (listtag.isEmpty()) {
return listtag1.isEmpty();
} else {
for(int i = 0; i < listtag.size(); ++i) {
Tag tag = listtag.get(i);
boolean flag = false;
for(int j = 0; j < listtag1.size(); ++j) {
if (compareNbt(tag, listtag1.get(j), pCompareListTag)) {
flag = true;
break;
}
}
if (!flag) {
return false;
}
}
return true;
}
} else {
return pTag.equals(pOther);
}
}
public static IntArrayTag createUUID(UUID pUuid) {
return new IntArrayTag(UUIDUtil.uuidToIntArray(pUuid));
}
public static UUID loadUUID(Tag pTag) {
if (pTag.getType() != IntArrayTag.TYPE) {
throw new IllegalArgumentException("Expected UUID-Tag to be of type " + IntArrayTag.TYPE.getName() + ", but found " + pTag.getType().getName() + ".");
} else {
int[] aint = ((IntArrayTag)pTag).getAsIntArray();
if (aint.length != 4) {
throw new IllegalArgumentException("Expected UUID-Array to be of length 4, but found " + aint.length + ".");
} else {
return UUIDUtil.uuidFromIntArray(aint);
}
}
}
public static BlockPos readBlockPos(CompoundTag pTag) {
return new BlockPos(pTag.getInt("X"), pTag.getInt("Y"), pTag.getInt("Z"));
}
public static CompoundTag writeBlockPos(BlockPos pPos) {
CompoundTag compoundtag = new CompoundTag();
compoundtag.putInt("X", pPos.getX());
compoundtag.putInt("Y", pPos.getY());
compoundtag.putInt("Z", pPos.getZ());
return compoundtag;
}
public static BlockState readBlockState(HolderGetter<Block> pBlockGetter, CompoundTag pTag) {
if (!pTag.contains("Name", 8)) {
return Blocks.AIR.defaultBlockState();
} else {
ResourceLocation resourcelocation = new ResourceLocation(pTag.getString("Name"));
Optional<? extends Holder<Block>> optional = pBlockGetter.get(ResourceKey.create(Registries.BLOCK, resourcelocation));
if (optional.isEmpty()) {
return Blocks.AIR.defaultBlockState();
} else {
Block block = optional.get().value();
BlockState blockstate = block.defaultBlockState();
if (pTag.contains("Properties", 10)) {
CompoundTag compoundtag = pTag.getCompound("Properties");
StateDefinition<Block, BlockState> statedefinition = block.getStateDefinition();
for(String s : compoundtag.getAllKeys()) {
Property<?> property = statedefinition.getProperty(s);
if (property != null) {
blockstate = setValueHelper(blockstate, property, s, compoundtag, pTag);
}
}
}
return blockstate;
}
}
}
private static <S extends StateHolder<?, S>, T extends Comparable<T>> S setValueHelper(S pStateHolder, Property<T> pProperty, String pPropertyName, CompoundTag pPropertiesTag, CompoundTag pBlockStateTag) {
Optional<T> optional = pProperty.getValue(pPropertiesTag.getString(pPropertyName));
if (optional.isPresent()) {
return pStateHolder.setValue(pProperty, optional.get());
} else {
LOGGER.warn("Unable to read property: {} with value: {} for blockstate: {}", pPropertyName, pPropertiesTag.getString(pPropertyName), pBlockStateTag.toString());
return pStateHolder;
}
}
public static CompoundTag writeBlockState(BlockState pState) {
CompoundTag compoundtag = new CompoundTag();
compoundtag.putString("Name", BuiltInRegistries.BLOCK.getKey(pState.getBlock()).toString());
ImmutableMap<Property<?>, Comparable<?>> immutablemap = pState.getValues();
if (!immutablemap.isEmpty()) {
CompoundTag compoundtag1 = new CompoundTag();
for(Map.Entry<Property<?>, Comparable<?>> entry : immutablemap.entrySet()) {
Property<?> property = entry.getKey();
compoundtag1.putString(property.getName(), getName(property, entry.getValue()));
}
compoundtag.put("Properties", compoundtag1);
}
return compoundtag;
}
public static CompoundTag writeFluidState(FluidState pState) {
CompoundTag compoundtag = new CompoundTag();
compoundtag.putString("Name", BuiltInRegistries.FLUID.getKey(pState.getType()).toString());
ImmutableMap<Property<?>, Comparable<?>> immutablemap = pState.getValues();
if (!immutablemap.isEmpty()) {
CompoundTag compoundtag1 = new CompoundTag();
for(Map.Entry<Property<?>, Comparable<?>> entry : immutablemap.entrySet()) {
Property<?> property = entry.getKey();
compoundtag1.putString(property.getName(), getName(property, entry.getValue()));
}
compoundtag.put("Properties", compoundtag1);
}
return compoundtag;
}
private static <T extends Comparable<T>> String getName(Property<T> pProperty, Comparable<?> pValue) {
return pProperty.getName((T)pValue);
}
public static String prettyPrint(Tag pTag) {
return prettyPrint(pTag, false);
}
public static String prettyPrint(Tag pTag, boolean pPrettyPrintArray) {
return prettyPrint(new StringBuilder(), pTag, 0, pPrettyPrintArray).toString();
}
public static StringBuilder prettyPrint(StringBuilder pStringBuilder, Tag pTag, int pIndentLevel, boolean pPrettyPrintArray) {
switch (pTag.getId()) {
case 0:
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 8:
pStringBuilder.append((Object)pTag);
break;
case 7:
ByteArrayTag bytearraytag = (ByteArrayTag)pTag;
byte[] abyte = bytearraytag.getAsByteArray();
int k1 = abyte.length;
indent(pIndentLevel, pStringBuilder).append("byte[").append(k1).append("] {\n");
if (!pPrettyPrintArray) {
indent(pIndentLevel + 1, pStringBuilder).append(" // Skipped, supply withBinaryBlobs true");
} else {
indent(pIndentLevel + 1, pStringBuilder);
for(int i2 = 0; i2 < abyte.length; ++i2) {
if (i2 != 0) {
pStringBuilder.append(',');
}
if (i2 % 16 == 0 && i2 / 16 > 0) {
pStringBuilder.append('\n');
if (i2 < abyte.length) {
indent(pIndentLevel + 1, pStringBuilder);
}
} else if (i2 != 0) {
pStringBuilder.append(' ');
}
pStringBuilder.append(String.format(Locale.ROOT, "0x%02X", abyte[i2] & 255));
}
}
pStringBuilder.append('\n');
indent(pIndentLevel, pStringBuilder).append('}');
break;
case 9:
ListTag listtag = (ListTag)pTag;
int k = listtag.size();
int j1 = listtag.getElementType();
String s1 = j1 == 0 ? "undefined" : TagTypes.getType(j1).getPrettyName();
indent(pIndentLevel, pStringBuilder).append("list<").append(s1).append(">[").append(k).append("] [");
if (k != 0) {
pStringBuilder.append('\n');
}
for(int i3 = 0; i3 < k; ++i3) {
if (i3 != 0) {
pStringBuilder.append(",\n");
}
indent(pIndentLevel + 1, pStringBuilder);
prettyPrint(pStringBuilder, listtag.get(i3), pIndentLevel + 1, pPrettyPrintArray);
}
if (k != 0) {
pStringBuilder.append('\n');
}
indent(pIndentLevel, pStringBuilder).append(']');
break;
case 10:
CompoundTag compoundtag = (CompoundTag)pTag;
List<String> list = Lists.newArrayList(compoundtag.getAllKeys());
Collections.sort(list);
indent(pIndentLevel, pStringBuilder).append('{');
if (pStringBuilder.length() - pStringBuilder.lastIndexOf("\n") > 2 * (pIndentLevel + 1)) {
pStringBuilder.append('\n');
indent(pIndentLevel + 1, pStringBuilder);
}
int i1 = list.stream().mapToInt(String::length).max().orElse(0);
String s = Strings.repeat(" ", i1);
for(int l2 = 0; l2 < list.size(); ++l2) {
if (l2 != 0) {
pStringBuilder.append(",\n");
}
String s2 = list.get(l2);
indent(pIndentLevel + 1, pStringBuilder).append('"').append(s2).append('"').append((CharSequence)s, 0, s.length() - s2.length()).append(": ");
prettyPrint(pStringBuilder, compoundtag.get(s2), pIndentLevel + 1, pPrettyPrintArray);
}
if (!list.isEmpty()) {
pStringBuilder.append('\n');
}
indent(pIndentLevel, pStringBuilder).append('}');
break;
case 11:
IntArrayTag intarraytag = (IntArrayTag)pTag;
int[] aint = intarraytag.getAsIntArray();
int l = 0;
for(int k3 : aint) {
l = Math.max(l, String.format(Locale.ROOT, "%X", k3).length());
}
int l1 = aint.length;
indent(pIndentLevel, pStringBuilder).append("int[").append(l1).append("] {\n");
if (!pPrettyPrintArray) {
indent(pIndentLevel + 1, pStringBuilder).append(" // Skipped, supply withBinaryBlobs true");
} else {
indent(pIndentLevel + 1, pStringBuilder);
for(int k2 = 0; k2 < aint.length; ++k2) {
if (k2 != 0) {
pStringBuilder.append(',');
}
if (k2 % 16 == 0 && k2 / 16 > 0) {
pStringBuilder.append('\n');
if (k2 < aint.length) {
indent(pIndentLevel + 1, pStringBuilder);
}
} else if (k2 != 0) {
pStringBuilder.append(' ');
}
pStringBuilder.append(String.format(Locale.ROOT, "0x%0" + l + "X", aint[k2]));
}
}
pStringBuilder.append('\n');
indent(pIndentLevel, pStringBuilder).append('}');
break;
case 12:
LongArrayTag longarraytag = (LongArrayTag)pTag;
long[] along = longarraytag.getAsLongArray();
long i = 0L;
for(long j : along) {
i = Math.max(i, (long)String.format(Locale.ROOT, "%X", j).length());
}
long j2 = (long)along.length;
indent(pIndentLevel, pStringBuilder).append("long[").append(j2).append("] {\n");
if (!pPrettyPrintArray) {
indent(pIndentLevel + 1, pStringBuilder).append(" // Skipped, supply withBinaryBlobs true");
} else {
indent(pIndentLevel + 1, pStringBuilder);
for(int j3 = 0; j3 < along.length; ++j3) {
if (j3 != 0) {
pStringBuilder.append(',');
}
if (j3 % 16 == 0 && j3 / 16 > 0) {
pStringBuilder.append('\n');
if (j3 < along.length) {
indent(pIndentLevel + 1, pStringBuilder);
}
} else if (j3 != 0) {
pStringBuilder.append(' ');
}
pStringBuilder.append(String.format(Locale.ROOT, "0x%0" + i + "X", along[j3]));
}
}
pStringBuilder.append('\n');
indent(pIndentLevel, pStringBuilder).append('}');
break;
default:
pStringBuilder.append("<UNKNOWN :(>");
}
return pStringBuilder;
}
private static StringBuilder indent(int pIndentLevel, StringBuilder pStringBuilder) {
int i = pStringBuilder.lastIndexOf("\n") + 1;
int j = pStringBuilder.length() - i;
for(int k = 0; k < 2 * pIndentLevel - j; ++k) {
pStringBuilder.append(' ');
}
return pStringBuilder;
}
public static Component toPrettyComponent(Tag pTag) {
return (new TextComponentTagVisitor("", 0)).visit(pTag);
}
public static String structureToSnbt(CompoundTag pTag) {
return (new SnbtPrinterTagVisitor()).visit(packStructureTemplate(pTag));
}
public static CompoundTag snbtToStructure(String pText) throws CommandSyntaxException {
return unpackStructureTemplate(TagParser.parseTag(pText));
}
@VisibleForTesting
static CompoundTag packStructureTemplate(CompoundTag pTag) {
boolean flag = pTag.contains("palettes", 9);
ListTag listtag;
if (flag) {
listtag = pTag.getList("palettes", 9).getList(0);
} else {
listtag = pTag.getList("palette", 10);
}
ListTag listtag1 = listtag.stream().map(CompoundTag.class::cast).map(NbtUtils::packBlockState).map(StringTag::valueOf).collect(Collectors.toCollection(ListTag::new));
pTag.put("palette", listtag1);
if (flag) {
ListTag listtag2 = new ListTag();
ListTag listtag3 = pTag.getList("palettes", 9);
listtag3.stream().map(ListTag.class::cast).forEach((p_178049_) -> {
CompoundTag compoundtag = new CompoundTag();
for(int i = 0; i < p_178049_.size(); ++i) {
compoundtag.putString(listtag1.getString(i), packBlockState(p_178049_.getCompound(i)));
}
listtag2.add(compoundtag);
});
pTag.put("palettes", listtag2);
}
if (pTag.contains("entities", 9)) {
ListTag listtag4 = pTag.getList("entities", 10);
ListTag listtag6 = listtag4.stream().map(CompoundTag.class::cast).sorted(Comparator.comparing((p_178080_) -> {
return p_178080_.getList("pos", 6);
}, YXZ_LISTTAG_DOUBLE_COMPARATOR)).collect(Collectors.toCollection(ListTag::new));
pTag.put("entities", listtag6);
}
ListTag listtag5 = pTag.getList("blocks", 10).stream().map(CompoundTag.class::cast).sorted(Comparator.comparing((p_178078_) -> {
return p_178078_.getList("pos", 3);
}, YXZ_LISTTAG_INT_COMPARATOR)).peek((p_178045_) -> {
p_178045_.putString("state", listtag1.getString(p_178045_.getInt("state")));
}).collect(Collectors.toCollection(ListTag::new));
pTag.put("data", listtag5);
pTag.remove("blocks");
return pTag;
}
@VisibleForTesting
static CompoundTag unpackStructureTemplate(CompoundTag pTag) {
ListTag listtag = pTag.getList("palette", 8);
Map<String, Tag> map = listtag.stream().map(StringTag.class::cast).map(StringTag::getAsString).collect(ImmutableMap.toImmutableMap(Function.identity(), NbtUtils::unpackBlockState));
if (pTag.contains("palettes", 9)) {
pTag.put("palettes", pTag.getList("palettes", 10).stream().map(CompoundTag.class::cast).map((p_178033_) -> {
return map.keySet().stream().map(p_178033_::getString).map(NbtUtils::unpackBlockState).collect(Collectors.toCollection(ListTag::new));
}).collect(Collectors.toCollection(ListTag::new)));
pTag.remove("palette");
} else {
pTag.put("palette", map.values().stream().collect(Collectors.toCollection(ListTag::new)));
}
if (pTag.contains("data", 9)) {
Object2IntMap<String> object2intmap = new Object2IntOpenHashMap<>();
object2intmap.defaultReturnValue(-1);
for(int i = 0; i < listtag.size(); ++i) {
object2intmap.put(listtag.getString(i), i);
}
ListTag listtag1 = pTag.getList("data", 10);
for(int j = 0; j < listtag1.size(); ++j) {
CompoundTag compoundtag = listtag1.getCompound(j);
String s = compoundtag.getString("state");
int k = object2intmap.getInt(s);
if (k == -1) {
throw new IllegalStateException("Entry " + s + " missing from palette");
}
compoundtag.putInt("state", k);
}
pTag.put("blocks", listtag1);
pTag.remove("data");
}
return pTag;
}
@VisibleForTesting
static String packBlockState(CompoundTag p_178076_) {
StringBuilder stringbuilder = new StringBuilder(p_178076_.getString("Name"));
if (p_178076_.contains("Properties", 10)) {
CompoundTag compoundtag = p_178076_.getCompound("Properties");
String s = compoundtag.getAllKeys().stream().sorted().map((p_178036_) -> {
return p_178036_ + ":" + compoundtag.get(p_178036_).getAsString();
}).collect(Collectors.joining(","));
stringbuilder.append('{').append(s).append('}');
}
return stringbuilder.toString();
}
@VisibleForTesting
static CompoundTag unpackBlockState(String p_178054_) {
CompoundTag compoundtag = new CompoundTag();
int i = p_178054_.indexOf(123);
String s;
if (i >= 0) {
s = p_178054_.substring(0, i);
CompoundTag compoundtag1 = new CompoundTag();
if (i + 2 <= p_178054_.length()) {
String s1 = p_178054_.substring(i + 1, p_178054_.indexOf(125, i));
COMMA_SPLITTER.split(s1).forEach((p_178040_) -> {
List<String> list = COLON_SPLITTER.splitToList(p_178040_);
if (list.size() == 2) {
compoundtag1.putString(list.get(0), list.get(1));
} else {
LOGGER.error("Something went wrong parsing: '{}' -- incorrect gamedata!", (Object)p_178054_);
}
});
compoundtag.put("Properties", compoundtag1);
}
} else {
s = p_178054_;
}
compoundtag.putString("Name", s);
return compoundtag;
}
public static CompoundTag addCurrentDataVersion(CompoundTag pTag) {
int i = SharedConstants.getCurrentVersion().getDataVersion().getVersion();
return addDataVersion(pTag, i);
}
public static CompoundTag addDataVersion(CompoundTag pTag, int pDataVersion) {
pTag.putInt("DataVersion", pDataVersion);
return pTag;
}
public static int getDataVersion(CompoundTag pTag, int pDefaultValue) {
return pTag.contains("DataVersion", 99) ? pTag.getInt("DataVersion") : pDefaultValue;
}
}
@@ -0,0 +1,24 @@
package net.minecraft.nbt;
public abstract class NumericTag implements Tag {
protected NumericTag() {
}
public abstract long getAsLong();
public abstract int getAsInt();
public abstract short getAsShort();
public abstract byte getAsByte();
public abstract double getAsDouble();
public abstract float getAsFloat();
public abstract Number getAsNumber();
public String toString() {
return this.getAsString();
}
}
@@ -0,0 +1,132 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class ShortTag extends NumericTag {
private static final int SELF_SIZE_IN_BYTES = 10;
public static final TagType<ShortTag> TYPE = new TagType.StaticSize<ShortTag>() {
public ShortTag load(DataInput p_129277_, int p_129278_, NbtAccounter p_129279_) throws IOException {
p_129279_.accountBytes(10L);
return ShortTag.valueOf(p_129277_.readShort());
}
public StreamTagVisitor.ValueResult parse(DataInput p_197517_, StreamTagVisitor p_197518_) throws IOException {
return p_197518_.visit(p_197517_.readShort());
}
public int size() {
return 2;
}
public String getName() {
return "SHORT";
}
public String getPrettyName() {
return "TAG_Short";
}
public boolean isValue() {
return true;
}
};
private final short data;
ShortTag(short pData) {
this.data = pData;
}
public static ShortTag valueOf(short pData) {
return pData >= -128 && pData <= 1024 ? ShortTag.Cache.cache[pData - -128] : new ShortTag(pData);
}
public void write(DataOutput pOutput) throws IOException {
pOutput.writeShort(this.data);
}
public int sizeInBytes() {
return 10;
}
public byte getId() {
return 2;
}
public TagType<ShortTag> getType() {
return TYPE;
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public ShortTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof ShortTag && this.data == ((ShortTag)pOther).data;
}
}
public int hashCode() {
return this.data;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitShort(this);
}
public long getAsLong() {
return (long)this.data;
}
public int getAsInt() {
return this.data;
}
public short getAsShort() {
return this.data;
}
public byte getAsByte() {
return (byte)(this.data & 255);
}
public double getAsDouble() {
return (double)this.data;
}
public float getAsFloat() {
return (float)this.data;
}
public Number getAsNumber() {
return this.data;
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
static class Cache {
private static final int HIGH = 1024;
private static final int LOW = -128;
static final ShortTag[] cache = new ShortTag[1153];
private Cache() {
}
static {
for(int i = 0; i < cache.length; ++i) {
cache[i] = new ShortTag((short)(-128 + i));
}
}
}
}
@@ -0,0 +1,231 @@
package net.minecraft.nbt;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import net.minecraft.Util;
public class SnbtPrinterTagVisitor implements TagVisitor {
private static final Map<String, List<String>> KEY_ORDER = Util.make(Maps.newHashMap(), (p_178114_) -> {
p_178114_.put("{}", Lists.newArrayList("DataVersion", "author", "size", "data", "entities", "palette", "palettes"));
p_178114_.put("{}.data.[].{}", Lists.newArrayList("pos", "state", "nbt"));
p_178114_.put("{}.entities.[].{}", Lists.newArrayList("blockPos", "pos"));
});
private static final Set<String> NO_INDENTATION = Sets.newHashSet("{}.size.[]", "{}.data.[].{}", "{}.palette.[].{}", "{}.entities.[].{}");
private static final Pattern SIMPLE_VALUE = Pattern.compile("[A-Za-z0-9._+-]+");
private static final String NAME_VALUE_SEPARATOR = String.valueOf(':');
private static final String ELEMENT_SEPARATOR = String.valueOf(',');
private static final String LIST_OPEN = "[";
private static final String LIST_CLOSE = "]";
private static final String LIST_TYPE_SEPARATOR = ";";
private static final String ELEMENT_SPACING = " ";
private static final String STRUCT_OPEN = "{";
private static final String STRUCT_CLOSE = "}";
private static final String NEWLINE = "\n";
private final String indentation;
private final int depth;
private final List<String> path;
private String result = "";
public SnbtPrinterTagVisitor() {
this(" ", 0, Lists.newArrayList());
}
public SnbtPrinterTagVisitor(String pIndentation, int pDepth, List<String> pPath) {
this.indentation = pIndentation;
this.depth = pDepth;
this.path = pPath;
}
public String visit(Tag pTag) {
pTag.accept(this);
return this.result;
}
public void visitString(StringTag pTag) {
this.result = StringTag.quoteAndEscape(pTag.getAsString());
}
public void visitByte(ByteTag pTag) {
this.result = pTag.getAsNumber() + "b";
}
public void visitShort(ShortTag pTag) {
this.result = pTag.getAsNumber() + "s";
}
public void visitInt(IntTag pTag) {
this.result = String.valueOf((Object)pTag.getAsNumber());
}
public void visitLong(LongTag pTag) {
this.result = pTag.getAsNumber() + "L";
}
public void visitFloat(FloatTag pTag) {
this.result = pTag.getAsFloat() + "f";
}
public void visitDouble(DoubleTag pTag) {
this.result = pTag.getAsDouble() + "d";
}
public void visitByteArray(ByteArrayTag pTag) {
StringBuilder stringbuilder = (new StringBuilder("[")).append("B").append(";");
byte[] abyte = pTag.getAsByteArray();
for(int i = 0; i < abyte.length; ++i) {
stringbuilder.append(" ").append((int)abyte[i]).append("B");
if (i != abyte.length - 1) {
stringbuilder.append(ELEMENT_SEPARATOR);
}
}
stringbuilder.append("]");
this.result = stringbuilder.toString();
}
public void visitIntArray(IntArrayTag pTag) {
StringBuilder stringbuilder = (new StringBuilder("[")).append("I").append(";");
int[] aint = pTag.getAsIntArray();
for(int i = 0; i < aint.length; ++i) {
stringbuilder.append(" ").append(aint[i]);
if (i != aint.length - 1) {
stringbuilder.append(ELEMENT_SEPARATOR);
}
}
stringbuilder.append("]");
this.result = stringbuilder.toString();
}
public void visitLongArray(LongArrayTag pTag) {
String s = "L";
StringBuilder stringbuilder = (new StringBuilder("[")).append("L").append(";");
long[] along = pTag.getAsLongArray();
for(int i = 0; i < along.length; ++i) {
stringbuilder.append(" ").append(along[i]).append("L");
if (i != along.length - 1) {
stringbuilder.append(ELEMENT_SEPARATOR);
}
}
stringbuilder.append("]");
this.result = stringbuilder.toString();
}
public void visitList(ListTag pTag) {
if (pTag.isEmpty()) {
this.result = "[]";
} else {
StringBuilder stringbuilder = new StringBuilder("[");
this.pushPath("[]");
String s = NO_INDENTATION.contains(this.pathString()) ? "" : this.indentation;
if (!s.isEmpty()) {
stringbuilder.append("\n");
}
for(int i = 0; i < pTag.size(); ++i) {
stringbuilder.append(Strings.repeat(s, this.depth + 1));
stringbuilder.append((new SnbtPrinterTagVisitor(s, this.depth + 1, this.path)).visit(pTag.get(i)));
if (i != pTag.size() - 1) {
stringbuilder.append(ELEMENT_SEPARATOR).append(s.isEmpty() ? " " : "\n");
}
}
if (!s.isEmpty()) {
stringbuilder.append("\n").append(Strings.repeat(s, this.depth));
}
stringbuilder.append("]");
this.result = stringbuilder.toString();
this.popPath();
}
}
public void visitCompound(CompoundTag pTag) {
if (pTag.isEmpty()) {
this.result = "{}";
} else {
StringBuilder stringbuilder = new StringBuilder("{");
this.pushPath("{}");
String s = NO_INDENTATION.contains(this.pathString()) ? "" : this.indentation;
if (!s.isEmpty()) {
stringbuilder.append("\n");
}
Collection<String> collection = this.getKeys(pTag);
Iterator<String> iterator = collection.iterator();
while(iterator.hasNext()) {
String s1 = iterator.next();
Tag tag = pTag.get(s1);
this.pushPath(s1);
stringbuilder.append(Strings.repeat(s, this.depth + 1)).append(handleEscapePretty(s1)).append(NAME_VALUE_SEPARATOR).append(" ").append((new SnbtPrinterTagVisitor(s, this.depth + 1, this.path)).visit(tag));
this.popPath();
if (iterator.hasNext()) {
stringbuilder.append(ELEMENT_SEPARATOR).append(s.isEmpty() ? " " : "\n");
}
}
if (!s.isEmpty()) {
stringbuilder.append("\n").append(Strings.repeat(s, this.depth));
}
stringbuilder.append("}");
this.result = stringbuilder.toString();
this.popPath();
}
}
private void popPath() {
this.path.remove(this.path.size() - 1);
}
private void pushPath(String pKey) {
this.path.add(pKey);
}
protected List<String> getKeys(CompoundTag pTag) {
Set<String> set = Sets.newHashSet(pTag.getAllKeys());
List<String> list = Lists.newArrayList();
List<String> list1 = KEY_ORDER.get(this.pathString());
if (list1 != null) {
for(String s : list1) {
if (set.remove(s)) {
list.add(s);
}
}
if (!set.isEmpty()) {
set.stream().sorted().forEach(list::add);
}
} else {
list.addAll(set);
Collections.sort(list);
}
return list;
}
public String pathString() {
return String.join(".", this.path);
}
protected static String handleEscapePretty(String pText) {
return SIMPLE_VALUE.matcher(pText).matches() ? pText : StringTag.quoteAndEscape(pText);
}
public void visitEnd(EndTag pTag) {
}
}
@@ -0,0 +1,50 @@
package net.minecraft.nbt;
public interface StreamTagVisitor {
StreamTagVisitor.ValueResult visitEnd();
StreamTagVisitor.ValueResult visit(String pEntry);
StreamTagVisitor.ValueResult visit(byte pEntry);
StreamTagVisitor.ValueResult visit(short pEntry);
StreamTagVisitor.ValueResult visit(int pEntry);
StreamTagVisitor.ValueResult visit(long pEntry);
StreamTagVisitor.ValueResult visit(float pEntry);
StreamTagVisitor.ValueResult visit(double pEntry);
StreamTagVisitor.ValueResult visit(byte[] pEntry);
StreamTagVisitor.ValueResult visit(int[] pEntry);
StreamTagVisitor.ValueResult visit(long[] pEntry);
StreamTagVisitor.ValueResult visitList(TagType<?> pType, int p_197528_);
StreamTagVisitor.EntryResult visitEntry(TagType<?> pType);
StreamTagVisitor.EntryResult visitEntry(TagType<?> pType, String pId);
StreamTagVisitor.EntryResult visitElement(TagType<?> pType, int p_197537_);
StreamTagVisitor.ValueResult visitContainerEnd();
StreamTagVisitor.ValueResult visitRootEntry(TagType<?> pType);
public static enum EntryResult {
ENTER,
SKIP,
BREAK,
HALT;
}
public static enum ValueResult {
CONTINUE,
BREAK,
HALT;
}
}
@@ -0,0 +1,147 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.UTFDataFormatException;
import java.util.Objects;
import net.minecraft.Util;
public class StringTag implements Tag {
private static final int SELF_SIZE_IN_BYTES = 36;
public static final TagType<StringTag> TYPE = new TagType.VariableSize<StringTag>() {
public StringTag load(DataInput p_129315_, int p_129316_, NbtAccounter p_129317_) throws IOException {
p_129317_.accountBytes(36L);
String s = p_129315_.readUTF();
p_129317_.readUTF(s);
return StringTag.valueOf(s);
}
public StreamTagVisitor.ValueResult parse(DataInput p_197570_, StreamTagVisitor p_197571_) throws IOException {
return p_197571_.visit(p_197570_.readUTF());
}
public void skip(DataInput p_197568_) throws IOException {
StringTag.skipString(p_197568_);
}
public String getName() {
return "STRING";
}
public String getPrettyName() {
return "TAG_String";
}
public boolean isValue() {
return true;
}
};
private static final StringTag EMPTY = new StringTag("");
private static final char DOUBLE_QUOTE = '"';
private static final char SINGLE_QUOTE = '\'';
private static final char ESCAPE = '\\';
private static final char NOT_SET = '\u0000';
private final String data;
public static void skipString(DataInput pInput) throws IOException {
pInput.skipBytes(pInput.readUnsignedShort());
}
private StringTag(String pData) {
Objects.requireNonNull(pData, "Null string not allowed");
this.data = pData;
}
public static StringTag valueOf(String pData) {
return pData.isEmpty() ? EMPTY : new StringTag(pData);
}
public void write(DataOutput pOutput) throws IOException {
try {
pOutput.writeUTF(this.data);
} catch (UTFDataFormatException utfdataformatexception) {
Util.logAndPauseIfInIde("Failed to write NBT String", utfdataformatexception);
pOutput.writeUTF("");
}
}
public int sizeInBytes() {
return 36 + 2 * this.data.length();
}
public byte getId() {
return 8;
}
public TagType<StringTag> getType() {
return TYPE;
}
public String toString() {
return Tag.super.getAsString();
}
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
public StringTag copy() {
return this;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else {
return pOther instanceof StringTag && Objects.equals(this.data, ((StringTag)pOther).data);
}
}
public int hashCode() {
return this.data.hashCode();
}
public String getAsString() {
return this.data;
}
public void accept(TagVisitor pVisitor) {
pVisitor.visitString(this);
}
public static String quoteAndEscape(String pText) {
StringBuilder stringbuilder = new StringBuilder(" ");
char c0 = 0;
for(int i = 0; i < pText.length(); ++i) {
char c1 = pText.charAt(i);
if (c1 == '\\') {
stringbuilder.append('\\');
} else if (c1 == '"' || c1 == '\'') {
if (c0 == 0) {
c0 = (char)(c1 == '"' ? 39 : 34);
}
if (c0 == c1) {
stringbuilder.append('\\');
}
}
stringbuilder.append(c1);
}
if (c0 == 0) {
c0 = '"';
}
stringbuilder.setCharAt(0, c0);
stringbuilder.append(c0);
return stringbuilder.toString();
}
public StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor) {
return pVisitor.visit(this.data);
}
}
@@ -0,0 +1,127 @@
package net.minecraft.nbt;
import com.google.common.collect.Lists;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
public class StringTagVisitor implements TagVisitor {
private static final Pattern SIMPLE_VALUE = Pattern.compile("[A-Za-z0-9._+-]+");
private final StringBuilder builder = new StringBuilder();
public String visit(Tag pTag) {
pTag.accept(this);
return this.builder.toString();
}
public void visitString(StringTag pTag) {
this.builder.append(StringTag.quoteAndEscape(pTag.getAsString()));
}
public void visitByte(ByteTag pTag) {
this.builder.append((Object)pTag.getAsNumber()).append('b');
}
public void visitShort(ShortTag pTag) {
this.builder.append((Object)pTag.getAsNumber()).append('s');
}
public void visitInt(IntTag pTag) {
this.builder.append((Object)pTag.getAsNumber());
}
public void visitLong(LongTag pTag) {
this.builder.append((Object)pTag.getAsNumber()).append('L');
}
public void visitFloat(FloatTag pTag) {
this.builder.append(pTag.getAsFloat()).append('f');
}
public void visitDouble(DoubleTag pTag) {
this.builder.append(pTag.getAsDouble()).append('d');
}
public void visitByteArray(ByteArrayTag pTag) {
this.builder.append("[B;");
byte[] abyte = pTag.getAsByteArray();
for(int i = 0; i < abyte.length; ++i) {
if (i != 0) {
this.builder.append(',');
}
this.builder.append((int)abyte[i]).append('B');
}
this.builder.append(']');
}
public void visitIntArray(IntArrayTag pTag) {
this.builder.append("[I;");
int[] aint = pTag.getAsIntArray();
for(int i = 0; i < aint.length; ++i) {
if (i != 0) {
this.builder.append(',');
}
this.builder.append(aint[i]);
}
this.builder.append(']');
}
public void visitLongArray(LongArrayTag pTag) {
this.builder.append("[L;");
long[] along = pTag.getAsLongArray();
for(int i = 0; i < along.length; ++i) {
if (i != 0) {
this.builder.append(',');
}
this.builder.append(along[i]).append('L');
}
this.builder.append(']');
}
public void visitList(ListTag pTag) {
this.builder.append('[');
for(int i = 0; i < pTag.size(); ++i) {
if (i != 0) {
this.builder.append(',');
}
this.builder.append((new StringTagVisitor()).visit(pTag.get(i)));
}
this.builder.append(']');
}
public void visitCompound(CompoundTag pTag) {
this.builder.append('{');
List<String> list = Lists.newArrayList(pTag.getAllKeys());
Collections.sort(list);
for(String s : list) {
if (this.builder.length() != 1) {
this.builder.append(',');
}
this.builder.append(handleEscape(s)).append(':').append((new StringTagVisitor()).visit(pTag.get(s)));
}
this.builder.append('}');
}
protected static String handleEscape(String pText) {
return SIMPLE_VALUE.matcher(pText).matches() ? pText : StringTag.quoteAndEscape(pText);
}
public void visitEnd(EndTag pTag) {
this.builder.append("END");
}
}
@@ -0,0 +1,58 @@
package net.minecraft.nbt;
import java.io.DataOutput;
import java.io.IOException;
public interface Tag {
int OBJECT_HEADER = 8;
int ARRAY_HEADER = 12;
int OBJECT_REFERENCE = 4;
int STRING_SIZE = 28;
byte TAG_END = 0;
byte TAG_BYTE = 1;
byte TAG_SHORT = 2;
byte TAG_INT = 3;
byte TAG_LONG = 4;
byte TAG_FLOAT = 5;
byte TAG_DOUBLE = 6;
byte TAG_BYTE_ARRAY = 7;
byte TAG_STRING = 8;
byte TAG_LIST = 9;
byte TAG_COMPOUND = 10;
byte TAG_INT_ARRAY = 11;
byte TAG_LONG_ARRAY = 12;
byte TAG_ANY_NUMERIC = 99;
int MAX_DEPTH = 512;
void write(DataOutput pOutput) throws IOException;
String toString();
byte getId();
TagType<?> getType();
/**
* Creates a deep copy of the value held by this tag. Primitive and string tage will return the same tag instance
* while all other objects will return a new tag instance with the copied data.
*/
Tag copy();
int sizeInBytes();
default String getAsString() {
return (new StringTagVisitor()).visit(this);
}
void accept(TagVisitor pVisitor);
StreamTagVisitor.ValueResult accept(StreamTagVisitor pVisitor);
default void acceptAsRoot(StreamTagVisitor pVisitor) {
StreamTagVisitor.ValueResult streamtagvisitor$valueresult = pVisitor.visitRootEntry(this.getType());
if (streamtagvisitor$valueresult == StreamTagVisitor.ValueResult.CONTINUE) {
this.accept(pVisitor);
}
}
}
@@ -0,0 +1,279 @@
package net.minecraft.nbt;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import java.util.List;
import java.util.regex.Pattern;
import net.minecraft.network.chat.Component;
public class TagParser {
public static final SimpleCommandExceptionType ERROR_TRAILING_DATA = new SimpleCommandExceptionType(Component.translatable("argument.nbt.trailing"));
public static final SimpleCommandExceptionType ERROR_EXPECTED_KEY = new SimpleCommandExceptionType(Component.translatable("argument.nbt.expected.key"));
public static final SimpleCommandExceptionType ERROR_EXPECTED_VALUE = new SimpleCommandExceptionType(Component.translatable("argument.nbt.expected.value"));
public static final Dynamic2CommandExceptionType ERROR_INSERT_MIXED_LIST = new Dynamic2CommandExceptionType((p_129366_, p_129367_) -> {
return Component.translatable("argument.nbt.list.mixed", p_129366_, p_129367_);
});
public static final Dynamic2CommandExceptionType ERROR_INSERT_MIXED_ARRAY = new Dynamic2CommandExceptionType((p_129357_, p_129358_) -> {
return Component.translatable("argument.nbt.array.mixed", p_129357_, p_129358_);
});
public static final DynamicCommandExceptionType ERROR_INVALID_ARRAY = new DynamicCommandExceptionType((p_129355_) -> {
return Component.translatable("argument.nbt.array.invalid", p_129355_);
});
public static final char ELEMENT_SEPARATOR = ',';
public static final char NAME_VALUE_SEPARATOR = ':';
private static final char LIST_OPEN = '[';
private static final char LIST_CLOSE = ']';
private static final char STRUCT_CLOSE = '}';
private static final char STRUCT_OPEN = '{';
private static final Pattern DOUBLE_PATTERN_NOSUFFIX = Pattern.compile("[-+]?(?:[0-9]+[.]|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?", 2);
private static final Pattern DOUBLE_PATTERN = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?d", 2);
private static final Pattern FLOAT_PATTERN = Pattern.compile("[-+]?(?:[0-9]+[.]?|[0-9]*[.][0-9]+)(?:e[-+]?[0-9]+)?f", 2);
private static final Pattern BYTE_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)b", 2);
private static final Pattern LONG_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)l", 2);
private static final Pattern SHORT_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)s", 2);
private static final Pattern INT_PATTERN = Pattern.compile("[-+]?(?:0|[1-9][0-9]*)");
private final StringReader reader;
public static CompoundTag parseTag(String pText) throws CommandSyntaxException {
return (new TagParser(new StringReader(pText))).readSingleStruct();
}
@VisibleForTesting
CompoundTag readSingleStruct() throws CommandSyntaxException {
CompoundTag compoundtag = this.readStruct();
this.reader.skipWhitespace();
if (this.reader.canRead()) {
throw ERROR_TRAILING_DATA.createWithContext(this.reader);
} else {
return compoundtag;
}
}
public TagParser(StringReader pReader) {
this.reader = pReader;
}
protected String readKey() throws CommandSyntaxException {
this.reader.skipWhitespace();
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_KEY.createWithContext(this.reader);
} else {
return this.reader.readString();
}
}
protected Tag readTypedValue() throws CommandSyntaxException {
this.reader.skipWhitespace();
int i = this.reader.getCursor();
if (StringReader.isQuotedStringStart(this.reader.peek())) {
return StringTag.valueOf(this.reader.readQuotedString());
} else {
String s = this.reader.readUnquotedString();
if (s.isEmpty()) {
this.reader.setCursor(i);
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
} else {
return this.type(s);
}
}
}
private Tag type(String pValue) {
try {
if (FLOAT_PATTERN.matcher(pValue).matches()) {
return FloatTag.valueOf(Float.parseFloat(pValue.substring(0, pValue.length() - 1)));
}
if (BYTE_PATTERN.matcher(pValue).matches()) {
return ByteTag.valueOf(Byte.parseByte(pValue.substring(0, pValue.length() - 1)));
}
if (LONG_PATTERN.matcher(pValue).matches()) {
return LongTag.valueOf(Long.parseLong(pValue.substring(0, pValue.length() - 1)));
}
if (SHORT_PATTERN.matcher(pValue).matches()) {
return ShortTag.valueOf(Short.parseShort(pValue.substring(0, pValue.length() - 1)));
}
if (INT_PATTERN.matcher(pValue).matches()) {
return IntTag.valueOf(Integer.parseInt(pValue));
}
if (DOUBLE_PATTERN.matcher(pValue).matches()) {
return DoubleTag.valueOf(Double.parseDouble(pValue.substring(0, pValue.length() - 1)));
}
if (DOUBLE_PATTERN_NOSUFFIX.matcher(pValue).matches()) {
return DoubleTag.valueOf(Double.parseDouble(pValue));
}
if ("true".equalsIgnoreCase(pValue)) {
return ByteTag.ONE;
}
if ("false".equalsIgnoreCase(pValue)) {
return ByteTag.ZERO;
}
} catch (NumberFormatException numberformatexception) {
}
return StringTag.valueOf(pValue);
}
public Tag readValue() throws CommandSyntaxException {
this.reader.skipWhitespace();
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
} else {
char c0 = this.reader.peek();
if (c0 == '{') {
return this.readStruct();
} else {
return c0 == '[' ? this.readList() : this.readTypedValue();
}
}
}
protected Tag readList() throws CommandSyntaxException {
return this.reader.canRead(3) && !StringReader.isQuotedStringStart(this.reader.peek(1)) && this.reader.peek(2) == ';' ? this.readArrayTag() : this.readListTag();
}
public CompoundTag readStruct() throws CommandSyntaxException {
this.expect('{');
CompoundTag compoundtag = new CompoundTag();
this.reader.skipWhitespace();
while(this.reader.canRead() && this.reader.peek() != '}') {
int i = this.reader.getCursor();
String s = this.readKey();
if (s.isEmpty()) {
this.reader.setCursor(i);
throw ERROR_EXPECTED_KEY.createWithContext(this.reader);
}
this.expect(':');
compoundtag.put(s, this.readValue());
if (!this.hasElementSeparator()) {
break;
}
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_KEY.createWithContext(this.reader);
}
}
this.expect('}');
return compoundtag;
}
private Tag readListTag() throws CommandSyntaxException {
this.expect('[');
this.reader.skipWhitespace();
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
} else {
ListTag listtag = new ListTag();
TagType<?> tagtype = null;
while(this.reader.peek() != ']') {
int i = this.reader.getCursor();
Tag tag = this.readValue();
TagType<?> tagtype1 = tag.getType();
if (tagtype == null) {
tagtype = tagtype1;
} else if (tagtype1 != tagtype) {
this.reader.setCursor(i);
throw ERROR_INSERT_MIXED_LIST.createWithContext(this.reader, tagtype1.getPrettyName(), tagtype.getPrettyName());
}
listtag.add(tag);
if (!this.hasElementSeparator()) {
break;
}
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
}
}
this.expect(']');
return listtag;
}
}
private Tag readArrayTag() throws CommandSyntaxException {
this.expect('[');
int i = this.reader.getCursor();
char c0 = this.reader.read();
this.reader.read();
this.reader.skipWhitespace();
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
} else if (c0 == 'B') {
return new ByteArrayTag(this.readArray(ByteArrayTag.TYPE, ByteTag.TYPE));
} else if (c0 == 'L') {
return new LongArrayTag(this.readArray(LongArrayTag.TYPE, LongTag.TYPE));
} else if (c0 == 'I') {
return new IntArrayTag(this.readArray(IntArrayTag.TYPE, IntTag.TYPE));
} else {
this.reader.setCursor(i);
throw ERROR_INVALID_ARRAY.createWithContext(this.reader, String.valueOf(c0));
}
}
private <T extends Number> List<T> readArray(TagType<?> pArrayType, TagType<?> pElementType) throws CommandSyntaxException {
List<T> list = Lists.newArrayList();
while(true) {
if (this.reader.peek() != ']') {
int i = this.reader.getCursor();
Tag tag = this.readValue();
TagType<?> tagtype = tag.getType();
if (tagtype != pElementType) {
this.reader.setCursor(i);
throw ERROR_INSERT_MIXED_ARRAY.createWithContext(this.reader, tagtype.getPrettyName(), pArrayType.getPrettyName());
}
if (pElementType == ByteTag.TYPE) {
list.add((T)(Byte)((NumericTag)tag).getAsByte());
} else if (pElementType == LongTag.TYPE) {
list.add((T)(Long)((NumericTag)tag).getAsLong());
} else {
list.add((T)(Integer)((NumericTag)tag).getAsInt());
}
if (this.hasElementSeparator()) {
if (!this.reader.canRead()) {
throw ERROR_EXPECTED_VALUE.createWithContext(this.reader);
}
continue;
}
}
this.expect(']');
return list;
}
}
private boolean hasElementSeparator() {
this.reader.skipWhitespace();
if (this.reader.canRead() && this.reader.peek() == ',') {
this.reader.skip();
this.reader.skipWhitespace();
return true;
} else {
return false;
}
}
private void expect(char pExpected) throws CommandSyntaxException {
this.reader.skipWhitespace();
this.reader.expect(pExpected);
}
}
@@ -0,0 +1,88 @@
package net.minecraft.nbt;
import java.io.DataInput;
import java.io.IOException;
public interface TagType<T extends Tag> {
T load(DataInput pInput, int pDepth, NbtAccounter pAccounter) throws IOException;
StreamTagVisitor.ValueResult parse(DataInput pInput, StreamTagVisitor pVisitor) throws IOException;
default void parseRoot(DataInput pInput, StreamTagVisitor pVisitor) throws IOException {
switch (pVisitor.visitRootEntry(this)) {
case CONTINUE:
this.parse(pInput, pVisitor);
case HALT:
default:
break;
case BREAK:
this.skip(pInput);
}
}
void skip(DataInput pInput, int p_197577_) throws IOException;
void skip(DataInput pInput) throws IOException;
default boolean isValue() {
return false;
}
String getName();
String getPrettyName();
static TagType<EndTag> createInvalid(final int pId) {
return new TagType<EndTag>() {
private IOException createException() {
return new IOException("Invalid tag id: " + pId);
}
public EndTag load(DataInput p_129387_, int p_129388_, NbtAccounter p_129389_) throws IOException {
throw this.createException();
}
public StreamTagVisitor.ValueResult parse(DataInput p_197589_, StreamTagVisitor p_197590_) throws IOException {
throw this.createException();
}
public void skip(DataInput p_197586_, int p_197587_) throws IOException {
throw this.createException();
}
public void skip(DataInput p_197584_) throws IOException {
throw this.createException();
}
public String getName() {
return "INVALID[" + pId + "]";
}
public String getPrettyName() {
return "UNKNOWN_" + pId;
}
};
}
public interface StaticSize<T extends Tag> extends TagType<T> {
default void skip(DataInput p_197595_) throws IOException {
p_197595_.skipBytes(this.size());
}
default void skip(DataInput p_197597_, int p_197598_) throws IOException {
p_197597_.skipBytes(this.size() * p_197598_);
}
int size();
}
public interface VariableSize<T extends Tag> extends TagType<T> {
default void skip(DataInput p_197600_, int p_197601_) throws IOException {
for(int i = 0; i < p_197601_; ++i) {
this.skip(p_197600_);
}
}
}
}
@@ -0,0 +1,9 @@
package net.minecraft.nbt;
public class TagTypes {
private static final TagType<?>[] TYPES = new TagType[]{EndTag.TYPE, ByteTag.TYPE, ShortTag.TYPE, IntTag.TYPE, LongTag.TYPE, FloatTag.TYPE, DoubleTag.TYPE, ByteArrayTag.TYPE, StringTag.TYPE, ListTag.TYPE, CompoundTag.TYPE, IntArrayTag.TYPE, LongArrayTag.TYPE};
public static TagType<?> getType(int pId) {
return pId >= 0 && pId < TYPES.length ? TYPES[pId] : TagType.createInvalid(pId);
}
}
@@ -0,0 +1,29 @@
package net.minecraft.nbt;
public interface TagVisitor {
void visitString(StringTag pTag);
void visitByte(ByteTag pTag);
void visitShort(ShortTag pTag);
void visitInt(IntTag pTag);
void visitLong(LongTag pTag);
void visitFloat(FloatTag pTag);
void visitDouble(DoubleTag pTag);
void visitByteArray(ByteArrayTag pTag);
void visitIntArray(IntArrayTag pTag);
void visitLongArray(LongArrayTag pTag);
void visitList(ListTag pTag);
void visitCompound(CompoundTag pTag);
void visitEnd(EndTag pTag);
}
@@ -0,0 +1,228 @@
package net.minecraft.nbt;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.bytes.ByteCollection;
import it.unimi.dsi.fastutil.bytes.ByteOpenHashSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Pattern;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import org.slf4j.Logger;
public class TextComponentTagVisitor implements TagVisitor {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int INLINE_LIST_THRESHOLD = 8;
private static final ByteCollection INLINE_ELEMENT_TYPES = new ByteOpenHashSet(Arrays.asList((byte)1, (byte)2, (byte)3, (byte)4, (byte)5, (byte)6));
private static final ChatFormatting SYNTAX_HIGHLIGHTING_KEY = ChatFormatting.AQUA;
private static final ChatFormatting SYNTAX_HIGHLIGHTING_STRING = ChatFormatting.GREEN;
private static final ChatFormatting SYNTAX_HIGHLIGHTING_NUMBER = ChatFormatting.GOLD;
private static final ChatFormatting SYNTAX_HIGHLIGHTING_NUMBER_TYPE = ChatFormatting.RED;
private static final Pattern SIMPLE_VALUE = Pattern.compile("[A-Za-z0-9._+-]+");
private static final String NAME_VALUE_SEPARATOR = String.valueOf(':');
private static final String ELEMENT_SEPARATOR = String.valueOf(',');
private static final String LIST_OPEN = "[";
private static final String LIST_CLOSE = "]";
private static final String LIST_TYPE_SEPARATOR = ";";
private static final String ELEMENT_SPACING = " ";
private static final String STRUCT_OPEN = "{";
private static final String STRUCT_CLOSE = "}";
private static final String NEWLINE = "\n";
private final String indentation;
private final int depth;
private Component result = CommonComponents.EMPTY;
public TextComponentTagVisitor(String pIndentation, int pDepth) {
this.indentation = pIndentation;
this.depth = pDepth;
}
public Component visit(Tag pTag) {
pTag.accept(this);
return this.result;
}
public void visitString(StringTag pTag) {
String s = StringTag.quoteAndEscape(pTag.getAsString());
String s1 = s.substring(0, 1);
Component component = Component.literal(s.substring(1, s.length() - 1)).withStyle(SYNTAX_HIGHLIGHTING_STRING);
this.result = Component.literal(s1).append(component).append(s1);
}
public void visitByte(ByteTag pTag) {
Component component = Component.literal("b").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
this.result = Component.literal(String.valueOf((Object)pTag.getAsNumber())).append(component).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
}
public void visitShort(ShortTag pTag) {
Component component = Component.literal("s").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
this.result = Component.literal(String.valueOf((Object)pTag.getAsNumber())).append(component).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
}
public void visitInt(IntTag pTag) {
this.result = Component.literal(String.valueOf((Object)pTag.getAsNumber())).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
}
public void visitLong(LongTag pTag) {
Component component = Component.literal("L").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
this.result = Component.literal(String.valueOf((Object)pTag.getAsNumber())).append(component).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
}
public void visitFloat(FloatTag pTag) {
Component component = Component.literal("f").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
this.result = Component.literal(String.valueOf(pTag.getAsFloat())).append(component).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
}
public void visitDouble(DoubleTag pTag) {
Component component = Component.literal("d").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
this.result = Component.literal(String.valueOf(pTag.getAsDouble())).append(component).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
}
public void visitByteArray(ByteArrayTag pTag) {
Component component = Component.literal("B").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
MutableComponent mutablecomponent = Component.literal("[").append(component).append(";");
byte[] abyte = pTag.getAsByteArray();
for(int i = 0; i < abyte.length; ++i) {
MutableComponent mutablecomponent1 = Component.literal(String.valueOf((int)abyte[i])).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
mutablecomponent.append(" ").append(mutablecomponent1).append(component);
if (i != abyte.length - 1) {
mutablecomponent.append(ELEMENT_SEPARATOR);
}
}
mutablecomponent.append("]");
this.result = mutablecomponent;
}
public void visitIntArray(IntArrayTag pTag) {
Component component = Component.literal("I").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
MutableComponent mutablecomponent = Component.literal("[").append(component).append(";");
int[] aint = pTag.getAsIntArray();
for(int i = 0; i < aint.length; ++i) {
mutablecomponent.append(" ").append(Component.literal(String.valueOf(aint[i])).withStyle(SYNTAX_HIGHLIGHTING_NUMBER));
if (i != aint.length - 1) {
mutablecomponent.append(ELEMENT_SEPARATOR);
}
}
mutablecomponent.append("]");
this.result = mutablecomponent;
}
public void visitLongArray(LongArrayTag pTag) {
Component component = Component.literal("L").withStyle(SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
MutableComponent mutablecomponent = Component.literal("[").append(component).append(";");
long[] along = pTag.getAsLongArray();
for(int i = 0; i < along.length; ++i) {
Component component1 = Component.literal(String.valueOf(along[i])).withStyle(SYNTAX_HIGHLIGHTING_NUMBER);
mutablecomponent.append(" ").append(component1).append(component);
if (i != along.length - 1) {
mutablecomponent.append(ELEMENT_SEPARATOR);
}
}
mutablecomponent.append("]");
this.result = mutablecomponent;
}
public void visitList(ListTag pTag) {
if (pTag.isEmpty()) {
this.result = Component.literal("[]");
} else if (INLINE_ELEMENT_TYPES.contains(pTag.getElementType()) && pTag.size() <= 8) {
String s = ELEMENT_SEPARATOR + " ";
MutableComponent mutablecomponent2 = Component.literal("[");
for(int j = 0; j < pTag.size(); ++j) {
if (j != 0) {
mutablecomponent2.append(s);
}
mutablecomponent2.append((new TextComponentTagVisitor(this.indentation, this.depth)).visit(pTag.get(j)));
}
mutablecomponent2.append("]");
this.result = mutablecomponent2;
} else {
MutableComponent mutablecomponent = Component.literal("[");
if (!this.indentation.isEmpty()) {
mutablecomponent.append("\n");
}
for(int i = 0; i < pTag.size(); ++i) {
MutableComponent mutablecomponent1 = Component.literal(Strings.repeat(this.indentation, this.depth + 1));
mutablecomponent1.append((new TextComponentTagVisitor(this.indentation, this.depth + 1)).visit(pTag.get(i)));
if (i != pTag.size() - 1) {
mutablecomponent1.append(ELEMENT_SEPARATOR).append(this.indentation.isEmpty() ? " " : "\n");
}
mutablecomponent.append(mutablecomponent1);
}
if (!this.indentation.isEmpty()) {
mutablecomponent.append("\n").append(Strings.repeat(this.indentation, this.depth));
}
mutablecomponent.append("]");
this.result = mutablecomponent;
}
}
public void visitCompound(CompoundTag pTag) {
if (pTag.isEmpty()) {
this.result = Component.literal("{}");
} else {
MutableComponent mutablecomponent = Component.literal("{");
Collection<String> collection = pTag.getAllKeys();
if (LOGGER.isDebugEnabled()) {
List<String> list = Lists.newArrayList(pTag.getAllKeys());
Collections.sort(list);
collection = list;
}
if (!this.indentation.isEmpty()) {
mutablecomponent.append("\n");
}
MutableComponent mutablecomponent1;
for(Iterator<String> iterator = collection.iterator(); iterator.hasNext(); mutablecomponent.append(mutablecomponent1)) {
String s = iterator.next();
mutablecomponent1 = Component.literal(Strings.repeat(this.indentation, this.depth + 1)).append(handleEscapePretty(s)).append(NAME_VALUE_SEPARATOR).append(" ").append((new TextComponentTagVisitor(this.indentation, this.depth + 1)).visit(pTag.get(s)));
if (iterator.hasNext()) {
mutablecomponent1.append(ELEMENT_SEPARATOR).append(this.indentation.isEmpty() ? " " : "\n");
}
}
if (!this.indentation.isEmpty()) {
mutablecomponent.append("\n").append(Strings.repeat(this.indentation, this.depth));
}
mutablecomponent.append("}");
this.result = mutablecomponent;
}
}
protected static Component handleEscapePretty(String pText) {
if (SIMPLE_VALUE.matcher(pText).matches()) {
return Component.literal(pText).withStyle(SYNTAX_HIGHLIGHTING_KEY);
} else {
String s = StringTag.quoteAndEscape(pText);
String s1 = s.substring(0, 1);
Component component = Component.literal(s.substring(1, s.length() - 1)).withStyle(SYNTAX_HIGHLIGHTING_KEY);
return Component.literal(s1).append(component).append(s1);
}
}
public void visitEnd(EndTag pTag) {
this.result = CommonComponents.EMPTY;
}
}
@@ -0,0 +1,8 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
package net.minecraft.nbt;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;
@@ -0,0 +1,77 @@
package net.minecraft.nbt.visitors;
import com.google.common.collect.ImmutableSet;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Set;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StreamTagVisitor;
import net.minecraft.nbt.TagType;
public class CollectFields extends CollectToTag {
private int fieldsToGetCount;
private final Set<TagType<?>> wantedTypes;
private final Deque<FieldTree> stack = new ArrayDeque<>();
public CollectFields(FieldSelector... pSelectors) {
this.fieldsToGetCount = pSelectors.length;
ImmutableSet.Builder<TagType<?>> builder = ImmutableSet.builder();
FieldTree fieldtree = FieldTree.createRoot();
for(FieldSelector fieldselector : pSelectors) {
fieldtree.addEntry(fieldselector);
builder.add(fieldselector.type());
}
this.stack.push(fieldtree);
builder.add(CompoundTag.TYPE);
this.wantedTypes = builder.build();
}
public StreamTagVisitor.ValueResult visitRootEntry(TagType<?> pType) {
return pType != CompoundTag.TYPE ? StreamTagVisitor.ValueResult.HALT : super.visitRootEntry(pType);
}
public StreamTagVisitor.EntryResult visitEntry(TagType<?> pType) {
FieldTree fieldtree = this.stack.element();
if (this.depth() > fieldtree.depth()) {
return super.visitEntry(pType);
} else if (this.fieldsToGetCount <= 0) {
return StreamTagVisitor.EntryResult.HALT;
} else {
return !this.wantedTypes.contains(pType) ? StreamTagVisitor.EntryResult.SKIP : super.visitEntry(pType);
}
}
public StreamTagVisitor.EntryResult visitEntry(TagType<?> pType, String pId) {
FieldTree fieldtree = this.stack.element();
if (this.depth() > fieldtree.depth()) {
return super.visitEntry(pType, pId);
} else if (fieldtree.selectedFields().remove(pId, pType)) {
--this.fieldsToGetCount;
return super.visitEntry(pType, pId);
} else {
if (pType == CompoundTag.TYPE) {
FieldTree fieldtree1 = fieldtree.fieldsToRecurse().get(pId);
if (fieldtree1 != null) {
this.stack.push(fieldtree1);
return super.visitEntry(pType, pId);
}
}
return StreamTagVisitor.EntryResult.SKIP;
}
}
public StreamTagVisitor.ValueResult visitContainerEnd() {
if (this.depth() == this.stack.element().depth()) {
this.stack.pop();
}
return super.visitContainerEnd();
}
public int getMissingFieldCount() {
return this.fieldsToGetCount;
}
}
@@ -0,0 +1,156 @@
package net.minecraft.nbt.visitors;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.nbt.ByteArrayTag;
import net.minecraft.nbt.ByteTag;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.DoubleTag;
import net.minecraft.nbt.EndTag;
import net.minecraft.nbt.FloatTag;
import net.minecraft.nbt.IntArrayTag;
import net.minecraft.nbt.IntTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.LongArrayTag;
import net.minecraft.nbt.LongTag;
import net.minecraft.nbt.ShortTag;
import net.minecraft.nbt.StreamTagVisitor;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.nbt.TagType;
public class CollectToTag implements StreamTagVisitor {
private String lastId = "";
@Nullable
private Tag rootTag;
private final Deque<Consumer<Tag>> consumerStack = new ArrayDeque<>();
@Nullable
public Tag getResult() {
return this.rootTag;
}
protected int depth() {
return this.consumerStack.size();
}
private void appendEntry(Tag pTag) {
this.consumerStack.getLast().accept(pTag);
}
public StreamTagVisitor.ValueResult visitEnd() {
this.appendEntry(EndTag.INSTANCE);
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(String pEntry) {
this.appendEntry(StringTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(byte pEntry) {
this.appendEntry(ByteTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(short pEntry) {
this.appendEntry(ShortTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(int pEntry) {
this.appendEntry(IntTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(long pEntry) {
this.appendEntry(LongTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(float pEntry) {
this.appendEntry(FloatTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(double pEntry) {
this.appendEntry(DoubleTag.valueOf(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(byte[] pEntry) {
this.appendEntry(new ByteArrayTag(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(int[] pEntry) {
this.appendEntry(new IntArrayTag(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visit(long[] pEntry) {
this.appendEntry(new LongArrayTag(pEntry));
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visitList(TagType<?> pType, int p_197688_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.EntryResult visitElement(TagType<?> pType, int p_197710_) {
this.enterContainerIfNeeded(pType);
return StreamTagVisitor.EntryResult.ENTER;
}
public StreamTagVisitor.EntryResult visitEntry(TagType<?> pType) {
return StreamTagVisitor.EntryResult.ENTER;
}
public StreamTagVisitor.EntryResult visitEntry(TagType<?> pType, String pId) {
this.lastId = pId;
this.enterContainerIfNeeded(pType);
return StreamTagVisitor.EntryResult.ENTER;
}
private void enterContainerIfNeeded(TagType<?> pType) {
if (pType == ListTag.TYPE) {
ListTag listtag = new ListTag();
this.appendEntry(listtag);
this.consumerStack.addLast(listtag::add);
} else if (pType == CompoundTag.TYPE) {
CompoundTag compoundtag = new CompoundTag();
this.appendEntry(compoundtag);
this.consumerStack.addLast((p_197703_) -> {
compoundtag.put(this.lastId, p_197703_);
});
}
}
public StreamTagVisitor.ValueResult visitContainerEnd() {
this.consumerStack.removeLast();
return StreamTagVisitor.ValueResult.CONTINUE;
}
public StreamTagVisitor.ValueResult visitRootEntry(TagType<?> pType) {
if (pType == ListTag.TYPE) {
ListTag listtag = new ListTag();
this.rootTag = listtag;
this.consumerStack.addLast(listtag::add);
} else if (pType == CompoundTag.TYPE) {
CompoundTag compoundtag = new CompoundTag();
this.rootTag = compoundtag;
this.consumerStack.addLast((p_197681_) -> {
compoundtag.put(this.lastId, p_197681_);
});
} else {
this.consumerStack.addLast((p_197705_) -> {
this.rootTag = p_197705_;
});
}
return StreamTagVisitor.ValueResult.CONTINUE;
}
}
@@ -0,0 +1,18 @@
package net.minecraft.nbt.visitors;
import java.util.List;
import net.minecraft.nbt.TagType;
public record FieldSelector(List<String> path, TagType<?> type, String name) {
public FieldSelector(TagType<?> pType, String pName) {
this(List.of(), pType, pName);
}
public FieldSelector(String pElement, TagType<?> pType, String pName) {
this(List.of(pElement), pType, pName);
}
public FieldSelector(String pFirstElement, String pSecondElement, TagType<?> pType, String pName) {
this(List.of(pFirstElement, pSecondElement), pType, pName);
}
}
@@ -0,0 +1,30 @@
package net.minecraft.nbt.visitors;
import java.util.HashMap;
import java.util.Map;
import net.minecraft.nbt.TagType;
public record FieldTree(int depth, Map<String, TagType<?>> selectedFields, Map<String, FieldTree> fieldsToRecurse) {
private FieldTree(int pDepth) {
this(pDepth, new HashMap<>(), new HashMap<>());
}
public static FieldTree createRoot() {
return new FieldTree(1);
}
public void addEntry(FieldSelector pSelector) {
if (this.depth <= pSelector.path().size()) {
this.fieldsToRecurse.computeIfAbsent(pSelector.path().get(this.depth - 1), (p_202534_) -> {
return new FieldTree(this.depth + 1);
}).addEntry(pSelector);
} else {
this.selectedFields.put(pSelector.name(), pSelector.type());
}
}
public boolean isSelected(TagType<?> pType, String pName) {
return pType.equals(this.selectedFields().get(pName));
}
}
@@ -0,0 +1,77 @@
package net.minecraft.nbt.visitors;
import net.minecraft.nbt.StreamTagVisitor;
import net.minecraft.nbt.TagType;
public interface SkipAll extends StreamTagVisitor {
SkipAll INSTANCE = new SkipAll() {
};
default StreamTagVisitor.ValueResult visitEnd() {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(String p_197729_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(byte p_197719_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(short p_197739_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(int p_197725_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(long p_197727_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(float p_197723_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(double p_197721_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(byte[] p_197741_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(int[] p_197743_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visit(long[] p_197745_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visitList(TagType<?> p_197733_, int p_197734_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.EntryResult visitElement(TagType<?> p_197750_, int p_197751_) {
return StreamTagVisitor.EntryResult.SKIP;
}
default StreamTagVisitor.EntryResult visitEntry(TagType<?> p_197731_) {
return StreamTagVisitor.EntryResult.SKIP;
}
default StreamTagVisitor.EntryResult visitEntry(TagType<?> p_197736_, String p_197737_) {
return StreamTagVisitor.EntryResult.SKIP;
}
default StreamTagVisitor.ValueResult visitContainerEnd() {
return StreamTagVisitor.ValueResult.CONTINUE;
}
default StreamTagVisitor.ValueResult visitRootEntry(TagType<?> p_197748_) {
return StreamTagVisitor.ValueResult.CONTINUE;
}
}
@@ -0,0 +1,45 @@
package net.minecraft.nbt.visitors;
import java.util.ArrayDeque;
import java.util.Deque;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StreamTagVisitor;
import net.minecraft.nbt.TagType;
public class SkipFields extends CollectToTag {
private final Deque<FieldTree> stack = new ArrayDeque<>();
public SkipFields(FieldSelector... pSelectors) {
FieldTree fieldtree = FieldTree.createRoot();
for(FieldSelector fieldselector : pSelectors) {
fieldtree.addEntry(fieldselector);
}
this.stack.push(fieldtree);
}
public StreamTagVisitor.EntryResult visitEntry(TagType<?> pType, String pId) {
FieldTree fieldtree = this.stack.element();
if (fieldtree.isSelected(pType, pId)) {
return StreamTagVisitor.EntryResult.SKIP;
} else {
if (pType == CompoundTag.TYPE) {
FieldTree fieldtree1 = fieldtree.fieldsToRecurse().get(pId);
if (fieldtree1 != null) {
this.stack.push(fieldtree1);
}
}
return super.visitEntry(pType, pId);
}
}
public StreamTagVisitor.ValueResult visitContainerEnd() {
if (this.depth() == this.stack.element().depth()) {
this.stack.pop();
}
return super.visitContainerEnd();
}
}
@@ -0,0 +1,8 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
package net.minecraft.nbt.visitors;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;