Skip to content

Commit

Permalink
Merge 55b3faf into b56ad64
Browse files Browse the repository at this point in the history
  • Loading branch information
Querz committed Apr 25, 2020
2 parents b56ad64 + 55b3faf commit 46b01c5
Show file tree
Hide file tree
Showing 87 changed files with 2,086 additions and 2,476 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,4 @@ doc/
# ignore out
out/

# ignore patches
*.patch
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2016 Querz
Copyright (c) 2016 - 2020 Querz

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
38 changes: 7 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# NBT
[![Build Status](https://travis-ci.org/Querz/NBT.svg?branch=master)](https://travis-ci.org/Querz/NBT) [![Coverage Status](https://img.shields.io/coveralls/github/Querz/NBT/master.svg)](https://coveralls.io/github/Querz/NBT?branch=master) [![Release](https://jitpack.io/v/Querz/NBT.svg)](https://jitpack.io/#Querz/NBT)
#### A java implementation of the [NBT protocol](http://minecraft.gamepedia.com/NBT_format), including a way to implement custom tags.
#### A java implementation of the [NBT protocol](http://minecraft.gamepedia.com/NBT_format) for Minecraft Java Edition.
---
### Specification
According to the [specification](https://minecraft.gamepedia.com/NBT_format), there are currently 13 different types of tags:
Expand Down Expand Up @@ -56,33 +56,31 @@ Some methods do not provide a parameter to specify the maximum depth, but instea
### Utility
There are several utility methods to make your life easier if you use this library.
#### NBTUtil
`NBTUtil.writeTag()` lets you write a Tag into a gzip compressed or uncompressed file in one line (not counting exception handling). Files are gzip compressed by default.
`NBTUtil.write()` lets you write a Tag into a gzip compressed or uncompressed file in one line (not counting exception handling). Files are gzip compressed by default.

Example usage:
```java
NBTUtil.writeTag(tag, "filename.dat");
NBTUtil.write(namedTag, "filename.dat");
```
`NBTUtil.readTag()` reads any file containing NBT data. No worry about compression, it will automatically uncompress gzip compressed files.
`NBTUtil.read()` reads any file containing NBT data. No worry about compression, it will automatically uncompress gzip compressed files.

Example usage:
```java
Tag<?> tag = NBTUtil.readTag("filename.dat");
NamedTag namedTag = NBTUtil.read("filename.dat");
```
#### Playing Minecraft?
Each tag can be converted into a JSON-like NBT String used in Minecraft commands.
Each tag can be converted into an NBT String (SNBT) used in Minecraft commands.

Example usage:
```java
CompoundTag c = new CompoundTag();
c.putByte("blah", (byte) 5);
c.putString("foo", "bär");
System.out.println(c.toTagString()); // {blah:5b,foo:"bär"}

ListTag<StringTag> s = new ListTag<>(StringTag.class);
s.addString("test");
s.add(new StringTag("text"));
c.add("list", s);
System.out.println(c.toTagString()); // {blah:5b,foo:"bär",list:[test,text]}
System.out.println(SNBTUtil.toSNBT(c)); // {blah:5b,foo:"bär",list:[test,text]}

```
There is also a tool to read, change and write MCA files.
Expand Down Expand Up @@ -117,25 +115,3 @@ mcaFile.cleanupPalettesAndBlockStates();
chunk.cleanupPalettesAndBlockStates();
section.cleanupPaletteAndBlockStates();
```

---
### Custom tags
Interested in more advanced features, and the default NBT protocol just isn't enough? Simply create your own tags!
There are 4 example classes in `net.querz.nbt.custom` that show how to implement custom tags:
| Class | ID | Description |
| ------------- | :-: | ----------- |
| [ObjectTag](src/main/java/net/querz/nbt/custom/ObjectTag.java) | 90 | A wrapper tag that serializes and deserializes any object using the default java serialization. |
| [ShortArrayTag](src/main/java/net/querz/nbt/custom/ShortArrayTag.java) | 100 | In addition to the already existing `ByteArrayTag`, `IntArrayTag` and `LongArrayTag`. |
| [CharTag](src/main/java/net/querz/nbt/custom/CharTag.java) | 110 | `Character` (char) tag. |
| [StructTag](src/main/java/net/querz/nbt/custom/StructTag.java) | 120 | Similar to the `ListTag`, but with the ability to store multiple types. |
To be able to use a custom tag with deserialization, a `Supplier` and the custom tag class must be registered at runtime alongside its id with `TagFactory.registerCustomTag()`. The `Supplier` can be anything that returns a new instance of this custom tag. Here is an example using the custom tags no-args constructor:
```java
TagFactory.registerCustomTag(90, ObjectTag::new, ObjectTag.class);
```
#### Nesting
As mentioned before, serialization and deserialization methods are provided with a parameter indicating the maximum processing depth of the structure. This is not guaranteed when using custom tags, it is the responsibility of the creator of that custom tag to call `Tag#decrementMaxDepth(int)` to correctly update the nesting depth.
It is also highly encouraged to document the custom tag behaviour when it does so to make users aware of the possible exceptions thrown by `Tag#decrementMaxDepth(int)`.
8 changes: 1 addition & 7 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ apply plugin: 'jacoco'

group = 'net.querz.nbt'
archivesBaseName = 'nbt'
version = '4.1'
version = '5.0'
sourceCompatibility = '1.8'
targetCompatibility = '1.8'
compileJava.options.encoding = 'UTF-8'
Expand Down Expand Up @@ -53,9 +53,3 @@ artifacts {
archives sourcesJar
archives javadocJar
}

jar {
manifest {
attributes('Automatic-Module-Name': 'net.querz.nbt')
}
}
42 changes: 42 additions & 0 deletions src/main/java/net/querz/io/Deserializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package net.querz.io;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

public interface Deserializer<T> {

T fromStream(InputStream stream) throws IOException;

default T fromFile(File file) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file))) {
return fromStream(bis);
}
}

