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

- closes #2968

Co-authored-by: Matthew Miller <mnmiller1@me.com>
Dieser Commit ist enthalten in:
Jordan 2024-11-04 11:20:17 +00:00 committet von GitHub
Ursprung c213dae547
Commit 44f7b63fb1
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: B5690EEEBB952194
3 geänderte Dateien mit 59 neuen und 9 gelöschten Zeilen

Datei anzeigen

@ -127,6 +127,7 @@ import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.NullRegion; import com.sk89q.worldedit.regions.NullRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionIntersection; import com.sk89q.worldedit.regions.RegionIntersection;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.regions.Regions;
import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape; import com.sk89q.worldedit.regions.shape.ArbitraryBiomeShape;
import com.sk89q.worldedit.regions.shape.ArbitraryShape; import com.sk89q.worldedit.regions.shape.ArbitraryShape;
@ -1804,18 +1805,59 @@ public class EditSession extends PassthroughExtent implements AutoCloseable {
* @throws MaxChangedBlocksException thrown if too many blocks are changed * @throws MaxChangedBlocksException thrown if too many blocks are changed
*/ */
public int stackCuboidRegion( public int stackCuboidRegion(
Region region, BlockVector3 offset, int count, Region region,
boolean copyEntities, boolean copyBiomes, Mask mask BlockVector3 offset,
int count,
boolean copyEntities,
boolean copyBiomes,
Mask mask
) throws MaxChangedBlocksException { ) throws MaxChangedBlocksException {
checkNotNull(region); checkNotNull(region);
checkNotNull(offset); 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"); checkArgument(count >= 1, "count >= 1 required");
BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
BlockVector3 offsetAbs = offset.abs();
if (offsetAbs.x() < size.x() && offsetAbs.y() < size.y() && offsetAbs.z() < size.z()) {
throw new RegionOperationException(Caption.of("worldedit.stack.intersecting-region"));
}
BlockVector3 to = region.getMinimumPoint(); BlockVector3 to = region.getMinimumPoint();
ForwardExtentCopy copy = new ForwardExtentCopy(this, region, this, to); ForwardExtentCopy copy = new ForwardExtentCopy(this, region, this, to);
copy.setRepetitions(count); copy.setRepetitions(count);
copy.setTransform(new AffineTransform().translate(offset.multiply(size))); copy.setTransform(new AffineTransform().translate(offset));
copy.setCopyingEntities(copyEntities); copy.setCopyingEntities(copyEntities);
copy.setCopyingBiomes(copyBiomes); copy.setCopyingBiomes(copyBiomes);
final Region allowedRegion; final Region allowedRegion;

Datei anzeigen

@ -594,7 +594,7 @@ public class RegionCommands {
session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(actor, session); session.getRegionSelector(world).explainRegionAdjust(actor, session);
} catch (RegionOperationException e) { } catch (RegionOperationException e) {
actor.printError(TextComponent.of(e.getMessage())); actor.printError(e.getRichMessage());
} }
} }
@ -640,7 +640,7 @@ public class RegionCommands {
int count, int count,
@Arg(desc = "How far to move the contents each stack", def = Offset.FORWARD) @Arg(desc = "How far to move the contents each stack", def = Offset.FORWARD)
@Offset @Offset
BlockVector3 direction, BlockVector3 offset,
@Switch(name = 's', desc = "Shift the selection to the last stacked copy") @Switch(name = 's', desc = "Shift the selection to the last stacked copy")
boolean moveSelection, boolean moveSelection,
@Switch(name = 'a', desc = "Ignore air blocks") @Switch(name = 'a', desc = "Ignore air blocks")
@ -649,6 +649,8 @@ public class RegionCommands {
boolean copyEntities, boolean copyEntities,
@Switch(name = 'b', desc = "Also copy biomes") @Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes, boolean copyBiomes,
@Switch(name = 'r', desc = "Use block units")
boolean blockUnits,
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air") @ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air")
Mask mask Mask mask
) throws WorldEditException { ) throws WorldEditException {
@ -668,19 +670,24 @@ public class RegionCommands {
combinedMask = mask; combinedMask = mask;
} }
int affected = editSession.stackCuboidRegion(region, direction, 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) { if (moveSelection) {
try { try {
final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1); final BlockVector3 size = region.getMaximumPoint().subtract(region.getMinimumPoint()).add(1, 1, 1);
final BlockVector3 shiftSize = blockUnits ? offset : offset.multiply(size);
final BlockVector3 shiftVector = direction.multiply(size).multiply(count); final BlockVector3 shiftVector = shiftSize.multiply(count);
region.shift(shiftVector); region.shift(shiftVector);
session.getRegionSelector(world).learnChanges(); session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(actor, session); session.getRegionSelector(world).explainRegionAdjust(actor, session);
} catch (RegionOperationException e) { } catch (RegionOperationException e) {
actor.printError(TextComponent.of(e.getMessage())); actor.printError(e.getRichMessage());
} }
} }

Datei anzeigen

@ -478,6 +478,7 @@
"worldedit.curve.convex-only": "//curve only works with convex polyhedral selections", "worldedit.curve.convex-only": "//curve only works with convex polyhedral selections",
"worldedit.replace.replaced": "{0} blocks have been replaced.", "worldedit.replace.replaced": "{0} blocks have been replaced.",
"worldedit.stack.changed": "{0} blocks changed. Undo with //undo", "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.regenerated": "Region regenerated.",
"worldedit.regen.failed": "Unable to regenerate chunks. Check console for details.", "worldedit.regen.failed": "Unable to regenerate chunks. Check console for details.",
"worldedit.walls.changed": "{0} blocks have been changed.", "worldedit.walls.changed": "{0} blocks have been changed.",