Skip to content

Commit 4d205b2

Browse files
committed
Implement SNBT and pretty printing
1 parent 8059c5a commit 4d205b2

18 files changed

Lines changed: 240 additions & 45 deletions

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group = "net.thenextlvl"
8-
version = "4.0.3"
8+
version = "4.1.0"
99

1010
java {
1111
toolchain.languageVersion = JavaLanguageVersion.of(21)

src/main/java/net/thenextlvl/nbt/serialization/NBT.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package net.thenextlvl.nbt.serialization;
22

3+
import net.thenextlvl.nbt.tag.Tag;
34
import org.jetbrains.annotations.Contract;
45

56
import java.lang.reflect.Type;
@@ -9,6 +10,33 @@
910
* as well as to register custom serializers and deserializers for different types.
1011
*/
1112
public sealed interface NBT extends TagSerializationContext, TagDeserializationContext permits SimpleNBT {
13+
/**
14+
* Returns whether the NBT output is formatted with indentation and line breaks.
15+
*
16+
* @return true if pretty printing is enabled, false otherwise
17+
* @since 4.1.0
18+
*/
19+
@Contract(pure = true)
20+
boolean isPrettyPrinting();
21+
22+
/**
23+
* Returns the number of indents used for pretty printing.
24+
*
25+
* @return the number of indents used for pretty printing
26+
* @since 4.1.0
27+
*/
28+
@Contract(pure = true)
29+
int getIndents();
30+
31+
/**
32+
* Returns a string representation of the given Tag.
33+
*
34+
* @param tag the Tag to be converted to a string
35+
* @return a string representation of the Tag
36+
*/
37+
@Contract(value = "_ -> new", pure = true)
38+
String toString(Tag tag);
39+
1240
/**
1341
* Creates a new instance of the Builder class for constructing NBT objects.
1442
*
@@ -91,6 +119,26 @@ sealed interface Builder permits SimpleNBT.Builder {
91119
@Contract(value = "_, _ -> this", mutates = "this")
92120
<T> Builder registerTypeAdapter(Type type, TagSerializer<T> serializer);
93121

122+
/**
123+
* Sets whether the NBT output should be formatted with indentation and line breaks.
124+
*
125+
* @param prettyPrinting whether to enable pretty printing
126+
* @return the current builder instance for chaining
127+
* @since 4.1.0
128+
*/
129+
@Contract(value = "_ -> this", mutates = "this")
130+
Builder setPrettyPrinting(boolean prettyPrinting);
131+
132+
/**
133+
* Sets the number of indents to use for pretty printing.
134+
*
135+
* @param indents the number of indents to use
136+
* @return the current builder instance for chaining
137+
* @since 4.1.0
138+
*/
139+
@Contract(value = "_ -> this", mutates = "this")
140+
Builder setIndents(int indents);
141+
94142
/**
95143
* Constructs and returns an instance of NBT using the configured serializers and deserializers.
96144
*

src/main/java/net/thenextlvl/nbt/serialization/SimpleNBT.java

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
import net.thenextlvl.nbt.serialization.adapters.ShortAdapter;
1414
import net.thenextlvl.nbt.serialization.adapters.StringAdapter;
1515
import net.thenextlvl.nbt.serialization.adapters.UUIDAdapter;
16+
import net.thenextlvl.nbt.tag.CompoundTag;
17+
import net.thenextlvl.nbt.tag.IterableTag;
18+
import net.thenextlvl.nbt.tag.ListTag;
1619
import net.thenextlvl.nbt.tag.Tag;
1720
import org.jspecify.annotations.NonNull;
1821

@@ -27,9 +30,13 @@
2730

2831
final class SimpleNBT implements NBT {
2932
private final SerializationRegistry registry;
33+
private final boolean prettyPrinting;
34+
private final int indents;
3035

31-
private SimpleNBT(SerializationRegistry registry) {
36+
private SimpleNBT(SerializationRegistry registry, boolean prettyPrinting, int indents) {
3237
this.registry = registry;
38+
this.prettyPrinting = prettyPrinting;
39+
this.indents = indents;
3340
}
3441

3542
@Override
@@ -79,8 +86,64 @@ public Tag serialize(Object object, Type type) throws ParserException {
7986
throw new ParserException("No tag serializer registered for type: " + type);
8087
}
8188

89+
@Override
90+
public boolean isPrettyPrinting() {
91+
return prettyPrinting;
92+
}
93+
94+
@Override
95+
public int getIndents() {
96+
return indents;
97+
}
98+
99+
@Override
100+
public String toString(Tag tag) {
101+
return prettyPrinting ? "\"\": " + prettify(tag, 0) : tag.toString();
102+
}
103+
104+
private String prettify(Tag tag, int depth) {
105+
final var indent = " ".repeat(indents);
106+
final var currentIndent = indent.repeat(depth);
107+
return switch (tag) {
108+
case CompoundTag compoundTag -> {
109+
var builder = new StringBuilder("{");
110+
for (var entry : compoundTag.entrySet()) {
111+
builder.append("\n");
112+
builder.append(indent.repeat(depth + 1)).append(entry.getKey()).append(": ")
113+
.append(prettify(entry.getValue(), depth + 1));
114+
}
115+
yield builder.append("\n").append(currentIndent).append("}").toString();
116+
}
117+
case ListTag<?> listTag -> {
118+
var builder = new StringBuilder("[");
119+
boolean first = true;
120+
for (var value : listTag) {
121+
if (!first) builder.append(",");
122+
first = false;
123+
builder.append("\n");
124+
builder.append(indent.repeat(depth + 1)).append(prettify(value, depth + 1));
125+
}
126+
yield builder.append("\n").append(currentIndent).append("]").toString();
127+
}
128+
case IterableTag<?> iterableTag -> {
129+
var builder = new StringBuilder("[ ");
130+
for (int i = 0; i < iterableTag.size(); i++) {
131+
if (i > 0) builder.append(", ");
132+
Object obj = iterableTag.get(i);
133+
builder.append(obj);
134+
if (obj instanceof Long) builder.append("l");
135+
else if (obj instanceof Byte) builder.append("b");
136+
}
137+
yield builder.append(" ]").toString();
138+
}
139+
default -> tag.toString();
140+
};
141+
}
142+
82143
static final class Builder implements NBT.Builder {
83144
private final SerializationRegistry registry = new SerializationRegistry();
145+
private boolean prettyPrinting = false;
146+
private int indents = 4;
84147

85148
@Override
86149
public <T> NBT.Builder registerTypeHierarchyAdapter(Class<?> type, TagAdapter<T> adapter) {
@@ -118,9 +181,21 @@ public <T> NBT.Builder registerTypeAdapter(Type type, TagSerializer<T> serialize
118181
return this;
119182
}
120183

184+
@Override
185+
public NBT.Builder setPrettyPrinting(boolean prettyPrinting) {
186+
this.prettyPrinting = prettyPrinting;
187+
return this;
188+
}
189+
190+
@Override
191+
public NBT.Builder setIndents(int indents) {
192+
this.indents = indents;
193+
return this;
194+
}
195+
121196
@Override
122197
public NBT build() {
123-
return new SimpleNBT(registry.immutableCopy());
198+
return new SimpleNBT(registry.immutableCopy(), prettyPrinting, indents);
124199
}
125200
}
126201

src/main/java/net/thenextlvl/nbt/tag/ByteArrayTagImpl.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,12 @@ public int hashCode() {
5353

5454
@Override
5555
public String toString() {
56-
return getClass().getSimpleName() +
57-
"{" +
58-
"value=" + Arrays.toString(value) +
59-
'}';
56+
if (value.length == 0) return "[]";
57+
var builder = new StringBuilder("[");
58+
for (int i = 0; i < value.length; i++) {
59+
if (i > 0) builder.append(",");
60+
builder.append(value[i]).append("b");
61+
}
62+
return builder.append(']').toString();
6063
}
6164
}

src/main/java/net/thenextlvl/nbt/tag/ByteTagImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public ByteTagImpl(Byte value) {
1111

1212
@Override
1313
public byte getAsByte() {
14-
return getValue();
14+
return value;
1515
}
1616

1717
@Override
@@ -21,6 +21,11 @@ public byte getTypeId() {
2121

2222
@Override
2323
public void write(NBTOutputStream outputStream) throws IOException {
24-
outputStream.write(getValue());
24+
outputStream.write(value);
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return value + "b";
2530
}
2631
}

src/main/java/net/thenextlvl/nbt/tag/CompoundTagImpl.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ public static CompoundTag.Builder builder() {
109109
return new Builder();
110110
}
111111

112+
@Override
113+
public String toString() {
114+
if (isEmpty()) return "{}";
115+
var builder = new StringBuilder("{");
116+
var iterator = entrySet().iterator();
117+
while (iterator.hasNext()) {
118+
var entry = iterator.next();
119+
builder.append(entry.getKey()).append(':').append(entry.getValue());
120+
if (iterator.hasNext()) builder.append(",");
121+
}
122+
return builder.append('}').toString();
123+
}
124+
112125
public static final class Builder implements CompoundTag.Builder {
113126
private final Map<String, Tag> values = new LinkedHashMap<>();
114127

src/main/java/net/thenextlvl/nbt/tag/DoubleTagImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public DoubleTagImpl(Double value) {
1111

1212
@Override
1313
public double getAsDouble() {
14-
return getValue();
14+
return value;
1515
}
1616

1717
@Override
@@ -21,6 +21,6 @@ public byte getTypeId() {
2121

2222
@Override
2323
public void write(NBTOutputStream outputStream) throws IOException {
24-
outputStream.writeDouble(getValue());
24+
outputStream.writeDouble(value);
2525
}
2626
}

src/main/java/net/thenextlvl/nbt/tag/FloatTagImpl.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public FloatTagImpl(Float value) {
1111

1212
@Override
1313
public float getAsFloat() {
14-
return getValue();
14+
return value;
1515
}
1616

1717
@Override
@@ -21,6 +21,11 @@ public byte getTypeId() {
2121

2222
@Override
2323
public void write(NBTOutputStream outputStream) throws IOException {
24-
outputStream.writeFloat(getValue());
24+
outputStream.writeFloat(value);
25+
}
26+
27+
@Override
28+
public String toString() {
29+
return value + "f";
2530
}
2631
}

src/main/java/net/thenextlvl/nbt/tag/IntArrayTagImpl.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,12 @@ public int hashCode() {
5050

5151
@Override
5252
public String toString() {
53-
return getClass().getSimpleName() +
54-
"{" +
55-
"value=" + Arrays.toString(value) +
56-
'}';
53+
if (value.length == 0) return "[]";
54+
var builder = new StringBuilder("[");
55+
for (int i = 0; i < value.length; i++) {
56+
if (i > 0) builder.append(",");
57+
builder.append(value[i]);
58+
}
59+
return builder.append(']').toString();
5760
}
5861
}

src/main/java/net/thenextlvl/nbt/tag/IntTagImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public IntTagImpl(Integer value) {
1111

1212
@Override
1313
public int getAsInt() {
14-
return getValue();
14+
return value;
1515
}
1616

1717
@Override
@@ -21,6 +21,6 @@ public byte getTypeId() {
2121

2222
@Override
2323
public void write(NBTOutputStream outputStream) throws IOException {
24-
outputStream.writeInt(getValue());
24+
outputStream.writeInt(value);
2525
}
2626
}

0 commit comments

Comments
 (0)