default T fromBytes(byte[] data) throws IOException {
ByteArrayInputStream stream = new ByteArrayInputStream(data);
return fromStream(stream);
}

default T fromResource(Class<?> clazz, String path) throws IOException {
try (InputStream stream = clazz.getClassLoader().getResourceAsStream(path)) {
if (stream == null) {
throw new IOException("resource \"" + path + "\" not found");
}
return fromStream(stream);
}
}

default T fromURL(URL url) throws IOException {
try (InputStream stream = url.openStream()) {
return fromStream(stream);
}
}


}
7 changes: 7 additions & 0 deletions src/main/java/net/querz/io/ExceptionBiFunction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.querz.io;

@FunctionalInterface
public interface ExceptionBiFunction <T, U, R, E extends Exception> {

R accept(T t, U u) throws E;
}
7 changes: 7 additions & 0 deletions src/main/java/net/querz/io/ExceptionTriConsumer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.querz.io;

@FunctionalInterface
public interface ExceptionTriConsumer<T, U, V, E extends Exception> {

void accept(T t, U u, V v) throws E;
}
13 changes: 13 additions & 0 deletions src/main/java/net/querz/io/MaxDepthIO.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.querz.io;

public interface MaxDepthIO {

default int decrementMaxDepth(int maxDepth) {
if (maxDepth < 0) {
throw new IllegalArgumentException("negative maximum depth is not allowed");
} else if (maxDepth == 0) {
throw new MaxDepthReachedException("reached maximum depth of NBT structure");
}
return --maxDepth;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package net.querz.nbt;
package net.querz.io;

/**
* Exception indicating that the maximum (de-)serialization depth has been reached.
*/
@SuppressWarnings("serial")
public class MaxDepthReachedException extends RuntimeException {

public MaxDepthReachedException(String msg) {
super(msg);
}
Expand Down
26 changes: 26 additions & 0 deletions src/main/java/net/querz/io/Serializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package net.querz.io;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public interface Serializer<T> {

void toStream(T object, OutputStream out) throws IOException;

default void toFile(T object, File file) throws IOException {
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
toStream(object, bos);
}
}

default byte[] toBytes(T object) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
toStream(object, bos);
bos.close();
return bos.toByteArray();
}
}
37 changes: 37 additions & 0 deletions src/main/java/net/querz/io/StringDeserializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.querz.io;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;

public interface StringDeserializer<T> extends Deserializer<T> {

T fromReader(Reader reader) throws IOException;

default T fromString(String s) throws IOException {
return fromReader(new StringReader(s));
}

@Override
default T fromStream(InputStream stream) throws IOException {
try (Reader reader = new InputStreamReader(stream)) {
return fromReader(reader);
}
}

@Override
default T fromFile(File file) throws IOException {
try (Reader reader = new FileReader(file)) {
return fromReader(reader);
}
}

@Override
default T fromBytes(byte[] data) throws IOException {
return fromReader(new StringReader(new String(data)));
}
}
35 changes: 35 additions & 0 deletions src/main/java/net/querz/io/StringSerializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package net.querz.io;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;

public interface StringSerializer<T> extends Serializer<T> {

void toWriter(T object, Writer writer) throws IOException;

default String toString(T object) throws IOException {
Writer writer = new StringWriter();
toWriter(object, writer);
writer.flush();
return writer.toString();
}

@Override
default void toStream(T object, OutputStream stream) throws IOException {
Writer writer = new OutputStreamWriter(stream);
toWriter(object, writer);
writer.flush();
}

@Override
default void toFile(T object, File file) throws IOException {
try (Writer writer = new FileWriter(file)) {
toWriter(object, writer);
}
}
}
Loading

0 comments on commit 46b01c5

Please sign in to comment.