diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index a9f367791f..98d5ebccb8 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -54,6 +54,7 @@ import com.sk89q.worldedit.function.block.Counter; import com.sk89q.worldedit.function.block.Naturalizer; import com.sk89q.worldedit.function.block.SnowSimulator; +import com.sk89q.worldedit.function.block.Thawer; import com.sk89q.worldedit.function.generator.ForestGenerator; import com.sk89q.worldedit.function.generator.GardenPatchGenerator; import com.sk89q.worldedit.function.mask.BlockMask; @@ -2075,49 +2076,24 @@ public final int thaw(BlockVector3 position, double radius) */ public int thaw(BlockVector3 position, double radius, int height) throws MaxChangedBlocksException { - int affected = 0; - double radiusSq = radius * radius; - - int ox = position.x(); - int oy = position.y(); - int oz = position.z(); - - BlockState air = BlockTypes.AIR.getDefaultState(); - BlockState water = BlockTypes.WATER.getDefaultState(); - - int centerY = Math.max(getWorld().getMinY(), Math.min(getWorld().getMaxY(), oy)); - int minY = Math.max(getWorld().getMinY(), centerY - height); - int maxY = Math.min(getWorld().getMaxY(), centerY + height); - - int ceilRadius = (int) Math.ceil(radius); - for (int x = ox - ceilRadius; x <= ox + ceilRadius; ++x) { - for (int z = oz - ceilRadius; z <= oz + ceilRadius; ++z) { - if (BlockVector3.at(x, oy, z).distanceSq(position) > radiusSq) { - continue; - } - - for (int y = maxY; y > minY; --y) { - BlockVector3 pt = BlockVector3.at(x, y, z); - BlockType id = getBlock(pt).getBlockType(); - if (id == BlockTypes.ICE) { - if (setBlock(pt, water)) { - ++affected; - } - } else if (id == BlockTypes.SNOW) { - if (setBlock(pt, air)) { - ++affected; - } - } else if (id.getMaterial().isAir()) { - continue; - } + return thaw(new CylinderRegion(position, Vector2.at(radius, radius), position.y(), height)); + } - break; - } - } - } + /** + * Thaw blocks in a cylinder. + * + * @param region the region to thaw in + * @return number of blocks affected + * @throws MaxChangedBlocksException thrown if too many blocks are changed + */ + public final int thaw(FlatRegion region) throws MaxChangedBlocksException { + checkNotNull(region); - return affected; + Thawer thawer = new Thawer(this); + LayerVisitor layerVisitor = new LayerVisitor(region, region.getMinimumY(), region.getMaximumY(), thawer); + Operations.completeLegacy(layerVisitor); + return thawer.getAffected(); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 818770a769..11a081e116 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -335,7 +335,10 @@ public int thaw(Actor actor, LocalSession session, EditSession editSession, height = Math.max(1, height); we.checkMaxRadius(size); - int affected = editSession.thaw(session.getPlacementPosition(actor), size, height); + BlockVector3 position = session.getPlacementPosition(actor); + + CylinderRegion region = new CylinderRegion(position, Vector2.at(size, size), position.y() - height, position.y() + height); + int affected = editSession.thaw(region); actor.printInfo(TranslatableComponent.of( "worldedit.thaw.removed", TextComponent.of(affected) )); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/Thawer.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/Thawer.java new file mode 100644 index 0000000000..b6cc854309 --- /dev/null +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/Thawer.java @@ -0,0 +1,83 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.function.block; + +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.LayerFunction; +import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.world.block.BlockState; +import com.sk89q.worldedit.world.block.BlockType; +import com.sk89q.worldedit.world.block.BlockTypes; + +public class Thawer implements LayerFunction { + + private final BlockState air = BlockTypes.AIR.getDefaultState(); + private final BlockState water = BlockTypes.WATER.getDefaultState(); + + private final Extent extent; + + private int affected; + + /** + * Create a new instance. + * + * @param extent the extent to thaw in + */ + public Thawer(Extent extent) { + this.extent = extent; + this.affected = 0; + } + + public int getAffected() { + return this.affected; + } + + @Override + public boolean isGround(BlockVector3 position) { + BlockState block = this.extent.getBlock(position); + + // Stop searching when we hit anything non-air + return !block.getBlockType().getMaterial().isAir(); + } + + @Override + public boolean apply(BlockVector3 position, int depth) throws WorldEditException { + if (depth > 0) { + // We only care about the first layer. + return false; + } + + BlockState block = this.extent.getBlock(position); + BlockType blockType = block.getBlockType(); + + if (blockType == BlockTypes.ICE) { + if (this.extent.setBlock(position, water)) { + affected++; + } + } else if (blockType == BlockTypes.SNOW) { + if (this.extent.setBlock(position, air)) { + affected++; + } + } + + return false; + } +}