Skip to content

Commit

Permalink
Bump minestom version to support 1.21.1 for testing
Browse files Browse the repository at this point in the history
Create BlockEntity record to support block entity format across versions

Apply Block data when applying rotations

Add empty block data when generating a new schematic, will be replaced

Add loading tile entity support for v1, v2, and v3 schematics
  • Loading branch information
utfunderscore committed Sep 7, 2024
1 parent d46f28e commit 599a08a
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 9 deletions.
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
metadata.format.version = "1.1"

[versions]
minestom = "1_20_5-323c75f8a5"
minestom = "b0bad7e180"
logback = "1.4.5" # For tests only

nexuspublish = "1.3.0"
Expand Down
25 changes: 25 additions & 0 deletions src/main/java/net/hollowcube/schem/BlockEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.hollowcube.schem;

import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;

public record BlockEntity(String id, Point point, CompoundBinaryTag trimmedTag) {

public static BlockEntity fromV3(CompoundBinaryTag blockTag) {
int[] position = blockTag.getIntArray("Pos");
return new BlockEntity(blockTag.getString("Id"), new Vec(position[0], position[1], position[2]), blockTag.getCompound("Data"));
}

public static BlockEntity fromV1(CompoundBinaryTag entityCompound) {
int[] position = entityCompound.getIntArray("Pos");
String id = entityCompound.getString("Id");
CompoundBinaryTag stripped = CompoundBinaryTag
.builder()
.put(entityCompound)
.remove("Pos")
.remove("Id")
.remove("Extra").build();
return new BlockEntity(id, new Vec(position[0], position[1], position[2]), stripped);
}
}
4 changes: 4 additions & 0 deletions src/main/java/net/hollowcube/schem/CoordinateUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,8 @@ private static String rotate90(String in) {
};
}

public static String getCoordinateKey(int x, int y, int z) {
return x + "," + y + "," + z;
}

}
18 changes: 16 additions & 2 deletions src/main/java/net/hollowcube/schem/Schematic.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package net.hollowcube.schem;

