Merge remote-tracking branch 'upstream/main'
This commit is contained in:
@ -64,9 +64,9 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
private final int headerSize;
|
||||
|
||||
private RandomAccessFile braf;
|
||||
private MappedByteBuffer byteBuffer;
|
||||
private MappedByteBuffer byteBuffer = null;
|
||||
|
||||
private FileChannel fileChannel;
|
||||
private FileChannel fileChannel = null;
|
||||
private boolean hasBiomes = false;
|
||||
private boolean canHaveBiomes = true;
|
||||
private int nbtBytesRemaining;
|
||||
@ -142,7 +142,7 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.braf = new RandomAccessFile(file, "rw");
|
||||
long fileLength = (long) getVolume() * 2L + (long) headerSize;
|
||||
long fileLength = (long) (getVolume() << 1) + (long) headerSize;
|
||||
braf.setLength(0);
|
||||
braf.setLength(fileLength);
|
||||
this.nbtBytesRemaining = Integer.MAX_VALUE - (int) fileLength;
|
||||
@ -153,7 +153,11 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
byteBuffer.putChar(6, (char) getHeight());
|
||||
byteBuffer.putChar(8, (char) getLength());
|
||||
} catch (IOException e) {
|
||||
close();
|
||||
throw new RuntimeException(e);
|
||||
} catch (Throwable t) {
|
||||
close();
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,11 +182,15 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
nbtMap = new HashMap<>();
|
||||
try {
|
||||
this.file = file;
|
||||
checkFileLength(file);
|
||||
this.braf = new RandomAccessFile(file, "rw");
|
||||
braf.setLength(file.length());
|
||||
this.nbtBytesRemaining = Integer.MAX_VALUE - (int) file.length();
|
||||
init();
|
||||
long biomeLength = (long) ((getHeight() >> 2) + 1) * ((getLength() >> 2) + 1) * ((getWidth() >> 2) + 1);
|
||||
|
||||
int biomeLength = ((getHeight() >> 2) + 1) * ((getLength() >> 2) + 1) * ((getWidth() >> 2) + 1);
|
||||
canHaveBiomes = (long) headerSize + biomeLength < Integer.MAX_VALUE;
|
||||
|
||||
if (headerSize >= VERSION_2_HEADER_SIZE) {
|
||||
readBiomeStatusFromHeader();
|
||||
int nbtCount = readNBTSavedCountFromHeader();
|
||||
@ -190,12 +198,42 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
if (Settings.settings().CLIPBOARD.SAVE_CLIPBOARD_NBT_TO_DISK && (nbtCount + entitiesCount > 0)) {
|
||||
loadNBTFromFileFooter(nbtCount, entitiesCount, biomeLength);
|
||||
}
|
||||
} else if (braf.length() - headerSize == ((long) getVolume() << 1) + biomeLength) {
|
||||
} else if (canHaveBiomes && braf.length() - headerSize == ((long) getVolume() << 1) + biomeLength) {
|
||||
hasBiomes = true;
|
||||
}
|
||||
getAndSetOffsetAndOrigin();
|
||||
} catch (IOException e) {
|
||||
close();
|
||||
throw new RuntimeException(e);
|
||||
} catch (Throwable t) {
|
||||
close();
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkFileLength(File file) throws IOException {
|
||||
long expectedFileSize = headerSize + ((long) getVolume() << 1);
|
||||
if (file.length() > Integer.MAX_VALUE) {
|
||||
if (expectedFileSize >= Integer.MAX_VALUE) {
|
||||
throw new IOException(String.format(
|
||||
"Cannot load clipboard of file size: %d > 2147483647 bytes (2.147 GiB), " + "volume: %d blocks",
|
||||
file.length(),
|
||||
getVolume()
|
||||
));
|
||||
} else {
|
||||
throw new IOException(String.format(
|
||||
"Cannot load clipboard of file size > 2147483647 bytes (2.147 GiB). Possible corrupt file? Mismatch" +
|
||||
" between volume `%d` and file length `%d`!",
|
||||
file.length(),
|
||||
getVolume()
|
||||
));
|
||||
}
|
||||
} else if (expectedFileSize != file.length()) {
|
||||
throw new IOException(String.format(
|
||||
"Possible corrupt clipboard file? Mismatch between expected file size `%d` and actual file size `%d`!",
|
||||
expectedFileSize,
|
||||
file.length()
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,13 +533,26 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
fileChannel.close();
|
||||
braf.close();
|
||||
file.setWritable(true);
|
||||
closeDirectBuffer(byteBuffer);
|
||||
MappedByteBuffer tmpBuffer = byteBuffer;
|
||||
byteBuffer = null;
|
||||
closeDirectBuffer(tmpBuffer);
|
||||
fileChannel = null;
|
||||
braf = null;
|
||||
} else if (fileChannel != null) {
|
||||
fileChannel.close();
|
||||
fileChannel = null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
if (fileChannel != null) {
|
||||
try {
|
||||
fileChannel.close();
|
||||
fileChannel = null;
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Could not close file channel on clipboard {}. If this belongs to a player, the server may " +
|
||||
"need to be restarted for clipboard use to work.", getFile().getName(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -657,8 +708,6 @@ public class DiskOptimizedClipboard extends LinearClipboard {
|
||||
char ordinal = byteBuffer.getChar(diskIndex);
|
||||
return BlockState.getFromOrdinal(ordinal);
|
||||
} catch (IndexOutOfBoundsException ignored) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return BlockTypes.AIR.getDefaultState();
|
||||
}
|
||||
|
||||
@ -126,8 +126,6 @@ public abstract class FaweStreamChangeSet extends AbstractChangeSet {
|
||||
|
||||
@Override
|
||||
public void readCombined(FaweInputStream in, MutableBlockChange change, boolean dir) throws IOException {
|
||||
int from1 = in.read();
|
||||
int from2 = in.read();
|
||||
change.ordinal = in.readVarInt();
|
||||
}
|
||||
|
||||
|
||||
@ -20,6 +20,13 @@ public class FaweOutputStream extends DataOutputStream {
|
||||
return parent;
|
||||
}
|
||||
|
||||
// overwritten to un-synchronized
|
||||
@Override
|
||||
public void write(final int b) throws IOException {
|
||||
out.write(b);
|
||||
written++;
|
||||
}
|
||||
|
||||
public void write(int b, int amount) throws IOException {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
write(b);
|
||||
|
||||
@ -6,6 +6,7 @@ import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.zaxxer.sparsebits.SparseBitSet;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
@ -235,12 +236,15 @@ public class LocalBlockVectorSet implements BlockVector3Set {
|
||||
return toArray((Object[]) null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> T[] toArray(T[] array) {
|
||||
int size = size();
|
||||
if (array == null || array.length < size) {
|
||||
array = (T[]) new BlockVector3[size];
|
||||
if (array.length < size) {
|
||||
array = Arrays.copyOf(array, size);
|
||||
} else if (array.length > size) {
|
||||
array[size] = null; // mark as end to comply with the method contract
|
||||
}
|
||||
int index = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
||||
@ -73,7 +73,16 @@ public class PropertyKeySet implements Set<PropertyKey> {
|
||||
@Nonnull
|
||||
@Override
|
||||
public <T> T[] toArray(@Nonnull T[] a) {
|
||||
T[] array = Arrays.copyOf(a, this.bits.cardinality());
|
||||
T[] array;
|
||||
final int cardinality = this.bits.cardinality();
|
||||
if (cardinality > a.length) {
|
||||
array = Arrays.copyOf(a, cardinality);
|
||||
} else {
|
||||
array = a;
|
||||
if (a.length > cardinality) {
|
||||
array[cardinality] = null; // mark as end to comply with the method contract
|
||||
}
|
||||
}
|
||||
Iterator<PropertyKey> iter = iterator();
|
||||
for (int i = 0; i < array.length && iter.hasNext(); i++) {
|
||||
array[i] = (T) iter.next();
|
||||
|
||||
@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.formatting.text.Component;
|
||||
import it.unimi.dsi.fastutil.io.FastBufferedInputStream;
|
||||
import it.unimi.dsi.fastutil.io.FastBufferedOutputStream;
|
||||
import net.jpountz.lz4.LZ4BlockInputStream;
|
||||
import net.jpountz.lz4.LZ4BlockOutputStream;
|
||||
import net.jpountz.lz4.LZ4Compressor;
|
||||
@ -40,7 +41,6 @@ import javax.imageio.ImageIO;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
@ -273,9 +273,12 @@ public class MainUtil {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Note: The returned stream is not thread safe.
|
||||
*/
|
||||
public static FaweOutputStream getCompressedOS(OutputStream os, int amount, int buffer) throws IOException {
|
||||
os.write((byte) 10 + amount);
|
||||
os = new BufferedOutputStream(os, buffer);
|
||||
os = new FastBufferedOutputStream(os, buffer);
|
||||
if (amount == 0) {
|
||||
return new FaweOutputStream(os);
|
||||
}
|
||||
@ -296,7 +299,7 @@ public class MainUtil {
|
||||
os = new LZ4BlockOutputStream(os, buffer, factory.highCompressor());
|
||||
}
|
||||
}
|
||||
os = new BufferedOutputStream(os, buffer);
|
||||
os = new FastBufferedOutputStream(os, buffer);
|
||||
return new FaweOutputStream(os);
|
||||
}
|
||||
|
||||
|
||||
@ -3025,9 +3025,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
||||
|
||||
// transform
|
||||
expression.evaluate(new double[]{scaled.getX(), scaled.getY(), scaled.getZ()}, timeout);
|
||||
int xv = (int) (x.getValue() * unit.getX() + zero2.getX());
|
||||
int yv = (int) (y.getValue() * unit.getY() + zero2.getY());
|
||||
int zv = (int) (z.getValue() * unit.getZ() + zero2.getZ());
|
||||
int xv = (int) Math.floor(x.getValue() * unit.getX() + zero2.getX());
|
||||
int yv = (int) Math.floor(y.getValue() * unit.getY() + zero2.getY());
|
||||
int zv = (int) Math.floor(z.getValue() * unit.getZ() + zero2.getZ());
|
||||
|
||||
BlockState get;
|
||||
if (yv >= minY && yv <= maxY) {
|
||||
|
||||
@ -169,9 +169,14 @@ public class ToolUtilCommands {
|
||||
public void traceMask(
|
||||
Player player, LocalSession session,
|
||||
@Arg(desc = "The trace mask to set", def = "")
|
||||
Mask maskOpt
|
||||
Mask maskOpt
|
||||
) throws WorldEditException {
|
||||
session.getBrushTool(player, false).setTraceMask(maskOpt);
|
||||
BrushTool brushTool = session.getBrushTool(player, false);
|
||||
if (brushTool == null) {
|
||||
player.print(Caption.of("worldedit.brush.none.equipped"));
|
||||
return;
|
||||
}
|
||||
brushTool.setTraceMask(maskOpt);
|
||||
if (maskOpt == null) {
|
||||
player.print(Caption.of("worldedit.tool.tracemask.disabled"));
|
||||
} else {
|
||||
|
||||
@ -64,7 +64,11 @@ public class FloatingTreeRemover implements BlockTool {
|
||||
|| type == BlockTypes.RED_MUSHROOM_BLOCK
|
||||
|| type == BlockTypes.BROWN_MUSHROOM_BLOCK
|
||||
|| type == BlockTypes.MUSHROOM_STEM
|
||||
|| type == BlockTypes.VINE;
|
||||
|| type == BlockTypes.VINE
|
||||
|| type == BlockTypes.NETHER_WART_BLOCK
|
||||
|| type == BlockTypes.WARPED_WART_BLOCK
|
||||
|| type == BlockTypes.CRIMSON_STEM
|
||||
|| type == BlockTypes.WARPED_STEM;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -207,7 +207,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
|
||||
}).collect(Collectors.toSet());
|
||||
if (!blocked.isEmpty()) {
|
||||
throw new DisallowedUsageException(Caption.of(
|
||||
"fawe.error.limit.disallowed-block",
|
||||
"fawe.error.limit.disallowed-property",
|
||||
TextComponent.of(input)
|
||||
));
|
||||
}
|
||||
|
||||
@ -283,6 +283,7 @@
|
||||
"worldedit.brush.butcher.equip": "Butcher brush equipped ({0}).",
|
||||
"worldedit.brush.operation.equip": "Set brush to {0}.",
|
||||
"worldedit.brush.none.equip": "Brush unbound from your current item.",
|
||||
"worldedit.brush.none.equipped": "You have no brush bound to your current item. Try /brush sphere for a basic brush.",
|
||||
"worldedit.setbiome.changed": "Biomes were changed in {0} columns. You may have to rejoin your game (or close and reopen your world) to see a change.",
|
||||
"worldedit.setbiome.not-locatable": "Command sender must be present in the world to use the -p flag.",
|
||||
"worldedit.drawsel.disabled": "Server CUI disabled.",
|
||||
|
||||
Reference in New Issue
Block a user