Skip to content

Commit

Permalink
Add the trim command
Browse files Browse the repository at this point in the history
Fixes #1629
  • Loading branch information
haykam821 authored and me4502 committed Jun 24, 2023
1 parent a3a5b07 commit 1844b75
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.MultiDirection;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector;
Expand Down Expand Up @@ -504,6 +505,133 @@ private BlockVector3[] getChangesForEachDir(int amount, boolean onlyHorizontal,
return changes.build().map(v -> v.multiply(amount)).toArray(BlockVector3[]::new);
}

@Command(
name = "/trim",
desc = "Minimize the selection to encompass matching blocks"
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.trim")
public void trim(Actor actor, World world, LocalSession session,
@Arg(desc = "Mask of blocks to keep within the selection", def = "#existing")
Mask mask) throws WorldEditException {
// Avoid checking blocks outside the original region but within the cuboid region
Region originalRegion = session.getSelection(world);
boolean skipContains = originalRegion instanceof CuboidRegion;

// Result region will be cuboid
CuboidRegion region = originalRegion.getBoundingBox();

BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();

int minY = 0;
boolean found = false;

outer: for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
BlockVector3 vec = BlockVector3.at(x, y, z);

if ((skipContains || originalRegion.contains(vec)) && mask.test(vec)) {
found = true;
minY = y;

break outer;
}
}
}
}

// If anything was found in the first pass, then the remaining variables are guaranteed to be set
if (!found) {
throw new StopExecutionException(TranslatableComponent.of(
"worldedit.trim.no-blocks"));
}

int maxY = minY;

outer: for (int y = max.getBlockY(); y > minY; y--) {
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
BlockVector3 vec = BlockVector3.at(x, y, z);

if ((skipContains || originalRegion.contains(vec)) && mask.test(vec)) {
maxY = y;
break outer;
}
}
}
}

int minX = 0;

outer: for (int x = min.getBlockX(); x <= max.getBlockX(); x++) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
for (int y = minY; y <= maxY; y++) {
BlockVector3 vec = BlockVector3.at(x, y, z);

if ((skipContains || originalRegion.contains(vec)) && mask.test(vec)) {
minX = x;
break outer;
}
}
}
}

int maxX = minX;

outer: for (int x = max.getBlockX(); x > minX; x--) {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
for (int y = minY; y <= maxY; y++) {
BlockVector3 vec = BlockVector3.at(x, y, z);

if ((skipContains || originalRegion.contains(vec)) && mask.test(vec)) {
maxX = x;
break outer;
}
}
}
}

int minZ = 0;

outer: for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) {
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
BlockVector3 vec = BlockVector3.at(x, y, z);

if ((skipContains || originalRegion.contains(vec)) && mask.test(vec)) {
minZ = z;
break outer;
}
}
}
}

int maxZ = minZ;

outer: for (int z = max.getBlockZ(); z > minZ; z--) {
for (int x = minX; x <= maxX; x++) {
for (int y = minY; y <= maxY; y++) {
BlockVector3 vec = BlockVector3.at(x, y, z);

if ((skipContains || originalRegion.contains(vec)) && mask.test(vec)) {
maxZ = z;
break outer;
}
}
}
}

session.setRegionSelector(world, new CuboidRegionSelector(
world, BlockVector3.at(minX, minY, minZ), BlockVector3.at(maxX, maxY, maxZ)
));

session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(actor, session);
actor.printInfo(TranslatableComponent.of("worldedit.trim.trim"));
}

@Command(
name = "/size",
desc = "Get information about the selection"
Expand Down
2 changes: 2 additions & 0 deletions worldedit-core/src/main/resources/lang/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@
"worldedit.shift.shifted": "Region shifted.",
"worldedit.outset.outset": "Region outset.",
"worldedit.inset.inset": "Region inset.",
"worldedit.trim.trim": "Region trimmed.",
"worldedit.trim.no-blocks": "No blocks matched the trim mask.",
"worldedit.size.offset": "Offset: {0}",
"worldedit.size.type": "Type: {0}",
"worldedit.size.size": "Size: {0}",
Expand Down

0 comments on commit 1844b75

Please sign in to comment.