import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.instance.batch.BatchOption;
import net.minestom.server.instance.batch.RelativeBlockBatch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.utils.Utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.UnaryOperator;
Expand All @@ -23,11 +27,12 @@ public record Schematic(
Point size,
Point offset,
Block[] palette,
byte[] blocks
byte[] blocks,
Map<String, BlockEntity> blockEntities
) {
private static final System.Logger logger = System.getLogger(Schematic.class.getName());

static final Schematic EMPTY = new Schematic(Vec.ZERO, Vec.ZERO, new Block[0], new byte[0]);
static final Schematic EMPTY = new Schematic(Vec.ZERO, Vec.ZERO, new Block[0], new byte[0], Collections.emptyMap());

public Schematic {
palette = Arrays.copyOf(palette, palette.length);
Expand Down Expand Up @@ -71,6 +76,15 @@ public void apply(@NotNull Rotation rotation, @NotNull BiConsumer<Point, Block>
block = Block.AIR;
}

// If block entity is present at the current coordinate, apply its handler
// and NBT data to the block.
BlockEntity blockEntity = blockEntities.get(CoordinateUtil.getCoordinateKey(x, y, z));
if(blockEntity != null) {
BlockHandler handler = MinecraftServer.getBlockManager().getHandlerOrDummy(blockEntity.id());
block = block.withHandler(handler);
block = blockEntity.trimmedTag().size() > 0 ? block.withNbt(blockEntity.trimmedTag()) : block;
}

applicator.accept(
CoordinateUtil.rotatePos(offset.add(x, y, z), rotation),
CoordinateUtil.rotateBlock(block, rotation));
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/net/hollowcube/schem/SchematicBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.jetbrains.annotations.NotNull;

import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -116,6 +117,6 @@ public void setOffset(@NotNull Point point) {
var out = new byte[blockBytes.position()];
blockBytes.flip().get(out);

return new Schematic(size, offset, palette, out);
return new Schematic(size, offset, palette, out, Collections.emptyMap());
}
}
60 changes: 55 additions & 5 deletions src/main/java/net/hollowcube/schem/SchematicReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@

import net.hollowcube.schem.blockpalette.BlockPaletteParser;
import net.hollowcube.schem.blockpalette.CommandBlockPaletteParser;
import net.kyori.adventure.nbt.BinaryTagIO;
import net.kyori.adventure.nbt.CompoundBinaryTag;
import net.kyori.adventure.nbt.IntBinaryTag;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentBlockState;
import net.kyori.adventure.nbt.*;
import net.minestom.server.command.builder.exception.ArgumentSyntaxException;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.instance.block.Block;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;

import java.io.InputStream;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;

/**
Expand Down Expand Up @@ -61,6 +60,13 @@ public SchematicReader withBlockPaletteParser(BlockPaletteParser parser) {
}
}

/**
* Reads a Sponge Schematic from a CompoundBinaryTag.
* @see <a href="https://github.com/SpongePowered/Schematic-Specification/">Sponge Schematic Specification</a>
*
* @param tag A CompoundBinaryTag containing the schematic data
* @param version The schematic specification version (1, 2, or 3)
*/
private @NotNull Schematic read(@NotNull CompoundBinaryTag tag, int version) {
short width = tag.getShort("Width");
short height = tag.getShort("Height");
Expand All @@ -80,6 +86,9 @@ public SchematicReader withBlockPaletteParser(BlockPaletteParser parser) {
CompoundBinaryTag palette;
byte[] blockArray;
Integer paletteSize;
Map<String, BlockEntity> blockEntitiesMap = new HashMap<>();


if (version == 3) {
var blockEntries = tag.getCompound("Blocks");
Check.notNull(blockEntries, "Missing required field 'Blocks'");
Expand All @@ -89,13 +98,53 @@ public SchematicReader withBlockPaletteParser(BlockPaletteParser parser) {
blockArray = blockEntries.getByteArray("Data");
Check.notNull(blockArray, "Missing required field 'Blocks.Data'");
paletteSize = palette.size();
ListBinaryTag blockEntities = blockEntries.getList("BlockEntities");
Check.notNull(blockEntities, "Missing required field 'Blocks.BlockEntities'");
for (BinaryTag entities : blockEntities) {
if (entities instanceof CompoundBinaryTag entity) {
BlockEntity blockEntity = BlockEntity.fromV3(entity);
System.out.println(blockEntity);

Point coordinate = blockEntity.point();
blockEntitiesMap.put(CoordinateUtil.getCoordinateKey(coordinate.blockX(), coordinate.blockY(), coordinate.blockZ()), blockEntity);
}
}
} else if(version == 2) {
palette = tag.getCompound("Palette");
Check.notNull(palette, "Missing required field 'Palette'");
blockArray = tag.getByteArray("BlockData");
Check.notNull(blockArray, "Missing required field 'BlockData'");
paletteSize = tag.getInt("PaletteMax");
Check.notNull(paletteSize, "Missing required field 'PaletteMax'");
ListBinaryTag blockEntities = tag.getList("BlockEntities");
Check.notNull(blockEntities, "Missing required field 'BlockEntities'");
for (BinaryTag entity : blockEntities) {
if (entity instanceof CompoundBinaryTag entityCompound) {
BlockEntity blockEntity = BlockEntity.fromV1(entityCompound);
System.out.println(blockEntity);

Point coordinate = blockEntity.point();
blockEntitiesMap.put(CoordinateUtil.getCoordinateKey(coordinate.blockX(), coordinate.blockY(), coordinate.blockZ()), blockEntity);
}
}
} else {
palette = tag.getCompound("Palette");
Check.notNull(palette, "Missing required field 'Palette'");
blockArray = tag.getByteArray("BlockData");
Check.notNull(blockArray, "Missing required field 'BlockData'");
paletteSize = tag.getInt("PaletteMax");
Check.notNull(paletteSize, "Missing required field 'PaletteMax'");
ListBinaryTag blockEntities = tag.getList("TileEntities");
Check.notNull(blockEntities, "Missing required field 'TileEntities'");
for (BinaryTag entity : blockEntities) {
if (entity instanceof CompoundBinaryTag entityCompound) {
BlockEntity blockEntity = BlockEntity.fromV1(entityCompound);
System.out.println(blockEntity);

Point coordinate = blockEntity.point();
blockEntitiesMap.put(CoordinateUtil.getCoordinateKey(coordinate.blockX(), coordinate.blockY(), coordinate.blockZ()), blockEntity);
}
}
}

Block[] paletteBlocks = new Block[paletteSize];
Expand All @@ -114,7 +163,8 @@ public SchematicReader withBlockPaletteParser(BlockPaletteParser parser) {
new Vec(width, height, length),
offset,
paletteBlocks,
blockArray
blockArray,
blockEntitiesMap
);
}

Expand Down

0 comments on commit 599a08a

Please sign in to comment.