mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-06 04:46:40 +00:00
It started on work with commands then I got carried away.
This commit is contained in:
@ -43,6 +43,7 @@ import javax.annotation.Nullable;
|
||||
* A base class for {@link Extent}s that merely passes extents onto another.
|
||||
*/
|
||||
public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
|
||||
private final Extent extent;
|
||||
|
||||
/**
|
||||
@ -60,14 +61,19 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
*
|
||||
* @return the extent
|
||||
*/
|
||||
public final Extent getExtent() {
|
||||
public Extent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
return getBlock(position.getX(),position.getY(),position.getZ());
|
||||
}
|
||||
|
||||
/*
|
||||
Queue based methods
|
||||
TODO NOT IMPLEMENTED: IQueueExtent and such need to implement these
|
||||
*/
|
||||
Queue based methods
|
||||
TODO NOT IMPLEMENTED: IQueueExtent and such need to implement these
|
||||
*/
|
||||
public boolean isQueueEnabled() {
|
||||
return extent.isQueueEnabled();
|
||||
}
|
||||
@ -78,7 +84,8 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
if (!(extent instanceof ForgetfulExtentBuffer)) { // placeholder
|
||||
extent.disableQueue();
|
||||
}
|
||||
} catch (FaweException ignored) {}
|
||||
} catch (FaweException ignored) {
|
||||
}
|
||||
if (extent instanceof AbstractDelegateExtent) {
|
||||
Extent next = ((AbstractDelegateExtent) extent).getExtent();
|
||||
new ExtentTraverser(this).setNext(next);
|
||||
@ -108,8 +115,7 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
} else {
|
||||
history.setChangeSet(changeSet);
|
||||
}
|
||||
}
|
||||
else if (extent instanceof AbstractDelegateExtent) {
|
||||
} else if (extent instanceof AbstractDelegateExtent) {
|
||||
((AbstractDelegateExtent) extent).setChangeSet(changeSet);
|
||||
} else if (changeSet != null) {
|
||||
new ExtentTraverser<>(this).setNext(new HistoryExtent(extent, changeSet));
|
||||
@ -124,21 +130,12 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
/*
|
||||
Bounds
|
||||
*/
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return extent.getMinimumPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return extent.getMaximumPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return extent.getMaxY();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Input + Output
|
||||
*/
|
||||
@ -147,7 +144,6 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
public BlockState getBlock(int x, int y, int z) {
|
||||
return extent.getBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getFullBlock(int x, int y, int z) {
|
||||
return extent.getFullBlock(x, y, z);
|
||||
@ -164,10 +160,12 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
|
||||
throws WorldEditException {
|
||||
return extent.setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Light
|
||||
*/
|
||||
@ -184,7 +182,6 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
}
|
||||
return getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
public int getOpacity(int x, int y, int z) {
|
||||
if (extent instanceof LightingExtent) {
|
||||
return ((LightingExtent) extent).getOpacity(x, y, z);
|
||||
@ -217,15 +214,21 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Generic
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + ":" + extent.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return extent.getMinimumPoint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMaximumPoint() {
|
||||
return extent.getMaximumPoint();
|
||||
}
|
||||
|
||||
protected Operation commitBefore() {
|
||||
return null;
|
||||
}
|
||||
@ -234,7 +237,9 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
|
||||
public @Nullable Operation commit() {
|
||||
Operation ours = commitBefore();
|
||||
Operation other = null;
|
||||
if (extent != this) other = extent.commit();
|
||||
if (extent != this) {
|
||||
other = extent.commit();
|
||||
}
|
||||
if (ours != null && other != null) {
|
||||
return new OperationQueue(ours, other);
|
||||
} else if (ours != null) {
|
||||
|
@ -45,8 +45,6 @@ import javax.annotation.Nullable;
|
||||
*/
|
||||
public class NullExtent implements Extent {
|
||||
|
||||
public static final NullExtent INSTANCE = new NullExtent();
|
||||
|
||||
@Override
|
||||
public BlockVector3 getMinimumPoint() {
|
||||
return BlockVector3.ZERO;
|
||||
@ -73,6 +71,7 @@ public class NullExtent implements Extent {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
}
|
||||
|
@ -19,9 +19,11 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.buffer;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Masks;
|
||||
@ -29,16 +31,14 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Buffers changes to an {@link Extent} and allows retrieval of the changed blocks,
|
||||
* without modifying the underlying extent.
|
||||
*/
|
||||
public class ExtentBuffer extends AbstractDelegateExtent {
|
||||
public class ExtentBuffer extends AbstractBufferingExtent {
|
||||
|
||||
private final Map<BlockVector3, BaseBlock> buffer = Maps.newHashMap();
|
||||
private final Mask mask;
|
||||
@ -66,6 +66,14 @@ public class ExtentBuffer extends AbstractDelegateExtent {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
|
||||
if (mask.test(position)) {
|
||||
return Optional.of(buffer.computeIfAbsent(position, (pos -> getExtent().getFullBlock(pos))));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlock(BlockVector3 position) {
|
||||
if (mask.test(position)) {
|
||||
|
@ -61,7 +61,7 @@ public interface Clipboard extends Extent {
|
||||
|
||||
/**
|
||||
* Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector2)}
|
||||
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes#OCEAN} instead of {@code null}
|
||||
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes.OCEAN} instead of {@code null}
|
||||
* if biomes aren't present. However, it might not be desired to set areas to ocean if the clipboard is defaulting
|
||||
* to ocean, instead of having biomes explicitly set.
|
||||
*
|
||||
|
@ -72,13 +72,27 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
||||
|
||||
@Override
|
||||
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
|
||||
throw new IOException("This format does not support saving, use `.schem` as format");
|
||||
throw new IOException("This format does not support saving");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
String name = file.getName().toLowerCase();
|
||||
return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce");
|
||||
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("Materials")) {
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
SPONGE_SCHEMATIC("sponge", "schem") {
|
||||
@ -113,8 +127,23 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
||||
|
||||
@Override
|
||||
public boolean isFormat(File file) {
|
||||
String name = file.getName().toLowerCase();
|
||||
return name.endsWith(".schem") || name.endsWith(".sponge");
|
||||
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;
|
||||
}
|
||||
|
||||
},
|
||||
@ -149,6 +178,8 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
|
||||
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
|
||||
NamedTag rootTag = str.readNamedTag();
|
||||
CompoundTag structureTag = (CompoundTag) rootTag.getTag();
|
||||
|
||||
// Check
|
||||
Map<String, Tag> structure = structureTag.getValue();
|
||||
if (!structure.containsKey("DataVersion")) {
|
||||
return false;
|
||||
|
@ -69,7 +69,7 @@ public class ClipboardFormats {
|
||||
checkNotNull(format);
|
||||
|
||||
for (String key : format.getAliases()) {
|
||||
String lowKey = key.toLowerCase(Locale.ROOT);
|
||||
String lowKey = key.toLowerCase(Locale.ENGLISH);
|
||||
ClipboardFormat old = aliasMap.put(lowKey, format);
|
||||
if (old != null) {
|
||||
aliasMap.put(lowKey, old);
|
||||
@ -77,7 +77,7 @@ public class ClipboardFormats {
|
||||
}
|
||||
}
|
||||
for (String ext : format.getFileExtensions()) {
|
||||
String lowExt = ext.toLowerCase(Locale.ROOT);
|
||||
String lowExt = ext.toLowerCase(Locale.ENGLISH);
|
||||
fileExtensionMap.put(lowExt, format);
|
||||
}
|
||||
registeredFormats.add(format);
|
||||
@ -99,7 +99,7 @@ public class ClipboardFormats {
|
||||
@Nullable
|
||||
public static ClipboardFormat findByAlias(String alias) {
|
||||
checkNotNull(alias);
|
||||
return aliasMap.get(alias.toLowerCase(Locale.ROOT).trim());
|
||||
return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -157,7 +157,7 @@ public class ClipboardFormats {
|
||||
* It is not in SchematicCommands because it may rely on internal register calls.
|
||||
*/
|
||||
public static String[] getFileExtensionArray() {
|
||||
return fileExtensionMap.keySet().toArray(new String[0]);
|
||||
return fileExtensionMap.keySet().toArray(new String[fileExtensionMap.keySet().size()]);
|
||||
}
|
||||
|
||||
private ClipboardFormats() {
|
||||
@ -259,7 +259,7 @@ public class ClipboardFormats {
|
||||
File[] files = dir.listFiles(pathname -> {
|
||||
String input = pathname.getName();
|
||||
String extension = input.substring(input.lastIndexOf('.') + 1);
|
||||
return (extensions.contains(extension.toLowerCase()));
|
||||
return (extensions.contains(extension.toLowerCase(Locale.ENGLISH)));
|
||||
});
|
||||
LazyClipboardHolder[] clipboards = new LazyClipboardHolder[files.length];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
|
@ -19,10 +19,18 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import com.sk89q.jnbt.DoubleTag;
|
||||
import com.sk89q.jnbt.FloatTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Writes {@code Clipboard}s.
|
||||
@ -39,4 +47,18 @@ public interface ClipboardWriter extends Closeable {
|
||||
*/
|
||||
void write(Clipboard clipboard) throws IOException;
|
||||
|
||||
default Tag writeVector(Vector3 vector) {
|
||||
List<DoubleTag> list = new ArrayList<>();
|
||||
list.add(new DoubleTag(vector.getX()));
|
||||
list.add(new DoubleTag(vector.getY()));
|
||||
list.add(new DoubleTag(vector.getZ()));
|
||||
return new ListTag(DoubleTag.class, list);
|
||||
}
|
||||
|
||||
default Tag writeRotation(Location location) {
|
||||
List<FloatTag> list = new ArrayList<>();
|
||||
list.add(new FloatTag(location.getYaw()));
|
||||
list.add(new FloatTag(location.getPitch()));
|
||||
return new ListTag(FloatTag.class, list);
|
||||
}
|
||||
}
|
||||
|
@ -19,9 +19,12 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.jnbt.NBTStreamer.LazyReader;
|
||||
import com.boydti.fawe.object.FaweInputStream;
|
||||
import com.boydti.fawe.object.FaweOutputStream;
|
||||
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
|
||||
@ -31,21 +34,15 @@ import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
|
||||
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
|
||||
import com.boydti.fawe.object.io.FastByteArraysInputStream;
|
||||
import com.boydti.fawe.util.IOUtil;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.sk89q.jnbt.ByteArrayTag;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.NBTInputStream;
|
||||
import com.sk89q.jnbt.NamedTag;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.extension.input.InputParseException;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
@ -60,18 +57,16 @@ import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import com.sk89q.worldedit.world.entity.EntityType;
|
||||
import com.sk89q.worldedit.world.entity.EntityTypes;
|
||||
import com.sk89q.worldedit.world.storage.NBTConversions;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Reads schematic files using the Sponge Schematic Specification.
|
||||
@ -174,24 +169,18 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
|
||||
/// readBiomes
|
||||
|
||||
streamer.addReader("Schematic.BlockData.#", new NBTStreamer.LazyReader() {
|
||||
@Override
|
||||
public void accept(Integer arrayLen, DataInputStream dis) {
|
||||
try (FaweOutputStream blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut))) {
|
||||
IOUtil.copy(dis, blocks, arrayLen);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
streamer.addReader("Schematic.BlockData.#", (LazyReader) (arrayLen, dis) -> {
|
||||
try (FaweOutputStream blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut))) {
|
||||
IOUtil.copy(dis, blocks, arrayLen);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
streamer.addReader("Schematic.Biomes.#", new NBTStreamer.LazyReader() {
|
||||
@Override
|
||||
public void accept(Integer arrayLen, DataInputStream dis) {
|
||||
try (FaweOutputStream biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut))) {
|
||||
IOUtil.copy(dis, biomes, arrayLen);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
streamer.addReader("Schematic.Biomes.#", (LazyReader) (arrayLen, dis) -> {
|
||||
try (FaweOutputStream biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut))) {
|
||||
IOUtil.copy(dis, biomes, arrayLen);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
streamer.addReader("Schematic.TileEntities.#", (BiConsumer<Integer, CompoundTag>) (index, value) -> {
|
||||
@ -291,6 +280,17 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
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);
|
||||
@ -349,6 +349,36 @@ public class SpongeSchematicReader extends NBTSchematicReader {
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
|
@ -19,13 +19,19 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.clipboard.io;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import com.boydti.fawe.jnbt.NBTStreamer;
|
||||
import com.boydti.fawe.object.clipboard.FaweClipboard;
|
||||
import com.boydti.fawe.util.IOUtil;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sk89q.jnbt.*;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.jnbt.IntArrayTag;
|
||||
import com.sk89q.jnbt.ListTag;
|
||||
import com.sk89q.jnbt.NBTConstants;
|
||||
import com.sk89q.jnbt.NBTOutputStream;
|
||||
import com.sk89q.jnbt.StringTag;
|
||||
import com.sk89q.jnbt.Tag;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
@ -34,18 +40,13 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.math.Vector3;
|
||||
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.BiomeTypes;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutput;
|
||||
@ -53,13 +54,13 @@ import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
|
||||
/**
|
||||
* Writes schematic files using the Sponge schematic format.
|
||||
@ -345,21 +346,6 @@ public class SpongeSchematicWriter implements ClipboardWriter {
|
||||
schematic.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
|
||||
}
|
||||
|
||||
private static Tag writeVector(Vector3 vector) {
|
||||
List<DoubleTag> list = new ArrayList<>();
|
||||
list.add(new DoubleTag(vector.getX()));
|
||||
list.add(new DoubleTag(vector.getY()));
|
||||
list.add(new DoubleTag(vector.getZ()));
|
||||
return new ListTag(DoubleTag.class, list);
|
||||
}
|
||||
|
||||
private static Tag writeRotation(Location location) {
|
||||
List<FloatTag> list = new ArrayList<>();
|
||||
list.add(new FloatTag(location.getYaw()));
|
||||
list.add(new FloatTag(location.getPitch()));
|
||||
return new ListTag(FloatTag.class, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
outputStream.close();
|
||||
|
@ -28,14 +28,10 @@ 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.BlockTypes;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Applies a {@link BlockBag} to operations.
|
||||
@ -44,7 +40,7 @@ public class BlockBagExtent extends AbstractDelegateExtent {
|
||||
|
||||
private final boolean mine;
|
||||
private int[] missingBlocks = new int[BlockTypes.size()];
|
||||
private final BlockBag blockBag;
|
||||
private BlockBag blockBag;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
@ -52,13 +48,12 @@ public class BlockBagExtent extends AbstractDelegateExtent {
|
||||
* @param extent the extent
|
||||
* @param blockBag the block bag
|
||||
*/
|
||||
public BlockBagExtent(Extent extent, @Nonnull BlockBag blockBag) {
|
||||
public BlockBagExtent(Extent extent, @Nullable BlockBag blockBag) {
|
||||
this(extent, blockBag, false);
|
||||
}
|
||||
|
||||
public BlockBagExtent(Extent extent, @Nonnull BlockBag blockBag, boolean mine) {
|
||||
public BlockBagExtent(Extent extent, @Nullable BlockBag blockBag, boolean mine) {
|
||||
super(extent);
|
||||
checkNotNull(blockBag);
|
||||
this.blockBag = blockBag;
|
||||
this.mine = mine;
|
||||
}
|
||||
@ -72,6 +67,14 @@ public class BlockBagExtent extends AbstractDelegateExtent {
|
||||
return blockBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block bag.
|
||||
*
|
||||
* @param blockBag a block bag, which may be null if none is used
|
||||
*/
|
||||
public void setBlockBag(@Nullable BlockBag blockBag) {
|
||||
this.blockBag = blockBag;
|
||||
}
|
||||
/**
|
||||
* Gets the list of missing blocks and clears the list for the next
|
||||
* operation.
|
||||
|
@ -19,22 +19,24 @@
|
||||
|
||||
package com.sk89q.worldedit.extent.reorder;
|
||||
|
||||
import com.google.common.collect.Table;
|
||||
import com.google.common.collect.TreeBasedTable;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.RunContext;
|
||||
import com.sk89q.worldedit.function.operation.SetLocatedBlocks;
|
||||
import com.sk89q.worldedit.math.BlockVector2;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.util.collection.LocatedBlockList;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A special extent that batches changes into Minecraft chunks. This helps
|
||||
@ -42,17 +44,19 @@ import java.util.TreeMap;
|
||||
* loaded repeatedly, however it does take more memory due to caching the
|
||||
* blocks.
|
||||
*/
|
||||
public class ChunkBatchingExtent extends AbstractDelegateExtent {
|
||||
public class ChunkBatchingExtent extends AbstractBufferingExtent {
|
||||
|
||||
/**
|
||||
* Comparator optimized for sorting chunks by the region file they reside
|
||||
* in. This allows for file caches to be used while loading the chunk.
|
||||
*/
|
||||
private static final Comparator<BlockVector2> REGION_OPTIMIZED_SORT =
|
||||
Comparator.comparing((BlockVector2 vec) -> vec.divide(32), BlockVector2.COMPARING_GRID_ARRANGEMENT)
|
||||
Comparator.comparing((BlockVector2 vec) -> vec.shr(5), BlockVector2.COMPARING_GRID_ARRANGEMENT)
|
||||
.thenComparing(BlockVector2.COMPARING_GRID_ARRANGEMENT);
|
||||
|
||||
private final SortedMap<BlockVector2, LocatedBlockList> batches = new TreeMap<>(REGION_OPTIMIZED_SORT);
|
||||
private final Table<BlockVector2, BlockVector3, BaseBlock> batches =
|
||||
TreeBasedTable.create(REGION_OPTIMIZED_SORT, BlockVector3.sortByCoordsYzx());
|
||||
private final Set<BlockVector3> containedBlocks = new HashSet<>();
|
||||
private boolean enabled;
|
||||
|
||||
public ChunkBatchingExtent(Extent extent) {
|
||||
@ -76,16 +80,32 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
private BlockVector2 getChunkPos(BlockVector3 location) {
|
||||
return location.shr(4).toBlockVector2();
|
||||
}
|
||||
|
||||
private BlockVector3 getInChunkPos(BlockVector3 location) {
|
||||
return BlockVector3.at(location.getX() & 15, location.getY(), location.getZ() & 15);
|
||||
}
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
|
||||
if (!enabled) {
|
||||
return getExtent().setBlock(location, block);
|
||||
return setDelegateBlock(location, block);
|
||||
}
|
||||
BlockVector2 chunkPos = BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4);
|
||||
batches.computeIfAbsent(chunkPos, k -> new LocatedBlockList()).add(location, block);
|
||||
BlockVector2 chunkPos = getChunkPos(location);
|
||||
BlockVector3 inChunkPos = getInChunkPos(location);
|
||||
batches.put(chunkPos, inChunkPos, block.toBaseBlock());
|
||||
containedBlocks.add(location);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
|
||||
if (!containedBlocks.contains(position)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(batches.get(getChunkPos(position), getInChunkPos(position)));
|
||||
}
|
||||
@Override
|
||||
protected Operation commitBefore() {
|
||||
if (!commitRequired()) {
|
||||
@ -94,17 +114,22 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent {
|
||||
return new Operation() {
|
||||
|
||||
// we get modified between create/resume -- only create this on resume to prevent CME
|
||||
private Iterator<LocatedBlockList> batchIterator;
|
||||
private Iterator<Map.Entry<BlockVector2, Map<BlockVector3, BaseBlock>>> batchIterator;
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
if (batchIterator == null) {
|
||||
batchIterator = batches.values().iterator();
|
||||
batchIterator = batches.rowMap().entrySet().iterator();
|
||||
}
|
||||
if (!batchIterator.hasNext()) {
|
||||
return null;
|
||||
}
|
||||
new SetLocatedBlocks(getExtent(), batchIterator.next()).resume(run);
|
||||
Map.Entry<BlockVector2, Map<BlockVector3, BaseBlock>> next = batchIterator.next();
|
||||
BlockVector3 chunkOffset = next.getKey().toBlockVector3().shl(4);
|
||||
for (Map.Entry<BlockVector3, BaseBlock> block : next.getValue().entrySet()) {
|
||||
getExtent().setBlock(block.getKey().add(chunkOffset), block.getValue());
|
||||
containedBlocks.remove(block.getKey());
|
||||
}
|
||||
batchIterator.remove();
|
||||
return this;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
package com.sk89q.worldedit.extent.reorder;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.OperationQueue;
|
||||
@ -33,16 +33,19 @@ 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.BlockTypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Re-orders blocks into several stages.
|
||||
*/
|
||||
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
|
||||
public class MultiStageReorder extends AbstractBufferingExtent implements ReorderingExtent {
|
||||
|
||||
private static final Map<BlockType, PlacementPriority> priorityMap = new HashMap<>();
|
||||
|
||||
@ -139,6 +142,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
|
||||
priorityMap.put(BlockTypes.MOVING_PISTON, PlacementPriority.FINAL);
|
||||
}
|
||||
|
||||
private final Set<BlockVector3> containedBlocks = new HashSet<>();
|
||||
private Map<PlacementPriority, LocatedBlockList> stages = new HashMap<>();
|
||||
|
||||
private boolean enabled;
|
||||
@ -212,7 +216,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
|
||||
@Override
|
||||
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
|
||||
if (!enabled) {
|
||||
return super.setBlock(location, block);
|
||||
return setDelegateBlock(location, block);
|
||||
}
|
||||
|
||||
BlockState existing = getBlock(location);
|
||||
@ -240,9 +244,21 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
|
||||
}
|
||||
|
||||
stages.get(priority).add(location, block);
|
||||
containedBlocks.add(location);
|
||||
return !existing.equalsFuzzy(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
|
||||
if (!containedBlocks.contains(position)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return stages.values().stream()
|
||||
.map(blocks -> blocks.get(position))
|
||||
.filter(Objects::nonNull)
|
||||
.findAny();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation commitBefore() {
|
||||
if (!commitRequired()) {
|
||||
|
Reference in New Issue
Block a user