Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-10-03 20:21:05 +02:00
extend to lazy clipboard
Dieser Commit ist enthalten in:
Ursprung
7b241ef01a
Commit
040c98d163
@ -52,12 +52,12 @@ public class OncePerChunkExtent extends AbstractDelegateExtent implements IBatch
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldRun(int chunkX, int chunkZ) {
|
private boolean shouldRun(int chunkX, int chunkZ) {
|
||||||
final long pair = (long) chunkX << 32 | chunkZ & 0xffffffffL;
|
|
||||||
if (pair == lastPair) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
lastPair = pair;
|
|
||||||
synchronized (set) {
|
synchronized (set) {
|
||||||
|
final long pair = (long) chunkX << 32 | chunkZ & 0xffffffffL;
|
||||||
|
if (pair == lastPair) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
lastPair = pair;
|
||||||
return set.add(chunkX, chunkZ);
|
return set.add(chunkX, chunkZ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,10 +68,16 @@ public class OncePerChunkExtent extends AbstractDelegateExtent implements IBatch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the task run once per chunk.
|
||||||
|
*/
|
||||||
public Consumer<IChunkGet> getTask() {
|
public Consumer<IChunkGet> getTask() {
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the task to be run once per chunk
|
||||||
|
*/
|
||||||
public void setTask(Consumer<IChunkGet> task) {
|
public void setTask(Consumer<IChunkGet> task) {
|
||||||
this.task = task;
|
this.task = task;
|
||||||
}
|
}
|
||||||
@ -181,4 +187,12 @@ public class OncePerChunkExtent extends AbstractDelegateExtent implements IBatch
|
|||||||
super.setSkyLight(x, y, z, value);
|
super.setSkyLight(x, y, z, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the chunks visited
|
||||||
|
*/
|
||||||
|
public void reset() {
|
||||||
|
lastPair = Long.MAX_VALUE;
|
||||||
|
set.clear();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,10 @@ package com.fastasyncworldedit.core.extent.clipboard;
|
|||||||
|
|
||||||
import com.fastasyncworldedit.core.Fawe;
|
import com.fastasyncworldedit.core.Fawe;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.NBTUtils;
|
|
||||||
import com.sk89q.jnbt.Tag;
|
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.entity.BaseEntity;
|
import com.sk89q.worldedit.entity.BaseEntity;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.session.request.Request;
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
@ -18,9 +15,7 @@ import com.sk89q.worldedit.world.biome.BiomeType;
|
|||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@ -50,17 +45,17 @@ public abstract class ReadOnlyClipboard extends SimpleClipboard {
|
|||||||
return of(() -> extent, region);
|
return of(() -> extent, region);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadOnlyClipboard of(Extent extent, final Region region, boolean copyEntities, boolean copyBiomes) {
|
|
||||||
Fawe.instance().getQueueHandler().unCache();
|
|
||||||
return of(() -> extent, region, copyEntities, copyBiomes);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ReadOnlyClipboard of(Supplier<Extent> supplier, final Region region) {
|
public static ReadOnlyClipboard of(Supplier<Extent> supplier, final Region region) {
|
||||||
return of(supplier, region, true, false);
|
return of(supplier, region, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ReadOnlyClipboard of(Supplier<Extent> supplier, final Region region, boolean copyEntities, boolean copyBiomes) {
|
public static ReadOnlyClipboard of(Supplier<Extent> supplier, final Region region, boolean copyEntities, boolean copyBiomes) {
|
||||||
return new WorldCopyClipboard(supplier, region, copyEntities, copyBiomes);
|
return of(supplier.get(), region, copyEntities, copyBiomes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ReadOnlyClipboard of(Extent extent, final Region region, boolean copyEntities, boolean copyBiomes) {
|
||||||
|
Fawe.instance().getQueueHandler().unCache();
|
||||||
|
return WorldCopyClipboard.of(extent, region, copyEntities, copyBiomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Supplier<Extent> supply() {
|
private static Supplier<Extent> supply() {
|
||||||
|
@ -1,14 +1,22 @@
|
|||||||
package com.fastasyncworldedit.core.extent.clipboard;
|
package com.fastasyncworldedit.core.extent.clipboard;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
import com.sk89q.worldedit.EditSessionBuilder;
|
||||||
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
import com.sk89q.worldedit.entity.Entity;
|
import com.sk89q.worldedit.entity.Entity;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
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;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@ -16,26 +24,47 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
|||||||
|
|
||||||
private final boolean hasBiomes;
|
private final boolean hasBiomes;
|
||||||
private final boolean hasEntities;
|
private final boolean hasEntities;
|
||||||
private Extent extent;
|
private final Extent extent;
|
||||||
private Supplier<Extent> supplier;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link WorldCopyClipboard#of(Extent, Region)}
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "TODO")
|
||||||
public WorldCopyClipboard(Supplier<Extent> supplier, Region region) {
|
public WorldCopyClipboard(Supplier<Extent> supplier, Region region) {
|
||||||
this(supplier, region, true, false);
|
this(supplier, region, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated use {@link WorldCopyClipboard#of(Extent, Region, boolean, boolean)}
|
||||||
|
*/
|
||||||
|
@Deprecated(forRemoval = true, since = "TODO")
|
||||||
public WorldCopyClipboard(Supplier<Extent> supplier, Region region, boolean hasEntities, boolean hasBiomes) {
|
public WorldCopyClipboard(Supplier<Extent> supplier, Region region, boolean hasEntities, boolean hasBiomes) {
|
||||||
super(region);
|
super(region);
|
||||||
this.hasBiomes = hasBiomes;
|
this.hasBiomes = hasBiomes;
|
||||||
this.hasEntities = hasEntities;
|
this.hasEntities = hasEntities;
|
||||||
this.supplier = supplier;
|
this.extent = supplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorldCopyClipboard(Extent extent, Region region, boolean hasEntities, boolean hasBiomes) {
|
||||||
|
super(region);
|
||||||
|
this.hasBiomes = hasBiomes;
|
||||||
|
this.hasEntities = hasEntities;
|
||||||
|
this.extent = extent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WorldCopyClipboard of(Extent extent, Region region) {
|
||||||
|
return of(extent, region, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WorldCopyClipboard of(Extent extent, Region region, boolean hasEntities) {
|
||||||
|
return of(extent, region, hasEntities, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WorldCopyClipboard of(Extent extent, Region region, boolean hasEntities, boolean hasBiomes) {
|
||||||
|
return new WorldCopyClipboard(extent, region, hasEntities, hasBiomes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Extent getExtent() {
|
public Extent getExtent() {
|
||||||
if (extent != null) {
|
|
||||||
return extent;
|
|
||||||
}
|
|
||||||
extent = supplier.get();
|
|
||||||
supplier = null;
|
|
||||||
return extent;
|
return extent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +89,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Deprecated
|
||||||
public List<? extends Entity> getEntities() {
|
public List<? extends Entity> getEntities() {
|
||||||
if (!hasEntities) {
|
if (!hasEntities) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
@ -72,4 +102,69 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
|
|||||||
return hasBiomes;
|
return hasBiomes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paste(Extent toExtent, BlockVector3 to, boolean pasteAir, boolean pasteEntities, boolean pasteBiomes) {
|
||||||
|
boolean close = false;
|
||||||
|
if (toExtent instanceof World) {
|
||||||
|
close = true;
|
||||||
|
EditSessionBuilder builder = WorldEdit
|
||||||
|
.getInstance()
|
||||||
|
.newEditSessionBuilder()
|
||||||
|
.world((World) toExtent)
|
||||||
|
.checkMemory(false)
|
||||||
|
.allowedRegionsEverywhere()
|
||||||
|
.limitUnlimited()
|
||||||
|
.changeSetNull();
|
||||||
|
toExtent = builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Extent source = getExtent();
|
||||||
|
|
||||||
|
Collection<Entity> entities = pasteEntities ? ForwardExtentCopy.getEntities(source, region) : Collections.emptySet();
|
||||||
|
|
||||||
|
final BlockVector3 origin = this.getOrigin();
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
|
||||||
|
pasteBiomes &= this.hasBiomes();
|
||||||
|
|
||||||
|
for (BlockVector3 pos : this) {
|
||||||
|
BaseBlock block = pos.getFullBlock(this);
|
||||||
|
int xx = pos.getX() + relx;
|
||||||
|
int yy = pos.getY() + rely;
|
||||||
|
int zz = pos.getZ() + relz;
|
||||||
|
if (pasteBiomes) {
|
||||||
|
toExtent.setBiome(xx, yy, zz, pos.getBiome(this));
|
||||||
|
}
|
||||||
|
if (!pasteAir && block.getBlockType().getMaterial().isAir()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
toExtent.setBlock(xx, yy, zz, block);
|
||||||
|
}
|
||||||
|
// Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin)
|
||||||
|
final int entityOffsetX = to.getBlockX() - origin.getBlockX();
|
||||||
|
final int entityOffsetY = to.getBlockY() - origin.getBlockY();
|
||||||
|
final int entityOffsetZ = to.getBlockZ() - origin.getBlockZ();
|
||||||
|
// entities
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
// skip players on pasting schematic
|
||||||
|
if (entity.getState() != null && entity.getState().getType().getId()
|
||||||
|
.equals("minecraft:player")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Location pos = entity.getLocation();
|
||||||
|
Location newPos = new Location(pos.getExtent(), pos.getX() + entityOffsetX,
|
||||||
|
pos.getY() + entityOffsetY, pos.getZ() + entityOffsetZ, pos.getYaw(),
|
||||||
|
pos.getPitch()
|
||||||
|
);
|
||||||
|
toExtent.createEntity(newPos, entity.getState());
|
||||||
|
}
|
||||||
|
if (close) {
|
||||||
|
((EditSession) toExtent).close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -260,7 +260,7 @@ public class ParallelQueueExtent extends PassthroughExtent {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Clipboard lazyCopy(Region region) {
|
public Clipboard lazyCopy(Region region) {
|
||||||
Clipboard clipboard = new WorldCopyClipboard(() -> this, region);
|
Clipboard clipboard = WorldCopyClipboard.of(this, region);
|
||||||
clipboard.setOrigin(region.getMinimumPoint());
|
clipboard.setOrigin(region.getMinimumPoint());
|
||||||
return clipboard;
|
return clipboard;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package com.fastasyncworldedit.core.util;
|
|||||||
|
|
||||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||||
import com.sk89q.worldedit.extent.Extent;
|
import com.sk89q.worldedit.extent.Extent;
|
||||||
|
import com.sk89q.worldedit.internal.util.LogManagerCompat;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@ -9,6 +11,8 @@ import java.lang.reflect.Field;
|
|||||||
|
|
||||||
public class ExtentTraverser<T extends Extent> {
|
public class ExtentTraverser<T extends Extent> {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManagerCompat.getLogger();
|
||||||
|
|
||||||
private final T root;
|
private final T root;
|
||||||
private final ExtentTraverser<T> parent;
|
private final ExtentTraverser<T> parent;
|
||||||
|
|
||||||
@ -98,9 +102,8 @@ public class ExtentTraverser<T extends Extent> {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ExtentTraverser<T> next() {
|
public ExtentTraverser<T> next() {
|
||||||
try {
|
try {
|
||||||
if (root instanceof AbstractDelegateExtent) {
|
if (root instanceof AbstractDelegateExtent abstractDelegateExtent) {
|
||||||
AbstractDelegateExtent root = (AbstractDelegateExtent) this.root;
|
T value = (T) abstractDelegateExtent.getExtent();
|
||||||
T value = (T) root.getExtent();
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -113,4 +116,23 @@ public class ExtentTraverser<T extends Extent> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void printNestedExtents(Extent extent) {
|
||||||
|
String nested = printNestedExtent(new StringBuilder("Extent tree:"), new ExtentTraverser<>(extent), 0).toString();
|
||||||
|
LOGGER.info(nested);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static StringBuilder printNestedExtent(StringBuilder builder, ExtentTraverser<?> traverser, int depth) {
|
||||||
|
if (traverser == null || !traverser.exists()) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
String indent = " ".repeat(Math.max(0, depth)); // Adjust the indentation as needed
|
||||||
|
|
||||||
|
Extent extent = traverser.get();
|
||||||
|
builder.append("\n").append(indent).append("- ").append(extent.getClass().getSimpleName());
|
||||||
|
|
||||||
|
// Recursively print nested extents
|
||||||
|
printNestedExtent(builder, traverser.next(), depth + 1);
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3892,7 +3892,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Clipboard lazyCopy(Region region) {
|
public Clipboard lazyCopy(Region region) {
|
||||||
WorldCopyClipboard faweClipboard = new WorldCopyClipboard(() -> this, region);
|
WorldCopyClipboard faweClipboard = WorldCopyClipboard.of(this, region);
|
||||||
faweClipboard.setOrigin(region.getMinimumPoint());
|
faweClipboard.setOrigin(region.getMinimumPoint());
|
||||||
return faweClipboard;
|
return faweClipboard;
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import com.fastasyncworldedit.core.extent.clipboard.DiskOptimizedClipboard;
|
|||||||
import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
||||||
import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard;
|
import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard;
|
||||||
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
||||||
|
import com.fastasyncworldedit.core.extent.clipboard.WorldCopyClipboard;
|
||||||
import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream;
|
import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream;
|
||||||
import com.fastasyncworldedit.core.limit.FaweLimit;
|
import com.fastasyncworldedit.core.limit.FaweLimit;
|
||||||
import com.fastasyncworldedit.core.util.ImgurUtility;
|
import com.fastasyncworldedit.core.util.ImgurUtility;
|
||||||
@ -191,7 +192,7 @@ public class ClipboardCommands {
|
|||||||
throw FaweCache.MAX_CHECKS;
|
throw FaweCache.MAX_CHECKS;
|
||||||
}
|
}
|
||||||
session.setClipboard(null);
|
session.setClipboard(null);
|
||||||
ReadOnlyClipboard lazyClipboard = ReadOnlyClipboard.of(region, !skipEntities, copyBiomes);
|
ReadOnlyClipboard lazyClipboard = WorldCopyClipboard.of(editSession, region, !skipEntities, copyBiomes);
|
||||||
|
|
||||||
lazyClipboard.setOrigin(session.getPlacementPosition(actor));
|
lazyClipboard.setOrigin(session.getPlacementPosition(actor));
|
||||||
session.setClipboard(new ClipboardHolder(lazyClipboard));
|
session.setClipboard(new ClipboardHolder(lazyClipboard));
|
||||||
|
@ -679,7 +679,7 @@ public interface Extent extends InputExtent, OutputExtent {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
default Clipboard lazyCopy(Region region) {
|
default Clipboard lazyCopy(Region region) {
|
||||||
WorldCopyClipboard faweClipboard = new WorldCopyClipboard(() -> this, region);
|
WorldCopyClipboard faweClipboard = WorldCopyClipboard.of(this, region);
|
||||||
faweClipboard.setOrigin(region.getMinimumPoint());
|
faweClipboard.setOrigin(region.getMinimumPoint());
|
||||||
return faweClipboard;
|
return faweClipboard;
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,9 @@ public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable, Fl
|
|||||||
}
|
}
|
||||||
|
|
||||||
default void paste(Extent extent, BlockVector3 to, boolean pasteAir, boolean pasteEntities, boolean pasteBiomes) {
|
default void paste(Extent extent, BlockVector3 to, boolean pasteAir, boolean pasteEntities, boolean pasteBiomes) {
|
||||||
|
boolean close = false;
|
||||||
if (extent instanceof World) {
|
if (extent instanceof World) {
|
||||||
|
close = true;
|
||||||
EditSessionBuilder builder = WorldEdit
|
EditSessionBuilder builder = WorldEdit
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.newEditSessionBuilder()
|
.newEditSessionBuilder()
|
||||||
@ -419,6 +421,9 @@ public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable, Fl
|
|||||||
extent.createEntity(newPos, entity.getState());
|
extent.createEntity(newPos, entity.getState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (close) {
|
||||||
|
((EditSession) extent).close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//FAWE end
|
//FAWE end
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,21 @@ import com.fastasyncworldedit.core.configuration.Settings;
|
|||||||
import com.fastasyncworldedit.core.extent.BlockTranslateExtent;
|
import com.fastasyncworldedit.core.extent.BlockTranslateExtent;
|
||||||
import com.fastasyncworldedit.core.extent.OncePerChunkExtent;
|
import com.fastasyncworldedit.core.extent.OncePerChunkExtent;
|
||||||
import com.fastasyncworldedit.core.extent.PositionTransformExtent;
|
import com.fastasyncworldedit.core.extent.PositionTransformExtent;
|
||||||
|
import com.fastasyncworldedit.core.extent.clipboard.WorldCopyClipboard;
|
||||||
import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder;
|
import com.fastasyncworldedit.core.extent.processor.ExtentBatchProcessorHolder;
|
||||||
import com.fastasyncworldedit.core.function.RegionMaskTestFunction;
|
import com.fastasyncworldedit.core.function.RegionMaskTestFunction;
|
||||||
import com.fastasyncworldedit.core.function.block.BiomeCopy;
|
import com.fastasyncworldedit.core.function.block.BiomeCopy;
|
||||||
import com.fastasyncworldedit.core.function.block.CombinedBlockCopy;
|
import com.fastasyncworldedit.core.function.block.CombinedBlockCopy;
|
||||||
import com.fastasyncworldedit.core.function.block.SimpleBlockCopy;
|
import com.fastasyncworldedit.core.function.block.SimpleBlockCopy;
|
||||||
import com.fastasyncworldedit.core.function.visitor.IntersectRegionFunction;
|
import com.fastasyncworldedit.core.function.visitor.IntersectRegionFunction;
|
||||||
|
import com.fastasyncworldedit.core.queue.IChunkGet;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
import com.fastasyncworldedit.core.queue.IQueueChunk;
|
||||||
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
import com.fastasyncworldedit.core.queue.IQueueExtent;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
import com.fastasyncworldedit.core.queue.implementation.ParallelQueueExtent;
|
||||||
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
|
import com.fastasyncworldedit.core.queue.implementation.SingleThreadQueueExtent;
|
||||||
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
import com.fastasyncworldedit.core.util.ExtentTraverser;
|
||||||
import com.fastasyncworldedit.core.util.MaskTraverser;
|
import com.fastasyncworldedit.core.util.MaskTraverser;
|
||||||
|
import com.fastasyncworldedit.core.util.ProcessorTraverser;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.sk89q.worldedit.WorldEditException;
|
import com.sk89q.worldedit.WorldEditException;
|
||||||
@ -57,6 +60,7 @@ import com.sk89q.worldedit.math.BlockVector3;
|
|||||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||||
import com.sk89q.worldedit.math.transform.Identity;
|
import com.sk89q.worldedit.math.transform.Identity;
|
||||||
import com.sk89q.worldedit.math.transform.Transform;
|
import com.sk89q.worldedit.math.transform.Transform;
|
||||||
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.FlatRegion;
|
import com.sk89q.worldedit.regions.FlatRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
@ -69,7 +73,9 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -422,54 +428,7 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
blockCopy = new RegionVisitor(region, copy, preloader);
|
blockCopy = new RegionVisitor(region, copy, preloader);
|
||||||
}
|
}
|
||||||
|
|
||||||
Collection<Entity> entities;
|
Collection<Entity> entities = copyingEntities ? getEntities(source, region) : Collections.emptySet();
|
||||||
if (copyingEntities) {
|
|
||||||
IQueueExtent<IQueueChunk> queue;
|
|
||||||
Extent ext = source instanceof AbstractDelegateExtent ex ? ex.getExtent() : source;
|
|
||||||
ParallelQueueExtent parallel = new ExtentTraverser<>(source).findAndGet(ParallelQueueExtent.class);
|
|
||||||
if (parallel != null) {
|
|
||||||
queue = parallel.getExtent();
|
|
||||||
} else {
|
|
||||||
queue = new ExtentTraverser<>(source).findAndGet(SingleThreadQueueExtent.class);
|
|
||||||
}
|
|
||||||
if (Settings.settings().EXPERIMENTAL.IMPROVED_ENTITY_EDITS && queue != null) {
|
|
||||||
entities = new LinkedBlockingQueue<>();
|
|
||||||
OncePerChunkExtent oncePer = new OncePerChunkExtent(
|
|
||||||
ext,
|
|
||||||
queue,
|
|
||||||
(get) -> {
|
|
||||||
if (region.containsChunk(get.getX(), get.getZ())) {
|
|
||||||
entities.addAll(get.getFullEntities());
|
|
||||||
} else {
|
|
||||||
get.getFullEntities().forEach(e -> {
|
|
||||||
if (region.contains(e.getLocation().toBlockPoint())) {
|
|
||||||
entities.add(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
ExtentBatchProcessorHolder batchExtent =
|
|
||||||
new ExtentTraverser<>(source).findAndGet(ExtentBatchProcessorHolder.class);
|
|
||||||
if (batchExtent != null) {
|
|
||||||
batchExtent.getProcessor().join(oncePer);
|
|
||||||
} else {
|
|
||||||
new ExtentTraverser(source).setNext(oncePer);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (Settings.settings().EXPERIMENTAL.IMPROVED_ENTITY_EDITS) {
|
|
||||||
LOGGER.warn("Could not find IQueueExtent instance for entity retrieval, falling back to default method.");
|
|
||||||
}
|
|
||||||
// filter players since they can't be copied
|
|
||||||
entities = new HashSet<>(source.getEntities(region));
|
|
||||||
entities.removeIf(entity -> {
|
|
||||||
EntityProperties properties = entity.getFacet(EntityProperties.class);
|
|
||||||
return properties != null && !properties.isPasteable();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
entities = Collections.emptySet();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < repetitions; i++) {
|
for (int i = 0; i < repetitions; i++) {
|
||||||
Operations.completeBlindly(blockCopy);
|
Operations.completeBlindly(blockCopy);
|
||||||
@ -508,6 +467,78 @@ public class ForwardExtentCopy implements Operation {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If setting enabled, Creates a new OncePerChunkExtent instance to retain a list of entities for the given source extent,
|
||||||
|
* then add it to the source extent. If setting is not set simply returns the entities from {@link Extent#getEntities()} Accepts an
|
||||||
|
* optional region for entities to be within.
|
||||||
|
*
|
||||||
|
* @param source Source extent
|
||||||
|
* @param region Optional regions for entities to be within
|
||||||
|
* @return Collection of entities (may not be filled until an operation completes on the chunks)
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public static Collection<Entity> getEntities(Extent source, Region region) {
|
||||||
|
Extent extent = source;
|
||||||
|
if (source instanceof WorldCopyClipboard clip) {
|
||||||
|
extent = clip.getExtent();
|
||||||
|
}
|
||||||
|
IQueueExtent<IQueueChunk> queue = null;
|
||||||
|
if (Settings.settings().EXPERIMENTAL.IMPROVED_ENTITY_EDITS) {
|
||||||
|
ParallelQueueExtent parallel = new ExtentTraverser<>(extent).findAndGet(ParallelQueueExtent.class);
|
||||||
|
if (parallel != null) {
|
||||||
|
queue = parallel.getExtent();
|
||||||
|
} else {
|
||||||
|
queue = new ExtentTraverser<>(extent).findAndGet(SingleThreadQueueExtent.class);
|
||||||
|
}
|
||||||
|
if (queue == null) {
|
||||||
|
LOGGER.warn("Could not find IQueueExtent instance for entity retrieval, OncePerChunkExtent will not work.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (queue == null) {
|
||||||
|
Set<Entity> entities = new HashSet<>(region != null ? source.getEntities(region) : source.getEntities());
|
||||||
|
entities.removeIf(entity -> {
|
||||||
|
EntityProperties properties = entity.getFacet(EntityProperties.class);
|
||||||
|
return properties != null && !properties.isPasteable();
|
||||||
|
});
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
LinkedBlockingQueue<Entity> entities = new LinkedBlockingQueue<>();
|
||||||
|
Consumer<IChunkGet> task = (get) -> {
|
||||||
|
if (region == null || region instanceof CuboidRegion cuboid && cuboid.chunkContainedBy(
|
||||||
|
get.getX(),
|
||||||
|
get.getZ(),
|
||||||
|
get.getMinY(),
|
||||||
|
get.getMaxY()
|
||||||
|
)) {
|
||||||
|
entities.addAll(get.getFullEntities());
|
||||||
|
} else {
|
||||||
|
get.getFullEntities().forEach(e -> {
|
||||||
|
if (region.contains(e.getLocation().toBlockPoint())) {
|
||||||
|
entities.add(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Extent ext = extent instanceof AbstractDelegateExtent ex ? ex.getExtent() : extent;
|
||||||
|
ExtentBatchProcessorHolder batchExtent = new ExtentTraverser<>(extent).findAndGet(ExtentBatchProcessorHolder.class);
|
||||||
|
OncePerChunkExtent oncePer = new ExtentTraverser<>(extent).findAndGet(OncePerChunkExtent.class);
|
||||||
|
if (batchExtent != null && oncePer == null) {
|
||||||
|
oncePer = new ProcessorTraverser<>(batchExtent).find(OncePerChunkExtent.class);
|
||||||
|
}
|
||||||
|
if (oncePer != null) {
|
||||||
|
oncePer.reset();
|
||||||
|
oncePer.setTask(task);
|
||||||
|
} else {
|
||||||
|
oncePer = new OncePerChunkExtent(ext, queue, task);
|
||||||
|
if (false && batchExtent != null) {
|
||||||
|
batchExtent.getProcessor().join(oncePer);
|
||||||
|
} else {
|
||||||
|
new ExtentTraverser(extent).setNext(oncePer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return entities;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
}
|
}
|
||||||
|
@ -744,6 +744,26 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
|
|||||||
return maxZ;
|
return maxZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an entire chunk is contained by this region
|
||||||
|
*
|
||||||
|
* @param chunkX chunk x coord
|
||||||
|
* @param chunkZ chunk z coord
|
||||||
|
* @param chunkMinY The minimum Y level of the chunk
|
||||||
|
* @param chunkMaxY The maximum Y level of the chunk
|
||||||
|
* @return If the entire chunk is contained by this region
|
||||||
|
* @since TODO
|
||||||
|
*/
|
||||||
|
public boolean chunkContainedBy(int chunkX, int chunkZ, int chunkMinY, int chunkMaxY) {
|
||||||
|
int bx = chunkX << 4;
|
||||||
|
int bz = chunkZ << 4;
|
||||||
|
int tx = bx + 15;
|
||||||
|
int tz = bz + 15;
|
||||||
|
BlockVector3 min = getMinimumPoint();
|
||||||
|
BlockVector3 max = getMaximumPoint();
|
||||||
|
return min.getY() <= chunkMinY && max.getY() >= chunkMaxY && min.getX() <= bx && max.getX() >= tx && min.getZ() <= bz && max.getZ() >= tz;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void filter(
|
public void filter(
|
||||||
final IChunk chunk,
|
final IChunk chunk,
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren