Add support for schematics v3 output <3
This commit is contained in:
1 parent
a7204cceb7
commit
95ed2a8a85
3 files changed
+81
-27
No files matched your search
@@ -5,27 +5,20 @@ import io.ib67.sfcraft.ServerModule;
|
||||
import io.ib67.sfcraft.config.SFConfig;
|
||||
import io.ib67.sfcraft.module.SignatureService;
|
||||
import io.ib67.sfcraft.util.Helper;
|
||||
import io.ib67.sfcraft.util.LitematicConverter;
|
||||
import io.ib67.sfcraft.util.litematic.LitematicConverter;
|
||||
import io.ib67.sfcraft.util.litematic.LitematicConverterV3;
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.UploadedFile;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.log4j.Log4j2;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.nbt.NbtSizeTracker;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Log4j2
|
||||
public class WebModule extends ServerModule {
|
||||
@@ -87,7 +80,7 @@ public class WebModule extends ServerModule {
|
||||
log.info("Saved " + fileName + " as a schematic.");
|
||||
} else if (fileName.endsWith(".litematic")) {
|
||||
log.error("Handling new {}", fileName);
|
||||
var converter = new LitematicConverter(
|
||||
var converter = new LitematicConverterV3(
|
||||
file.content(),
|
||||
new NbtSizeTracker(config.maxSchematicSize, 16)
|
||||
);
|
||||
|
||||
+17
-17
@@ -1,4 +1,4 @@
|
||||
package io.ib67.sfcraft.util;
|
||||
package io.ib67.sfcraft.util.litematic;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
@@ -6,8 +6,6 @@ import lombok.SneakyThrows;
|
||||
import net.minecraft.nbt.*;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -17,8 +15,8 @@ import java.util.stream.Collectors;
|
||||
* Uses {@link NbtCompound} from Minecraft.
|
||||
*/
|
||||
public class LitematicConverter implements AutoCloseable {
|
||||
private final InputStream input;
|
||||
private final NbtSizeTracker sizeTracker;
|
||||
protected final InputStream input;
|
||||
protected final NbtSizeTracker sizeTracker;
|
||||
|
||||
public LitematicConverter(InputStream input, NbtSizeTracker sizeTracker) {
|
||||
this.input = input;
|
||||
@@ -41,7 +39,7 @@ public class LitematicConverter implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
private NbtCompound convertRegionToSchematic(int dataVersion, NbtCompound region) {
|
||||
protected NbtCompound convertRegionToSchematic(int dataVersion, NbtCompound region) {
|
||||
var worldEditTag = new NbtCompound();
|
||||
|
||||
// prepare metadata
|
||||
@@ -69,7 +67,7 @@ public class LitematicConverter implements AutoCloseable {
|
||||
return schematicsRoot;
|
||||
}
|
||||
|
||||
private SizeTuple readSizeTuple(NbtCompound region) {
|
||||
protected SizeTuple readSizeTuple(NbtCompound region) {
|
||||
var size = (NbtCompound) region.get("Size");
|
||||
var sizeX = size.getInt("x");
|
||||
var sizeY = size.getInt("y");
|
||||
@@ -77,27 +75,29 @@ public class LitematicConverter implements AutoCloseable {
|
||||
return new SizeTuple(sizeX, sizeY, sizeZ);
|
||||
}
|
||||
|
||||
private NbtList convertToWETileEntities(NbtList tileEntities) {
|
||||
protected NbtList convertToWETileEntities(NbtList tileEntities) {
|
||||
var weTEs = new NbtList();
|
||||
for (NbtElement _tileEntity : tileEntities) {
|
||||
var weTE = new NbtCompound();
|
||||
var tE = (NbtCompound) _tileEntity;
|
||||
tE.putIntArray("Pos", new int[]{
|
||||
weTE.putIntArray("Pos", new int[]{
|
||||
tE.getInt("x"),
|
||||
tE.getInt("y"),
|
||||
tE.getInt("z")
|
||||
});
|
||||
tE.putString("Id", tE.getString("id"));
|
||||
weTE.putString("Id", tE.getString("id"));
|
||||
// other properties
|
||||
tE.remove("x");
|
||||
tE.remove("y");
|
||||
tE.remove("z");
|
||||
tE.remove("id");
|
||||
weTEs.add(tE);
|
||||
weTE.put("Data",tE);
|
||||
weTEs.add(weTE);
|
||||
}
|
||||
return weTEs;
|
||||
}
|
||||
|
||||
private NbtCompound convertToWEPalette(NbtList paletteNbt) {
|
||||
protected NbtCompound convertToWEPalette(NbtList paletteNbt) {
|
||||
var wePalette = new NbtCompound();
|
||||
for (int i = 0; i < paletteNbt.size(); i++) {
|
||||
var entry = (NbtCompound) paletteNbt.get(i);
|
||||
@@ -117,7 +117,7 @@ public class LitematicConverter implements AutoCloseable {
|
||||
return wePalette;
|
||||
}
|
||||
|
||||
private NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
||||
protected NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
||||
var pos = (NbtCompound) region.get("Position");
|
||||
var nbt = new NbtCompound();
|
||||
nbt.putInt("WEOffsetX", pos.getInt("x") + (size.x < 0 ? size.x + 1 : 0));
|
||||
@@ -126,7 +126,7 @@ public class LitematicConverter implements AutoCloseable {
|
||||
return nbt;
|
||||
}
|
||||
|
||||
private byte[] convertToWEBlocks(int totalBlocks, NbtCompound region) {
|
||||
protected byte[] convertToWEBlocks(int totalBlocks, NbtCompound region) {
|
||||
var buf = Unpooled.buffer();
|
||||
var blockStates = region.getLongArray("BlockStates");
|
||||
|
||||
@@ -148,11 +148,11 @@ public class LitematicConverter implements AutoCloseable {
|
||||
}
|
||||
|
||||
bitMask = (1 << bitsPerBlock) - 1;
|
||||
while(remainingBits >= bitsPerBlock){
|
||||
while (remainingBits >= bitsPerBlock) {
|
||||
bits = blockState & bitMask;
|
||||
blockState = blockState >>> bitsPerBlock;
|
||||
remainingBits -= bitsPerBlock;
|
||||
if(blockIterated >= totalBlocks) break;
|
||||
if (blockIterated >= totalBlocks) break;
|
||||
writeBlocks(buf, (short) bits);
|
||||
blockIterated++;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ public class LitematicConverter implements AutoCloseable {
|
||||
return buf.array();
|
||||
}
|
||||
|
||||
private static int writeBlocks(ByteBuf buf, short block) {
|
||||
protected static int writeBlocks(ByteBuf buf, short block) {
|
||||
int b = block >>> 7;
|
||||
if (b == 0) {
|
||||
buf.writeByte(block);
|
||||
@@ -0,0 +1,61 @@
|
||||
package io.ib67.sfcraft.util.litematic;
|
||||
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtSizeTracker;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class LitematicConverterV3 extends LitematicConverter {
|
||||
public LitematicConverterV3(InputStream input, NbtSizeTracker sizeTracker) {
|
||||
super(input, sizeTracker);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NbtCompound convertRegionToSchematic(int dataVersion, NbtCompound region) {
|
||||
var schematicsTag = new NbtCompound();
|
||||
|
||||
// prepare metadata
|
||||
var size = readSizeTuple(region);
|
||||
schematicsTag.put("Metadata", convertToWeMeta(size, region));
|
||||
schematicsTag.putInt("DataVersion", dataVersion);
|
||||
schematicsTag.putInt("Version", 3);
|
||||
schematicsTag.putIntArray("Offset", new int[3]);
|
||||
|
||||
// dimensional data.
|
||||
schematicsTag.putShort("Height", (short) Math.abs(size.y()));
|
||||
schematicsTag.putShort("Length", (short) Math.abs(size.z()));
|
||||
schematicsTag.putShort("Width", (short) Math.abs(size.x()));
|
||||
|
||||
// block & tile entities
|
||||
var paletteNbt = region.getList("BlockStatePalette", NbtElement.COMPOUND_TYPE);
|
||||
var wePalette = convertToWEPalette(paletteNbt);
|
||||
var tileEntities = region.getList("TileEntities", NbtElement.COMPOUND_TYPE);
|
||||
|
||||
var blocksNbt = new NbtCompound();
|
||||
blocksNbt.put("Palette", wePalette);
|
||||
blocksNbt.putByteArray("Data", convertToWEBlocks(Math.abs(size.x() * size.y() * size.z()), region));
|
||||
blocksNbt.put("BlockEntities", convertToWETileEntities(tileEntities));
|
||||
|
||||
schematicsTag.put("Blocks", blocksNbt);
|
||||
var schematicsRoot = new NbtCompound();
|
||||
schematicsRoot.put("Schematic", schematicsTag);
|
||||
return schematicsRoot;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NbtElement convertToWeMeta(SizeTuple size, NbtCompound region) {
|
||||
var pos = (NbtCompound) region.get("Position");
|
||||
var worldEditNbt = new NbtCompound();
|
||||
worldEditNbt.putIntArray("Origin", new int[]{
|
||||
pos.getInt("x") + (size.x() < 0 ? size.x() + 1 : 0),
|
||||
pos.getInt("y") + (size.y() < 0 ? size.y() + 1 : 0),
|
||||
pos.getInt("z") + (size.z() < 0 ? size.z() + 1 : 0)
|
||||
});
|
||||
var Metadata = new NbtCompound();
|
||||
Metadata.put("WorldEdit", worldEditNbt);
|
||||
Metadata.putLong("Date", System.currentTimeMillis());
|
||||
|
||||
return Metadata;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user