Embed jars of our extra dependencies.

Use Ceres, add NBT serialization format.
Serialize Terminal using Ceres.
This commit is contained in:
Florian Nücke
2020-10-02 03:37:09 +02:00
parent 308a1c5e10
commit 28a945f887
6 changed files with 585 additions and 68 deletions

View File

@@ -46,7 +46,13 @@ compileJava {
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_1_8
}
configurations {
embed
compile.extendsFrom embed
}
repositories {
mavenCentral()
maven { url "http://dvs1.progwml6.com/files/maven" } // JEI
maven { url "http://maven.cil.li/" } // Sedna
}
@@ -54,8 +60,11 @@ repositories {
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
compile 'li.cil.sedna:sedna:0.0.1+'
compile 'li.cil.sedna:sedna-buildroot:0.0.1+'
compileOnly 'org.jetbrains:annotations:16.0.2'
embed 'li.cil.ceres:ceres:0.0.1+'
embed 'li.cil.sedna:sedna:0.0.1+'
embed 'li.cil.sedna:sedna-buildroot:0.0.1+'
compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}:${jei_version}:api")
runtimeOnly fg.deobf("mezz.jei:jei-${minecraft_version}:${jei_version}")
@@ -127,21 +136,57 @@ minecraft {
}
}
jar {
manifest {
attributes([
"Specification-Title" : "oc2",
"Specification-Vendor" : "Sangar",
"Specification-Version" : "1",
"Implementation-Title" : project.name,
"Implementation-Version" : "${semver}",
"Implementation-Vendor" : "Sangar",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
task generateMetaFiles {
ext.embeddedFiles = []
doLast {
file("${buildDir}/dependencyMeta/").deleteDir()
configurations.embed.resolvedConfiguration.resolvedArtifacts.each {
// Don't embed anything Minecraft provides anyway.
if (configurations.minecraft.resolvedConfiguration.resolvedArtifacts.contains(it)) {
return
}
ext.embeddedFiles.add(it.file)
def metaFile = file("${buildDir}/dependencyMeta/${it.file.name}.meta")
metaFile.parentFile.mkdirs()
def artifactRef = it.moduleVersion.toString()
if (it.classifier != null) {
artifactRef += ":${it.classifier}"
}
metaFile.text = "Maven-Artifact: $artifactRef"
}
}
}
jar.finalizedBy('reobfJar')
task embedFilesInJar {
dependsOn generateMetaFiles
doLast {
jar {
into('/') {
from generateMetaFiles.embeddedFiles
from "${buildDir}/dependencyMeta/"
}
manifest {
attributes([
"Specification-Title" : "oc2",
"Specification-Vendor" : "Sangar",
"Specification-Version" : "1",
"Implementation-Title" : project.name,
"Implementation-Version" : "${semver}",
"Implementation-Vendor" : "Sangar",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
'ContainedDeps' : generateMetaFiles.embeddedFiles.collect { it.name }.join(' ')
])
}
}
}
}
jar {
dependsOn embedFilesInJar
finalizedBy 'reobfJar'
}
task apiJar(type: Jar) {
from sourceSets.main.allSource

View File

@@ -4,6 +4,7 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue;
import li.cil.ceres.api.Serialized;
import li.cil.oc2.client.render.font.FontRenderer;
import li.cil.oc2.client.render.font.MonospaceFontRenderer;
import net.minecraft.client.Minecraft;
@@ -13,7 +14,6 @@ import net.minecraft.client.renderer.Matrix4f;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldVertexBufferUploader;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.NoteBlockInstrument;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -25,20 +25,21 @@ import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
// Implements a couple of control sequences from here: https://en.wikipedia.org/wiki/ANSI_escape_code#CSI_sequences
@Serialized
public final class Terminal {
private static final int TAB_WIDTH = 4;
private static final int WIDTH = 80, HEIGHT = 24;
private enum State {
public enum State { // Must be public for serialization.
NORMAL, // Currently reading characters normally.
ESCAPE, // Last character was ESC, figure out what kind next.
SEQUENCE, // Know what sequence we have, now parsing it.
}
private final ByteArrayFIFOQueue input = new ByteArrayFIFOQueue(32);
private final byte[] buffer = new byte[WIDTH * HEIGHT];
private byte[] buffer = new byte[WIDTH * HEIGHT];
private State state = State.NORMAL;
private final int[] args = new int[4];
private int[] args = new int[4];
private int argCount = 0;
private int x, y;
private int savedX, savedY;
@@ -76,53 +77,6 @@ public final class Terminal {
}
}
public CompoundNBT serialize(final boolean forClient) {
final CompoundNBT nbt = new CompoundNBT();
if (!forClient) {
// todo serialize input
}
nbt.putByteArray("buffer", buffer);
nbt.putByte("state", (byte) state.ordinal());
nbt.putIntArray("args", args);
nbt.putInt("argCount", argCount);
nbt.putInt("x", x);
nbt.putInt("y", y);
nbt.putInt("savedX", savedX);
nbt.putInt("savedY", savedY);
return nbt;
}
public void deserialize(final CompoundNBT nbt) {
if (nbt.contains("input")) {
// todo deserialize input
}
final byte[] buffer = nbt.getByteArray("buffer");
if (buffer.length == this.buffer.length) {
System.arraycopy(buffer, 0, this.buffer, 0, buffer.length);
}
final byte state = nbt.getByte("state");
final State[] states = State.values();
if (state >= 0 && state < states.length) {
this.state = states[state];
}
final int[] args = nbt.getIntArray("args");
if (args.length == this.args.length) {
System.arraycopy(args, 0, this.args, 0, args.length);
}
argCount = nbt.getInt("argCount");
x = nbt.getInt("x");
y = nbt.getInt("y");
savedX = nbt.getInt("savedX");
savedY = nbt.getInt("savedY");
}
public synchronized int readInput() {
if (input.isEmpty()) {
return -1;

View File

@@ -3,9 +3,10 @@ package li.cil.oc2.common.tile;
import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue;
import li.cil.oc2.OpenComputers;
import li.cil.oc2.client.gui.terminal.Terminal;
import li.cil.oc2.common.network.TerminalBlockOutputMessage;
import li.cil.oc2.common.network.Network;
import li.cil.oc2.common.network.TerminalBlockOutputMessage;
import li.cil.oc2.common.vm.VirtualMachineRunner;
import li.cil.oc2.serialization.NBTSerialization;
import li.cil.sedna.api.Sizes;
import li.cil.sedna.api.device.PhysicalMemory;
import li.cil.sedna.buildroot.Buildroot;
@@ -90,20 +91,22 @@ public final class ComputerTileEntity extends TileEntity implements ITickableTil
@Override
public CompoundNBT getUpdateTag() {
final CompoundNBT result = super.getUpdateTag();
result.put("terminal", terminal.serialize(true));
result.put("terminal", NBTSerialization.serialize(terminal));
return result;
}
@Override
public void handleUpdateTag(final CompoundNBT tag) {
super.handleUpdateTag(tag);
terminal.deserialize(tag.getCompound("terminal"));
NBTSerialization.deserialize(tag.getCompound("terminal"), terminal);
}
@Override
public void read(final CompoundNBT compound) {
super.read(compound);
joinVirtualMachine();
NBTSerialization.deserialize(compound.getCompound("terminal"), terminal);
// TODO deserialize VM
}
@@ -111,6 +114,7 @@ public final class ComputerTileEntity extends TileEntity implements ITickableTil
public CompoundNBT write(final CompoundNBT compound) {
final CompoundNBT result = super.write(compound);
joinVirtualMachine();
compound.put("terminal", NBTSerialization.serialize(terminal));
// TODO serialize VM
return result;
}

View File

@@ -0,0 +1,308 @@
package li.cil.oc2.serialization;
import li.cil.ceres.Ceres;
import li.cil.ceres.api.DeserializationVisitor;
import li.cil.ceres.api.SerializationException;
import li.cil.ceres.api.SerializationVisitor;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraftforge.common.util.Constants;
import org.jetbrains.annotations.Contract;
import javax.annotation.Nullable;
import java.lang.reflect.Array;
import java.util.UUID;
public final class NBTSerialization {
private static final String IS_NULL_SUFFIX = ".is_null";
public static CompoundNBT serialize(final Object value) throws SerializationException {
final CompoundNBT nbt = new CompoundNBT();
Ceres.getSerializer(value.getClass()).serialize(new Serializer(nbt), value);
return nbt;
}
@SuppressWarnings("unchecked")
public static <T> T deserialize(final CompoundNBT nbt, final T into) throws SerializationException {
return deserialize(nbt, (Class<T>) into.getClass(), into);
}
public static <T> T deserialize(final CompoundNBT nbt, final Class<T> type, @Nullable final T into) throws SerializationException {
return Ceres.getSerializer(type).deserialize(new Deserializer(nbt), type, into);
}
private static final class Serializer implements SerializationVisitor {
private final CompoundNBT nbt;
private Serializer(final CompoundNBT nbt) {
this.nbt = nbt;
}
@Override
public void putBoolean(final String name, final boolean value) {
nbt.putBoolean(name, value);
}
@Override
public void putByte(final String name, final byte value) {
nbt.putByte(name, value);
}
@Override
public void putChar(final String name, final char value) {
nbt.putInt(name, value);
}
@Override
public void putShort(final String name, final short value) {
nbt.putShort(name, value);
}
@Override
public void putInt(final String name, final int value) {
nbt.putInt(name, value);
}
@Override
public void putLong(final String name, final long value) {
nbt.putLong(name, value);
}
@Override
public void putFloat(final String name, final float value) {
nbt.putFloat(name, value);
}
@Override
public void putDouble(final String name, final double value) {
nbt.putDouble(name, value);
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
public void putObject(final String name, final Class<?> type, @Nullable final Object value) throws SerializationException {
if (putIsNull(name, value)) {
return;
}
if (type == boolean[].class) {
final boolean[] data = (boolean[]) value;
final byte[] convertedData = new byte[data.length];
for (int i = 0; i < data.length; i++) {
convertedData[i] = data[i] ? (byte) 1 : (byte) 0;
}
nbt.putByteArray(name, convertedData);
} else if (type == byte[].class) {
nbt.putByteArray(name, (byte[]) value);
} else if (type == char[].class) {
final char[] data = (char[]) value;
final int[] convertedData = new int[data.length];
for (int i = 0; i < data.length; i++) {
convertedData[i] = data[i];
}
nbt.putIntArray(name, convertedData);
} else if (type == short[].class) {
final short[] data = (short[]) value;
final int[] convertedData = new int[data.length];
for (int i = 0; i < data.length; i++) {
convertedData[i] = data[i];
}
nbt.putIntArray(name, convertedData);
} else if (type == int[].class) {
nbt.putIntArray(name, (int[]) value);
} else if (type == long[].class) {
nbt.putLongArray(name, (long[]) value);
} else if (type == float[].class) {
final float[] data = (float[]) value;
final int[] convertedData = new int[data.length];
for (int i = 0; i < data.length; i++) {
convertedData[i] = Float.floatToRawIntBits(data[i]);
}
nbt.putIntArray(name, convertedData);
} else if (type == double[].class) {
final double[] data = (double[]) value;
final long[] convertedData = new long[data.length];
for (int i = 0; i < data.length; i++) {
convertedData[i] = Double.doubleToRawLongBits(data[i]);
}
nbt.putLongArray(name, convertedData);
} else if (type.isArray()) {
final Class<?> componentType = type.getComponentType();
final li.cil.ceres.api.Serializer<?> serializer = Ceres.getSerializer(componentType);
final Object[] data = (Object[]) value;
final ListNBT listNBT = new ListNBT();
for (final Object datum : data) {
final CompoundNBT itemNBT = new CompoundNBT();
if (datum == null) {
itemNBT.putBoolean(IS_NULL_SUFFIX, true);
} else {
if (datum.getClass() != componentType) {
throw new SerializationException(String.format("Polymorphism detected in generic array [%s]. This is not supported.", name));
}
serializer.serialize(new Serializer(itemNBT), (Class) componentType, datum);
}
listNBT.add(itemNBT);
}
nbt.put(name, listNBT);
} else if (type.isEnum()) {
nbt.putString(name, ((Enum) value).name());
} else if (type == String.class) {
nbt.putString(name, (String) value);
} else if (type == UUID.class) {
final CompoundNBT uuidNBT = new CompoundNBT();
uuidNBT.putUniqueId(name, (UUID) value);
nbt.put(name, uuidNBT);
} else {
final CompoundNBT valueNBT = new CompoundNBT();
Ceres.getSerializer(type).serialize(new Serializer(valueNBT), (Class) type, value);
if (!valueNBT.isEmpty()) {
nbt.put(name, valueNBT);
}
}
}
@Contract(value = "_, null -> true")
private boolean putIsNull(final String name, @Nullable final Object value) {
final boolean isNull = value == null;
nbt.putBoolean(name + IS_NULL_SUFFIX, isNull);
return isNull;
}
}
private static final class Deserializer implements DeserializationVisitor {
private final CompoundNBT nbt;
private Deserializer(final CompoundNBT nbt) {
this.nbt = nbt;
}
@Override
public boolean getBoolean(final String name) {
return nbt.getBoolean(name);
}
@Override
public byte getByte(final String name) {
return nbt.getByte(name);
}
@Override
public char getChar(final String name) {
return (char) nbt.getInt(name);
}
@Override
public short getShort(final String name) {
return nbt.getShort(name);
}
@Override
public int getInt(final String name) {
return nbt.getInt(name);
}
@Override
public long getLong(final String name) {
return nbt.getLong(name);
}
@Override
public float getFloat(final String name) {
return nbt.getFloat(name);
}
@Override
public double getDouble(final String name) {
return nbt.getDouble(name);
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Nullable
@Override
public Object getObject(final String name, final Class<?> type, @Nullable final Object into) throws SerializationException {
if (isNull(name)) {
return null;
}
// Do not overwrite values which were not serialized before.
if (!nbt.contains(name)) {
return into;
}
if (type == boolean[].class) {
final byte[] convertedData = nbt.getByteArray(name);
final boolean[] data = new boolean[convertedData.length];
for (int i = 0; i < convertedData.length; i++) {
data[i] = convertedData[i] != 0;
}
return data;
} else if (type == byte[].class) {
return nbt.getByteArray(name);
} else if (type == char[].class) {
final int[] convertedData = nbt.getIntArray(name);
final char[] data = new char[convertedData.length];
for (int i = 0; i < convertedData.length; i++) {
data[i] = (char) convertedData[i];
}
return data;
} else if (type == short[].class) {
final int[] convertedData = nbt.getIntArray(name);
final short[] data = new short[convertedData.length];
for (int i = 0; i < convertedData.length; i++) {
data[i] = (short) convertedData[i];
}
return data;
} else if (type == int[].class) {
return nbt.getIntArray(name);
} else if (type == long[].class) {
return nbt.getLongArray(name);
} else if (type == float[].class) {
final int[] convertedData = nbt.getIntArray(name);
final float[] data = new float[convertedData.length];
for (int i = 0; i < convertedData.length; i++) {
data[i] = Float.intBitsToFloat(convertedData[i]);
}
return data;
} else if (type == double[].class) {
final long[] convertedData = nbt.getLongArray(name);
final double[] data = new double[convertedData.length];
for (int i = 0; i < convertedData.length; i++) {
data[i] = Double.longBitsToDouble(convertedData[i]);
}
return data;
} else if (type.isArray()) {
final Class<?> componentType = type.getComponentType();
final li.cil.ceres.api.Serializer<?> serializer = Ceres.getSerializer(componentType);
final ListNBT listNBT = nbt.getList(name, Constants.NBT.TAG_COMPOUND);
final Object[] data = (Object[]) Array.newInstance(componentType, listNBT.size());
for (int i = 0; i < listNBT.size(); i++) {
final CompoundNBT itemNBT = listNBT.getCompound(i);
if (itemNBT.contains(IS_NULL_SUFFIX)) {
continue;
}
data[i] = serializer.deserialize(new Deserializer(itemNBT), (Class) componentType, null);
}
return data;
} else if (type.isEnum()) {
return Enum.valueOf((Class) type, nbt.getString(name));
} else if (type == String.class) {
return nbt.getString(name);
} else if (type == UUID.class) {
return nbt.getCompound(name).getUniqueId(name);
} else {
final CompoundNBT valueNBT = nbt.getCompound(name);
return Ceres.getSerializer(type).deserialize(new Deserializer(valueNBT), (Class) type, into);
}
}
@Override
public boolean exists(final String name) {
return nbt.contains(name) || nbt.contains(name + IS_NULL_SUFFIX);
}
private boolean isNull(final String name) {
return nbt.getBoolean(name + IS_NULL_SUFFIX);
}
}
}

View File

@@ -0,0 +1,7 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package li.cil.oc2.serialization;
import mcp.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -0,0 +1,199 @@
package li.cil.oc2.serialization;
import li.cil.ceres.api.Serialized;
import net.minecraft.nbt.CompoundNBT;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.UUID;
public final class SerializationTests {
@Test
public void testSerializeFlat() {
final Flat value = new Flat();
final UUID uuid = UUID.randomUUID();
value.byteValue = 123;
value.shortValue = 234;
value.intValue = 456;
value.longValue = 567;
value.floatValue = 678.9f;
value.doubleValue = 789.0;
value.byteArrayValue = new byte[]{1, 2, 3};
value.intArrayValue = new int[]{4, 5, 6};
value.longArrayValue = new long[]{7, 8, 9};
value.stringValue = "test string";
value.uuidValue = uuid;
final CompoundNBT nbt = Assertions.assertDoesNotThrow(() -> NBTSerialization.serialize(value));
Assertions.assertEquals(123, nbt.getByte("byteValue"));
Assertions.assertEquals(234, nbt.getShort("shortValue"));
Assertions.assertEquals(456, nbt.getInt("intValue"));
Assertions.assertEquals(567, nbt.getLong("longValue"));
Assertions.assertEquals(678.9f, nbt.getFloat("floatValue"));
Assertions.assertEquals(789.0, nbt.getDouble("doubleValue"));
Assertions.assertArrayEquals(new byte[]{1, 2, 3}, nbt.getByteArray("byteArrayValue"));
Assertions.assertArrayEquals(new int[]{4, 5, 6}, nbt.getIntArray("intArrayValue"));
Assertions.assertArrayEquals(new long[]{7, 8, 9}, nbt.getLongArray("longArrayValue"));
Assertions.assertEquals("test string", nbt.getString("stringValue"));
Assertions.assertEquals(uuid, nbt.getCompound("uuidValue").getUniqueId("uuidValue"));
}
@Test
public void testDeserializeFlatInto() {
final CompoundNBT nbt = new CompoundNBT();
nbt.putByte("byteValue", (byte) 98);
nbt.putShort("shortValue", (short) 876);
nbt.putInt("intValue", 765);
nbt.putLong("longValue", 654);
nbt.putFloat("floatValue", 543.2f);
nbt.putDouble("doubleValue", 432.1);
nbt.putByteArray("byteArrayValue", new byte[]{9, 8, 7});
nbt.putIntArray("intArrayValue", new int[]{8, 7, 6});
nbt.putLongArray("longArrayValue", new long[]{7, 6, 5});
nbt.putString("stringValue", "another test");
final UUID uuid = UUID.randomUUID();
final CompoundNBT uuidNBT = new CompoundNBT();
uuidNBT.putUniqueId("uuidValue", uuid);
nbt.put("uuidValue", uuidNBT);
final Flat value = Assertions.assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Flat.class, new Flat()));
Assertions.assertEquals(98, value.byteValue);
Assertions.assertEquals(876, value.shortValue);
Assertions.assertEquals(765, value.intValue);
Assertions.assertEquals(654, value.longValue);
Assertions.assertEquals(543.2f, value.floatValue);
Assertions.assertEquals(432, .1, value.doubleValue);
Assertions.assertArrayEquals(new byte[]{9, 8, 7}, value.byteArrayValue);
Assertions.assertArrayEquals(new int[]{8, 7, 6}, value.intArrayValue);
Assertions.assertArrayEquals(new long[]{7, 6, 5}, value.longArrayValue);
Assertions.assertEquals("another test", value.stringValue);
Assertions.assertEquals(uuid, value.uuidValue);
}
@Test
public void testDeserializeFlatNew() {
final CompoundNBT nbt = new CompoundNBT();
nbt.putByte("byteValue", (byte) 98);
nbt.putShort("shortValue", (short) 876);
nbt.putInt("intValue", 765);
nbt.putLong("longValue", 654);
nbt.putFloat("floatValue", 543.2f);
nbt.putDouble("doubleValue", 432.1);
nbt.putByteArray("byteArrayValue", new byte[]{9, 8, 7});
nbt.putIntArray("intArrayValue", new int[]{8, 7, 6});
nbt.putLongArray("longArrayValue", new long[]{7, 6, 5});
nbt.putString("stringValue", "another test");
final UUID uuid = UUID.randomUUID();
final CompoundNBT uuidNBT = new CompoundNBT();
uuidNBT.putUniqueId("uuidValue", uuid);
nbt.put("uuidValue", uuidNBT);
final Flat value = Assertions.assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Flat.class, null));
Assertions.assertEquals(98, value.byteValue);
Assertions.assertEquals(876, value.shortValue);
Assertions.assertEquals(765, value.intValue);
Assertions.assertEquals(654, value.longValue);
Assertions.assertEquals(543.2f, value.floatValue);
Assertions.assertEquals(432, .1, value.doubleValue);
Assertions.assertArrayEquals(new byte[]{9, 8, 7}, value.byteArrayValue);
Assertions.assertArrayEquals(new int[]{8, 7, 6}, value.intArrayValue);
Assertions.assertArrayEquals(new long[]{7, 6, 5}, value.longArrayValue);
Assertions.assertEquals("another test", value.stringValue);
Assertions.assertEquals(uuid, value.uuidValue);
}
@Test
public void testModifiers() {
final WithModifiers value = new WithModifiers();
final CompoundNBT nbt = Assertions.assertDoesNotThrow(() -> NBTSerialization.serialize(value));
Assertions.assertTrue(nbt.contains("nonTransientInt"));
Assertions.assertEquals(123, nbt.getInt("nonTransientInt"));
Assertions.assertFalse(nbt.contains("transientInt"));
Assertions.assertFalse(nbt.contains("finalInt"));
nbt.putIntArray("finalIntArray", new int[]{8, 7, 6});
Assertions.assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, value));
Assertions.assertArrayEquals(new int[]{4, 5, 6}, value.finalIntArray);
}
@Test
public void testSerializeNested() {
final Nested root = new Nested();
root.value = 123;
root.child = new Nested();
root.child.value = 234;
final CompoundNBT nbt = Assertions.assertDoesNotThrow(() -> NBTSerialization.serialize(root));
Assertions.assertEquals(123, nbt.getInt("value"));
Assertions.assertTrue(nbt.contains("child"));
Assertions.assertEquals(234, nbt.getCompound("child").getInt("value"));
}
@Test
public void testDeserializeNestedInto() {
final CompoundNBT nbt = new CompoundNBT();
nbt.putInt("value", 123);
final CompoundNBT child = new CompoundNBT();
nbt.put("child", child);
child.putInt("value", 234);
final Nested value = Assertions.assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Nested.class, new Nested()));
Assertions.assertEquals(123, value.value);
Assertions.assertEquals(234, value.child.value);
Assertions.assertNull(value.child.child);
}
@Test
public void testDeserializeNestedNew() {
final CompoundNBT nbt = new CompoundNBT();
nbt.putInt("value", 123);
final CompoundNBT child = new CompoundNBT();
nbt.put("child", child);
child.putInt("value", 234);
final Nested value = Assertions.assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Nested.class, null));
Assertions.assertEquals(123, value.value);
Assertions.assertEquals(234, value.child.value);
Assertions.assertNull(value.child.child);
}
@Serialized
private static final class Flat {
private byte byteValue;
private short shortValue;
private int intValue;
private long longValue;
private float floatValue;
private double doubleValue;
private byte[] byteArrayValue;
private int[] intArrayValue;
private long[] longArrayValue;
private String stringValue;
private UUID uuidValue;
}
@Serialized
private static final class WithModifiers {
private int nonTransientInt = 123;
private transient int transientInt = 345;
private final int finalInt = 678;
private final int[] finalIntArray = {4, 5, 6};
}
@Serialized
private static final class Nested {
private int value;
private Nested child;
}
}