Skip to content

Commit 3500445

Browse files
authored
Merge pull request #1 from iBuyMountainDew/rewrite
Rewrite for 1.3.0
2 parents b425a6f + c9c91c4 commit 3500445

43 files changed

Lines changed: 2170 additions & 2508 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<br>
44
</h1>
55

6-
<h4 align="center">Basic library for reading and writing Minecraft's NBT format.</h4>
6+
<h4 align="center">Flexible and intuitive library for reading and writing Minecraft's NBT format.</h4>
77

88
<p align="center">
99
<a href="#overview">Overview</a>
@@ -23,18 +23,18 @@ NBT (Named Binary Tag) is a binary format devised by Notch to be Minecraft's pri
2323

2424
There are 12 types of tag that can be used in a complaint NBT file (see [TagType.java](src/main/java/dev/dewy/nbt/utils/TagType.java) for descriptions of each):
2525

26-
- [Byte](src/main/java/dev/dewy/nbt/tags/number/ByteTag.java)
27-
- [Short](src/main/java/dev/dewy/nbt/tags/number/ShortTag.java)
28-
- [Int](src/main/java/dev/dewy/nbt/tags/number/IntTag.java)
29-
- [Long](src/main/java/dev/dewy/nbt/tags/number/LongTag.java)
30-
- [Float](src/main/java/dev/dewy/nbt/tags/number/FloatTag.java)
31-
- [Double](src/main/java/dev/dewy/nbt/tags/number/DoubleTag.java)
26+
- [Byte](src/main/java/dev/dewy/nbt/tags/primitive/ByteTag.java)
27+
- [Short](src/main/java/dev/dewy/nbt/tags/primitive/ShortTag.java)
28+
- [Int](src/main/java/dev/dewy/nbt/tags/primitive/IntTag.java)
29+
- [Long](src/main/java/dev/dewy/nbt/tags/primitive/LongTag.java)
30+
- [Float](src/main/java/dev/dewy/nbt/tags/primitive/FloatTag.java)
31+
- [Double](src/main/java/dev/dewy/nbt/tags/primitive/DoubleTag.java)
3232
- [Byte Array](src/main/java/dev/dewy/nbt/tags/array/ByteArrayTag.java)
3333
- [Int Array](src/main/java/dev/dewy/nbt/tags/array/IntArrayTag.java)
3434
- [Long Array](src/main/java/dev/dewy/nbt/tags/array/LongArrayTag.java)
35-
- [String](src/main/java/dev/dewy/nbt/tags/StringTag.java)
36-
- [List](src/main/java/dev/dewy/nbt/tags/ListTag.java)
37-
- [Compound](src/main/java/dev/dewy/nbt/tags/CompoundTag.java)
35+
- [String](src/main/java/dev/dewy/nbt/tags/primitive/StringTag.java)
36+
- [List](src/main/java/dev/dewy/nbt/tags/collection/ListTag.java)
37+
- [Compound](src/main/java/dev/dewy/nbt/tags/collection/CompoundTag.java)
3838

3939
All valid NBT structures begin with a compound tag; the root compound (abstracted as the [root tag](src/main/java/dev/dewy/nbt/tags/RootTag.java)). Everything else in the NBT structure is a child of this root compound.
4040

@@ -48,34 +48,37 @@ repositories {
4848
}
4949
5050
dependencies {
51-
implementation "dev.dewy:nbt:1.2.0"
51+
implementation "dev.dewy:nbt:1.3.0"
5252
}
5353
```
5454

5555
#### NBTReader Sample: Base64
5656

57-
The NBTReader class can be used to easily (de)serialize NBT data:
57+
The [Nbt](src/main/java/dev/dewy/nbt/Nbt.java) class can be used to easily (de)serialize NBT data:
5858

5959
```java
60-
RootTag root = NbtReader.fromBase64("CgALaGVsbG8gd29ybGQDAAR0ZXN0AAAAAAA=");
60+
public static final Nbt NBT = new Nbt();
61+
```
62+
63+
```java
64+
CompoundTag test = NBT.fromBase64("CgALaGVsbG8gd29ybGQDAAR0ZXN0AAAAAAA");
6165

