optimized biome streaming to schematics

Dieser Commit ist enthalten in:
Jesse Boyd 2019-07-18 22:36:50 +10:00
Ursprung be9430a92f
Commit 22a7ad7503
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 59F1DE6293AF6E1F
4 geänderte Dateien mit 74 neuen und 42 gelöschten Zeilen

Datei anzeigen

@ -37,6 +37,14 @@ public final class IOUtil {
return i; return i;
} }
public static void writeVarInt(OutputStream out, int value) throws IOException {
while ((value & -128) != 0) {
out.write(value & 127 | 128);
value >>>= 7;
}
out.write(value);
}
public static void copy(InputStream in, OutputStream out) throws IOException { public static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[8192]; byte[] buf = new byte[8192];
while (true) { while (true) {

Datei anzeigen

@ -127,6 +127,7 @@ import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.SimpleWorld;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -166,7 +167,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* using the {@link ChangeSetExtent}.</p> * using the {@link ChangeSetExtent}.</p>
*/ */
@SuppressWarnings({"FieldCanBeLocal"}) @SuppressWarnings({"FieldCanBeLocal"})
public class EditSession extends AbstractDelegateExtent SimpleWorld, AutoCloseable { public class EditSession extends AbstractDelegateExtent implements SimpleWorld, AutoCloseable {
private static final Logger log = LoggerFactory.getLogger(EditSession.class); private static final Logger log = LoggerFactory.getLogger(EditSession.class);

Datei anzeigen

@ -19,6 +19,7 @@
package com.sk89q.worldedit.extent.clipboard.io; package com.sk89q.worldedit.extent.clipboard.io;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.clipboard.FaweClipboard; import com.boydti.fawe.object.clipboard.FaweClipboard;
import com.boydti.fawe.util.IOUtil; import com.boydti.fawe.util.IOUtil;
@ -37,6 +38,7 @@ import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location; 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.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
@ -51,11 +53,13 @@ import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.IntStream;
/** /**
* Writes schematic files using the Sponge schematic format. * Writes schematic files using the Sponge schematic format.
@ -175,11 +179,7 @@ public class SpongeSchematicWriter implements ClipboardWriter {
palette[ordinal] = value = (char) size; palette[ordinal] = value = (char) size;
paletteList.add(ordinal); paletteList.add(ordinal);
} }
while ((value & -128) != 0) { IOUtil.writeVarInt(blocksOut, value);
blocksOut.write(value & 127 | 128);
value >>>= 7;
}
blocksOut.write(value);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -231,7 +231,6 @@ public class SpongeSchematicWriter implements ClipboardWriter {
writeBiomes(clipboard, out); writeBiomes(clipboard, out);
} }
TODO optimize
List<Tag> entities = new ArrayList<>(); List<Tag> entities = new ArrayList<>();
for (Entity entity : clipboard.getEntities()) { for (Entity entity : clipboard.getEntities()) {
BaseEntity state = entity.getState(); BaseEntity state = entity.getState();
@ -263,49 +262,63 @@ public class SpongeSchematicWriter implements ClipboardWriter {
}); });
} }
private void writeBiomes(Clipboard clipboard, NBTOutputStream schematic) throws IOException { private void writeBiomes(Clipboard clipboard, NBTOutputStream out) throws IOException {
TODO optimize ByteArrayOutputStream biomesCompressed = new ByteArrayOutputStream();
DataOutputStream biomesOut = new DataOutputStream(new LZ4BlockOutputStream(biomesCompressed));
List<Integer> paletteList = new ArrayList<>();
int[] palette = new int[BiomeTypes.getMaxId() + 1];
Arrays.fill(palette, Integer.MAX_VALUE);
int[] paletteMax = {0};
NBTStreamer.ByteReader task = new NBTStreamer.ByteReader() {
@Override
public void run(int index, int ordinal) {
try {
int value = palette[ordinal];
if (value == Integer.MAX_VALUE) {
int size = paletteMax[0]++;
palette[ordinal] = value = size;
paletteList.add(ordinal);
}
IOUtil.writeVarInt(biomesOut, value);
} catch (IOException e) {
e.printStackTrace();
}
}
};
if (clipboard instanceof BlockArrayClipboard) {
((BlockArrayClipboard) clipboard).IMP.streamBiomes(task);
} else {
BlockVector3 min = clipboard.getMinimumPoint(); BlockVector3 min = clipboard.getMinimumPoint();
int width = clipboard.getRegion().getWidth(); int width = clipboard.getRegion().getWidth();
int length = clipboard.getRegion().getLength(); int length = clipboard.getRegion().getLength();
for (int z = 0, i = 0; z < length; z++) {
ByteArrayOutputStream buffer = new ByteArrayOutputStream(width * length);
int paletteMax = 0;
Map<String, Integer> palette = new HashMap<>();
for (int z = 0; z < length; z++) {
int z0 = min.getBlockZ() + z; int z0 = min.getBlockZ() + z;
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++, i++) {
int x0 = min.getBlockX() + x; int x0 = min.getBlockX() + x;
BlockVector2 pt = BlockVector2.at(x0, z0); BlockVector2 pt = BlockVector2.at(x0, z0);
BiomeType biome = clipboard.getBiome(pt); BiomeType biome = clipboard.getBiome(pt);
task.run(i, biome.getInternalId());
String biomeKey = biome.getId();
int biomeId;
if (palette.containsKey(biomeKey)) {
biomeId = palette.get(biomeKey);
} else {
biomeId = paletteMax;
palette.put(biomeKey, biomeId);
paletteMax++;
}
while ((biomeId & -128) != 0) {
buffer.write(biomeId & 127 | 128);
biomeId >>>= 7;
}
buffer.write(biomeId);
} }
} }
}
biomesOut.close();
schematic.writeNamedTag("BiomePaletteMax", new IntTag(paletteMax)); out.writeNamedTag("BiomePaletteMax", paletteMax[0]);
Map<String, Tag> paletteTag = new HashMap<>(); out.writeLazyCompoundTag("BiomePalette", out12 -> {
palette.forEach((key, value) -> paletteTag.put(key, new IntTag(value))); for (int i = 0; i < paletteList.size(); i++) {
int ordinal = paletteList.get(i);
BiomeType state = BiomeTypes.get(ordinal);
out12.writeNamedTag(state.getId(), i);
}
});
schematic.writeNamedTag("BiomePalette", new CompoundTag(paletteTag)); out.writeNamedTagName("BiomeData", NBTConstants.TYPE_BYTE_ARRAY);
schematic.writeNamedTag("BiomeData", new ByteArrayTag(buffer.toByteArray())); out.writeInt(biomesOut.size());
try (LZ4BlockInputStream in = new LZ4BlockInputStream(new ByteArrayInputStream(biomesCompressed.toByteArray()))) {
IOUtil.copy(in, (DataOutput) out);
}
} }
private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException { private void writeEntities(Clipboard clipboard, NBTOutputStream schematic) throws IOException {

Datei anzeigen

@ -135,6 +135,16 @@ public final class BiomeTypes {
return BiomeType.REGISTRY.values(); return BiomeType.REGISTRY.values();
} }
public static int getMaxId() {
int maxBiomeId = 0;
for (BiomeType type : BiomeType.REGISTRY.values()) {
if (type.getInternalId() > maxBiomeId) {
maxBiomeId = type.getInternalId();
}
}
return maxBiomeId;
}
static { static {
OCEAN.setLegacyId(0); OCEAN.setLegacyId(0);
PLAINS.setLegacyId(1); PLAINS.setLegacyId(1);