mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-11-19 10:25:00 +00:00
Fix fast schematic reader/writer
- Have both sponge and fast r/w available but default to "fast" - Correctly "offset" entities in the schematic, and add a legacy mode for loading old FAWE schematics with entities required. - Lazily reading means it's read in order of appearance in the inputstream so we need to read schematic version first (skip past everything) and then reset the stream. Fixes #740 - Add an FAWEVersion to the metadata - Correctly actually return a BlockArrayClipboard when required. Fixes #454
This commit is contained in:
parent
82f640d132
commit
fbfe3221d7
@ -200,7 +200,7 @@ public class StreamDelegate {
|
|||||||
Object raw = is.readTagPayloadRaw(type, depth);
|
Object raw = is.readTagPayloadRaw(type, depth);
|
||||||
valueReader.apply(0, raw);
|
valueReader.apply(0, raw);
|
||||||
} else {
|
} else {
|
||||||
is.readTagPaylodLazy(type, depth + 1, this);
|
is.readTagPayloadLazy(type, depth + 1, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,14 @@ public final class NBTInputStream implements Closeable {
|
|||||||
this.is = dis;
|
this.is = dis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void mark(int mark) {
|
||||||
|
is.mark(mark);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() throws IOException {
|
||||||
|
is.reset();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads an NBT tag from the stream.
|
* Reads an NBT tag from the stream.
|
||||||
*
|
*
|
||||||
@ -99,7 +107,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
if (child != null) {
|
if (child != null) {
|
||||||
child.acceptRoot(this, type, 0);
|
child.acceptRoot(this, type, 0);
|
||||||
} else {
|
} else {
|
||||||
readTagPaylodLazy(type, 0);
|
readTagPayloadLazy(type, 0);
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -119,7 +127,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
|
|
||||||
private byte[] buf;
|
private byte[] buf;
|
||||||
|
|
||||||
public void readTagPaylodLazy(int type, int depth) throws IOException {
|
public void readTagPayloadLazy(int type, int depth) throws IOException {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NBTConstants.TYPE_END:
|
case NBTConstants.TYPE_END:
|
||||||
return;
|
return;
|
||||||
@ -152,7 +160,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
int childType = is.readByte();
|
int childType = is.readByte();
|
||||||
length = is.readInt();
|
length = is.readInt();
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
readTagPaylodLazy(childType, depth + 1);
|
readTagPayloadLazy(childType, depth + 1);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -165,7 +173,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
is.skipBytes(is.readShort() & 0xFFFF);
|
is.skipBytes(is.readShort() & 0xFFFF);
|
||||||
readTagPaylodLazy(childType, depth + 1);
|
readTagPayloadLazy(childType, depth + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case NBTConstants.TYPE_INT_ARRAY: {
|
case NBTConstants.TYPE_INT_ARRAY: {
|
||||||
@ -181,7 +189,7 @@ public final class NBTInputStream implements Closeable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void readTagPaylodLazy(int type, int depth, StreamDelegate scope) throws IOException {
|
public void readTagPayloadLazy(int type, int depth, StreamDelegate scope) throws IOException {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case NBTConstants.TYPE_END:
|
case NBTConstants.TYPE_END:
|
||||||
return;
|
return;
|
||||||
@ -293,11 +301,11 @@ public final class NBTInputStream implements Closeable {
|
|||||||
child = scope.get0();
|
child = scope.get0();
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
readTagPaylodLazy(childType, depth + 1);
|
readTagPayloadLazy(childType, depth + 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
readTagPaylodLazy(childType, depth + 1, child);
|
readTagPayloadLazy(childType, depth + 1, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -330,9 +338,9 @@ public final class NBTInputStream implements Closeable {
|
|||||||
}
|
}
|
||||||
StreamDelegate child = scope.get(is);
|
StreamDelegate child = scope.get(is);
|
||||||
if (child == null) {
|
if (child == null) {
|
||||||
readTagPaylodLazy(childType, depth + 1);
|
readTagPayloadLazy(childType, depth + 1);
|
||||||
} else {
|
} else {
|
||||||
readTagPaylodLazy(childType, depth + 1, child);
|
readTagPayloadLazy(childType, depth + 1, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ public class SchematicCommands {
|
|||||||
@Deprecated
|
@Deprecated
|
||||||
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.web", "worldedit.schematic.load.asset"})
|
@CommandPermissions({"worldedit.clipboard.load", "worldedit.schematic.load", "worldedit.schematic.load.web", "worldedit.schematic.load.asset"})
|
||||||
public void loadall(Player player, LocalSession session,
|
public void loadall(Player player, LocalSession session,
|
||||||
@Arg(desc = "Format name.", def = "schematic")
|
@Arg(desc = "Format name.", def = "fast")
|
||||||
String formatName,
|
String formatName,
|
||||||
@Arg(desc = "File name.")
|
@Arg(desc = "File name.")
|
||||||
String filename,
|
String filename,
|
||||||
@ -223,7 +223,7 @@ public class SchematicCommands {
|
|||||||
public void load(Actor actor, LocalSession session,
|
public void load(Actor actor, LocalSession session,
|
||||||
@Arg(desc = "File name.")
|
@Arg(desc = "File name.")
|
||||||
String filename,
|
String filename,
|
||||||
@Arg(desc = "Format name.", def = "sponge")
|
@Arg(desc = "Format name.", def = "fast")
|
||||||
String formatName) throws FilenameException {
|
String formatName) throws FilenameException {
|
||||||
LocalConfiguration config = worldEdit.getConfiguration();
|
LocalConfiguration config = worldEdit.getConfiguration();
|
||||||
|
|
||||||
@ -323,7 +323,7 @@ public class SchematicCommands {
|
|||||||
public void save(Actor actor, LocalSession session,
|
public void save(Actor actor, LocalSession session,
|
||||||
@Arg(desc = "File name.")
|
@Arg(desc = "File name.")
|
||||||
String filename,
|
String filename,
|
||||||
@Arg(desc = "Format name.", def = "sponge")
|
@Arg(desc = "Format name.", def = "fast")
|
||||||
String formatName,
|
String formatName,
|
||||||
@Switch(name = 'f', desc = "Overwrite an existing file.")
|
@Switch(name = 'f', desc = "Overwrite an existing file.")
|
||||||
boolean allowOverwrite,
|
boolean allowOverwrite,
|
||||||
|
@ -24,8 +24,11 @@ import com.boydti.fawe.object.io.ResettableFileInputStream;
|
|||||||
import com.boydti.fawe.object.schematic.MinecraftStructure;
|
import com.boydti.fawe.object.schematic.MinecraftStructure;
|
||||||
import com.boydti.fawe.object.schematic.PNGWriter;
|
import com.boydti.fawe.object.schematic.PNGWriter;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
import com.sk89q.jnbt.NBTOutputStream;
|
import com.sk89q.jnbt.NBTOutputStream;
|
||||||
|
import com.sk89q.jnbt.NamedTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
@ -35,6 +38,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
import java.util.zip.GZIPOutputStream;
|
import java.util.zip.GZIPOutputStream;
|
||||||
@ -44,6 +48,44 @@ import java.util.zip.GZIPOutputStream;
|
|||||||
*/
|
*/
|
||||||
public enum BuiltInClipboardFormat implements ClipboardFormat {
|
public enum BuiltInClipboardFormat implements ClipboardFormat {
|
||||||
|
|
||||||
|
FAST("fast", "fawe") {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrimaryFileExtension() {
|
||||||
|
return "schem";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||||
|
if (inputStream instanceof FileInputStream) {
|
||||||
|
inputStream = new ResettableFileInputStream((FileInputStream) inputStream);
|
||||||
|
}
|
||||||
|
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
||||||
|
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
||||||
|
return new FastSchematicReader(nbtStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||||
|
OutputStream gzip;
|
||||||
|
if (outputStream instanceof PGZIPOutputStream || outputStream instanceof GZIPOutputStream) {
|
||||||
|
gzip = outputStream;
|
||||||
|
} else {
|
||||||
|
outputStream = new BufferedOutputStream(outputStream);
|
||||||
|
gzip = new PGZIPOutputStream(outputStream);
|
||||||
|
}
|
||||||
|
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
||||||
|
return new FastSchematicWriter(nbtStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFormat(File file) {
|
||||||
|
String name = file.getName().toLowerCase(Locale.ROOT);
|
||||||
|
return name.endsWith(".schem") || name.endsWith(".sponge");
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Schematic format used by MCEdit.
|
* The Schematic format used by MCEdit.
|
||||||
*/
|
*/
|
||||||
@ -77,8 +119,49 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
|||||||
return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce");
|
return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
SPONGE_SCHEMATIC("sponge", "schem") {
|
SPONGE_SCHEMATIC("sponge", "schem") {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrimaryFileExtension() {
|
||||||
|
return "schem";
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public ClipboardReader getReader(InputStream inputStream) throws IOException {
|
||||||
|
NBTInputStream nbtStream = new NBTInputStream(new GZIPInputStream(inputStream));
|
||||||
|
return new SpongeSchematicReader(nbtStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||||
|
NBTOutputStream nbtStream = new NBTOutputStream(new GZIPOutputStream(outputStream));
|
||||||
|
return new SpongeSchematicWriter(nbtStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFormat(File file) {
|
||||||
|
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
|
||||||
|
NamedTag rootTag = str.readNamedTag();
|
||||||
|
if (!rootTag.getName().equals("Schematic")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
|
||||||
|
|
||||||
|
// Check
|
||||||
|
Map<String, Tag> schematic = schematicTag.getValue();
|
||||||
|
if (!schematic.containsKey("Version")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
BROKENENTITY("brokenentity", "legacyentity", "le", "be", "brokenentities", "legacyentities") {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPrimaryFileExtension() {
|
public String getPrimaryFileExtension() {
|
||||||
return "schem";
|
return "schem";
|
||||||
@ -91,7 +174,9 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
|||||||
}
|
}
|
||||||
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
BufferedInputStream buffered = new BufferedInputStream(inputStream);
|
||||||
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
NBTInputStream nbtStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(buffered)));
|
||||||
return new FastSchematicReader(nbtStream);
|
FastSchematicReader reader = new FastSchematicReader(nbtStream);
|
||||||
|
reader.setBrokenEntities(true);
|
||||||
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -104,13 +189,14 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
|||||||
gzip = new PGZIPOutputStream(outputStream);
|
gzip = new PGZIPOutputStream(outputStream);
|
||||||
}
|
}
|
||||||
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
NBTOutputStream nbtStream = new NBTOutputStream(new BufferedOutputStream(gzip));
|
||||||
return new FastSchematicWriter(nbtStream);
|
FastSchematicWriter writer = new FastSchematicWriter(nbtStream);
|
||||||
|
writer.setBrokenEntities(true);
|
||||||
|
return writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFormat(File file) {
|
public boolean isFormat(File file) {
|
||||||
String name = file.getName().toLowerCase(Locale.ROOT);
|
return false;
|
||||||
return name.endsWith(".schem") || name.endsWith(".sponge");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -30,10 +30,12 @@ import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
|||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.IntTag;
|
import com.sk89q.jnbt.IntTag;
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
import com.sk89q.jnbt.NamedTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
import com.sk89q.jnbt.Tag;
|
import com.sk89q.jnbt.Tag;
|
||||||
import com.sk89q.worldedit.WorldEdit;
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
import com.sk89q.worldedit.extension.platform.Capability;
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||||
@ -45,6 +47,7 @@ import com.sk89q.worldedit.world.DataFixer;
|
|||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
import com.sk89q.worldedit.world.block.BlockTypesCache;
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
import com.sk89q.worldedit.world.entity.EntityType;
|
||||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||||
@ -58,6 +61,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.OptionalInt;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@ -70,9 +74,10 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(FastSchematicReader.class);
|
private static final Logger log = LoggerFactory.getLogger(FastSchematicReader.class);
|
||||||
private final NBTInputStream inputStream;
|
private final NBTInputStream inputStream;
|
||||||
private DataFixer fixer = null;
|
private DataFixer fixer;
|
||||||
private int dataVersion = -1;
|
private int dataVersion = -1;
|
||||||
private int version = -1;
|
private int version = -1;
|
||||||
|
private int faweWritten = -1;
|
||||||
|
|
||||||
private FastByteArrayOutputStream blocksOut;
|
private FastByteArrayOutputStream blocksOut;
|
||||||
private FaweOutputStream blocks;
|
private FaweOutputStream blocks;
|
||||||
@ -92,6 +97,7 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
private char[] palette;
|
private char[] palette;
|
||||||
private char[] biomePalette;
|
private char[] biomePalette;
|
||||||
private BlockVector3 min = BlockVector3.ZERO;
|
private BlockVector3 min = BlockVector3.ZERO;
|
||||||
|
private boolean brokenEntities = false;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,6 +111,10 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
this.fixer = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataFixer();
|
this.fixer = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING).getDataFixer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBrokenEntities(boolean brokenEntities) {
|
||||||
|
this.brokenEntities = brokenEntities;
|
||||||
|
}
|
||||||
|
|
||||||
private String fix(String palettePart) {
|
private String fix(String palettePart) {
|
||||||
if (fixer == null || dataVersion == -1) {
|
if (fixer == null || dataVersion == -1) {
|
||||||
return palettePart;
|
return palettePart;
|
||||||
@ -133,7 +143,7 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
return fixer.fixUp(DataFixer.FixTypes.BIOME, biomePalettePart, dataVersion);
|
return fixer.fixUp(DataFixer.FixTypes.BIOME, biomePalettePart, dataVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StreamDelegate createDelegate() {
|
public StreamDelegate createVersionDelegate() {
|
||||||
StreamDelegate root = new StreamDelegate();
|
StreamDelegate root = new StreamDelegate();
|
||||||
StreamDelegate schematic = root.add("Schematic");
|
StreamDelegate schematic = root.add("Schematic");
|
||||||
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v);
|
schematic.add("DataVersion").withInt((i, v) -> dataVersion = v);
|
||||||
@ -143,6 +153,12 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
dataVersion = Constants.DATA_VERSION_MC_1_13_2;
|
dataVersion = Constants.DATA_VERSION_MC_1_13_2;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StreamDelegate createDelegate() {
|
||||||
|
StreamDelegate root = new StreamDelegate();
|
||||||
|
StreamDelegate schematic = root.add("Schematic");
|
||||||
schematic.add("Width").withInt((i, v) -> width = v);
|
schematic.add("Width").withInt((i, v) -> width = v);
|
||||||
schematic.add("Height").withInt((i, v) -> height = v);
|
schematic.add("Height").withInt((i, v) -> height = v);
|
||||||
schematic.add("Length").withInt((i, v) -> length = v);
|
schematic.add("Length").withInt((i, v) -> length = v);
|
||||||
@ -152,17 +168,19 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
|
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
|
||||||
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
|
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
|
||||||
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
||||||
|
metadata.add("FAWEVersion").withInt((i, v) -> faweWritten = v);
|
||||||
|
|
||||||
StreamDelegate paletteDelegate = schematic.add("Palette");
|
StreamDelegate paletteDelegate = schematic.add("Palette");
|
||||||
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
|
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
|
||||||
palette = new char[v.size()];
|
palette = new char[v.size()];
|
||||||
for (Entry<String, Object> entry : v.entrySet()) {
|
for (Entry<String, Object> entry : v.entrySet()) {
|
||||||
BlockState state = null;
|
BlockState state;
|
||||||
try {
|
|
||||||
String palettePart = fix(entry.getKey());
|
String palettePart = fix(entry.getKey());
|
||||||
|
try {
|
||||||
state = BlockState.get(palettePart);
|
state = BlockState.get(palettePart);
|
||||||
} catch (InputParseException e) {
|
} catch (InputParseException ignored) {
|
||||||
e.printStackTrace();
|
log.warn("Invalid BlockState in palette: " + palettePart + ". Block will be replaced with air.");
|
||||||
|
state = BlockTypes.AIR.getDefaultState();
|
||||||
}
|
}
|
||||||
int index = (int) entry.getValue();
|
int index = (int) entry.getValue();
|
||||||
palette[index] = (char) state.getOrdinal();
|
palette[index] = (char) state.getOrdinal();
|
||||||
@ -224,10 +242,14 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
@Override
|
@Override
|
||||||
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
|
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
|
||||||
StreamDelegate root = createDelegate();
|
StreamDelegate root = createDelegate();
|
||||||
|
StreamDelegate versions = createVersionDelegate();
|
||||||
|
inputStream.mark(Integer.MAX_VALUE);
|
||||||
|
inputStream.readNamedTagLazy(versions);
|
||||||
|
inputStream.reset();
|
||||||
inputStream.readNamedTagLazy(root);
|
inputStream.readNamedTagLazy(root);
|
||||||
|
|
||||||
if (version != 1 && version != 2) {
|
if (version != 1 && version != 2) {
|
||||||
throw new IOException("This schematic version is currently not supported");
|
throw new IOException("This schematic version is currently not supported (" + version + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blocks != null) {
|
if (blocks != null) {
|
||||||
@ -240,9 +262,11 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
biomes = null;
|
biomes = null;
|
||||||
|
|
||||||
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
||||||
BlockVector3 origin = BlockVector3.ZERO;
|
BlockVector3 origin;
|
||||||
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
|
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
|
||||||
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
|
origin = BlockVector3.at(-offsetX, -offsetY, -offsetZ);
|
||||||
|
} else {
|
||||||
|
origin = BlockVector3.ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
Clipboard clipboard = createOutput.apply(dimensions);
|
Clipboard clipboard = createOutput.apply(dimensions);
|
||||||
@ -352,7 +376,7 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
if (id == null) {
|
if (id == null) {
|
||||||
id = (StringTag) value.get("id");
|
id = (StringTag) value.get("id");
|
||||||
if (id == null) {
|
if (id == null) {
|
||||||
return null;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
value.put("id", id);
|
value.put("id", id);
|
||||||
@ -363,7 +387,26 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
ent = fixEntity(ent);
|
ent = fixEntity(ent);
|
||||||
BaseEntity state = new BaseEntity(type, ent);
|
BaseEntity state = new BaseEntity(type, ent);
|
||||||
Location loc = ent.getEntityLocation(clipboard);
|
Location loc = ent.getEntityLocation(clipboard);
|
||||||
|
if (brokenEntities) {
|
||||||
clipboard.createEntity(loc, state);
|
clipboard.createEntity(loc, state);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (faweWritten == -1) {
|
||||||
|
int locX = loc.getBlockX();
|
||||||
|
int locY = loc.getBlockY();
|
||||||
|
int locZ = loc.getBlockZ();
|
||||||
|
BlockVector3 max = min.add(dimensions).subtract(BlockVector3.ONE);
|
||||||
|
if (locX < min.getX() || locY < min.getY() || locZ < min.getZ()
|
||||||
|
|| locX > max.getX() || locY > max.getY() || locZ > max.getZ()) {
|
||||||
|
for (Entity e : clipboard.getEntities()) {
|
||||||
|
clipboard.removeEntity(e);
|
||||||
|
}
|
||||||
|
log.error("Detected schematic entity outside clipboard region. FAWE will not load entities. "
|
||||||
|
+ "Please try loading the schematic with the format \"legacyentity\"");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clipboard.createEntity(loc.setPosition(loc.subtract(min.toVector3())), state);
|
||||||
} else {
|
} else {
|
||||||
log.debug("Invalid entity: " + id);
|
log.debug("Invalid entity: " + id);
|
||||||
}
|
}
|
||||||
@ -372,7 +415,7 @@ public class FastSchematicReader extends NBTSchematicReader {
|
|||||||
clipboard.setOrigin(origin);
|
clipboard.setOrigin(origin);
|
||||||
|
|
||||||
if (!min.equals(BlockVector3.ZERO)) {
|
if (!min.equals(BlockVector3.ZERO)) {
|
||||||
new BlockArrayClipboard(clipboard, min);
|
clipboard = new BlockArrayClipboard(clipboard, min);
|
||||||
}
|
}
|
||||||
|
|
||||||
return clipboard;
|
return clipboard;
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extent.clipboard.io;
|
package com.sk89q.worldedit.extent.clipboard.io;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||||
import com.boydti.fawe.object.FaweOutputStream;
|
import com.boydti.fawe.object.FaweOutputStream;
|
||||||
import com.boydti.fawe.util.IOUtil;
|
import com.boydti.fawe.util.IOUtil;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.IntArrayTag;
|
import com.sk89q.jnbt.IntArrayTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
@ -39,6 +39,7 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
|||||||
import com.sk89q.worldedit.function.visitor.Order;
|
import com.sk89q.worldedit.function.visitor.Order;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
@ -58,8 +59,6 @@ import java.util.HashMap;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -72,6 +71,7 @@ public class FastSchematicWriter implements ClipboardWriter {
|
|||||||
|
|
||||||
private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
|
private static final int MAX_SIZE = Short.MAX_VALUE - Short.MIN_VALUE;
|
||||||
private final NBTOutputStream outputStream;
|
private final NBTOutputStream outputStream;
|
||||||
|
private boolean brokenEntities = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new schematic writer.
|
* Create a new schematic writer.
|
||||||
@ -83,6 +83,10 @@ public class FastSchematicWriter implements ClipboardWriter {
|
|||||||
this.outputStream = outputStream;
|
this.outputStream = outputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBrokenEntities(boolean brokenEntities) {
|
||||||
|
this.brokenEntities = brokenEntities;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(Clipboard clipboard) throws IOException {
|
public void write(Clipboard clipboard) throws IOException {
|
||||||
// For now always write the latest version. Maybe provide support for earlier if more appear.
|
// For now always write the latest version. Maybe provide support for earlier if more appear.
|
||||||
@ -132,6 +136,7 @@ public class FastSchematicWriter implements ClipboardWriter {
|
|||||||
out1.writeNamedTag("WEOffsetX", offset.getBlockX());
|
out1.writeNamedTag("WEOffsetX", offset.getBlockX());
|
||||||
out1.writeNamedTag("WEOffsetY", offset.getBlockY());
|
out1.writeNamedTag("WEOffsetY", offset.getBlockY());
|
||||||
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
|
out1.writeNamedTag("WEOffsetZ", offset.getBlockZ());
|
||||||
|
out1.writeNamedTag("FAWEVersion", Fawe.get().getVersion().build);
|
||||||
});
|
});
|
||||||
|
|
||||||
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
|
ByteArrayOutputStream blocksCompressed = new ByteArrayOutputStream();
|
||||||
@ -240,8 +245,12 @@ public class FastSchematicWriter implements ClipboardWriter {
|
|||||||
|
|
||||||
// Store our location data, overwriting any
|
// Store our location data, overwriting any
|
||||||
values.remove("id");
|
values.remove("id");
|
||||||
|
Location loc = entity.getLocation();
|
||||||
|
if (!brokenEntities) {
|
||||||
|
loc = loc.setPosition(loc.add(min.toVector3()));
|
||||||
|
}
|
||||||
values.put("Id", new StringTag(state.getType().getId()));
|
values.put("Id", new StringTag(state.getType().getId()));
|
||||||
values.put("Pos", writeVector(entity.getLocation()));
|
values.put("Pos", writeVector(loc));
|
||||||
values.put("Rotation", writeRotation(entity.getLocation()));
|
values.put("Rotation", writeRotation(entity.getLocation()));
|
||||||
|
|
||||||
CompoundTag entityTag = new CompoundTag(values);
|
CompoundTag entityTag = new CompoundTag(values);
|
||||||
@ -311,30 +320,6 @@ public class FastSchematicWriter implements ClipboardWriter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException {
|
|
||||||
List<CompoundTag> entities = clipboard.getEntities().stream().map(e -> {
|
|
||||||
BaseEntity state = e.getState();
|
|
||||||
if (state == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Map<String, Tag> values = Maps.newHashMap();
|
|
||||||
CompoundTag rawData = state.getNbtData();
|
|
||||||
if (rawData != null) {
|
|
||||||
values.putAll(rawData.getValue());
|
|
||||||
}
|
|
||||||
values.remove("id");
|
|
||||||
values.put("Id", new StringTag(state.getType().getId()));
|
|
||||||
values.put("Pos", writeVector(e.getLocation().toVector()));
|
|
||||||
values.put("Rotation", writeRotation(e.getLocation()));
|
|
||||||
|
|
||||||
return new CompoundTag(values);
|
|
||||||
}).filter(Objects::nonNull).collect(Collectors.toList());
|
|
||||||
if (entities.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
schematic.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
|
@ -378,7 +378,7 @@ public class SchematicReader implements ClipboardReader {
|
|||||||
|
|
||||||
BlockVector3 min = BlockVector3.at(originX, originY, originZ);
|
BlockVector3 min = BlockVector3.at(originX, originY, originZ);
|
||||||
if (!min.equals(BlockVector3.ZERO)) {
|
if (!min.equals(BlockVector3.ZERO)) {
|
||||||
new BlockArrayClipboard(clipboard, min);
|
clipboard = new BlockArrayClipboard(clipboard, min);
|
||||||
}
|
}
|
||||||
return clipboard;
|
return clipboard;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.extent.clipboard.io;
|
package com.sk89q.worldedit.extent.clipboard.io;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.sk89q.jnbt.ByteArrayTag;
|
import com.sk89q.jnbt.ByteArrayTag;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
@ -114,6 +115,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
|||||||
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
|
metadata.put("WEOffsetX", new IntTag(offset.getBlockX()));
|
||||||
metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
|
metadata.put("WEOffsetY", new IntTag(offset.getBlockY()));
|
||||||
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
|
metadata.put("WEOffsetZ", new IntTag(offset.getBlockZ()));
|
||||||
|
metadata.put("FAWEVersion", new IntTag(Fawe.get().getVersion().build));
|
||||||
|
|
||||||
schematic.put("Metadata", new CompoundTag(metadata));
|
schematic.put("Metadata", new CompoundTag(metadata));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user