Optimize copy and load

This commit is contained in:
Jesse Boyd 2017-04-22 21:22:09 +10:00
parent 1f539f4b80
commit 1bd8c3935a
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
14 changed files with 269 additions and 104 deletions

View File

@ -28,7 +28,7 @@ ext {
date = git.head().date.format("yy.MM.dd") date = git.head().date.format("yy.MM.dd")
revision = "-${git.head().abbreviatedId}" revision = "-${git.head().abbreviatedId}"
parents = git.head().parentIds; parents = git.head().parentIds;
index = -91; // Offset to mach CI index = -92; // Offset to mach CI
int major, minor, patch; int major, minor, patch;
major = minor = patch = 0; major = minor = patch = 0;
for (;parents != null && !parents.isEmpty();index++) { for (;parents != null && !parents.isEmpty();index++) {

View File

@ -105,6 +105,7 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.EllipsoidRegion;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.shape.ArbitraryShape; import com.sk89q.worldedit.regions.shape.ArbitraryShape;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.session.PasteBuilder; import com.sk89q.worldedit.session.PasteBuilder;
import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.session.request.Request;
@ -460,6 +461,7 @@ public class Fawe {
// Clipboards // Clipboards
BlockArrayClipboard.inject(); // Optimizations + disk BlockArrayClipboard.inject(); // Optimizations + disk
CuboidClipboard.inject(); // Optimizations CuboidClipboard.inject(); // Optimizations
ClipboardHolder.inject(); // Closeable
// Regions // Regions
CuboidRegion.inject(); // Optimizations CuboidRegion.inject(); // Optimizations
// Extents // Extents

View File

@ -39,19 +39,19 @@ public class SchematicStreamer extends NBTStreamer {
addReader("Schematic.Blocks.#", new ByteReader() { addReader("Schematic.Blocks.#", new ByteReader() {
@Override @Override
public void run(int index, int value) { public void run(int index, int value) {
fc.setId(index, value); if (value != 0) fc.setId(index, value);
} }
}); });
addReader("Schematic.Data.#", new ByteReader() { addReader("Schematic.Data.#", new ByteReader() {
@Override @Override
public void run(int index, int value) { public void run(int index, int value) {
fc.setData(index, value); if (value != 0) fc.setData(index, value);
} }
}); });
addReader("Schematic.AddBlocks.#", new ByteReader() { addReader("Schematic.AddBlocks.#", new ByteReader() {
@Override @Override
public void run(int index, int value) { public void run(int index, int value) {
fc.setAdd(index, value); if (value != 0) fc.setAdd(index, value);
} }
}); });

View File

@ -71,6 +71,16 @@ public class AbstractDelegateFaweClipboard extends FaweClipboard {
parent.setDimensions(dimensions); parent.setDimensions(dimensions);
} }
@Override
public void flush() {
parent.flush();
}
@Override
public void close() {
parent.close();
}
@Override @Override
public Vector getDimensions() { public Vector getDimensions() {
return parent.getDimensions(); return parent.getDimensions();

View File

@ -5,7 +5,6 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer; import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.IntegerTrio; import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
@ -22,6 +21,11 @@ import com.sk89q.worldedit.regions.CuboidRegion;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -50,8 +54,11 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
private final HashSet<ClipboardEntity> entities; private final HashSet<ClipboardEntity> entities;
private final File file; private final File file;
private final BufferedRandomAccessFile raf; private RandomAccessFile braf;
private MappedByteBuffer mbb;
private int last; private int last;
private FileChannel fc;
public DiskOptimizedClipboard(int width, int height, int length, UUID uuid) { public DiskOptimizedClipboard(int width, int height, int length, UUID uuid) {
this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.CLIPBOARD + File.separator + uuid + ".bd")); this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.CLIPBOARD + File.separator + uuid + ".bd"));
@ -62,14 +69,16 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
nbtMap = new HashMap<>(); nbtMap = new HashMap<>();
entities = new HashSet<>(); entities = new HashSet<>();
this.file = file; this.file = file;
this.raf = new BufferedRandomAccessFile(file, "rw", 16); this.braf = new RandomAccessFile(file, "rw");
raf.setLength(file.length()); braf.setLength(file.length());
long size = (raf.length() - HEADER_SIZE) >> 1; init();
raf.seek(2); long size = (braf.length() - HEADER_SIZE) >> 1;
mbb.position(2);
last = Integer.MIN_VALUE; last = Integer.MIN_VALUE;
width = (int) raf.readChar(); width = (int) mbb.getChar();
height = (int) raf.readChar(); height = (int) mbb.getChar();
length = (int) raf.readChar(); length = (int) mbb.getChar();
area = width * length; area = width * length;
autoCloseTask(); autoCloseTask();
} catch (IOException e) { } catch (IOException e) {
@ -77,6 +86,13 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
} }
} }
private void init() throws IOException {
if (this.fc == null) {
this.fc = braf.getChannel();
this.mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, file.length());
}
}
@Override @Override
public Vector getDimensions() { public Vector getDimensions() {
return new Vector(width, height, length); return new Vector(width, height, length);
@ -90,15 +106,15 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
return true; return true;
} }
}; };
raf.seek(8); mbb.position(8);
last = Integer.MIN_VALUE; last = Integer.MIN_VALUE;
int ox = raf.readShort(); int ox = mbb.getShort();
int oy = raf.readShort(); int oy = mbb.getShort();
int oz = raf.readShort(); int oz = mbb.getShort();
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, this); BlockArrayClipboard clipboard = new BlockArrayClipboard(region, this);
clipboard.setOrigin(new Vector(ox, oy, oz)); clipboard.setOrigin(new Vector(ox, oy, oz));
return clipboard; return clipboard;
} catch (IOException e) { } catch (Throwable e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
return null; return null;
@ -115,22 +131,26 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
this.area = width * length; this.area = width * length;
try { try {
if (!file.exists()) { if (!file.exists()) {
file.getParentFile().mkdirs(); File parent = file.getParentFile();
if (parent != null) {
file.getParentFile().mkdirs();
}
file.createNewFile(); file.createNewFile();
} }
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
this.raf = new BufferedRandomAccessFile(file, "rw", 16); this.braf = new RandomAccessFile(file, "rw");
long volume = (long) width * (long) height * (long) length * 2l + (long) HEADER_SIZE; long volume = (long) width * (long) height * (long) length * 2l + (long) HEADER_SIZE;
raf.setLength(0); braf.setLength(0);
raf.setLength(volume); braf.setLength(volume);
init();
// write length etc // write length etc
raf.seek(2); mbb.position(2);
last = Integer.MIN_VALUE; last = Integer.MIN_VALUE;
raf.writeChar(width); mbb.putChar((char) width);
raf.writeChar(height); mbb.putChar((char) height);
raf.writeChar(length); mbb.putChar((char) length);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -139,12 +159,12 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void setOrigin(Vector offset) { public void setOrigin(Vector offset) {
try { try {
raf.seek(8); mbb.position(8);
last = Integer.MIN_VALUE; last = Integer.MIN_VALUE;
raf.writeShort(offset.getBlockX()); mbb.putShort((short) offset.getBlockX());
raf.writeShort(offset.getBlockY()); mbb.putShort((short) offset.getBlockY());
raf.writeShort(offset.getBlockZ()); mbb.putShort((short) offset.getBlockZ());
} catch (IOException e) { } catch (Throwable e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
} }
@ -157,34 +177,51 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
length = dimensions.getBlockZ(); length = dimensions.getBlockZ();
area = width * length; area = width * length;
long size = width * height * length * 2l + HEADER_SIZE; long size = width * height * length * 2l + HEADER_SIZE;
raf.setLength(size); braf.setLength(size);
raf.seek(2); init();
mbb.position(2);
last = Integer.MIN_VALUE; last = Integer.MIN_VALUE;
raf.writeChar(width); mbb.putChar((char) width);
raf.writeChar(height); mbb.putChar((char) height);
raf.writeChar(length); mbb.putChar((char) length);
} catch (IOException e) { } catch (IOException e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
} }
@Override
public void flush() { public void flush() {
try { mbb.force();
raf.flush();
} catch (IOException e) {
MainUtil.handleError(e);
}
} }
public DiskOptimizedClipboard(int width, int height, int length) { public DiskOptimizedClipboard(int width, int height, int length) {
this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.CLIPBOARD + File.separator + UUID.randomUUID() + ".bd")); this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.CLIPBOARD + File.separator + UUID.randomUUID() + ".bd"));
} }
private void closeDirectBuffer(ByteBuffer cb) {
if (cb==null || !cb.isDirect()) return;
// we could use this type cast and call functions without reflection code,
// but static import from sun.* package is risky for non-SUN virtual machine.
//try { ((sun.nio.ch.DirectBuffer)cb).cleaner().clean(); } catch (Exception ex) { }
try {
Method cleaner = cb.getClass().getMethod("cleaner");
cleaner.setAccessible(true);
Method clean = Class.forName("sun.misc.Cleaner").getMethod("clean");
clean.setAccessible(true);
clean.invoke(cleaner.invoke(cb));
} catch(Exception ex) { }
cb = null;
}
@Override
public void close() { public void close() {
try { try {
raf.close(); mbb.force();
fc.close();
braf.close();
file.setWritable(true); file.setWritable(true);
System.gc(); closeDirectBuffer(mbb);
} catch (IOException e) { } catch (IOException e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
@ -213,37 +250,37 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void streamIds(NBTStreamer.ByteReader task) { public void streamIds(NBTStreamer.ByteReader task) {
try { try {
raf.seek(HEADER_SIZE); mbb.force();
mbb.position(HEADER_SIZE);
int index = 0; int index = 0;
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) { for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
int combinedId = raf.readChar(); int combinedId = mbb.getChar();
task.run(index++, FaweCache.getId(combinedId)); task.run(index++, FaweCache.getId(combinedId));
} }
} }
} }
} catch (IOException e) { } catch (Throwable e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
} }
public static long start;
@Override @Override
public void streamDatas(NBTStreamer.ByteReader task) { public void streamDatas(NBTStreamer.ByteReader task) {
try { try {
raf.seek(HEADER_SIZE); mbb.force();
mbb.position(HEADER_SIZE);
int index = 0; int index = 0;
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) { for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
int combinedId = raf.readChar(); int combinedId = mbb.getChar();
task.run(index++, FaweCache.getData(combinedId)); task.run(index++, FaweCache.getData(combinedId));
} }
} }
} }
} catch (IOException e) { } catch (Throwable e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
} }
@ -256,7 +293,8 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void forEach(final BlockReader task, boolean air) { public void forEach(final BlockReader task, boolean air) {
try { try {
raf.seek(HEADER_SIZE); mbb.force();
mbb.position(HEADER_SIZE);
IntegerTrio trio = new IntegerTrio(); IntegerTrio trio = new IntegerTrio();
final boolean hasTile = !nbtMap.isEmpty(); final boolean hasTile = !nbtMap.isEmpty();
if (air) { if (air) {
@ -264,7 +302,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) { for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
char combinedId = raf.readChar(); char combinedId = mbb.getChar();
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
if (block.canStoreNBTData()) { if (block.canStoreNBTData()) {
trio.set(x, y, z); trio.set(x, y, z);
@ -282,7 +320,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) { for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
char combinedId = raf.readChar(); char combinedId = mbb.getChar();
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
task.run(x, y, z, block); task.run(x, y, z, block);
} }
@ -293,7 +331,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
for (int y = 0; y < height; y++) { for (int y = 0; y < height; y++) {
for (int z = 0; z < length; z++) { for (int z = 0; z < length; z++) {
for (int x = 0; x < width; x++) { for (int x = 0; x < width; x++) {
int combinedId = raf.readChar(); int combinedId = mbb.getChar();
if (combinedId != 0) { if (combinedId != 0) {
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
if (block.canStoreNBTData()) { if (block.canStoreNBTData()) {
@ -310,7 +348,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
} }
} }
} }
} catch (IOException e) { } catch (Throwable e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
} }
@ -324,10 +362,10 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try { try {
int i = getIndex(x, y, z); int i = getIndex(x, y, z);
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); mbb.position((HEADER_SIZE) + (i << 1));
} }
last = i; last = i;
int combinedId = raf.readChar(); int combinedId = mbb.getChar();
BaseBlock block = FaweCache.CACHE_BLOCK[combinedId]; BaseBlock block = FaweCache.CACHE_BLOCK[combinedId];
if (block.canStoreNBTData()) { if (block.canStoreNBTData()) {
CompoundTag nbt = nbtMap.get(new IntegerTrio(x, y, z)); CompoundTag nbt = nbtMap.get(new IntegerTrio(x, y, z));
@ -358,13 +396,13 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
try { try {
int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width)); int i = x + ((ylast == y) ? ylasti : (ylasti = ((ylast = y)) * area)) + ((zlast == z) ? zlasti : (zlasti = (zlast = z) * width));
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); mbb.position((HEADER_SIZE) + (i << 1));
} }
last = i; last = i;
final int id = block.getId(); final int id = block.getId();
final int data = block.getData(); final int data = block.getData();
int combined = (id << 4) + data; int combined = (id << 4) + data;
raf.writeChar(combined); mbb.putChar((char) combined);
CompoundTag tile = block.getNbtData(); CompoundTag tile = block.getNbtData();
if (tile != null) { if (tile != null) {
setTile(x, y, z, tile); setTile(x, y, z, tile);
@ -379,16 +417,20 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void setId(int i, int id) { public void setId(int i, int id) {
try { try {
int index;
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); index = (HEADER_SIZE) + (i << 1);
} else {
index = mbb.position();
} }
last = i; last = i;
mbb.position(index + 1);
// 00000000 00000000 // 00000000 00000000
// [ id ]data // [ id ]data
int id1 = raf.readCurrent(); byte id2 = mbb.get();
raf.writeUnsafe(id >> 4); mbb.position(index);
int id2 = raf.readCurrent(); mbb.put((byte) (id >> 4));
raf.writeUnsafe(((id & 0xFF) << 4) + (id2 & 0xFF)); mbb.put((byte) (((id & 0xFF) << 4) + (id2 & 0xFF)));
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
@ -397,10 +439,10 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
public void setCombined(int i, int combined) { public void setCombined(int i, int combined) {
try { try {
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1)); mbb.position((HEADER_SIZE) + (i << 1));
} }
last = i; last = i;
raf.writeChar(combined); mbb.putChar((char) combined);
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
@ -409,15 +451,14 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void setAdd(int i, int add) { public void setAdd(int i, int add) {
try { try {
if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1));
}
last = i; last = i;
int index = (HEADER_SIZE) + (i << 1);
mbb.position(index);
// 00000000 00000000 // 00000000 00000000
// [ id ]data // [ id ]data
int id = (raf.readCurrent() & 0xFF); char combined = mbb.getChar();
raf.writeUnsafe(id + (add >> 4)); mbb.position(index);
raf.read1(); mbb.putChar((char) ((combined & 0xFFFF) + (add << 12)));
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }
@ -426,17 +467,17 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
@Override @Override
public void setData(int i, int data) { public void setData(int i, int data) {
try { try {
int index;
if (i != last + 1) { if (i != last + 1) {
raf.seek((HEADER_SIZE) + (i << 1) + 1); index = (HEADER_SIZE) + (i << 1) + 1;
} else { } else {
raf.seek(raf.getFilePointer() + 1); index = mbb.position() + 1;
} }
mbb.position(index);
last = i; last = i;
// 00000000 00000000 byte id = mbb.get();
// [ id ]data mbb.position(index);
// int skip = raf.read1(); mbb.put((byte) ((id & 0xF0) + data));
int id2 = raf.readCurrent();
raf.writeUnsafe((id2 & 0xF0) + data);
} catch (Exception e) { } catch (Exception e) {
MainUtil.handleError(e); MainUtil.handleError(e);
} }

View File

@ -94,6 +94,10 @@ public abstract class FaweClipboard {
return tiles; return tiles;
} }
public void close() {}
public void flush() {}
/** /**
* Stores entity data. * Stores entity data.
*/ */

View File

@ -34,4 +34,11 @@ public class MultiClipboardHolder extends ClipboardHolder{
public void setTransform(Transform transform) { public void setTransform(Transform transform) {
holder.setTransform(transform); holder.setTransform(transform);
} }
@Override
public void close() {
for (ClipboardHolder holder : holders) {
if (holder != null) holder.close();
}
}
} }

View File

@ -1,12 +0,0 @@
package com.boydti.fawe.object.clipboard;
import com.google.common.io.ByteSource;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.world.registry.WorldData;
import java.util.UUID;
public class RandomClipboardHolder extends LazyClipboardHolder {
public RandomClipboardHolder(ByteSource source, ClipboardFormat format, WorldData worldData, UUID uuid) {
super(source, format, worldData, uuid);
}
}

View File

@ -28,7 +28,6 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
@ -45,8 +44,6 @@ import com.sk89q.worldedit.command.tool.SinglePickaxe;
import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.Masks;
@ -794,14 +791,8 @@ public class LocalSession {
* @param clipboard the clipboard, or null if the clipboard is to be cleared * @param clipboard the clipboard, or null if the clipboard is to be cleared
*/ */
public void setClipboard(@Nullable ClipboardHolder clipboard) { public void setClipboard(@Nullable ClipboardHolder clipboard) {
if (this.clipboard != null && clipboard != null) { if (this.clipboard != null) {
Clipboard clip = clipboard.getClipboard(); this.clipboard.close();
if (clip instanceof BlockArrayClipboard) {
BlockArrayClipboard bac = (BlockArrayClipboard) clip;
if (bac.IMP instanceof DiskOptimizedClipboard) {
((DiskOptimizedClipboard) bac.IMP).flush();
}
}
} }
this.clipboard = clipboard; this.clipboard = clipboard;
} }

View File

@ -112,6 +112,7 @@ public class ClipboardCommands {
if (volume >= limit.MAX_CHECKS) { if (volume >= limit.MAX_CHECKS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS); throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
} }
session.setClipboard(null);
final Vector origin = region.getMinimumPoint(); final Vector origin = region.getMinimumPoint();
final int mx = origin.getBlockX(); final int mx = origin.getBlockX();
final int my = origin.getBlockY(); final int my = origin.getBlockY();
@ -149,7 +150,7 @@ public class ClipboardCommands {
if (volume >= limit.MAX_CHECKS) { if (volume >= limit.MAX_CHECKS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS); throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
} }
session.setClipboard(null);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, player.getUniqueId()); BlockArrayClipboard clipboard = new BlockArrayClipboard(region, player.getUniqueId());
clipboard.setOrigin(session.getPlacementPosition(player)); clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint()); ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
@ -193,6 +194,7 @@ public class ClipboardCommands {
if (volume >= limit.MAX_CHANGES) { if (volume >= limit.MAX_CHANGES) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES); throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
} }
session.setClipboard(null);
final Vector origin = region.getMinimumPoint(); final Vector origin = region.getMinimumPoint();
final int mx = origin.getBlockX(); final int mx = origin.getBlockX();
final int my = origin.getBlockY(); final int my = origin.getBlockY();
@ -232,6 +234,7 @@ public class ClipboardCommands {
if (volume >= limit.MAX_CHANGES) { if (volume >= limit.MAX_CHANGES) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES); throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
} }
session.setClipboard(null);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, player.getUniqueId()); BlockArrayClipboard clipboard = new BlockArrayClipboard(region, player.getUniqueId());
clipboard.setOrigin(session.getPlacementPosition(player)); clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint()); ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());

View File

@ -103,6 +103,7 @@ public class SchematicCommands {
} }
try { try {
WorldData wd = player.getWorld().getWorldData(); WorldData wd = player.getWorld().getWorldData();
session.setClipboard(null);
ClipboardHolder[] all = format.loadAllFromInput(player, wd, filename, true); ClipboardHolder[] all = format.loadAllFromInput(player, wd, filename, true);
if (all != null) { if (all != null) {
MultiClipboardHolder multi = new MultiClipboardHolder(wd, all); MultiClipboardHolder multi = new MultiClipboardHolder(wd, all);
@ -177,6 +178,7 @@ public class SchematicCommands {
final ClipboardReader reader = format.getReader(in); final ClipboardReader reader = format.getReader(in);
final WorldData worldData = player.getWorld().getWorldData(); final WorldData worldData = player.getWorld().getWorldData();
final Clipboard clipboard; final Clipboard clipboard;
session.setClipboard(null);
if (reader instanceof SchematicReader) { if (reader instanceof SchematicReader) {
clipboard = ((SchematicReader) reader).read(player.getWorld().getWorldData(), player.getUniqueId()); clipboard = ((SchematicReader) reader).read(player.getWorld().getWorldData(), player.getUniqueId());
} else if (reader instanceof StructureFormat) { } else if (reader instanceof StructureFormat) {

View File

@ -115,6 +115,10 @@ public class BlockArrayClipboard implements Clipboard, LightingExtent {
this.mz = origin.getBlockZ(); this.mz = origin.getBlockZ();
} }
public void close() {
IMP.close();
}
@Override @Override
public Region getRegion() { public Region getRegion() {
return region.clone(); return region.clone();

View File

@ -0,0 +1,112 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.session;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.world.registry.WorldData;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Holds the clipboard and the current transform on the clipboard.
*/
public class ClipboardHolder {
private final WorldData worldData;
private final Clipboard clipboard;
private Transform transform = new Identity();
/**
* Create a new instance with the given clipboard.
*
* @param clipboard the clipboard
* @param worldData the mapping of blocks, entities, and so on
*/
public ClipboardHolder(Clipboard clipboard, WorldData worldData) {
checkNotNull(clipboard);
checkNotNull(worldData);
this.clipboard = clipboard;
this.worldData = worldData;
}
/**
* Get the mapping used for blocks, entities, and so on.
*
* @return the mapping
*/
public WorldData getWorldData() {
return worldData;
}
/**
* Get the clipboard.
* <p>
* If there is a transformation applied, the returned clipboard will
* not contain its effect.
*
* @return the clipboard
*/
public Clipboard getClipboard() {
return clipboard;
}
/**
* Set the transform.
*
* @param transform the transform
*/
public void setTransform(Transform transform) {
checkNotNull(transform);
this.transform = transform;
}
/**
* Get the transform.
*
* @return the transform
*/
public Transform getTransform() {
return transform;
}
/**
* Create a builder for an operation to paste this clipboard.
*
* @return a builder
*/
public PasteBuilder createPaste(Extent targetExtent, WorldData targetWorldData) {
return new PasteBuilder(this, targetExtent, targetWorldData);
}
public void close() {
if (clipboard instanceof BlockArrayClipboard) {
((BlockArrayClipboard) clipboard).close();
}
}
public static Class<?> inject() {
return ClipboardHolder.class;
}
}

View File

@ -221,6 +221,7 @@ public class SessionManager {
private void save(SessionHolder holder) { private void save(SessionHolder holder) {
SessionKey key = holder.key; SessionKey key = holder.key;
holder.session.setClipboard(null);
if (key.isPersistent()) { if (key.isPersistent()) {
try { try {
if (holder.session.compareAndResetDirty()) { if (holder.session.compareAndResetDirty()) {