Skip to content

Commit d1865b6

Browse files
chore: improve performance of upstream's trim command (#3170)
Co-authored-by: Hannes Greule <[email protected]>
1 parent 6cce42d commit d1865b6

File tree

1 file changed

+75
-98
lines changed

1 file changed

+75
-98
lines changed

worldedit-core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java

Lines changed: 75 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@
2121

2222
import com.fastasyncworldedit.core.configuration.Caption;
2323
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
24+
import com.fastasyncworldedit.core.extent.filter.ForkedFilter;
25+
import com.fastasyncworldedit.core.extent.filter.MaskFilter;
26+
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
2427
import com.fastasyncworldedit.core.function.mask.IdMask;
28+
import com.fastasyncworldedit.core.queue.Filter;
2529
import com.fastasyncworldedit.core.regions.selector.FuzzyRegionSelector;
2630
import com.fastasyncworldedit.core.regions.selector.PolyhedralRegionSelector;
2731
import com.fastasyncworldedit.core.util.MaskTraverser;
@@ -48,7 +52,6 @@
4852
import com.sk89q.worldedit.function.block.BlockDistributionCounter;
4953
import com.sk89q.worldedit.function.mask.Mask;
5054
import com.sk89q.worldedit.function.mask.MaskIntersection;
51-
import com.sk89q.worldedit.function.mask.Masks;
5255
import com.sk89q.worldedit.function.mask.RegionMask;
5356
import com.sk89q.worldedit.function.operation.Operations;
5457
import com.sk89q.worldedit.function.visitor.RegionVisitor;
@@ -518,125 +521,99 @@ private BlockVector3[] getChangesForEachDir(int amount, boolean onlyHorizontal,
518521
)
519522
@Logging(REGION)
520523
@CommandPermissions("worldedit.selection.trim")
521-
public void trim(Actor actor, World world, LocalSession session,
524+
public void trim(Actor actor, World world, LocalSession session, EditSession editSession,
522525
@Arg(desc = "Mask of blocks to keep within the selection", def = "#existing")
523526
Mask mask) throws WorldEditException {
527+
//FAWE start
524528
// Avoid checking blocks outside the original region but within the cuboid region
525529
Region originalRegion = session.getSelection(world);
526-
if (!(originalRegion instanceof CuboidRegion)) {
527-
mask = new MaskIntersection(new RegionMask(originalRegion), mask);
528-
}
530+
new MaskTraverser(mask).setNewExtent(editSession);
529531

530532
// Result region will be cuboid
531-
CuboidRegion region = originalRegion.getBoundingBox();
532-
533-
BlockVector3 min = region.getMinimumPoint();
534-
BlockVector3 max = region.getMaximumPoint();
535-
536-
int minY = 0;
537-
boolean found = false;
538-
539-
outer: for (int y = min.y(); y <= max.y(); y++) {
540-
for (int x = min.x(); x <= max.x(); x++) {
541-
for (int z = min.z(); z <= max.z(); z++) {
542-
BlockVector3 vec = BlockVector3.at(x, y, z);
543-
544-
if (mask.test(vec)) {
545-
found = true;
546-
minY = y;
547-
548-
break outer;
549-
}
550-
}
533+
final CuboidRegion region = originalRegion.getBoundingBox();
534+
535+
// subtract offset to determine if there was any change later
536+
final BlockVector3 min = region.getMinimumPoint().subtract(BlockVector3.ONE);
537+
final BlockVector3 max = region.getMaximumPoint();
538+
539+
class TrimFilter extends ForkedFilter<TrimFilter> {
540+
private int minX;
541+
private int minY;
542+
private int minZ;
543+
private int maxX;
544+
private int maxY;
545+
private int maxZ;
546+
547+
public TrimFilter(final BlockVector3 min, final BlockVector3 max) {
548+
super(null);
549+
this.minX = max.x();
550+
this.minY = max.y();
551+
this.minZ = max.z();
552+
this.maxX = min.x();
553+
this.maxY = min.y();
554+
this.maxZ = min.z();
551555
}
552-
}
553556

554-
// If anything was found in the first pass, then the remaining variables are guaranteed to be set
555-
if (!found) {
556-
throw new StopExecutionException(Caption.of("worldedit.trim.no-blocks"));
557-
}
558-
559-
int maxY = minY;
560-
561-
outer: for (int y = max.y(); y > minY; y--) {
562-
for (int x = min.x(); x <= max.x(); x++) {
563-
for (int z = min.z(); z <= max.z(); z++) {
564-
BlockVector3 vec = BlockVector3.at(x, y, z);
565-
566-
if (mask.test(vec)) {
567-
maxY = y;
568-
break outer;
569-
}
570-
}
557+
public TrimFilter(
558+
final TrimFilter root,
559+
final int minX,
560+
final int minY,
561+
final int minZ,
562+
final int maxX,
563+
final int maxY,
564+
final int maxZ
565+
) {
566+
super(root);
567+
this.minX = minX;
568+
this.minY = minY;
569+
this.minZ = minZ;
570+
this.maxX = maxX;
571+
this.maxY = maxY;
572+
this.maxZ = maxZ;
571573
}
572-
}
573-
574-
int minX = 0;
575574

576-
outer: for (int x = min.x(); x <= max.x(); x++) {
577-
for (int z = min.z(); z <= max.z(); z++) {
578-
for (int y = minY; y <= maxY; y++) {
579-
BlockVector3 vec = BlockVector3.at(x, y, z);
580-
581-
if (mask.test(vec)) {
582-
minX = x;
583-
break outer;
584-
}
585-
}
575+
@Override
576+
public void applyBlock(final FilterBlock block) {
577+
this.minX = Math.min(this.minX, block.x());
578+
this.maxX = Math.max(this.maxX, block.x());
579+
this.minY = Math.min(this.minY, block.y());
580+
this.maxY = Math.max(this.maxY, block.y());
581+
this.minZ = Math.min(this.minZ, block.z());
582+
this.maxZ = Math.max(this.maxZ, block.z());
586583
}
587-
}
588-
589-
int maxX = minX;
590584

591-
outer: for (int x = max.x(); x > minX; x--) {
592-
for (int z = min.z(); z <= max.z(); z++) {
593-
for (int y = minY; y <= maxY; y++) {
594-
BlockVector3 vec = BlockVector3.at(x, y, z);
595-
596-
if (mask.test(vec)) {
597-
maxX = x;
598-
break outer;
599-
}
600-
}
585+
@Override
586+
public TrimFilter init() {
587+
return new TrimFilter(this, this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ);
601588
}
602-
}
603-
604-
int minZ = 0;
605-
606-
outer: for (int z = min.z(); z <= max.z(); z++) {
607-
for (int x = minX; x <= maxX; x++) {
608-
for (int y = minY; y <= maxY; y++) {
609-
BlockVector3 vec = BlockVector3.at(x, y, z);
610589

611-
if (mask.test(vec)) {
612-
minZ = z;
613-
break outer;
614-
}
615-
}
590+
@Override
591+
public void join(final TrimFilter filter) {
592+
this.minX = Math.min(this.minX, filter.minX);
593+
this.maxX = Math.max(this.maxX, filter.maxX);
594+
this.minY = Math.min(this.minY, filter.minY);
595+
this.maxY = Math.max(this.maxY, filter.maxY);
596+
this.minZ = Math.min(this.minZ, filter.minZ);
597+
this.maxZ = Math.max(this.maxZ, filter.maxZ);
616598
}
617-
}
618-
619-
int maxZ = minZ;
620-
621-
outer: for (int z = max.z(); z > minZ; z--) {
622-
for (int x = minX; x <= maxX; x++) {
623-
for (int y = minY; y <= maxY; y++) {
624-
BlockVector3 vec = BlockVector3.at(x, y, z);
625599

626-
if (mask.test(vec)) {
627-
maxZ = z;
628-
break outer;
629-
}
630-
}
631-
}
632600
}
601+
TrimFilter result = editSession.apply(region, new MaskFilter<>(new TrimFilter(min, max), mask), true).getParent();
633602

634603
final CuboidRegionSelector selector;
604+
final BlockVector3 newMin = BlockVector3.at(result.minX, result.minY, result.minZ);
605+
final BlockVector3 newMax = BlockVector3.at(result.maxX, result.maxY, result.maxZ);
606+
607+
// If anything was found, then all variables are guaranteed to be set to something inside the region
608+
if (newMax.equals(min)) {
609+
throw new StopExecutionException(Caption.of("worldedit.trim.no-blocks"));
610+
}
635611
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) {
636-
selector = new ExtendingCuboidRegionSelector(world, BlockVector3.at(minX, minY, minZ), BlockVector3.at(maxX, maxY, maxZ));
612+
selector = new ExtendingCuboidRegionSelector(world, newMin, newMax);
637613
} else {
638-
selector = new CuboidRegionSelector(world, BlockVector3.at(minX, minY, minZ), BlockVector3.at(maxX, maxY, maxZ));
614+
selector = new CuboidRegionSelector(world, newMin, newMax);
639615
}
616+
//FAWE end
640617
session.setRegionSelector(world, selector);
641618

642619
session.getRegionSelector(world).learnChanges();

0 commit comments

Comments
 (0)