Allow stacking by block units with //stack (#1539)

* Allow stacking by block units with //stack

* Delegate out the old method

* Use CuboidRegion as the type of the new region

* Fixed up PR notes

* Add docs

* No indent

* Formatting

* Use the bounding box rather than limiting it

* Don't limit to cuboid

* Make the old one use the block unit method

* Update the selection movement too

* Fixed affected being missed

* Use an assertion erorr
This commit is contained in:
Matthew Miller 2020-09-29 19:38:26 +10:00 committed by GitHub
parent 25957c4498
commit a1313a0edd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 6 deletions

View File

@ -99,6 +99,7 @@
import com.sk89q.worldedit.regions.EllipsoidRegion;
import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.Regions;
import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape;
import com.sk89q.worldedit.regions.shape.ArbitraryShape;
@ -1401,13 +1402,44 @@ public int stackCuboidRegion(Region region, BlockVector3 offset, int count,
boolean copyEntities, boolean copyBiomes, Mask mask) throws MaxChangedBlocksException {
checkNotNull(region);
checkNotNull(offset);
BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
try {
return stackRegionBlockUnits(region, offset.multiply(size), count, copyEntities, copyBiomes, mask);
} catch (RegionOperationException e) {
// Should never be able to happen
throw new AssertionError(e);
}
}
/**
* Stack a region using block units.
*
* @param region the region to stack
* @param offset how far to move the contents each stack in block units
* @param count the number of times to stack
* @param copyEntities true to copy entities
* @param copyBiomes true to copy biomes
* @param mask source mask for the operation (only matching blocks are copied)
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
* @throws RegionOperationException thrown if the region operation is invalid
*/
public int stackRegionBlockUnits(Region region, BlockVector3 offset, int count,
boolean copyEntities, boolean copyBiomes, Mask mask) throws MaxChangedBlocksException, RegionOperationException {
checkNotNull(region);
checkNotNull(offset);
checkArgument(count >= 1, "count >= 1 required");
BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
BlockVector3 offsetAbs = offset.abs();
if (offsetAbs.getX() < size.getX() && offsetAbs.getY() < size.getY() && offsetAbs.getZ() < size.getZ()) {
throw new RegionOperationException(TranslatableComponent.of("worldedit.stack.intersecting-region"));
}
BlockVector3 to = region.getMinimumPoint();
ForwardExtentCopy copy = new ForwardExtentCopy(this, region, this, to);
copy.setRepetitions(count);
copy.setTransform(new AffineTransform().translate(offset.multiply(size)));
copy.setTransform(new AffineTransform().translate(offset));
copy.setCopyingEntities(copyEntities);
copy.setCopyingBiomes(copyBiomes);
if (mask != null) {

View File

@ -338,7 +338,7 @@ public int move(Actor actor, World world, EditSession editSession, LocalSession
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(actor, session);
} catch (RegionOperationException e) {
actor.printError(TextComponent.of(e.getMessage()));
actor.printError(e.getRichMessage());
}
}
@ -367,9 +367,10 @@ public int stack(Actor actor, World world, EditSession editSession, LocalSession
boolean copyEntities,
@Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes,
@Switch(name = 'r', desc = "Use block units")
boolean blockUnits,
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
Mask mask) throws WorldEditException {
Mask combinedMask;
if (ignoreAirBlocks) {
if (mask == null) {
@ -381,19 +382,25 @@ public int stack(Actor actor, World world, EditSession editSession, LocalSession
combinedMask = mask;
}
int affected = editSession.stackCuboidRegion(region, offset, count, copyEntities, copyBiomes, combinedMask);
int affected;
if (blockUnits) {
affected = editSession.stackRegionBlockUnits(region, offset, count, copyEntities, copyBiomes, combinedMask);
} else {
affected = editSession.stackCuboidRegion(region, offset, count, copyEntities, copyBiomes, combinedMask);
}
if (moveSelection) {
try {
final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final BlockVector3 shiftVector = offset.multiply(size).multiply(count);
final BlockVector3 shiftSize = blockUnits ? offset : offset.multiply(size);
final BlockVector3 shiftVector = shiftSize.multiply(count);
region.shift(shiftVector);
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(actor, session);
} catch (RegionOperationException e) {
actor.printError(TextComponent.of(e.getMessage()));
actor.printError(e.getRichMessage());
}
}

View File

@ -191,6 +191,7 @@
"worldedit.curve.invalid-type": "//curve only works with convex polyhedral selections",
"worldedit.replace.replaced": "{0} blocks have been replaced.",
"worldedit.stack.changed": "{0} blocks changed. Undo with //undo",
"worldedit.stack.intersecting-region": "Stack offset must not collide with the region when using block units",
"worldedit.regen.regenerated": "Region regenerated.",
"worldedit.regen.failed": "Unable to regenerate chunks. Check console for details.",
"worldedit.walls.changed": "{0} blocks have been changed.",