Merge pull request 'Fix Schematics Readers' (#72) from Schematics/1.21 into main

Reviewed-on: https://steamwar.de/devlabs/SteamWar/SteamWar/pulls/72
Reviewed-by: Lixfel <lixfel@steamwar.de>
This commit is contained in:
Lixfel
2025-01-01 12:42:01 +01:00
19 changed files with 205 additions and 132 deletions
@@ -22,7 +22,6 @@ package de.steamwar.core;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.*;
import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extension.input.InputParseException;
@@ -45,36 +44,29 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import de.steamwar.sql.NoClipboardException;
import de.steamwar.sql.NodeData;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
public class WorldEditWrapper14 implements WorldEditWrapper {
private static final ClipboardFormat SCHEMATIC = BuiltInClipboardFormat.MCEDIT_SCHEMATIC;
private static final ClipboardFormat SCHEM = BuiltInClipboardFormat.SPONGE_SCHEMATIC;
@Override
public InputStream getPlayerClipboard(Player player, boolean schemFormat) {
return WorldEditWrapper.getPlayerClipboard(player, schemFormat, (outputStream, clipboard, clipboardHolder) -> {
if(schemFormat){
ClipboardWriter writer = SCHEM.getWriter(outputStream);
writer.write(clipboard);
writer.close();
}else{
SCHEMATIC.getWriter(outputStream).write(clipboard);
}
public InputStream getPlayerClipboard(Player player) {
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) -> {
ClipboardWriter writer = BuiltInClipboardFormat.SPONGE_SCHEMATIC.getWriter(outputStream);
writer.write(clipboard);
writer.close();
});
}
@Override
public void setPlayerClipboard(Player player, InputStream is, boolean schemFormat) {
public void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat) {
Clipboard clipboard = null;
try {
clipboard = getClipboard(is, schemFormat);
@@ -90,12 +82,17 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
}
@Override
public Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException {
public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException {
try {
if(schemFormat){
return new SpongeSchematicReader(new NBTInputStream(is)).read();
}else{
return new MCEditSchematicReader(new NBTInputStream(is)).read();
switch (schemFormat) {
case SPONGE_V2:
case SPONGE_V3:
return new SpongeSchematicReader(new NBTInputStream(is)).read();
case MCEDIT:
return new MCEditSchematicReader(new NBTInputStream(is)).read();
default:
throw new IOException("This schematic format is currently not supported");
}
} catch (NullPointerException e) {
throw new NoClipboardException();
@@ -124,6 +121,11 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
return new org.bukkit.util.Vector(v.getX(), v.getY(), v.getZ());
}
@Override
public NodeData.SchematicFormat getNativeFormat() {
return NodeData.SchematicFormat.SPONGE_V2;
}
private static class MCEditSchematicReader extends NBTSchematicReader {
private final NBTInputStream inputStream;
@@ -387,7 +389,7 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
inputStream.close();
}
}
private static class SpongeSchematicReader extends NBTSchematicReader {
public static class SpongeSchematicReader extends NBTSchematicReader {
private final NBTInputStream inputStream;
private DataFixer fixer = null;
@@ -418,7 +420,7 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
dataVersion = 1631; // this is a relatively safe assumption unless someone imports a schematic from 1.12, e.g. sponge 7.1-
fixer = platform.getDataFixer();
return readVersion1(schematicTag);
} else if (schematicVersion == 2) {
} else if (schematicVersion == 2 || schematicVersion == 3) {
dataVersion = requireTag(schematic, "DataVersion", IntTag.class).getValue();
if (dataVersion < liveDataVersion) {
fixer = platform.getDataFixer();
@@ -447,14 +449,18 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
private CompoundTag getBaseTag() throws IOException {
NamedTag rootTag = inputStream.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
throw new IOException("Tag 'Schematic' does not exist or is not first");
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
if (schematic.size() == 1) {
schematicTag = requireTag(schematic, "Schematic", CompoundTag.class);
schematic = schematicTag.getValue();
} else if (!rootTag.getName().equals("Schematic")) {
throw new IOException("Tag 'Schematic' does not exist or is not first");
}
schematicVersion = requireTag(schematic, "Version", IntTag.class).getValue();
return schematicTag;
}
@@ -499,12 +505,16 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
region = new CuboidRegion(origin, origin.add(width, height, length).subtract(BlockVector3.ONE));
}
IntTag paletteMaxTag = getTag(schematic, "PaletteMax", IntTag.class);
Map<String, Tag> paletteObject = requireTag(schematic, "Palette", CompoundTag.class).getValue();
if (paletteMaxTag != null && paletteObject.size() != paletteMaxTag.getValue()) {
throw new IOException("Block palette size does not match expected size.");
Map<String, Tag> blockContainer = null;
boolean v3Mode = false;
if (schematicVersion == 3) {
blockContainer = requireTag(schematic, "Blocks", CompoundTag.class).getValue();
v3Mode = true;
}
Map<String, Tag> paletteObject = requireTag(v3Mode ? blockContainer: schematic, "Palette", CompoundTag.class).getValue();
Map<Integer, BlockState> palette = new HashMap<>();
ParserContext parserContext = new ParserContext();
@@ -526,12 +536,12 @@ public class WorldEditWrapper14 implements WorldEditWrapper {
palette.put(id, state);
}
byte[] blocks = requireTag(schematic, "BlockData", ByteArrayTag.class).getValue();
byte[] blocks = requireTag(v3Mode ? blockContainer: schematic, v3Mode ? "Data" : "BlockData", ByteArrayTag.class).getValue();
Map<BlockVector3, Map<String, Tag>> tileEntitiesMap = new HashMap<>();
ListTag tileEntities = getTag(schematic, "BlockEntities", ListTag.class);
ListTag tileEntities = getTag(v3Mode ? blockContainer: schematic, "BlockEntities", ListTag.class);
if (tileEntities == null) {
tileEntities = getTag(schematic, "TileEntities", ListTag.class);
tileEntities = getTag(v3Mode ? blockContainer: schematic, "TileEntities", ListTag.class);
}
if (tileEntities != null) {
List<Map<String, Tag>> tileEntityTags = tileEntities.getValue().stream()