forked from SteamWar/SteamWar
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:
@@ -28,12 +28,15 @@ import java.sql.PreparedStatement;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public class NodeData {
|
||||
|
||||
static {
|
||||
new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
|
||||
new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
|
||||
new SqlTypeMapper<>(BufferedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("BufferedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
|
||||
|
||||
SqlTypeMapper.ordinalEnumMapper(SchematicFormat.class);
|
||||
}
|
||||
|
||||
private static final Table<NodeData> table = new Table<>(NodeData.class);
|
||||
@@ -48,19 +51,18 @@ public class NodeData {
|
||||
throw new IllegalArgumentException("Node is a directory");
|
||||
return get.select(rs -> {
|
||||
if(rs.next()) {
|
||||
return new NodeData(node.getId(), rs.getBoolean("NodeFormat"));
|
||||
return new NodeData(node.getId(), SchematicFormat.values()[rs.getInt("NodeFormat")]);
|
||||
} else {
|
||||
return new NodeData(node.getId(), false);
|
||||
return new NodeData(node.getId(), SchematicFormat.MCEDIT);
|
||||
}
|
||||
}, node);
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Field(keys = {Table.PRIMARY})
|
||||
private final int nodeId;
|
||||
|
||||
@Field
|
||||
private boolean nodeFormat;
|
||||
private SchematicFormat nodeFormat;
|
||||
|
||||
public InputStream schemData() throws IOException {
|
||||
try {
|
||||
@@ -81,12 +83,18 @@ public class NodeData {
|
||||
}
|
||||
}
|
||||
|
||||
public void saveFromStream(InputStream blob, boolean newFormat) {
|
||||
public void saveFromStream(InputStream blob, SchematicFormat newFormat) {
|
||||
updateDatabase.update(nodeId, newFormat, blob);
|
||||
nodeFormat = newFormat;
|
||||
}
|
||||
|
||||
public boolean getNodeFormat() {
|
||||
return nodeFormat;
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum SchematicFormat {
|
||||
MCEDIT(".schematic"),
|
||||
SPONGE_V2(".schem"),
|
||||
SPONGE_V3(".schem");
|
||||
|
||||
private final String fileEnding;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,11 +375,10 @@ public class SchematicNode {
|
||||
return nodeType == null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public boolean getSchemFormat() {
|
||||
public String getFileEnding() {
|
||||
if(isDir())
|
||||
throw new SecurityException("Node is Directory");
|
||||
return NodeData.get(this).getNodeFormat();
|
||||
return NodeData.get(this).getNodeFormat().getFileEnding();
|
||||
}
|
||||
|
||||
public int getRank() {
|
||||
|
||||
+2
-1
@@ -42,6 +42,7 @@ import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import de.steamwar.fightsystem.FightSystem;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import de.steamwar.sql.SchematicData;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import org.bukkit.DyeColor;
|
||||
@@ -144,6 +145,6 @@ public class WorldeditWrapper14 implements WorldeditWrapper {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
|
||||
new SchematicData(schem).saveFromBytes(outputStream.toByteArray(), true);
|
||||
new SchematicData(schem).saveFromBytes(outputStream.toByteArray(), NodeData.SchematicFormat.SPONGE_V2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import de.steamwar.fightsystem.FightSystem;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import de.steamwar.sql.SchematicData;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import org.bukkit.DyeColor;
|
||||
@@ -142,6 +143,6 @@ public class WorldeditWrapper8 implements WorldeditWrapper {
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
|
||||
new SchematicData(schem).saveFromBytes(outputStream.toByteArray(), false);
|
||||
new SchematicData(schem).saveFromBytes(outputStream.toByteArray(), NodeData.SchematicFormat.MCEDIT);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ package de.steamwar.fightsystem.record;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.TrickyTrialsWrapper;
|
||||
import de.steamwar.core.WorldEditWrapper;
|
||||
import de.steamwar.entity.REntity;
|
||||
import de.steamwar.entity.REntityServer;
|
||||
import de.steamwar.entity.RPlayer;
|
||||
@@ -523,7 +524,7 @@ public class PacketProcessor implements Listener {
|
||||
public void close() {
|
||||
// FAWE 1.12 calls close...
|
||||
}
|
||||
}, Core.getVersion() > 12);
|
||||
}, WorldEditWrapper.impl.getNativeFormat());
|
||||
|
||||
execSync(() -> team.pasteSchem(schemId, clipboard));
|
||||
}
|
||||
|
||||
+1
-1
@@ -245,7 +245,7 @@ public class SchematicCommandUtils {
|
||||
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_ELO", player, node.getElo(Season.getSeason()));
|
||||
}
|
||||
|
||||
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_FORMAT", player, node.getSchemFormat() ? ".schem" : ".schematic");
|
||||
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_FORMAT", player, node.getFileEnding());
|
||||
CheckedSchematic.getLastDeclinedOfNode(node.getId()).stream().findFirst().ifPresent(checkedSchematic -> SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_STATUS", player, checkedSchematic.getEndTime(), checkedSchematic.getDeclineReason()));
|
||||
} else {
|
||||
SchematicSystem.MESSAGE.sendPrefixless("UTIL_INFO_TYPE", player, SchematicSystem.MESSAGE.parse("UTIL_INFO_TYPE_DIR", player));
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.*;
|
||||
import de.steamwar.sql.NoClipboardException;
|
||||
import de.steamwar.sql.NodeData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -31,11 +32,19 @@ public class WorldEditWrapper18 extends WorldEditWrapper14 {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException {
|
||||
public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException {
|
||||
NBTInputStream nbtStream = new NBTInputStream(is);
|
||||
//Use FAWE reader due to FAWE capability of reading corrupt FAWE schems
|
||||
try {
|
||||
return (schemFormat ? new SpongeSchematicReader(nbtStream) : new MCEditSchematicReader(nbtStream)).read();
|
||||
switch (schemFormat) {
|
||||
case MCEDIT:
|
||||
return new MCEditSchematicReader(nbtStream).read();
|
||||
case SPONGE_V2:
|
||||
case SPONGE_V3:
|
||||
return new WorldEditWrapper14.SpongeSchematicReader(nbtStream).read();
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported schematic format");
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
throw new NoClipboardException();
|
||||
}
|
||||
|
||||
@@ -21,7 +21,13 @@ plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_18", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_14", "default"))
|
||||
@@ -29,16 +35,6 @@ dependencies {
|
||||
|
||||
compileOnly(libs.fawe21)
|
||||
|
||||
compileOnly(libs.paperapi21) {
|
||||
attributes {
|
||||
// Very Hacky, but it works
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
}
|
||||
compileOnly(libs.nms21) {
|
||||
attributes {
|
||||
// Very Hacky, but it works
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
}
|
||||
compileOnly(libs.paperapi21)
|
||||
compileOnly(libs.nms21)
|
||||
}
|
||||
|
||||
@@ -20,33 +20,30 @@
|
||||
package de.steamwar.core;
|
||||
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2;
|
||||
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.MCEditSchematicReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV1Reader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV2Reader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.sponge.SpongeSchematicV3Reader;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.enginehub.linbus.stream.LinBinaryIO;
|
||||
import org.enginehub.linbus.stream.LinStream;
|
||||
import org.enginehub.linbus.tree.LinCompoundTag;
|
||||
import org.enginehub.linbus.tree.LinRootEntry;
|
||||
import org.enginehub.linbus.tree.LinTagType;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class WorldEditWrapper21 implements WorldEditWrapper {
|
||||
|
||||
@Override
|
||||
public InputStream getPlayerClipboard(Player player, boolean schemFormat) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, schemFormat, (outputStream, clipboard, clipboardHolder) -> {
|
||||
public InputStream getPlayerClipboard(Player player) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) -> {
|
||||
ClipboardWriter writer = BuiltInClipboardFormat.FAST_V3.getWriter(outputStream);
|
||||
writer.write(clipboard);
|
||||
writer.close();
|
||||
@@ -54,7 +51,7 @@ public class WorldEditWrapper21 implements WorldEditWrapper {
|
||||
}
|
||||
|
||||
@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);
|
||||
@@ -70,35 +67,12 @@ public class WorldEditWrapper21 implements WorldEditWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException {
|
||||
if (!schemFormat) {
|
||||
return new MCEditSchematicReader(new NBTInputStream(is)).read();
|
||||
} else {
|
||||
BufferedInputStream bis = new BufferedInputStream(is);
|
||||
|
||||
bis.mark(Integer.MAX_VALUE);
|
||||
|
||||
LinStream linStream = LinBinaryIO.read(new DataInputStream(bis));
|
||||
|
||||
LinCompoundTag entry = LinRootEntry.readFrom(linStream).value();
|
||||
|
||||
if (entry.value().size() == 1) {
|
||||
entry = entry.getTag("Schematic", LinTagType.compoundTag());
|
||||
}
|
||||
|
||||
bis.reset();
|
||||
|
||||
switch (entry.getTag("Version", LinTagType.intTag()).valueAsInt()) {
|
||||
case 1:
|
||||
return new SpongeSchematicV1Reader(entry.linStream()).read();
|
||||
case 2:
|
||||
return new FastSchematicReaderV2(new NBTInputStream(bis)).read();
|
||||
case 3:
|
||||
return new FastSchematicReaderV3(bis).read();
|
||||
default:
|
||||
throw new IOException("Unknown schematic version");
|
||||
}
|
||||
}
|
||||
public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException {
|
||||
return switch (schemFormat) {
|
||||
case MCEDIT -> new MCEditSchematicReader(new NBTInputStream(is)).read();
|
||||
case SPONGE_V2 -> new SpongeSchematicV2Reader(LinBinaryIO.read(new DataInputStream(is))).read();
|
||||
case SPONGE_V3 -> new SpongeSchematicV3Reader(LinBinaryIO.read(new DataInputStream(is))).read();
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,4 +96,9 @@ public class WorldEditWrapper21 implements WorldEditWrapper {
|
||||
v = transform.apply(v);
|
||||
return new org.bukkit.util.Vector(v.x(), v.y(), v.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeData.SchematicFormat getNativeFormat() {
|
||||
return NodeData.SchematicFormat.SPONGE_V3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -50,13 +51,13 @@ import java.util.stream.Collectors;
|
||||
public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
|
||||
@Override
|
||||
public InputStream getPlayerClipboard(Player player, boolean schemFormat) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, schemFormat, (outputStream, clipboard, clipboardHolder) ->
|
||||
public InputStream getPlayerClipboard(Player player) {
|
||||
return WorldEditWrapper.getPlayerClipboard(player, (outputStream, clipboard, clipboardHolder) ->
|
||||
ClipboardFormat.SCHEMATIC.getWriter(outputStream).write(clipboard, clipboardHolder.getWorldData()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerClipboard(Player player, InputStream is, boolean schemFormat) {
|
||||
public void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat) {
|
||||
WorldData world = new BukkitWorld(player.getWorld()).getWorldData();
|
||||
Clipboard clipboard;
|
||||
try {
|
||||
@@ -70,11 +71,16 @@ public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException {
|
||||
if(schemFormat)
|
||||
return new SpongeSchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
|
||||
else
|
||||
return new SchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
|
||||
public Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException {
|
||||
switch (schemFormat) {
|
||||
case MCEDIT:
|
||||
return new SchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
|
||||
case SPONGE_V2:
|
||||
case SPONGE_V3:
|
||||
return new SpongeSchematicReader(new NBTInputStream(is)).read(WorldEdit.getInstance().getServer().getWorlds().get(0).getWorldData());
|
||||
default:
|
||||
throw new IllegalArgumentException("Unsupported schematic format");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,6 +105,11 @@ public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
return new org.bukkit.util.Vector(v.getX(), v.getY(), v.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeData.SchematicFormat getNativeFormat() {
|
||||
return NodeData.SchematicFormat.MCEDIT;
|
||||
}
|
||||
|
||||
private static class SpongeSchematicReader implements ClipboardReader {
|
||||
|
||||
private final NBTInputStream inputStream;
|
||||
@@ -137,6 +148,13 @@ public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
IDConverter8 ids = new IDConverter8();
|
||||
|
||||
Map<String, Tag> schematic = schematicTag.getValue();
|
||||
boolean v3Mode = false;
|
||||
|
||||
if (schematic.size() == 1) {
|
||||
schematic = (requireTag(schematic, "Schematic", CompoundTag.class)).getValue();
|
||||
v3Mode = true;
|
||||
}
|
||||
|
||||
int width = (requireTag(schematic, "Width", ShortTag.class)).getValue();
|
||||
int height = (requireTag(schematic, "Height", ShortTag.class)).getValue();
|
||||
int length = (requireTag(schematic, "Length", ShortTag.class)).getValue();
|
||||
@@ -167,10 +185,13 @@ public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector.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;
|
||||
|
||||
if (v3Mode) {
|
||||
blockContainer = getTag(schematic, "Blocks", CompoundTag.class).getValue();
|
||||
}
|
||||
|
||||
Map<String, Tag> paletteObject = requireTag(v3Mode ? blockContainer : schematic, "Palette", CompoundTag.class).getValue();
|
||||
|
||||
Map<Integer, BaseBlock> palette = new HashMap<>();
|
||||
ParserContext parserContext = new ParserContext();
|
||||
@@ -182,11 +203,11 @@ public class WorldEditWrapper8 implements WorldEditWrapper {
|
||||
palette.put(requireTag(paletteObject, palettePart, IntTag.class).getValue(), new BaseBlock(blockID.getBlockId(), blockID.getDataId()));
|
||||
}
|
||||
|
||||
byte[] blocks = requireTag(schematic, "BlockData", ByteArrayTag.class).getValue();
|
||||
byte[] blocks = requireTag(v3Mode ? blockContainer : schematic, v3Mode ? "Data" : "BlockData", ByteArrayTag.class).getValue();
|
||||
Map<BlockVector, 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) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import de.steamwar.sql.NoClipboardException;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import de.steamwar.sql.NodeData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
@@ -36,20 +37,22 @@ import java.util.logging.Level;
|
||||
public interface WorldEditWrapper {
|
||||
WorldEditWrapper impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
|
||||
InputStream getPlayerClipboard(Player player, boolean schemFormat);
|
||||
void setPlayerClipboard(Player player, InputStream is, boolean schemFormat);
|
||||
Clipboard getClipboard(InputStream is, boolean schemFormat) throws IOException;
|
||||
InputStream getPlayerClipboard(Player player);
|
||||
void setPlayerClipboard(Player player, InputStream is, NodeData.SchematicFormat schemFormat);
|
||||
Clipboard getClipboard(InputStream is, NodeData.SchematicFormat schemFormat) throws IOException;
|
||||
|
||||
Vector getOrigin(Clipboard clipboard);
|
||||
Vector getMinimum(Region region);
|
||||
Vector getMaximum(Region region);
|
||||
Vector applyTransform(Vector vector, Transform transform);
|
||||
|
||||
NodeData.SchematicFormat getNativeFormat();
|
||||
|
||||
static WorldEditPlugin getWorldEditPlugin() {
|
||||
return (WorldEditPlugin) Bukkit.getPluginManager().getPlugin("WorldEdit");
|
||||
}
|
||||
|
||||
public static InputStream getPlayerClipboard(Player player, boolean schemFormat, SchematicWriter consumer) {
|
||||
static InputStream getPlayerClipboard(Player player, SchematicWriter consumer) {
|
||||
ClipboardHolder clipboardHolder;
|
||||
try {
|
||||
clipboardHolder = WorldEditWrapper.getWorldEditPlugin().getSession(player).getClipboard();
|
||||
@@ -85,7 +88,7 @@ public interface WorldEditWrapper {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public static interface SchematicWriter {
|
||||
interface SchematicWriter {
|
||||
void write(OutputStream outputStream, Clipboard clipboard, ClipboardHolder holder) throws IOException;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.util.zip.GZIPInputStream;
|
||||
|
||||
public class SchematicData {
|
||||
|
||||
public static Clipboard clipboardFromStream(InputStream is, boolean schemFormat) {
|
||||
public static Clipboard clipboardFromStream(InputStream is, NodeData.SchematicFormat schemFormat) {
|
||||
try {
|
||||
return WorldEditWrapper.impl.getClipboard(is, schemFormat);
|
||||
} catch (IOException e) {
|
||||
@@ -61,15 +61,11 @@ public class SchematicData {
|
||||
}
|
||||
|
||||
public void saveFromPlayer(Player player) throws IOException, NoClipboardException {
|
||||
saveFromPlayer(player, Core.getVersion() > 12);
|
||||
}
|
||||
|
||||
public void saveFromPlayer(Player player, boolean newFormat) throws IOException, NoClipboardException {
|
||||
data.saveFromStream(WorldEditWrapper.impl.getPlayerClipboard(player, newFormat), newFormat);
|
||||
data.saveFromStream(WorldEditWrapper.impl.getPlayerClipboard(player), WorldEditWrapper.impl.getNativeFormat());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void saveFromBytes(byte[] bytes, boolean newFormat) {
|
||||
public void saveFromBytes(byte[] bytes, NodeData.SchematicFormat newFormat) {
|
||||
data.saveFromStream(new ByteArrayInputStream(bytes), newFormat);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,5 +40,10 @@ dependencies {
|
||||
implementation(project(":SpigotCore:SpigotCore_18"))
|
||||
implementation(project(":SpigotCore:SpigotCore_19"))
|
||||
implementation(project(":SpigotCore:SpigotCore_20"))
|
||||
implementation(project(":SpigotCore:SpigotCore_21"))
|
||||
implementation(project(":SpigotCore:SpigotCore_21")) {
|
||||
attributes {
|
||||
// Very Hacky, but it works
|
||||
attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 21)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,4 +63,6 @@ dependencies {
|
||||
implementation(libs.msgpack)
|
||||
|
||||
implementation(libs.apolloprotos)
|
||||
|
||||
implementation(libs.nbt)
|
||||
}
|
||||
+16
-1
@@ -25,10 +25,13 @@ import de.steamwar.sql.NodeData;
|
||||
import de.steamwar.sql.Punishment;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import dev.dewy.nbt.Nbt;
|
||||
import dev.dewy.nbt.tags.collection.CompoundTag;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.dv8tion.jda.api.hooks.ListenerAdapter;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
@@ -38,6 +41,8 @@ import java.util.logging.Level;
|
||||
|
||||
public class DiscordSchemUpload extends ListenerAdapter {
|
||||
|
||||
private static final Nbt NBT = new Nbt();
|
||||
|
||||
private static final List<String> SCHEM_FILE_ENDINGS = Arrays.asList(".schem", ".schematic");
|
||||
|
||||
@Override
|
||||
@@ -79,7 +84,17 @@ public class DiscordSchemUpload extends ListenerAdapter {
|
||||
node = SchematicNode.createSchematic(user.getId(), name, null);
|
||||
|
||||
try (InputStream in = attachment.getProxy().download().get()) {
|
||||
NodeData.get(node).saveFromStream(in, fileName.substring(dot).equalsIgnoreCase(".schem"));
|
||||
CompoundTag tags = NBT.fromStream(new DataInputStream(in));
|
||||
|
||||
NodeData.SchematicFormat version = NodeData.SchematicFormat.SPONGE_V2;
|
||||
|
||||
if (tags.size() == 1) {
|
||||
version = NodeData.SchematicFormat.SPONGE_V3;
|
||||
} else if (tags.contains("Materials")) {
|
||||
version = NodeData.SchematicFormat.MCEDIT;
|
||||
}
|
||||
|
||||
NodeData.get(node).saveFromStream(in, version);
|
||||
sender.system("DC_SCHEMUPLOAD_SUCCESS", name);
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
|
||||
@@ -53,4 +53,5 @@ dependencies {
|
||||
implementation(libs.yamlconfig)
|
||||
implementation(libs.kotlinxSerializationCbor)
|
||||
implementation(libs.ktorRateLimit)
|
||||
implementation(libs.nbt)
|
||||
}
|
||||
@@ -22,10 +22,13 @@ package de.steamwar.routes
|
||||
import de.steamwar.plugins.SWAuthPrincipal
|
||||
import de.steamwar.plugins.SWPermissionCheck
|
||||
import de.steamwar.sql.NodeData
|
||||
import de.steamwar.sql.NodeData.SchematicFormat
|
||||
import de.steamwar.sql.NodeDownload
|
||||
import de.steamwar.sql.NodeMember
|
||||
import de.steamwar.sql.SWException
|
||||
import de.steamwar.sql.SchematicNode
|
||||
import dev.dewy.nbt.Nbt
|
||||
import dev.dewy.nbt.tags.collection.CompoundTag
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.auth.*
|
||||
@@ -33,6 +36,7 @@ import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.decodeFromByteArray
|
||||
import java.security.MessageDigest
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
@@ -71,6 +75,8 @@ data class SchematicCode(val id: Int, val code: String, val expires: Long)
|
||||
@Serializable
|
||||
data class UploadSchematic(val name: String, val content: String)
|
||||
|
||||
val nbt = Nbt()
|
||||
|
||||
fun Route.configureSchematic() {
|
||||
route("/download/{code}") {
|
||||
get {
|
||||
@@ -88,7 +94,7 @@ fun Route.configureSchematic() {
|
||||
return@get
|
||||
}
|
||||
|
||||
call.response.header("Content-Disposition", "attachment; filename=\"${node.name}.${if (data.nodeFormat) "schem" else "schematic"}\"")
|
||||
call.response.header("Content-Disposition", "attachment; filename=\"${node.name}${data.nodeFormat.fileEnding}\"")
|
||||
call.respondBytes(data.schemData().readAllBytes(), contentType = ContentType.Application.OctetStream, status = HttpStatusCode.OK)
|
||||
}
|
||||
get("/info") {
|
||||
@@ -112,16 +118,34 @@ fun Route.configureSchematic() {
|
||||
|
||||
val user = call.principal<SWAuthPrincipal>()!!.user
|
||||
|
||||
val content = Base64.getDecoder().decode(file.content)
|
||||
var node = SchematicNode.getSchematicNode(user.id, schemName, 0)
|
||||
if (node == null) {
|
||||
node = SchematicNode.createSchematic(user.id, schemName, 0)
|
||||
}
|
||||
|
||||
val data = NodeData(node.id, false)
|
||||
data.saveFromStream(content.inputStream(), schemType == "schem")
|
||||
try {
|
||||
val content = Base64.getDecoder().decode(file.content)
|
||||
|
||||
call.respond(ResponseSchematic(node))
|
||||
var schem = nbt.fromByteArray(content)
|
||||
|
||||
if (schem.size() == 1) schem = schem.first() as CompoundTag
|
||||
|
||||
val version = schem.let {
|
||||
if (it.contains("Materials"))
|
||||
return@let SchematicFormat.MCEDIT
|
||||
else if (it.contains("Blocks"))
|
||||
return@let SchematicFormat.SPONGE_V3
|
||||
else
|
||||
return@let SchematicFormat.SPONGE_V2
|
||||
}
|
||||
|
||||
val data = NodeData(node.id, version)
|
||||
data.saveFromStream(content.inputStream(), version)
|
||||
|
||||
call.respond(ResponseSchematic(node))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,8 @@ dependencyResolutionManagement {
|
||||
library("yamlconfig", "org.bspfsystems:yamlconfiguration:1.3.0")
|
||||
library("kotlinxSerializationCbor", "org.jetbrains.kotlinx:kotlinx-serialization-cbor:1.4.1")
|
||||
library("ktorRateLimit", "io.ktor:ktor-server-rate-limit:$ktorVersion")
|
||||
|
||||
library("nbt", "dev.dewy:nbt:1.5.1")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user