62-
System.out.println(root.getName()); // hello world
63-
System.out.println(root.getCompound().getInt("test").getValue()); // 0
66+
System.out.println(test.getName()); // hello world
67+
System.out.println(test.<IntTag>get("test").getValue()); // 0
6468
```
6569

6670
See the [NbtTest](src/test/java/dev/dewy/nbt/test/NbtTest.java) class for full sample usage.
6771

6872
### Features
6973

7074
- Fully compliant with Mojang's "standards"
71-
- Small and lightweight (32Kb!)
75+
- Small and lightweight (36Kb!)
7276
- Supports all Java edition NBT tags (including long array)
7377
- Intuitive and flexible reading and writing functionality
7478

7579
#### Planned
7680

77-
- SNBT (Stringified NBT) support for Java and Bedrock
78-
- BNBT (Bedrock NBT) support
81+
- SNBT (Stringified NBT) support
7982
- ENBT (Extended NBT) format (missing data types e.g., double array) support
8083
- JSON (De)serialization
8184

build.gradle

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

77
group "dev.dewy"
8-
version "1.2.0"
8+
version "1.3.0"
9+
10+
repositories {
11+
mavenCentral()
12+
}
13+
14+
dependencies {
15+
implementation "org.apache.commons:commons-lang3:$lang3"
16+
17+
compileOnly "org.projectlombok:lombok:$lombok"
18+
annotationProcessor "org.projectlombok:lombok:$lombok"
19+
20+
testCompileOnly "org.projectlombok:lombok:$lombok"
21+
testAnnotationProcessor "org.projectlombok:lombok:$lombok"
22+
}
923

1024
task sourcesJar(type: Jar, dependsOn: classes) {
1125
classifier = "sources"

gradle.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lombok=1.18.20
2+
lang3=3.12.0

sample.nbt

43.5 KB
Binary file not shown.

samplegzip.nbt

14.9 KB
Binary file not shown.

samplezlib.nbt

14.9 KB
Binary file not shown.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package dev.dewy.nbt;
2+
3+
import java.io.BufferedInputStream;
4+
import java.io.IOException;
5+
import java.io.InputStream;
6+
7+
/**
8+
* Defines the types of compression supported by this library for NBT data.
9+
*
10+
* @author dewy
11+
*/
12+
public enum CompressionType {
13+
/**
14+
* No compression.
15+
*/
16+
NONE,
17+
18+
/**
19+
* GZIP compression ({@code GZIPInputStream} and {@code GZIPOutputStream}).
20+
*/
21+
GZIP,
22+
23+
/**
24+
* ZLIB compression ({@code InflaterInputStream} and {@code DeflaterOutputStream}).
25+
*/
26+
ZLIB;
27+
28+
static CompressionType getCompression(InputStream in) throws IOException {
29+
if (!in.markSupported()) {
30+
in = new BufferedInputStream(in);
31+
}
32+
in.mark(0);
33+
34+
if (in.read() == 120) {
35+
return ZLIB;
36+
}
37+
38+
in.reset();
39+
if (in.read() == 31) {
40+
return GZIP;
41+
}
42+
43+
return NONE;
44+
}
45+
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
package dev.dewy.nbt;
2+
3+
import dev.dewy.nbt.tags.collection.CompoundTag;
4+
import lombok.NonNull;
5+
6+
import java.io.*;
7+
import java.nio.charset.StandardCharsets;
8+
import java.util.Base64;
9+
import java.util.zip.DeflaterOutputStream;
10+
import java.util.zip.GZIPInputStream;
11+
import java.util.zip.GZIPOutputStream;
12+
import java.util.zip.InflaterInputStream;
13+
14+
/**
15+
* Standard interface for reading and writing NBT data structures.
16+
*
17+
* @author dewy
18+
*/
19+
public class Nbt {
20+
private @NonNull TagTypeRegistry typeRegistry;
21+
private final @NonNull NbtWriter writer;
22+
private final @NonNull NbtReader reader;
23+
24+
/**
25+
* Constructs an instance of this class using a default {@link TagTypeRegistry} (supporting the standard 12 tag types).
26+
*/
27+
public Nbt() {
28+
this(new TagTypeRegistry());
29+
}
30+
31+
/**
32+
* Constructs an instance of this class using a given {@link TagTypeRegistry}.
33+
*
34+
* @param typeRegistry the tag type registry to be used, typically containing custom tag entries.
35+
*/
36+
public Nbt(@NonNull TagTypeRegistry typeRegistry) {
37+
this.typeRegistry = typeRegistry;
38+
39+
this.writer = new NbtWriter(typeRegistry);
40+
this.reader = new NbtReader(typeRegistry);
41+
}
42+
43+
/**
44+
* Writes the given root {@link CompoundTag} to a provided {@link DataOutput} stream.
45+
*
46+
* @param compound the NBT structure to write, contained within a {@link CompoundTag}.
47+
* @param output the stream to write to.
48+
* @throws IOException if any I/O error occurs.
49+
*/
50+
public void toStream(@NonNull CompoundTag compound, @NonNull DataOutput output) throws IOException {
51+
this.writer.toStream(compound, output);
52+
}
53+
54+
/**
55+
* Writes the given root {@link CompoundTag} to a {@link File} with no compression.
56+
*
57+
* @param compound the NBT structure to write, contained within a {@link CompoundTag}.
58+
* @param file the file to write to.
59+
* @throws IOException if any I/O error occurs.
60+
*/
61+
public void toFile(@NonNull CompoundTag compound, @NonNull File file) throws IOException {
62+
this.toFile(compound, file, CompressionType.NONE);
63+
}
64+
65+
/**
66+
* Writes the given root {@link CompoundTag} to a {@link File} using a certain {@link CompressionType}.
67+
*
68+
* @param compound the NBT structure to write, contained within a {@link CompoundTag}.
69+
* @param file the file to write to.
70+
* @param compression the compression to be applied.
71+
* @throws IOException if any I/O error occurs.
72+
*/
73+
public void toFile(@NonNull CompoundTag compound, @NonNull File file, @NonNull CompressionType compression) throws IOException {
74+
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
75+
DataOutputStream dos = null;
76+
77+
switch (compression) {
78+
case NONE:
79+
dos = new DataOutputStream(bos);
80+
break;
81+
case GZIP:
82+
dos = new DataOutputStream(new GZIPOutputStream(bos));
83+
break;
84+
case ZLIB:
85+
dos = new DataOutputStream(new DeflaterOutputStream(bos));
86+
}
87+
88+
this.toStream(compound, dos);
89+
dos.close();
90+
}
91+
92+
/**
93+
* Converts the given root {@link CompoundTag} to a {@code byte[]} array.
94+
*
95+
* @param compound the NBT structure to write, contained within a {@link CompoundTag}.
96+
* @return the resulting {@code byte[]} array.
97+
* @throws IOException if any I/O error occurs.
98+
*/
99+
public byte[] toByteArray(@NonNull CompoundTag compound) throws IOException {
100+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
101+
DataOutputStream w = new DataOutputStream(new BufferedOutputStream(baos));
102+
103+
this.toStream(compound, w);
104+
w.flush();
105+
106+
return baos.toByteArray();
107+
}
108+
109+
/**
110+
* Converts the given root {@link CompoundTag} to a Base64 encoded string.
111+
*
112+
* @param compound the NBT structure to write, contained within a {@link CompoundTag}.
113+
* @return the resulting Base64 encoded string.
114+
* @throws IOException if any I/O error occurs.
115+
*/
116+
public String toBase64(@NonNull CompoundTag compound) throws IOException {
117+
return new String(Base64.getEncoder().encode(this.toByteArray(compound)), StandardCharsets.UTF_8);
118+
}
119+
120+
/**
121+
* Reads an NBT data structure (root {@link CompoundTag}) from a {@link DataInput} stream.
122+
*
123+
* @param input the stream to read from.
124+
* @return the root {@link CompoundTag} read from the stream.
125+
* @throws IOException if any I/O error occurs.
126+
*/
127+
public CompoundTag fromStream(@NonNull DataInput input) throws IOException {
128+
return this.reader.fromStream(input);
129+
}
130+
131+
/**
132+
* Reads an NBT data structure (root {@link CompoundTag}) from a {@link File}.
133+
*
134+
* @param file the file to read from.
135+
* @return the root {@link CompoundTag} read from the stream.
136+
* @throws IOException if any I/O error occurs.
137+
*/
138+
public CompoundTag fromFile(@NonNull File file) throws IOException {
139+
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
140+
DataInputStream in;
141+
142+
switch (CompressionType.getCompression(new FileInputStream(file))) {
143+
case NONE:
144+
in = new DataInputStream(bis);
145+
break;
146+
case GZIP:
147+
in = new DataInputStream(new GZIPInputStream(bis));
148+
break;
149+
case ZLIB:
150+
in = new DataInputStream(new InflaterInputStream(bis));
151+
break;
152+
default:
153+
throw new IllegalStateException("Illegal compression type. This should never happen.");
154+
}
155+
156+
CompoundTag result = this.fromStream(in);
157+
in.close();
158+
159+
return result;
160+
}
161+
162+
/**
163+
* Reads an NBT data structure (root {@link CompoundTag}) from a {@code byte[]} array.
164+
*
165+
* @param bytes the {@code byte[]} array to read from.
166+
* @return the root {@link CompoundTag} read from the stream.
167+
* @throws IOException if any I/O error occurs.
168+
*/
169+
public CompoundTag fromByteArray(@NonNull byte[] bytes) throws IOException {
170+
return fromStream(new DataInputStream(new BufferedInputStream(new ByteArrayInputStream(bytes))));
171+
}
172+
173+
/**
174+
* Decodes an NBT data structure (root {@link CompoundTag}) from a Base64 encoded string.
175+
*
176+
* @param encoded the encoded Base64 string to decode.
177+
* @return the decoded root {@link CompoundTag}.
178+
* @throws IOException if any I/O error occurs.
179+
*/
180+
public CompoundTag fromBase64(@NonNull String encoded) throws IOException {
181+
return fromByteArray(Base64.getDecoder().decode(encoded));
182+
}
183+
184+
/**
185+
* Returns the {@link TagTypeRegistry} currently in use by this instance.
186+
*
187+
* @return the {@link TagTypeRegistry} currently in use by this instance.
188+
*/
189+
public TagTypeRegistry getTypeRegistry() {
190+
return typeRegistry;
191+
}
192+
193+
/**
194+
* Sets the {@link TagTypeRegistry} currently in use by this instance. Used to utilise custom-made tag types.
195+
*
196+
* @param typeRegistry the new {@link TagTypeRegistry} to be set.
197+
*/
198+
public void setTypeRegistry(@NonNull TagTypeRegistry typeRegistry) {
199+
this.typeRegistry = typeRegistry;
200+
201+
this.writer.setTypeRegistry(typeRegistry);
202+
this.reader.setTypeRegistry(typeRegistry);
203+
}
204+
}

0 commit comments

Comments
 (0)