Skip to content

Commit aee75c1

Browse files
Timongcrafthaykam821me4502
authored
feat: add upstream's trim command (EngineHub/WorldEdit#2278) (#3168)
feat: add the trim command (EngineHub/WorldEdit#2278) * Add the trim command * Fix issues from PR review * Cleanup usages of deprecated Vector getters * chore: cleanup translations & memoize mask --------- Co-authored-by: haykam821 <[email protected]> Co-authored-by: Madeline Miller <[email protected]>
1 parent eca3ce2 commit aee75c1

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

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

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,15 @@
4747
import com.sk89q.worldedit.extent.clipboard.Clipboard;
4848
import com.sk89q.worldedit.function.block.BlockDistributionCounter;
4949
import com.sk89q.worldedit.function.mask.Mask;
50+
import com.sk89q.worldedit.function.mask.MaskIntersection;
51+
import com.sk89q.worldedit.function.mask.Masks;
52+
import com.sk89q.worldedit.function.mask.RegionMask;
5053
import com.sk89q.worldedit.function.operation.Operations;
5154
import com.sk89q.worldedit.function.visitor.RegionVisitor;
5255
import com.sk89q.worldedit.internal.annotation.Direction;
5356
import com.sk89q.worldedit.internal.annotation.MultiDirection;
5457
import com.sk89q.worldedit.math.BlockVector3;
58+
import com.sk89q.worldedit.regions.CuboidRegion;
5559
import com.sk89q.worldedit.regions.Region;
5660
import com.sk89q.worldedit.regions.RegionOperationException;
5761
import com.sk89q.worldedit.regions.RegionSelector;
@@ -508,6 +512,138 @@ private BlockVector3[] getChangesForEachDir(int amount, boolean onlyHorizontal,
508512
return changes.build().map(v -> v.multiply(amount)).toArray(BlockVector3[]::new);
509513
}
510514

515+
@Command(
516+
name = "/trim",
517+
desc = "Minimize the selection to encompass matching blocks"
518+
)
519+
@Logging(REGION)
520+
@CommandPermissions("worldedit.selection.trim")
521+
public void trim(Actor actor, World world, LocalSession session,
522+
@Arg(desc = "Mask of blocks to keep within the selection", def = "#existing")
523+
Mask mask) throws WorldEditException {
524+
// Avoid checking blocks outside the original region but within the cuboid region
525+
Region originalRegion = session.getSelection(world);
526+
if (!(originalRegion instanceof CuboidRegion)) {
527+
mask = new MaskIntersection(new RegionMask(originalRegion), mask);
528+
}
529+
530+
// 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+
}
551+
}
552+
}
553+
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+
}
571+
}
572+
}
573+
574+
int minX = 0;
575+
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+
}
586+
}
587+
}
588+
589+
int maxX = minX;
590+
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+
}
601+
}
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);
610+
611+
if (mask.test(vec)) {
612+
minZ = z;
613+
break outer;
614+
}
615+
}
616+
}
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);
625+
626+
if (mask.test(vec)) {
627+
maxZ = z;
628+
break outer;
629+
}
630+
}
631+
}
632+
}
633+
634+
final CuboidRegionSelector selector;
635+
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) {
636+
selector = new ExtendingCuboidRegionSelector(world, BlockVector3.at(minX, minY, minZ), BlockVector3.at(maxX, maxY, maxZ));
637+
} else {
638+
selector = new CuboidRegionSelector(world, BlockVector3.at(minX, minY, minZ), BlockVector3.at(maxX, maxY, maxZ));
639+
}
640+
session.setRegionSelector(world, selector);
641+
642+
session.getRegionSelector(world).learnChanges();
643+
session.getRegionSelector(world).explainRegionAdjust(actor, session);
644+
actor.print(Caption.of("worldedit.trim.trim"));
645+
}
646+
511647
@Command(
512648
name = "/size",
513649
desc = "Get information about the selection"

worldedit-core/src/main/resources/lang/strings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@
416416
"worldedit.shift.shifted": "Region shifted.",
417417
"worldedit.outset.outset": "Region outset.",
418418
"worldedit.inset.inset": "Region inset.",
419+
"worldedit.trim.trim": "Region trimmed.",
420+
"worldedit.trim.no-blocks": "No blocks matched the trim mask.",
419421
"worldedit.size.offset": "{0}: {1} @ {2} ({3} blocks)",
420422
"worldedit.size.type": "Type: {0}",
421423
"worldedit.size.size": "Size: {0}",

0 commit comments

Comments
 (0)