Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-07 20:10:06 +01:00
Legacy clipboards
Dieser Commit ist enthalten in:
Ursprung
c2cb463dae
Commit
2f3c6769c8
@ -1,429 +0,0 @@
|
|||||||
package com.boydti.fawe.jnbt;
|
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FaweInputStream;
|
|
||||||
import com.boydti.fawe.object.FaweOutputStream;
|
|
||||||
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
|
|
||||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
|
||||||
import com.boydti.fawe.object.clipboard.LinearClipboard;
|
|
||||||
import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
|
|
||||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
|
||||||
import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
|
||||||
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
|
||||||
import com.sk89q.jnbt.ListTag;
|
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
|
||||||
import com.sk89q.jnbt.StringTag;
|
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
|
||||||
import com.sk89q.worldedit.registry.state.PropertyKey;
|
|
||||||
import com.sk89q.worldedit.util.Direction;
|
|
||||||
import com.sk89q.worldedit.util.Location;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeType;
|
|
||||||
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockCategories;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockID;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypeSwitch;
|
|
||||||
import com.sk89q.worldedit.world.block.BlockTypeSwitchBuilder;
|
|
||||||
import com.sk89q.worldedit.world.entity.EntityType;
|
|
||||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
|
||||||
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
|
||||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
|
||||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
|
||||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
// TODO FIXME
|
|
||||||
public class SchematicStreamer implements Closeable {
|
|
||||||
private final UUID uuid;
|
|
||||||
private final NBTInputStream input;
|
|
||||||
private FastByteArrayOutputStream idOut = new FastByteArrayOutputStream();
|
|
||||||
private FastByteArrayOutputStream dataOut = new FastByteArrayOutputStream();
|
|
||||||
private FastByteArrayOutputStream addOut;
|
|
||||||
|
|
||||||
private FaweOutputStream ids;
|
|
||||||
private FaweOutputStream datas;
|
|
||||||
private FaweOutputStream adds;
|
|
||||||
|
|
||||||
public SchematicStreamer(NBTInputStream stream, UUID uuid) {
|
|
||||||
this.input = stream;
|
|
||||||
this.uuid = uuid;
|
|
||||||
clipboard = new BlockArrayClipboard(new CuboidRegion(BlockVector3.at(0, 0, 0), BlockVector3.at(0, 0, 0)), fc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addBlockReaders() throws IOException {
|
|
||||||
// NBTStreamReader<? extends Integer, ? extends Integer> idInit = new NBTStreamReader<Integer, Integer>() {
|
|
||||||
// @Override
|
|
||||||
// public void accept(Integer length, Integer type) {
|
|
||||||
// ids = new FaweOutputStream(new LZ4BlockOutputStream(idOut));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// NBTStreamReader<? extends Integer, ? extends Integer> dataInit = new NBTStreamReader<Integer, Integer>() {
|
|
||||||
// @Override
|
|
||||||
// public void accept(Integer length, Integer type) {
|
|
||||||
// datas = new FaweOutputStream(new LZ4BlockOutputStream(dataOut));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// NBTStreamReader<? extends Integer, ? extends Integer> addInit = new NBTStreamReader<Integer, Integer>() {
|
|
||||||
// @Override
|
|
||||||
// public void accept(Integer length, Integer type) {
|
|
||||||
// addOut = new FastByteArrayOutputStream();
|
|
||||||
// adds = new FaweOutputStream(new LZ4BlockOutputStream(addOut));
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// addReader("Schematic.Blocks", NBTStreamer.ReadType.INFO, idInit);
|
|
||||||
// addReader("Schematic.Data", NBTStreamer.ReadType.INFO, dataInit);
|
|
||||||
// addReader("Schematic.AddBlocks", NBTStreamer.ReadType.INFO, addInit);
|
|
||||||
// addReader("Schematic.Blocks", NBTStreamer.ReadType.ELEM, new ByteReader() {
|
|
||||||
// @Override
|
|
||||||
// public void run(int index, int value) {
|
|
||||||
// try {
|
|
||||||
// ids.write(value);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// throw new RuntimeException(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// addReader("Schematic.Data", NBTStreamer.ReadType.ELEM, new ByteReader() {
|
|
||||||
// @Override
|
|
||||||
// public void run(int index, int value) {
|
|
||||||
// try {
|
|
||||||
// datas.write(value);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// throw new RuntimeException(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// addReader("Schematic.AddBlocks", NBTStreamer.ReadType.ELEM, new ByteReader() {
|
|
||||||
// @Override
|
|
||||||
// public void run(int index, int value) {
|
|
||||||
// if (value != 0) {
|
|
||||||
// int first = value & 0x0F;
|
|
||||||
// int second = (value & 0xF0) >> 4;
|
|
||||||
// try {
|
|
||||||
// if (first != 0) adds.write(first);
|
|
||||||
// if (second != 0) adds.write(second);
|
|
||||||
// } catch (IOException e) {
|
|
||||||
// throw new RuntimeException(e);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// ByteReader biomeReader = new ByteReader() {
|
|
||||||
// @Override
|
|
||||||
// public void run(int index, int value) {
|
|
||||||
// BiomeType biome = BiomeTypes.getLegacy(value);
|
|
||||||
// if (biome != null) {
|
|
||||||
// fc.setBiome(index, biome);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// NBTStreamReader<Integer, Integer> initializer23 = new NBTStreamReader<Integer, Integer>() {
|
|
||||||
// @Override
|
|
||||||
// public void accept(Integer value1, Integer value2) {
|
|
||||||
// if (fc == null) setupClipboard(length * width * height);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// addReader("Schematic.AWEBiomes", NBTStreamer.ReadType.INFO,initializer23);
|
|
||||||
// addReader("Schematic.Biomes", NBTStreamer.ReadType.INFO,initializer23);
|
|
||||||
// addReader("Schematic.AWEBiomes", NBTStreamer.ReadType.ELEM,biomeReader); // AWE stores as an int[]
|
|
||||||
// addReader("Schematic.Biomes", NBTStreamer.ReadType.ELEM,biomeReader); // FAWE stores as a byte[] (4x smaller)
|
|
||||||
//
|
|
||||||
// // Tiles
|
|
||||||
// addReader("Schematic.TileEntities", NBTStreamer.ReadType.ELEM,(BiConsumer<Integer, CompoundTag>) (index, value) -> {
|
|
||||||
// if (fc == null) {
|
|
||||||
// setupClipboard(0);
|
|
||||||
// }
|
|
||||||
// int x = value.getInt("x");
|
|
||||||
// int y = value.getInt("y");
|
|
||||||
// int z = value.getInt("z");
|
|
||||||
// fc.setTile(x, y, z, value);
|
|
||||||
// });
|
|
||||||
// // Entities
|
|
||||||
// addReader("Schematic.Entities", NBTStreamer.ReadType.ELEM,(BiConsumer<Integer, CompoundTag>) (index, compound) -> {
|
|
||||||
// if (fc == null) {
|
|
||||||
// setupClipboard(0);
|
|
||||||
// }
|
|
||||||
// String id = compound.getString("id");
|
|
||||||
// if (id.isEmpty()) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// EntityType type = EntityTypes.parse(id);
|
|
||||||
// if (type != null) {
|
|
||||||
// compound.getValue().put("Id", new StringTag(type.getId()));
|
|
||||||
// BaseEntity state = new BaseEntity(type, compound);
|
|
||||||
//
|
|
||||||
// Location loc = compound.getEntityLocation(fc);
|
|
||||||
// fc.createEntity(loc, state);
|
|
||||||
// } else {
|
|
||||||
// Fawe.debug("Invalid entity: " + id);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void readFully() throws IOException {
|
|
||||||
// super.readFully();
|
|
||||||
// if (ids != null) ids.close();
|
|
||||||
// if (datas != null) datas.close();
|
|
||||||
// if (adds != null) adds.close();
|
|
||||||
// FaweInputStream idIn = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(idOut.toByteArrays())));
|
|
||||||
// FaweInputStream dataIn = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(dataOut.toByteArrays())));
|
|
||||||
//
|
|
||||||
// LegacyMapper remap = LegacyMapper.getInstance();
|
|
||||||
// BlockVector3 dimensions = fc.getDimensions();
|
|
||||||
// int length = dimensions.getBlockX() * dimensions.getBlockY() * dimensions.getBlockZ();
|
|
||||||
// if (adds == null) {
|
|
||||||
// for (int i = 0; i < length; i++) {
|
|
||||||
// fc.setBlock(i, remap.getBlockFromLegacyCombinedId(((idIn.read() & 0xFF) << 4) + (dataIn.read() & 0xF)));
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// FaweInputStream addIn = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(dataOut.toByteArrays())));
|
|
||||||
// for (int i = 0; i < length; i++) {
|
|
||||||
// fc.setBlock(i, remap.getBlockFromLegacyCombinedId(((addIn.read() & 0xFF) << 8) + ((idIn.read() & 0xFF) << 4) + (dataIn.read() & 0xF)));
|
|
||||||
// }
|
|
||||||
// addIn.close();
|
|
||||||
// }
|
|
||||||
// idIn.close();
|
|
||||||
// dataIn.close();
|
|
||||||
// }
|
|
||||||
|
|
||||||
private void fixStates() {
|
|
||||||
for (BlockVector3 pos : fc) {
|
|
||||||
BlockState block = pos.getBlock(fc);
|
|
||||||
if (block.getMaterial().isAir()) continue;
|
|
||||||
|
|
||||||
int x = pos.getX();
|
|
||||||
int y = pos.getY();
|
|
||||||
int z = pos.getZ();
|
|
||||||
|
|
||||||
BlockType type = block.getBlockType();
|
|
||||||
if (BlockCategories.STAIRS.contains(type)) {
|
|
||||||
Direction facing = (Direction) block.getState(PropertyKey.FACING);
|
|
||||||
|
|
||||||
BlockVector3 forward = facing.toBlockVector();
|
|
||||||
Direction left = facing.getLeft();
|
|
||||||
Direction right = facing.getRight();
|
|
||||||
|
|
||||||
BlockStateHolder forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ());
|
|
||||||
BlockType forwardType = forwardBlock.getBlockType();
|
|
||||||
if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) {
|
|
||||||
Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING);
|
|
||||||
if (forwardFacing == left) {
|
|
||||||
BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
|
|
||||||
BlockType rightType = rightBlock.getBlockType();
|
|
||||||
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
|
|
||||||
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "inner_left"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (forwardFacing == right) {
|
|
||||||
BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
|
|
||||||
BlockType leftType = leftBlock.getBlockType();
|
|
||||||
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
|
|
||||||
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_right"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockState backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ());
|
|
||||||
BlockType backwardsType = backwardsBlock.getBlockType();
|
|
||||||
if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) {
|
|
||||||
Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING);
|
|
||||||
if (backwardsFacing == left) {
|
|
||||||
BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
|
|
||||||
BlockType rightType = rightBlock.getBlockType();
|
|
||||||
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
|
|
||||||
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_left"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
} else if (backwardsFacing == right) {
|
|
||||||
BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
|
|
||||||
BlockType leftType = leftBlock.getBlockType();
|
|
||||||
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
|
|
||||||
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_right"));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int group = group(type);
|
|
||||||
if (group == -1) return;
|
|
||||||
BlockState set = block;
|
|
||||||
|
|
||||||
if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(group, x, y, z - 1)) set = set.with(PropertyKey.NORTH, true);
|
|
||||||
if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(group, x + 1, y, z)) set = set.with(PropertyKey.EAST, true);
|
|
||||||
if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(group, x, y, z + 1)) set = set.with(PropertyKey.SOUTH, true);
|
|
||||||
if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(group, x - 1, y, z)) set = set.with(PropertyKey.WEST, true);
|
|
||||||
|
|
||||||
if (group == 2) {
|
|
||||||
int ns = ((Boolean) set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0);
|
|
||||||
int ew = ((Boolean) set.getState(PropertyKey.EAST) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.WEST) ? 1 : 0);
|
|
||||||
if (Math.abs(ns - ew) != 2 || fc.getBlock(x, y + 1, z).getBlockType().getMaterial().isSolid()) {
|
|
||||||
set = set.with(PropertyKey.UP, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (set != block) pos.setBlock(fc, set);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private BlockTypeSwitch<Boolean> fullCube = new BlockTypeSwitchBuilder<>(false).add(type -> {
|
|
||||||
BlockMaterial mat = type.getMaterial();
|
|
||||||
return (mat.isFullCube() && !mat.isFragileWhenPushed() && mat.getLightValue() == 0 && mat.isOpaque() && mat.isSolid() && !mat.isTranslucent());
|
|
||||||
}, true).build();
|
|
||||||
|
|
||||||
private boolean merge(int group, int x, int y, int z) {
|
|
||||||
BlockState block = fc.getBlock(x, y, z);
|
|
||||||
BlockType type = block.getBlockType();
|
|
||||||
return group(type) == group || fullCube.apply(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
private int group(BlockType type) {
|
|
||||||
switch (type.getInternalId()) {
|
|
||||||
case BlockID.ACACIA_FENCE:
|
|
||||||
case BlockID.BIRCH_FENCE:
|
|
||||||
case BlockID.DARK_OAK_FENCE:
|
|
||||||
case BlockID.JUNGLE_FENCE:
|
|
||||||
case BlockID.OAK_FENCE:
|
|
||||||
case BlockID.SPRUCE_FENCE:
|
|
||||||
return 0;
|
|
||||||
case BlockID.NETHER_BRICK_FENCE:
|
|
||||||
return 1;
|
|
||||||
case BlockID.COBBLESTONE_WALL:
|
|
||||||
case BlockID.MOSSY_COBBLESTONE_WALL:
|
|
||||||
return 2;
|
|
||||||
case BlockID.IRON_BARS:
|
|
||||||
case BlockID.BLACK_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.BLUE_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.BROWN_MUSHROOM_BLOCK:
|
|
||||||
case BlockID.BROWN_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.CYAN_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.GLASS_PANE:
|
|
||||||
case BlockID.GRAY_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.GREEN_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.LIGHT_BLUE_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.LIGHT_GRAY_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.LIME_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.MAGENTA_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.ORANGE_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.PINK_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.PURPLE_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.RED_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.WHITE_STAINED_GLASS_PANE:
|
|
||||||
case BlockID.YELLOW_STAINED_GLASS_PANE:
|
|
||||||
return 3;
|
|
||||||
default:
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addDimensionReaders() {
|
|
||||||
// addReader("Schematic.Height",
|
|
||||||
// (BiConsumer<Integer, Short>) (index, value) -> height = (value));
|
|
||||||
// addReader("Schematic.Width", (BiConsumer<Integer, Short>) (index, value) -> width = (value));
|
|
||||||
// addReader("Schematic.Length",
|
|
||||||
// (BiConsumer<Integer, Short>) (index, value) -> length = (value));
|
|
||||||
// addReader("Schematic.WEOriginX",
|
|
||||||
// (BiConsumer<Integer, Integer>) (index, value) -> originX = (value));
|
|
||||||
// addReader("Schematic.WEOriginY",
|
|
||||||
// (BiConsumer<Integer, Integer>) (index, value) -> originY = (value));
|
|
||||||
// addReader("Schematic.WEOriginZ",
|
|
||||||
// (BiConsumer<Integer, Integer>) (index, value) -> originZ = (value));
|
|
||||||
// addReader("Schematic.WEOffsetX",
|
|
||||||
// (BiConsumer<Integer, Integer>) (index, value) -> offsetX = (value));
|
|
||||||
// addReader("Schematic.WEOffsetY",
|
|
||||||
// (BiConsumer<Integer, Integer>) (index, value) -> offsetY = (value));
|
|
||||||
// addReader("Schematic.WEOffsetZ",
|
|
||||||
// (BiConsumer<Integer, Integer>) (index, value) -> offsetZ = (value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int height;
|
|
||||||
private int width;
|
|
||||||
private int length;
|
|
||||||
|
|
||||||
private int originX;
|
|
||||||
private int originY;
|
|
||||||
private int originZ;
|
|
||||||
|
|
||||||
private int offsetX;
|
|
||||||
private int offsetY;
|
|
||||||
private int offsetZ;
|
|
||||||
|
|
||||||
private BlockArrayClipboard clipboard;
|
|
||||||
private LinearClipboard fc;
|
|
||||||
|
|
||||||
private LinearClipboard setupClipboard(int size) {
|
|
||||||
if (fc != null) {
|
|
||||||
if (fc.getDimensions().getX() == 0) {
|
|
||||||
// fc.setDimensions(BlockVector3.at(size, 1, 1));
|
|
||||||
}
|
|
||||||
return fc;
|
|
||||||
}
|
|
||||||
if (Settings.IMP.CLIPBOARD.USE_DISK) {
|
|
||||||
return fc = new DiskOptimizedClipboard(BlockVector3.at(size, 1, 1), uuid);
|
|
||||||
} else if (Settings.IMP.CLIPBOARD.COMPRESSION_LEVEL == 0) {
|
|
||||||
return fc = new CPUOptimizedClipboard(BlockVector3.at(size, 1, 1));
|
|
||||||
} else {
|
|
||||||
return fc = new MemoryOptimizedClipboard(BlockVector3.at(size, 1, 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockVector3 getOrigin() {
|
|
||||||
return BlockVector3.at(originX, originY, originZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockVector3 getOffset() {
|
|
||||||
return BlockVector3.at(offsetX, offsetY, offsetZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockVector3 getDimensions() {
|
|
||||||
return BlockVector3.at(width, height, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClipboard(LinearClipboard clipboard) {
|
|
||||||
this.fc = clipboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Clipboard getClipboard() throws IOException {
|
|
||||||
try {
|
|
||||||
setupClipboard(0);
|
|
||||||
addDimensionReaders();
|
|
||||||
addBlockReaders();
|
|
||||||
// readFully();
|
|
||||||
BlockVector3 min = BlockVector3.at(originX, originY, originZ);
|
|
||||||
BlockVector3 offset = BlockVector3.at(offsetX, offsetY, offsetZ);
|
|
||||||
BlockVector3 origin = min.subtract(offset);
|
|
||||||
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
|
||||||
// fc.setDimensions(dimensions);
|
|
||||||
fixStates();
|
|
||||||
CuboidRegion region = new CuboidRegion(min, min.add(width, height, length).subtract(BlockVector3.ONE));
|
|
||||||
// clipboard.init(region, fc);
|
|
||||||
clipboard.setOrigin(origin);
|
|
||||||
return clipboard;
|
|
||||||
} catch (Throwable e) {
|
|
||||||
if (fc != null) {
|
|
||||||
fc.close();
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
this.input.close();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +1,12 @@
|
|||||||
package com.boydti.fawe.jnbt.streamer;
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface InfoReader extends StreamReader<Integer> {
|
public interface InfoReader extends StreamReader<Integer> {
|
||||||
void apply(int length, int type);
|
void apply(int length, int type) throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void apply(int i, Integer value) {
|
default void apply(int i, Integer value) throws IOException {
|
||||||
apply(i, value.intValue());
|
apply(i, value.intValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.boydti.fawe.jnbt.streamer;
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface IntValueReader extends ValueReader<Integer> {
|
public interface IntValueReader extends ValueReader<Integer> {
|
||||||
void applyInt(int index, int value);
|
void applyInt(int index, int value) throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void apply(int index, Integer value) {
|
default void apply(int index, Integer value) throws IOException {
|
||||||
applyInt(index, value);
|
applyInt(index, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@ package com.boydti.fawe.jnbt.streamer;
|
|||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface LazyReader extends StreamReader<DataInputStream> {
|
public interface LazyReader extends StreamReader<DataInputStream> {
|
||||||
void apply(int index, NBTInputStream stream);
|
void apply(int index, NBTInputStream stream) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.boydti.fawe.jnbt.streamer;
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface LongValueReader extends ValueReader<Long> {
|
public interface LongValueReader extends ValueReader<Long> {
|
||||||
void applyLong(int index, long value);
|
void applyLong(int index, long value) throws IOException;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void apply(int index, Long value) {
|
default void apply(int index, Long value) throws IOException {
|
||||||
applyLong(index, value);
|
applyLong(index, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
package com.boydti.fawe.jnbt.streamer;
|
|
||||||
|
|
||||||
public enum ReaderType {
|
|
||||||
VALUE,
|
|
||||||
INFO,
|
|
||||||
ELEM,
|
|
||||||
}
|
|
@ -208,13 +208,13 @@ public class StreamDelegate {
|
|||||||
return elemReader;
|
return elemReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void acceptInfo(int length, int type) {
|
public void acceptInfo(int length, int type) throws IOException {
|
||||||
if (infoReader != null) {
|
if (infoReader != null) {
|
||||||
infoReader.apply(length, type);
|
infoReader.apply(length, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean acceptLazy(int length, NBTInputStream is) {
|
public boolean acceptLazy(int length, NBTInputStream is) throws IOException {
|
||||||
if (lazyReader != null) {
|
if (lazyReader != null) {
|
||||||
lazyReader.apply(length, is);
|
lazyReader.apply(length, is);
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.boydti.fawe.jnbt.streamer;
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public interface StreamReader<T> {
|
public interface StreamReader<T> {
|
||||||
void apply(int i, T value);
|
void apply(int i, T value) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
package com.boydti.fawe.jnbt.streamer;
|
package com.boydti.fawe.jnbt.streamer;
|
||||||
|
|
||||||
public interface ValueReader<T> extends StreamReader<T> {
|
import java.io.IOException;
|
||||||
void apply(int index, T value);
|
|
||||||
|
|
||||||
default void applyInt(int index, int value) {
|
public interface ValueReader<T> extends StreamReader<T> {
|
||||||
|
void apply(int index, T value) throws IOException;
|
||||||
|
|
||||||
|
default void applyInt(int index, int value) throws IOException {
|
||||||
apply(index, (T) (Integer) value);
|
apply(index, (T) (Integer) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void applyLong(int index, long value) {
|
default void applyLong(int index, long value) throws IOException {
|
||||||
apply(index, (T) (Long) value);
|
apply(index, (T) (Long) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void applyFloat(int index, float value) {
|
default void applyFloat(int index, float value) throws IOException {
|
||||||
apply(index, (T) (Float) value);
|
apply(index, (T) (Float) value);
|
||||||
}
|
}
|
||||||
|
|
||||||
default void applyDouble(int index, double value) {
|
default void applyDouble(int index, double value) throws IOException {
|
||||||
apply(index, (T) (Double) value);
|
apply(index, (T) (Double) value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -201,12 +201,17 @@ public class DiskOptimizedClipboard extends LinearClipboard implements Closeable
|
|||||||
if (!hasBiomes()) return;
|
if (!hasBiomes()) return;
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int mbbIndex = HEADER_SIZE + (getVolume() << 1);
|
int mbbIndex = HEADER_SIZE + (getVolume() << 1);
|
||||||
|
try {
|
||||||
for (int z = 0; z < getLength(); z++) {
|
for (int z = 0; z < getLength(); z++) {
|
||||||
for (int x = 0; x < getWidth(); x++, index++, mbbIndex++) {
|
for (int x = 0; x < getWidth(); x++, index++, mbbIndex++) {
|
||||||
int biome = byteBuffer.get(mbbIndex) & 0xFF;
|
int biome = byteBuffer.get(mbbIndex) & 0xFF;
|
||||||
task.applyInt(index, biome);
|
task.applyInt(index, biome);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -198,10 +198,14 @@ public class Schematic {
|
|||||||
|
|
||||||
public void paste(Extent extent, BlockVector3 to, boolean pasteAir) {
|
public void paste(Extent extent, BlockVector3 to, boolean pasteAir) {
|
||||||
Region region = clipboard.getRegion().clone();
|
Region region = clipboard.getRegion().clone();
|
||||||
final BlockVector3 bot = clipboard.getMinimumPoint();
|
|
||||||
final BlockVector3 origin = clipboard.getOrigin();
|
final BlockVector3 origin = clipboard.getOrigin();
|
||||||
|
|
||||||
final boolean copyBiomes = clipboard.hasBiomes();
|
final boolean copyBiomes = clipboard.hasBiomes();
|
||||||
|
// To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin)
|
||||||
|
final int relx = to.getBlockX() - origin.getBlockX();
|
||||||
|
final int rely = to.getBlockY() - origin.getBlockY();
|
||||||
|
final int relz = to.getBlockZ() - origin.getBlockZ();
|
||||||
|
|
||||||
clipboard.apply(clipboard, new Filter() {
|
clipboard.apply(clipboard, new Filter() {
|
||||||
@Override
|
@Override
|
||||||
public void applyBlock(FilterBlock block) {
|
public void applyBlock(FilterBlock block) {
|
||||||
@ -209,12 +213,10 @@ public class Schematic {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
System.out.println("Rel " + relx + "," + rely + "," + relz + " | " + to + " | " + origin);
|
||||||
|
|
||||||
System.out.println("TODO optimize paste using above apply");
|
System.out.println("TODO optimize paste using above apply");
|
||||||
// Optimize for BlockArrayClipboard
|
|
||||||
// To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin)
|
|
||||||
final int relx = to.getBlockX() - origin.getBlockX();
|
|
||||||
final int rely = to.getBlockY() - origin.getBlockY();
|
|
||||||
final int relz = to.getBlockZ() - origin.getBlockZ();
|
|
||||||
Operation visitor = new RegionVisitor(region, new RegionFunction() {
|
Operation visitor = new RegionVisitor(region, new RegionFunction() {
|
||||||
// MutableBlockVector2 mpos2d_2 = new MutableBlockVector2();
|
// MutableBlockVector2 mpos2d_2 = new MutableBlockVector2();
|
||||||
MutableBlockVector2 mpos2d = new MutableBlockVector2();
|
MutableBlockVector2 mpos2d = new MutableBlockVector2();
|
||||||
@ -226,6 +228,7 @@ public class Schematic {
|
|||||||
@Override
|
@Override
|
||||||
public boolean apply(BlockVector3 mutable) throws WorldEditException {
|
public boolean apply(BlockVector3 mutable) throws WorldEditException {
|
||||||
BlockState block = clipboard.getBlock(mutable);
|
BlockState block = clipboard.getBlock(mutable);
|
||||||
|
System.out.println("Pos " + mutable);
|
||||||
int xx = mutable.getBlockX() + relx;
|
int xx = mutable.getBlockX() + relx;
|
||||||
int zz = mutable.getBlockZ() + relz;
|
int zz = mutable.getBlockZ() + relz;
|
||||||
if (copyBiomes && xx != mpos2d.getBlockX() && zz != mpos2d.getBlockZ()) {
|
if (copyBiomes && xx != mpos2d.getBlockX() && zz != mpos2d.getBlockZ()) {
|
||||||
@ -261,3 +264,4 @@ public class Schematic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,25 +20,104 @@
|
|||||||
package com.sk89q.worldedit.extent.clipboard.io;
|
package com.sk89q.worldedit.extent.clipboard.io;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.FaweCache;
|
||||||
import com.boydti.fawe.jnbt.CorruptSchematicStreamer;
|
import com.boydti.fawe.jnbt.CorruptSchematicStreamer;
|
||||||
import com.boydti.fawe.jnbt.SchematicStreamer;
|
import com.boydti.fawe.jnbt.SchematicStreamer;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import com.boydti.fawe.jnbt.streamer.InfoReader;
|
||||||
|
import com.boydti.fawe.jnbt.streamer.IntValueReader;
|
||||||
|
import com.boydti.fawe.jnbt.streamer.StreamDelegate;
|
||||||
|
import com.boydti.fawe.jnbt.streamer.ValueReader;
|
||||||
|
import com.boydti.fawe.object.FaweInputStream;
|
||||||
|
import com.boydti.fawe.object.FaweOutputStream;
|
||||||
|
import com.boydti.fawe.object.clipboard.LinearClipboard;
|
||||||
|
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||||
|
import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
|
import com.sk89q.jnbt.IntTag;
|
||||||
import com.sk89q.jnbt.NBTInputStream;
|
import com.sk89q.jnbt.NBTInputStream;
|
||||||
|
import com.sk89q.jnbt.StringTag;
|
||||||
|
import com.sk89q.jnbt.Tag;
|
||||||
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
|
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.EntityNBTCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.FlowerPotCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NBTCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.NoteBlockCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.Pre13HangingCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.SignCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.io.legacycompat.SkullBlockCompatibilityHandler;
|
||||||
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
|
import com.sk89q.worldedit.registry.state.PropertyKey;
|
||||||
|
import com.sk89q.worldedit.util.Direction;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
import com.sk89q.worldedit.world.DataFixer;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeType;
|
||||||
|
import com.sk89q.worldedit.world.biome.BiomeTypes;
|
||||||
|
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockCategories;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockID;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypeSwitch;
|
||||||
|
import com.sk89q.worldedit.world.block.BlockTypeSwitchBuilder;
|
||||||
|
import com.sk89q.worldedit.world.entity.EntityType;
|
||||||
|
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||||
|
import com.sk89q.worldedit.world.registry.BlockMaterial;
|
||||||
|
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||||
|
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||||
|
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads schematic files based that are compatible with MCEdit and other editors.
|
* Reads schematic files based that are compatible with MCEdit and other editors.
|
||||||
*/
|
*/
|
||||||
public class SchematicReader implements ClipboardReader {
|
public class SchematicReader implements ClipboardReader {
|
||||||
|
|
||||||
|
private static final NBTCompatibilityHandler[] COMPATIBILITY_HANDLERS = {
|
||||||
|
new SignCompatibilityHandler(),
|
||||||
|
new FlowerPotCompatibilityHandler(),
|
||||||
|
new NoteBlockCompatibilityHandler(),
|
||||||
|
new SkullBlockCompatibilityHandler()
|
||||||
|
};
|
||||||
|
private static final EntityNBTCompatibilityHandler[] ENTITY_COMPATIBILITY_HANDLERS = {
|
||||||
|
new Pre13HangingCompatibilityHandler()
|
||||||
|
};
|
||||||
|
|
||||||
private NBTInputStream inputStream;
|
private NBTInputStream inputStream;
|
||||||
private InputStream rootStream;
|
private InputStream rootStream;
|
||||||
|
|
||||||
|
// private final DataFixer fixer; TODO
|
||||||
|
|
||||||
|
private FastByteArrayOutputStream idOut = new FastByteArrayOutputStream();
|
||||||
|
private FastByteArrayOutputStream dataOut = new FastByteArrayOutputStream();
|
||||||
|
private FastByteArrayOutputStream addOut;
|
||||||
|
private FastByteArrayOutputStream biomesOut;
|
||||||
|
|
||||||
|
private FaweOutputStream ids;
|
||||||
|
private FaweOutputStream datas;
|
||||||
|
private FaweOutputStream adds;
|
||||||
|
private FaweOutputStream biomes;
|
||||||
|
|
||||||
|
private List<Map<String, Object>> tiles;
|
||||||
|
private List<Map<String, Object>> entities;
|
||||||
|
|
||||||
|
private int width, height, length;
|
||||||
|
private int offsetX, offsetY, offsetZ;
|
||||||
|
private int originX, originY, originZ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance.
|
* Create a new instance.
|
||||||
*
|
*
|
||||||
@ -53,21 +132,393 @@ public class SchematicReader implements ClipboardReader {
|
|||||||
this.rootStream = in;
|
this.rootStream = in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StreamDelegate createDelegate() {
|
||||||
|
StreamDelegate root = new StreamDelegate();
|
||||||
|
StreamDelegate schematic = root.add("Schematic");
|
||||||
|
schematic.add("Width").withInt((i, v) -> width = v);
|
||||||
|
schematic.add("Height").withInt((i, v) -> height = v);
|
||||||
|
schematic.add("Length").withInt((i, v) -> length = v);
|
||||||
|
|
||||||
|
schematic.add("WEOriginX").withInt((i, v) -> originX = v);
|
||||||
|
schematic.add("WEOriginY").withInt((i, v) -> originY = v);
|
||||||
|
schematic.add("WEOriginZ").withInt((i, v) -> originZ = v);
|
||||||
|
|
||||||
|
StreamDelegate metadata = schematic.add("Metadata");
|
||||||
|
metadata.add("WEOffsetX").withInt((i, v) -> offsetX = v);
|
||||||
|
metadata.add("WEOffsetY").withInt((i, v) -> offsetY = v);
|
||||||
|
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
||||||
|
|
||||||
|
StreamDelegate blocksDelegate = schematic.add("Blocks");
|
||||||
|
blocksDelegate.withInfo((length, type) -> ids = new FaweOutputStream(new LZ4BlockOutputStream(idOut)));
|
||||||
|
blocksDelegate.withInt((index, value) -> ids.write(value));
|
||||||
|
|
||||||
|
StreamDelegate dataDelegate = schematic.add("Data");
|
||||||
|
dataDelegate.withInfo((length, type) -> datas = new FaweOutputStream(new LZ4BlockOutputStream(dataOut)));
|
||||||
|
dataDelegate.withInt((index, value) -> datas.write(value));
|
||||||
|
|
||||||
|
StreamDelegate addDelegate = schematic.add("AddBlocks");
|
||||||
|
addDelegate.withInfo((length, type) -> {
|
||||||
|
addOut = new FastByteArrayOutputStream();
|
||||||
|
adds = new FaweOutputStream(new LZ4BlockOutputStream(addOut));
|
||||||
|
});
|
||||||
|
addDelegate.withInt((index, value) -> {
|
||||||
|
if (value != 0) {
|
||||||
|
int first = value & 0x0F;
|
||||||
|
int second = (value & 0xF0) >> 4;
|
||||||
|
adds.write(first);
|
||||||
|
adds.write(second);
|
||||||
|
} else {
|
||||||
|
adds.write(0);
|
||||||
|
adds.write(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
StreamDelegate biomesDelegate = schematic.add("Biomes");
|
||||||
|
StreamDelegate aweBiomesDelegate = schematic.add("AWEBiomes");
|
||||||
|
|
||||||
|
InfoReader biomesInfo = (l, t) -> {
|
||||||
|
biomesOut = new FastByteArrayOutputStream();
|
||||||
|
biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut));
|
||||||
|
};
|
||||||
|
biomesDelegate.withInfo(biomesInfo);
|
||||||
|
aweBiomesDelegate.withInfo(biomesInfo);
|
||||||
|
|
||||||
|
IntValueReader biomeReader = (index, value) -> biomes.write(value);
|
||||||
|
biomesDelegate.withInt(biomeReader);
|
||||||
|
|
||||||
|
|
||||||
|
StreamDelegate tilesDelegate = schematic.add("TileEntities");
|
||||||
|
tilesDelegate.withInfo((length, type) -> tiles = new ArrayList<>(length));
|
||||||
|
tilesDelegate.withElem(new ValueReader<Map<String, Object>>() {
|
||||||
@Override
|
@Override
|
||||||
public Clipboard read() throws IOException {
|
public void apply(int index, Map<String, Object> tile) {
|
||||||
return read(UUID.randomUUID());
|
tiles.add(tile);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
StreamDelegate entitiesDelegate = schematic.add("Entities");
|
||||||
|
entitiesDelegate.withInfo((length, type) -> entities = new ArrayList<>(length));
|
||||||
|
entitiesDelegate.withElem(new ValueReader<Map<String, Object>>() {
|
||||||
|
@Override
|
||||||
|
public void apply(int index, Map<String, Object> entity) {
|
||||||
|
entities.add(entity);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Clipboard read(final UUID clipboardId) throws IOException {
|
private int readCombined(InputStream idIn, InputStream dataIn) throws IOException {
|
||||||
try {
|
return ((idIn.read() & 0xFF) << 4) + (dataIn.read() & 0xF);
|
||||||
return new SchematicStreamer(inputStream, clipboardId).getClipboard();
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
Fawe.debug("Input is corrupt!");
|
private int readCombined(InputStream idIn, InputStream dataIn, InputStream addIn) throws IOException {
|
||||||
e.printStackTrace();
|
return ((addIn.read() & 0xFF) << 8) + readCombined(idIn, dataIn);
|
||||||
return new CorruptSchematicStreamer(rootStream, clipboardId).recover();
|
}
|
||||||
|
|
||||||
|
private BlockState getBlock(int combined) {
|
||||||
|
BlockState state = LegacyMapper.getInstance().getBlockFromLegacyCombinedId(combined);
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write(int index, BlockState block, LinearClipboard clipboard) {
|
||||||
|
clipboard.setBlock(index, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void write(int x, int y, int z, BlockState block, Clipboard clipboard) {
|
||||||
|
clipboard.setBlock(x, y, z, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readwrite(int index, InputStream idIn, InputStream dataIn, LinearClipboard out) throws IOException {
|
||||||
|
readwrite(index, readCombined(idIn, dataIn), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readwrite(int x, int y, int z, InputStream idIn, InputStream dataIn, Clipboard out) throws IOException {
|
||||||
|
readwrite(x, y, z, readCombined(idIn, dataIn), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readwrite(int index, InputStream idIn, InputStream dataIn, InputStream addIn, LinearClipboard out) throws IOException {
|
||||||
|
readwrite(index, readCombined(idIn, dataIn, addIn), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readwrite(int x, int y, int z, InputStream idIn, InputStream dataIn, InputStream addIn, Clipboard out) throws IOException {
|
||||||
|
readwrite(x, y, z, readCombined(idIn, dataIn, addIn), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readwrite(int index, int combined, LinearClipboard out) throws IOException {
|
||||||
|
write(index, getBlock(combined), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readwrite(int x, int y, int z, int combined, Clipboard out) throws IOException {
|
||||||
|
write(x, y, z, getBlock(combined), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Clipboard read(UUID uuid, Function<BlockVector3, Clipboard> createOutput) throws IOException {
|
||||||
|
StreamDelegate root = createDelegate();
|
||||||
|
inputStream.readNamedTagLazy(root);
|
||||||
|
|
||||||
|
if (ids != null) ids.close();
|
||||||
|
if (datas != null) datas.close();
|
||||||
|
if (adds != null) adds.close();
|
||||||
|
if (biomes != null) biomes.close();
|
||||||
|
ids = null;
|
||||||
|
datas = null;
|
||||||
|
adds = null;
|
||||||
|
biomes = null;
|
||||||
|
|
||||||
|
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
||||||
|
BlockVector3 origin = BlockVector3.at(originX, originY, originZ);
|
||||||
|
if (offsetX != Integer.MIN_VALUE && offsetY != Integer.MIN_VALUE && offsetZ != Integer.MIN_VALUE) {
|
||||||
|
origin = origin.subtract(BlockVector3.at(offsetX, offsetY, offsetZ));
|
||||||
|
}
|
||||||
|
|
||||||
|
Clipboard clipboard = createOutput.apply(dimensions);
|
||||||
|
try (InputStream dataIn = new LZ4BlockInputStream(new FastByteArraysInputStream(dataOut.toByteArrays()));InputStream idIn = new LZ4BlockInputStream(new FastByteArraysInputStream(idOut.toByteArrays()))) {
|
||||||
|
if (addOut != null) {
|
||||||
|
try (FaweInputStream addIn = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(addOut.toByteArrays())))) {
|
||||||
|
if (clipboard instanceof LinearClipboard) {
|
||||||
|
LinearClipboard linear = (LinearClipboard) clipboard;
|
||||||
|
for (int y = 0, index = 0; y < height; y++) {
|
||||||
|
for (int z = 0; z < length; z++) {
|
||||||
|
for (int x = 0; x < width; x++, index++) {
|
||||||
|
readwrite(index, idIn, dataIn, addIn, linear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int z = 0; z < length; z++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
readwrite(x, y, z, idIn, dataIn, addIn, clipboard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (clipboard instanceof LinearClipboard) {
|
||||||
|
LinearClipboard linear = (LinearClipboard) clipboard;
|
||||||
|
for (int y = 0, index = 0; y < height; y++) {
|
||||||
|
for (int z = 0; z < length; z++) {
|
||||||
|
for (int x = 0; x < width; x++, index++) {
|
||||||
|
readwrite(index, idIn, dataIn, linear);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
for (int z = 0; z < length; z++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
readwrite(x, y, z, idIn, dataIn, clipboard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (biomes != null) {
|
||||||
|
try (InputStream biomesIn = new LZ4BlockInputStream(new FastByteArraysInputStream(biomesOut.toByteArrays()))) {
|
||||||
|
if (clipboard instanceof LinearClipboard) {
|
||||||
|
LinearClipboard linear = (LinearClipboard) clipboard;
|
||||||
|
int volume = width * length;
|
||||||
|
for (int index = 0; index < volume; index++) {
|
||||||
|
BiomeType biome = BiomeTypes.getLegacy(biomesIn.read());
|
||||||
|
if (biome != null) linear.setBiome(index, biome);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int z = 0; z < length; z++) {
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
BiomeType biome = BiomeTypes.getLegacy(biomesIn.read());
|
||||||
|
if (biome != null) clipboard.setBiome(x, 0, z, biome);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tiles
|
||||||
|
if (tiles != null && !tiles.isEmpty()) {
|
||||||
|
outer:
|
||||||
|
for (Map<String, Object> tileRaw : tiles) {
|
||||||
|
CompoundTag tile = FaweCache.IMP.asTag(tileRaw);
|
||||||
|
int x = (int) tileRaw.get("x");
|
||||||
|
int y = (int) tileRaw.get("y");
|
||||||
|
int z = (int) tileRaw.get("z");
|
||||||
|
|
||||||
|
BlockState block = clipboard.getBlock(x, y, z);
|
||||||
|
for (NBTCompatibilityHandler compat : COMPATIBILITY_HANDLERS) {
|
||||||
|
if (compat.isAffectedBlock(block)) {
|
||||||
|
block = compat.updateNBT(block, tile.getValue());
|
||||||
|
BaseBlock baseBlock = block.toBaseBlock(tile);
|
||||||
|
clipboard.setBlock(x, y, z, baseBlock);
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clipboard.setTile(x, y, z, tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// entities
|
||||||
|
if (entities != null && !entities.isEmpty()) {
|
||||||
|
for (Map<String, Object> entRaw : entities) {
|
||||||
|
String id = (String) entRaw.get("id");
|
||||||
|
if (id == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
entRaw.put("Id", id);
|
||||||
|
EntityType type = EntityTypes.parse(id);
|
||||||
|
if (type != null) {
|
||||||
|
CompoundTag ent = FaweCache.IMP.asTag(entRaw);
|
||||||
|
for (EntityNBTCompatibilityHandler compat : ENTITY_COMPATIBILITY_HANDLERS) {
|
||||||
|
if (compat.isAffectedEntity(type, ent)) {
|
||||||
|
ent = compat.updateNBT(type, ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BaseEntity state = new BaseEntity(type, ent);
|
||||||
|
Location loc = ent.getEntityLocation(clipboard);
|
||||||
|
clipboard.createEntity(loc, state);
|
||||||
|
} else {
|
||||||
|
Fawe.debug("Invalid entity: " + id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fixStates(clipboard);
|
||||||
|
clipboard.setOrigin(origin);
|
||||||
|
return clipboard;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fixStates(Clipboard fc) {
|
||||||
|
for (BlockVector3 pos : fc) {
|
||||||
|
BlockState block = pos.getBlock(fc);
|
||||||
|
if (block.getMaterial().isAir()) continue;
|
||||||
|
|
||||||
|
int x = pos.getX();
|
||||||
|
int y = pos.getY();
|
||||||
|
int z = pos.getZ();
|
||||||
|
|
||||||
|
BlockType type = block.getBlockType();
|
||||||
|
if (BlockCategories.STAIRS.contains(type)) {
|
||||||
|
Direction facing = block.getState(PropertyKey.FACING);
|
||||||
|
|
||||||
|
BlockVector3 forward = facing.toBlockVector();
|
||||||
|
Direction left = facing.getLeft();
|
||||||
|
Direction right = facing.getRight();
|
||||||
|
|
||||||
|
BlockStateHolder forwardBlock = fc.getBlock(x + forward.getBlockX(), y + forward.getBlockY(), z + forward.getBlockZ());
|
||||||
|
BlockType forwardType = forwardBlock.getBlockType();
|
||||||
|
if (forwardType.hasProperty(PropertyKey.SHAPE) && forwardType.hasProperty(PropertyKey.FACING)) {
|
||||||
|
Direction forwardFacing = (Direction) forwardBlock.getState(PropertyKey.FACING);
|
||||||
|
if (forwardFacing == left) {
|
||||||
|
BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
|
||||||
|
BlockType rightType = rightBlock.getBlockType();
|
||||||
|
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
|
||||||
|
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "inner_left"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (forwardFacing == right) {
|
||||||
|
BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
|
||||||
|
BlockType leftType = leftBlock.getBlockType();
|
||||||
|
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
|
||||||
|
fc.setBlock(x, y, z, block.with(PropertyKey.SHAPE, "inner_right"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockState backwardsBlock = fc.getBlock(x - forward.getBlockX(), y - forward.getBlockY(), z - forward.getBlockZ());
|
||||||
|
BlockType backwardsType = backwardsBlock.getBlockType();
|
||||||
|
if (backwardsType.hasProperty(PropertyKey.SHAPE) && backwardsType.hasProperty(PropertyKey.FACING)) {
|
||||||
|
Direction backwardsFacing = (Direction) backwardsBlock.getState(PropertyKey.FACING);
|
||||||
|
if (backwardsFacing == left) {
|
||||||
|
BlockState rightBlock = fc.getBlock(x + right.toBlockVector().getBlockX(), y + right.toBlockVector().getBlockY(), z + right.toBlockVector().getBlockZ());
|
||||||
|
BlockType rightType = rightBlock.getBlockType();
|
||||||
|
if (!rightType.hasProperty(PropertyKey.SHAPE) || rightBlock.getState(PropertyKey.FACING) != facing) {
|
||||||
|
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_left"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (backwardsFacing == right) {
|
||||||
|
BlockState leftBlock = fc.getBlock(x + left.toBlockVector().getBlockX(), y + left.toBlockVector().getBlockY(), z + left.toBlockVector().getBlockZ());
|
||||||
|
BlockType leftType = leftBlock.getBlockType();
|
||||||
|
if (!leftType.hasProperty(PropertyKey.SHAPE) || leftBlock.getState(PropertyKey.FACING) != facing) {
|
||||||
|
pos.setBlock(fc, block.with(PropertyKey.SHAPE, "outer_right"));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int group = group(type);
|
||||||
|
if (group == -1) return;
|
||||||
|
BlockState set = block;
|
||||||
|
|
||||||
|
if (set.getState(PropertyKey.NORTH) == Boolean.FALSE && merge(fc, group, x, y, z - 1)) set = set.with(PropertyKey.NORTH, true);
|
||||||
|
if (set.getState(PropertyKey.EAST) == Boolean.FALSE && merge(fc, group, x + 1, y, z)) set = set.with(PropertyKey.EAST, true);
|
||||||
|
if (set.getState(PropertyKey.SOUTH) == Boolean.FALSE && merge(fc, group, x, y, z + 1)) set = set.with(PropertyKey.SOUTH, true);
|
||||||
|
if (set.getState(PropertyKey.WEST) == Boolean.FALSE && merge(fc, group, x - 1, y, z)) set = set.with(PropertyKey.WEST, true);
|
||||||
|
|
||||||
|
if (group == 2) {
|
||||||
|
int ns = ((Boolean) set.getState(PropertyKey.NORTH) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.SOUTH) ? 1 : 0);
|
||||||
|
int ew = ((Boolean) set.getState(PropertyKey.EAST) ? 1 : 0) + ((Boolean) set.getState(PropertyKey.WEST) ? 1 : 0);
|
||||||
|
if (Math.abs(ns - ew) != 2 || fc.getBlock(x, y + 1, z).getBlockType().getMaterial().isSolid()) {
|
||||||
|
set = set.with(PropertyKey.UP, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (set != block) pos.setBlock(fc, set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private BlockTypeSwitch<Boolean> fullCube = new BlockTypeSwitchBuilder<>(false).add(type -> {
|
||||||
|
BlockMaterial mat = type.getMaterial();
|
||||||
|
return (mat.isFullCube() && !mat.isFragileWhenPushed() && mat.getLightValue() == 0 && mat.isOpaque() && mat.isSolid() && !mat.isTranslucent());
|
||||||
|
}, true).build();
|
||||||
|
|
||||||
|
private boolean merge(Clipboard fc, int group, int x, int y, int z) {
|
||||||
|
BlockState block = fc.getBlock(x, y, z);
|
||||||
|
BlockType type = block.getBlockType();
|
||||||
|
return group(type) == group || fullCube.apply(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int group(BlockType type) {
|
||||||
|
switch (type.getInternalId()) {
|
||||||
|
case BlockID.ACACIA_FENCE:
|
||||||
|
case BlockID.BIRCH_FENCE:
|
||||||
|
case BlockID.DARK_OAK_FENCE:
|
||||||
|
case BlockID.JUNGLE_FENCE:
|
||||||
|
case BlockID.OAK_FENCE:
|
||||||
|
case BlockID.SPRUCE_FENCE:
|
||||||
|
return 0;
|
||||||
|
case BlockID.NETHER_BRICK_FENCE:
|
||||||
|
return 1;
|
||||||
|
case BlockID.COBBLESTONE_WALL:
|
||||||
|
case BlockID.MOSSY_COBBLESTONE_WALL:
|
||||||
|
return 2;
|
||||||
|
case BlockID.IRON_BARS:
|
||||||
|
case BlockID.BLACK_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.BLUE_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.BROWN_MUSHROOM_BLOCK:
|
||||||
|
case BlockID.BROWN_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.CYAN_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.GLASS_PANE:
|
||||||
|
case BlockID.GRAY_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.GREEN_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.LIGHT_BLUE_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.LIGHT_GRAY_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.LIME_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.MAGENTA_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.ORANGE_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.PINK_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.PURPLE_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.RED_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.WHITE_STAINED_GLASS_PANE:
|
||||||
|
case BlockID.YELLOW_STAINED_GLASS_PANE:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
|
@ -82,6 +82,21 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
private DataFixer fixer = null;
|
private DataFixer fixer = null;
|
||||||
private int dataVersion = -1;
|
private int dataVersion = -1;
|
||||||
|
|
||||||
|
private FastByteArrayOutputStream blocksOut;
|
||||||
|
private FaweOutputStream blocks;
|
||||||
|
|
||||||
|
private FastByteArrayOutputStream biomesOut;
|
||||||
|
private FaweOutputStream biomes;
|
||||||
|
|
||||||
|
private List<Map<String, Object>> tiles;
|
||||||
|
private List<Map<String, Object>> entities;
|
||||||
|
|
||||||
|
private int width, height, length;
|
||||||
|
private int offsetX, offsetY, offsetZ;
|
||||||
|
private char[] palette, biomePalette;
|
||||||
|
private BlockVector3 min;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance.
|
* Create a new instance.
|
||||||
*
|
*
|
||||||
@ -92,11 +107,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
this.inputStream = inputStream;
|
this.inputStream = inputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int width, height, length;
|
|
||||||
private int offsetX, offsetY, offsetZ;
|
|
||||||
private char[] palette, biomePalette;
|
|
||||||
private BlockVector3 min;
|
|
||||||
|
|
||||||
private String fix(String palettePart) {
|
private String fix(String palettePart) {
|
||||||
if (fixer == null || dataVersion == -1) return palettePart;
|
if (fixer == null || dataVersion == -1) return palettePart;
|
||||||
return fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
|
return fixer.fixUp(DataFixer.FixTypes.BLOCK_STATE, palettePart, dataVersion);
|
||||||
@ -112,15 +122,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
return fixer.fixUp(DataFixer.FixTypes.ENTITY, tag, dataVersion);
|
return fixer.fixUp(DataFixer.FixTypes.ENTITY, tag, dataVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private FastByteArrayOutputStream blocksOut;
|
|
||||||
private FaweOutputStream blocks;
|
|
||||||
|
|
||||||
private FastByteArrayOutputStream biomesOut;
|
|
||||||
private FaweOutputStream biomes;
|
|
||||||
|
|
||||||
private List<Map<String, Object>> tiles;
|
|
||||||
private List<Map<String, Object>> entities;
|
|
||||||
|
|
||||||
public StreamDelegate createDelegate() {
|
public StreamDelegate createDelegate() {
|
||||||
StreamDelegate root = new StreamDelegate();
|
StreamDelegate root = new StreamDelegate();
|
||||||
StreamDelegate schematic = root.add("Schematic");
|
StreamDelegate schematic = root.add("Schematic");
|
||||||
@ -136,15 +137,12 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
metadata.add("WEOffsetZ").withInt((i, v) -> offsetZ = v);
|
||||||
|
|
||||||
StreamDelegate paletteDelegate = schematic.add("Palette");
|
StreamDelegate paletteDelegate = schematic.add("Palette");
|
||||||
paletteDelegate.withValue(new ValueReader<Map<String, Object>>() {
|
paletteDelegate.withValue((ValueReader<Map<String, Object>>) (ignore, v) -> {
|
||||||
@Override
|
|
||||||
public void apply(int ignore, Map<String, Object> v) {
|
|
||||||
palette = new char[v.size()];
|
palette = new char[v.size()];
|
||||||
for (Map.Entry<String, Object> entry : v.entrySet()) {
|
for (Entry<String, Object> entry : v.entrySet()) {
|
||||||
BlockState state = null;
|
BlockState state = null;
|
||||||
try {
|
try {
|
||||||
String palettePart = entry.getKey();
|
String palettePart = fix(entry.getKey());
|
||||||
palettePart = fix(entry.getKey());
|
|
||||||
state = BlockState.get(palettePart);
|
state = BlockState.get(palettePart);
|
||||||
} catch (InputParseException e) {
|
} catch (InputParseException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -152,65 +150,34 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
int index = (int) entry.getValue();
|
int index = (int) entry.getValue();
|
||||||
palette[index] = (char) state.getOrdinal();
|
palette[index] = (char) state.getOrdinal();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
StreamDelegate blockData = schematic.add("BlockData");
|
StreamDelegate blockData = schematic.add("BlockData");
|
||||||
blockData.withInfo((length, type) -> {
|
blockData.withInfo((length, type) -> {
|
||||||
blocksOut = new FastByteArrayOutputStream();
|
blocksOut = new FastByteArrayOutputStream();
|
||||||
blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
|
blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
|
||||||
});
|
});
|
||||||
blockData.withInt(new IntValueReader() {
|
blockData.withInt((index, value) -> blocks.writeVarInt(value));
|
||||||
@Override
|
|
||||||
public void applyInt(int index, int value) {
|
|
||||||
try {
|
|
||||||
blocks.writeVarInt(value);
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
StreamDelegate tilesDelegate = schematic.add("TileEntities");
|
StreamDelegate tilesDelegate = schematic.add("TileEntities");
|
||||||
tilesDelegate.withInfo((length, type) -> tiles = new ArrayList<>(length));
|
tilesDelegate.withInfo((length, type) -> tiles = new ArrayList<>(length));
|
||||||
tilesDelegate.withElem(new ValueReader<Map<String, Object>>() {
|
tilesDelegate.withElem((ValueReader<Map<String, Object>>) (index, tile) -> tiles.add(tile));
|
||||||
@Override
|
|
||||||
public void apply(int index, Map<String, Object> tile) {
|
|
||||||
tiles.add(tile);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
StreamDelegate entitiesDelegate = schematic.add("Entities");
|
StreamDelegate entitiesDelegate = schematic.add("Entities");
|
||||||
entitiesDelegate.withInfo((length, type) -> entities = new ArrayList<>(length));
|
entitiesDelegate.withInfo((length, type) -> entities = new ArrayList<>(length));
|
||||||
entitiesDelegate.withElem(new ValueReader<Map<String, Object>>() {
|
entitiesDelegate.withElem((ValueReader<Map<String, Object>>) (index, entity) -> entities.add(entity));
|
||||||
@Override
|
|
||||||
public void apply(int index, Map<String, Object> entity) {
|
|
||||||
entities.add(entity);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
StreamDelegate biomeData = schematic.add("BiomeData");
|
StreamDelegate biomeData = schematic.add("BiomeData");
|
||||||
biomeData.withInfo(new InfoReader() {
|
biomeData.withInfo((length, type) -> {
|
||||||
@Override
|
|
||||||
public void apply(int length, int type) {
|
|
||||||
biomesOut = new FastByteArrayOutputStream();
|
biomesOut = new FastByteArrayOutputStream();
|
||||||
biomes = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
|
biomes = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
biomeData.withElem(new IntValueReader() {
|
biomeData.withElem((IntValueReader) (index, value) -> {
|
||||||
@Override
|
|
||||||
public void applyInt(int index, int value) {
|
|
||||||
try {
|
try {
|
||||||
biomes.write(value); // byte of varInt
|
biomes.write(value); // byte of varInt
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
StreamDelegate biomePaletteDelegate = schematic.add("BiomePalette");
|
StreamDelegate biomePaletteDelegate = schematic.add("BiomePalette");
|
||||||
biomePaletteDelegate.withInfo(new InfoReader() {
|
biomePaletteDelegate.withInfo((length, type) -> biomePalette = new char[length]);
|
||||||
@Override
|
|
||||||
public void apply(int length, int type) {
|
|
||||||
biomePalette = new char[length];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
biomePaletteDelegate.withElem(new ValueReader<Map.Entry<String, Number>>() {
|
biomePaletteDelegate.withElem(new ValueReader<Map.Entry<String, Number>>() {
|
||||||
@Override
|
@Override
|
||||||
public void apply(int index, Map.Entry<String, Number> palettePart) {
|
public void apply(int index, Map.Entry<String, Number> palettePart) {
|
||||||
@ -220,7 +187,7 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
}
|
}
|
||||||
BiomeType biome = BiomeTypes.get(key);
|
BiomeType biome = BiomeTypes.get(key);
|
||||||
if (biome == null) {
|
if (biome == null) {
|
||||||
System.out.println("Unknown biome " + key);
|
System. out.println("Unknown biome " + key);
|
||||||
biome = BiomeTypes.FOREST;
|
biome = BiomeTypes.FOREST;
|
||||||
}
|
}
|
||||||
int paletteIndex = palettePart.getValue().intValue();
|
int paletteIndex = palettePart.getValue().intValue();
|
||||||
@ -244,13 +211,19 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
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();
|
||||||
inputStream.readNamedTagLazy(root);
|
inputStream.readNamedTagLazy(root);
|
||||||
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
if (blocks != null) blocks.close();
|
||||||
Clipboard clipboard = createOutput.apply(dimensions);
|
if (biomes != null) biomes.close();
|
||||||
|
blocks = null;
|
||||||
|
biomes = null;
|
||||||
|
|
||||||
|
BlockVector3 dimensions = BlockVector3.at(width, height, length);
|
||||||
BlockVector3 origin = min;
|
BlockVector3 origin = min;
|
||||||
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 = origin.subtract(BlockVector3.at(offsetX, offsetY, offsetZ));
|
origin = origin.subtract(BlockVector3.at(offsetX, offsetY, offsetZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Clipboard clipboard = createOutput.apply(dimensions);
|
||||||
|
|
||||||
if (blocksOut != null && blocksOut.getSize() != 0) {
|
if (blocksOut != null && blocksOut.getSize() != 0) {
|
||||||
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
|
try (FaweInputStream fis = new FaweInputStream(new LZ4BlockInputStream(new FastByteArraysInputStream(blocksOut.toByteArrays())))) {
|
||||||
if (clipboard instanceof LinearClipboard) {
|
if (clipboard instanceof LinearClipboard) {
|
||||||
@ -311,7 +284,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
int[] pos = tile.getIntArray("Pos");
|
int[] pos = tile.getIntArray("Pos");
|
||||||
int x,y,z;
|
int x,y,z;
|
||||||
if (pos.length != 3) {
|
if (pos.length != 3) {
|
||||||
System.out.println("Invalid tile " + tile);
|
|
||||||
if (!tile.containsKey("x") || !tile.containsKey("y") || !tile.containsKey("z")) {
|
if (!tile.containsKey("x") || !tile.containsKey("y") || !tile.containsKey("z")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -371,109 +343,6 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
|||||||
return clipboard;
|
return clipboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
private Clipboard readVersion2(BlockArrayClipboard version1, CompoundTag schematicTag) throws IOException {
|
|
||||||
Map<String, Tag> schematic = schematicTag.getValue();
|
|
||||||
if (schematic.containsKey("BiomeData")) {
|
|
||||||
readBiomes(version1, schematic);
|
|
||||||
}
|
|
||||||
if (schematic.containsKey("Entities")) {
|
|
||||||
readEntities(version1, schematic);
|
|
||||||
}
|
|
||||||
return version1;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private void readBiomes(BlockArrayClipboard clipboard, Map<String, Tag> schematic) throws IOException {
|
|
||||||
ByteArrayTag dataTag = requireTag(schematic, "BiomeData", ByteArrayTag.class);
|
|
||||||
IntTag maxTag = requireTag(schematic, "BiomePaletteMax", IntTag.class);
|
|
||||||
CompoundTag paletteTag = requireTag(schematic, "BiomePalette", CompoundTag.class);
|
|
||||||
|
|
||||||
Map<Integer, BiomeType> palette = new HashMap<>();
|
|
||||||
if (maxTag.getValue() != paletteTag.getValue().size()) {
|
|
||||||
throw new IOException("Biome palette size does not match expected size.");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Entry<String, Tag> palettePart : paletteTag.getValue().entrySet()) {
|
|
||||||
String key = palettePart.getKey();
|
|
||||||
if (fixer != null) {
|
|
||||||
key = fixer.fixUp(DataFixer.FixTypes.BIOME, key, dataVersion);
|
|
||||||
}
|
|
||||||
BiomeType biome = BiomeTypes.get(key);
|
|
||||||
if (biome == null) {
|
|
||||||
log.warn("Unknown biome type :" + key +
|
|
||||||
" in palette. Are you missing a mod or using a schematic made in a newer version of Minecraft?");
|
|
||||||
}
|
|
||||||
Tag idTag = palettePart.getValue();
|
|
||||||
if (!(idTag instanceof IntTag)) {
|
|
||||||
throw new IOException("Biome mapped to non-Int tag.");
|
|
||||||
}
|
|
||||||
palette.put(((IntTag) idTag).getValue(), biome);
|
|
||||||
}
|
|
||||||
|
|
||||||
int width = clipboard.getDimensions().getX();
|
|
||||||
|
|
||||||
byte[] biomes = dataTag.getValue();
|
|
||||||
int biomeIndex = 0;
|
|
||||||
int biomeJ = 0;
|
|
||||||
int bVal;
|
|
||||||
int varIntLength;
|
|
||||||
BlockVector2 min = clipboard.getMinimumPoint().toBlockVector2();
|
|
||||||
while (biomeJ < biomes.length) {
|
|
||||||
bVal = 0;
|
|
||||||
varIntLength = 0;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
bVal |= (biomes[biomeJ] & 127) << (varIntLength++ * 7);
|
|
||||||
if (varIntLength > 5) {
|
|
||||||
throw new IOException("VarInt too big (probably corrupted data)");
|
|
||||||
}
|
|
||||||
if (((biomes[biomeJ] & 128) != 128)) {
|
|
||||||
biomeJ++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
biomeJ++;
|
|
||||||
}
|
|
||||||
int z = biomeIndex / width;
|
|
||||||
int x = biomeIndex % width;
|
|
||||||
BiomeType type = palette.get(bVal);
|
|
||||||
clipboard.setBiome(min.add(x, z), type);
|
|
||||||
biomeIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
private void readEntities(BlockArrayClipboard clipboard, Map<String, Tag> schematic) throws IOException {
|
|
||||||
List<Tag> entList = requireTag(schematic, "Entities", ListTag.class).getValue();
|
|
||||||
if (entList.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (Tag et : entList) {
|
|
||||||
if (!(et instanceof CompoundTag)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
CompoundTag entityTag = (CompoundTag) et;
|
|
||||||
Map<String, Tag> tags = entityTag.getValue();
|
|
||||||
String id = requireTag(tags, "Id", StringTag.class).getValue();
|
|
||||||
entityTag = entityTag.createBuilder().putString("id", id).remove("Id").build();
|
|
||||||
|
|
||||||
if (fixer != null) {
|
|
||||||
entityTag = fixer.fixUp(DataFixer.FixTypes.ENTITY, entityTag, dataVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityType entityType = EntityTypes.get(id);
|
|
||||||
if (entityType != null) {
|
|
||||||
Location location = NBTConversions.toLocation(clipboard,
|
|
||||||
requireTag(tags, "Pos", ListTag.class),
|
|
||||||
requireTag(tags, "Rotation", ListTag.class));
|
|
||||||
BaseEntity state = new BaseEntity(entityType, entityTag);
|
|
||||||
clipboard.createEntity(location, state);
|
|
||||||
} else {
|
|
||||||
log.warn("Unknown entity when pasting schematic: " + id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
inputStream.close();
|
inputStream.close();
|
||||||
|
@ -57,7 +57,7 @@ import java.util.Map;
|
|||||||
public final class LegacyMapper {
|
public final class LegacyMapper {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(LegacyMapper.class);
|
private static final Logger log = LoggerFactory.getLogger(LegacyMapper.class);
|
||||||
private static LegacyMapper INSTANCE;
|
private static LegacyMapper INSTANCE = new LegacyMapper();
|
||||||
|
|
||||||
private final Int2ObjectArrayMap<Integer> blockStateToLegacyId4Data = new Int2ObjectArrayMap<>();
|
private final Int2ObjectArrayMap<Integer> blockStateToLegacyId4Data = new Int2ObjectArrayMap<>();
|
||||||
private final Int2ObjectArrayMap<Integer> extraId4DataToStateId = new Int2ObjectArrayMap<>();
|
private final Int2ObjectArrayMap<Integer> extraId4DataToStateId = new Int2ObjectArrayMap<>();
|
||||||
@ -267,10 +267,7 @@ public final class LegacyMapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LegacyMapper getInstance() {
|
public final static LegacyMapper getInstance() {
|
||||||
if (INSTANCE == null) {
|
|
||||||
INSTANCE = new LegacyMapper();
|
|
||||||
}
|
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren