diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index b4eeabf5..71f7a0f0 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -51,6 +51,7 @@ import com.sk89q.worldedit.command.WorldEditCommands; import com.sk89q.worldedit.command.composition.SelectionCommand; import com.sk89q.worldedit.command.tool.AreaPickaxe; import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.command.tool.FloodFillTool; import com.sk89q.worldedit.command.tool.LongRangeBuildTool; import com.sk89q.worldedit.command.tool.RecursivePickaxe; import com.sk89q.worldedit.command.tool.brush.GravityBrush; @@ -70,6 +71,8 @@ import com.sk89q.worldedit.extent.clipboard.io.SchematicReader; import com.sk89q.worldedit.extent.clipboard.io.SchematicWriter; import com.sk89q.worldedit.extent.inventory.BlockBagExtent; import com.sk89q.worldedit.extent.transform.BlockTransformExtent; +import com.sk89q.worldedit.function.block.BlockReplace; +import com.sk89q.worldedit.function.block.ExtentBlockCopy; import com.sk89q.worldedit.function.entity.ExtentEntityCopy; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.FuzzyBlockMask; @@ -101,6 +104,7 @@ import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; +import com.sk89q.worldedit.regions.shape.ArbitraryShape; import com.sk89q.worldedit.session.PasteBuilder; import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.request.Request; @@ -110,7 +114,6 @@ import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.util.command.parametric.ParametricCallable; import com.sk89q.worldedit.world.registry.BundledBlockData; import java.io.File; -import java.io.IOException; import java.io.InputStream; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; @@ -408,6 +411,7 @@ public class Fawe { ClipboardFormat.inject(); // Optimizations + new formats + api PasteBuilder.inject(); // Optimizations // Brushes/Tools + FloodFillTool.inject(); GravityBrush.inject(); // Fix for instant placement assumption LongRangeBuildTool.inject(); AreaPickaxe.inject(); // Fixes @@ -449,7 +453,9 @@ public class Fawe { // Block BaseBlock.inject(); // Optimizations // Pattern + ArbitraryShape.inject(); // Optimizations + update from legacy code Pattern.inject(); // Simplify API + com.sk89q.worldedit.patterns.Pattern.inject(); // Simplify API Patterns.inject(); // Optimizations (reduce object creation) RandomPattern.inject(); // Optimizations ClipboardPattern.inject(); // Optimizations @@ -467,6 +473,8 @@ public class Fawe { MaskUnion.inject(); // Optimizations // Operations Operations.inject(); // Optimizations + ExtentBlockCopy.inject(); // Optimizations + BlockReplace.inject(); // Optimizations + Features ForwardExtentCopy.inject(); // Fixes + optimizations ChangeSetExecutor.inject(); // Optimizations // BlockData diff --git a/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java index f9f21c48..9205d400 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java @@ -5,7 +5,6 @@ import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.function.pattern.Patterns; public class LineBrush implements Brush, ResettableTool { @@ -24,7 +23,7 @@ public class LineBrush implements Brush, ResettableTool { pos1 = position; return; } - editSession.drawLine(Patterns.wrap(pattern), pos1, position, size, !shell, flat); + editSession.drawLine(pattern, pos1, position, size, !shell, flat); if (!select) { pos1 = null; return; diff --git a/core/src/main/java/com/boydti/fawe/object/brush/SplatterBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/SplatterBrush.java index 13cc5282..0b517d16 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/SplatterBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/SplatterBrush.java @@ -3,6 +3,7 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.object.PseudoRandom; import com.boydti.fawe.object.collection.LocalBlockVectorSet; import com.boydti.fawe.object.mask.AdjacentAnyMask; +import com.boydti.fawe.object.pattern.BiomePattern; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; @@ -31,7 +32,13 @@ public class SplatterBrush extends ScatterBrush { public void apply(final EditSession editSession, final LocalBlockVectorSet placed, final Vector position, Pattern p, double size) throws MaxChangedBlocksException { final Pattern finalPattern; if (solid) { - finalPattern = new BlockPattern(p.apply(position)); + Pattern tmp; + try { + tmp = new BlockPattern(p.apply(position)); + } catch (BiomePattern.BiomePatternException ignore) { + tmp = ignore.getPattern(); + } + finalPattern = tmp; } else { finalPattern = p; } diff --git a/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java index 1074c7fb..ee65deb4 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java @@ -17,7 +17,6 @@ import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.math.interpolation.Node; import com.sk89q.worldedit.math.transform.AffineTransform; import java.util.ArrayList; @@ -140,7 +139,7 @@ public class SplineBrush implements Brush { int index = (int) (i * listSize / (double) (numSplines)); currentSpline.add(points.get(index)); } - editSession.drawSpline(Patterns.wrap(pattern), currentSpline, 0, 0, 0, 10, 0, true); + editSession.drawSpline(pattern, currentSpline, 0, 0, 0, 10, 0, true); } player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE_SECONDARY.s()); if (visualization) { diff --git a/core/src/main/java/com/boydti/fawe/object/extent/PatternTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/PatternTransform.java index bc76c699..adadab2b 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/PatternTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/PatternTransform.java @@ -16,6 +16,6 @@ public class PatternTransform extends ResettableExtent { @Override public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException { - return super.setBlock(location, pattern.apply(location)); + return pattern.apply(getExtent(), location); } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java new file mode 100644 index 00000000..e7c9bd66 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java @@ -0,0 +1,49 @@ +package com.boydti.fawe.object.pattern; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.biome.BaseBiome; + +public class BiomePattern extends ExistingPattern { + private final BaseBiome biome; + private BiomePatternException exception; + + public BiomePattern(Extent extent, BaseBiome biome) { + super(extent); + this.biome = biome; + this.exception = new BiomePatternException(); + } + + @Override + public BaseBlock apply(Vector position) { + throw exception; + } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + return extent.setBiome(new Vector2D(position.getBlockX(), position.getBlockZ()), biome); + } + + public class BiomePatternException extends RuntimeException { + + public BiomePatternException() { + super("Haha, you failed Empire92! Should've done things properly instead of some hacky AF biome pattern.\nHey, you! The one reading this stacktrace, can you do me a favor and report this on GitHub so I can get around to fixing it?"); + } + + public BiomePattern getPattern() { + return BiomePattern.this; + } + + public BaseBiome getBiome() { + return biome; + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java index 5c194886..e357bbe2 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java @@ -1,7 +1,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; import java.util.Arrays; @@ -25,4 +27,13 @@ public class Linear3DBlockPattern extends AbstractPattern { } return patternsArray[index].apply(position); } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + int index = (position.getBlockX() + position.getBlockY() + position.getBlockZ()) % patternsArray.length; + if (index < 0) { + index += patternsArray.length; + } + return patternsArray[index].apply(extent, position); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java index 79e0463f..3fee51ed 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java @@ -1,7 +1,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; import java.util.Arrays; @@ -26,6 +28,14 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat return patternsArray[index++].apply(position); } + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + if (index == patternsArray.length) { + index = 0; + } + return patternsArray[index++].apply(extent, position); + } + @Override public void reset() { index = 0; diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java index 7bec8bda..25e63d1b 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java @@ -1,7 +1,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -31,4 +33,13 @@ public class MaskedPattern extends AbstractPattern { } return secondaryPattern.apply(position); } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + patternExtent.setTarget(position); + if (mask.test(position)) { + return patternExtent.getAndResetTarget(extent, position); + } + return secondaryPattern.apply(extent, position); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java index 19c6df6c..7dcb4992 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java @@ -2,7 +2,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -22,4 +24,11 @@ public class NoXPattern extends AbstractPattern { mutable.mutZ((pos.getZ())); return pattern.apply(mutable); } + + @Override + public boolean apply(Extent extent, Vector pos) throws WorldEditException { + mutable.mutY((pos.getY())); + mutable.mutZ((pos.getZ())); + return pattern.apply(extent, mutable); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java index 3cb6b960..5769139c 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java @@ -2,7 +2,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -22,4 +24,11 @@ public class NoYPattern extends AbstractPattern { mutable.mutZ((pos.getZ())); return pattern.apply(mutable); } + + @Override + public boolean apply(Extent extent, Vector pos) throws WorldEditException { + mutable.mutX((pos.getX())); + mutable.mutZ((pos.getZ())); + return pattern.apply(extent, mutable); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java index 6f8b5ddf..99a2cb62 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java @@ -2,7 +2,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -22,4 +24,11 @@ public class NoZPattern extends AbstractPattern { mutable.mutY((pos.getY())); return pattern.apply(mutable); } + + @Override + public boolean apply(Extent extent, Vector pos) throws WorldEditException { + mutable.mutX((pos.getX())); + mutable.mutY((pos.getY())); + return pattern.apply(extent, mutable); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java index 0dde03ce..a86e86c5 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java @@ -2,7 +2,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -26,4 +28,12 @@ public class OffsetPattern extends AbstractPattern { mutable.mutZ((position.getZ() + dz)); return pattern.apply(mutable); } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + mutable.mutX((position.getX() + dx)); + mutable.mutY((position.getY() + dy)); + mutable.mutZ((position.getZ() + dz)); + return pattern.apply(extent, mutable); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java b/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java index a7922d7f..56af2d51 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java @@ -67,6 +67,16 @@ public class PatternExtent extends AbstractPattern implements Extent { this.target = vector; } + public boolean getAndResetTarget(Extent extent, Vector position) throws WorldEditException { + BaseBlock result = block; + if (result != null) { + block = null; + return extent.setBlock(position, result); + } else { + return pattern.apply(extent, target); + } + } + public BaseBlock getAndResetTarget() { BaseBlock result = block; if (result != null) { @@ -107,4 +117,9 @@ public class PatternExtent extends AbstractPattern implements Extent { public BaseBlock apply(Vector position) { return pattern.apply(position); } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + return pattern.apply(extent, position); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java index ea43075b..d1062b81 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java @@ -3,7 +3,9 @@ package com.boydti.fawe.object.pattern; import com.boydti.fawe.object.PseudoRandom; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -31,4 +33,12 @@ public class RandomOffsetPattern extends AbstractPattern { mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz)); return pattern.apply(mutable); } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + mutable.mutX((position.getX() + r.nextInt(dx2) - dx)); + mutable.mutY((position.getY() + r.nextInt(dy2) - dy)); + mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz)); + return pattern.apply(extent, mutable); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java index 1ce2bd9e..57617e41 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java @@ -2,7 +2,9 @@ package com.boydti.fawe.object.pattern; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -28,6 +30,17 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter return pattern.apply(mutable); } + @Override + public boolean apply(Extent extent, Vector pos) throws WorldEditException { + if (origin == null) { + origin = new Vector(pos); + } + mutable.mutX((pos.getX() - origin.getX())); + mutable.mutY((pos.getY() - origin.getY())); + mutable.mutZ((pos.getZ() - origin.getZ())); + return pattern.apply(extent, mutable); + } + @Override public void reset() { origin = null; diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java index ace3237e..971b009f 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java @@ -4,8 +4,10 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.PseudoRandom; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockType; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -46,4 +48,17 @@ public class SolidRandomOffsetPattern extends AbstractPattern { return pattern.apply(position); } } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + mutable.mutX((position.getX() + r.nextInt(dx2) - dx)); + mutable.mutY((position.getY() + r.nextInt(dy2) - dy)); + mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz)); + BaseBlock block = pattern.apply(mutable); + if (solid[FaweCache.getCombined(block)]) { + return pattern.apply(extent, mutable); + } else { + return pattern.apply(extent, position); + } + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java index cec348cd..11278430 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java @@ -4,8 +4,10 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.PseudoRandom; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockType; +import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -48,4 +50,19 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern { } return pattern.apply(position); } + + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + mutable.mutX((position.getX() + r.nextInt(dx2) - dx)); + mutable.mutY((position.getY() + r.nextInt(dy2) - dy)); + mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz)); + BaseBlock block = pattern.apply(mutable); + if (solid[FaweCache.getCombined(block)]) { + mutable.mutY(mutable.getY() + 1); + if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) { + return pattern.apply(extent, mutable); + } + } + return pattern.apply(extent, position); + } } \ No newline at end of file diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index f0006da2..cf57be97 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -52,7 +52,6 @@ import com.boydti.fawe.object.extent.ProcessedWEExtent; import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.extent.SlowExtent; import com.boydti.fawe.object.extent.SourceMaskExtent; -import com.boydti.fawe.object.function.block.LegacyBlockReplace; import com.boydti.fawe.object.mask.ResettableMask; import com.boydti.fawe.object.progress.ChatProgressTracker; import com.boydti.fawe.object.progress.DefaultProgressTracker; @@ -98,6 +97,7 @@ import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.BlockPattern; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.function.util.RegionOffset; import com.sk89q.worldedit.function.visitor.DownwardVisitor; @@ -116,8 +116,6 @@ import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.math.interpolation.Node; import com.sk89q.worldedit.math.noise.RandomNoise; import com.sk89q.worldedit.math.transform.AffineTransform; -import com.sk89q.worldedit.patterns.Pattern; -import com.sk89q.worldedit.patterns.SingleBlockPattern; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.FlatRegion; @@ -1111,7 +1109,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting public boolean setBlock(int x, int y, int z, Pattern pattern) { this.changes++; try { - return this.extent.setBlock(x, y, z, pattern.next(x, y, z)); + return this.extent.setBlock(x, y, z, pattern.apply(x, y, z)); } catch (WorldEditException e) { throw new RuntimeException("Unexpected exception", e); } @@ -1131,31 +1129,19 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } } - /** - * Sets the block at a position, subject to both history and block re-ordering. - * - * @param position the position - * @param pattern a pattern to use - * @return Whether the block changed -- not entirely dependable - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ @SuppressWarnings("deprecation") public boolean setBlock(final Vector position, final Pattern pattern) throws MaxChangedBlocksException { - return this.setBlockFast(position, pattern.next(position)); + this.changes++; + try { + return pattern.apply(this.extent, position); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } } - /** - * Set blocks that are in a set of positions and return the number of times - * that the block set calls returned true. - * - * @param vset a set of positions - * @param pattern the pattern - * @return the number of changed blocks - * @throws MaxChangedBlocksException thrown if too many blocks are changed - */ @SuppressWarnings("deprecation") private int setBlocks(final Set vset, final Pattern pattern) throws MaxChangedBlocksException { - RegionVisitor visitor = new RegionVisitor(vset, new LegacyBlockReplace(extent, pattern), this); + RegionVisitor visitor = new RegionVisitor(vset, new BlockReplace(extent, pattern), this); Operations.completeBlindly(visitor); changes += visitor.getAffected(); return changes; @@ -1431,7 +1417,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting */ @SuppressWarnings("deprecation") public int fillXZ(final Vector origin, final BaseBlock block, final double radius, final int depth, final boolean recursive) throws MaxChangedBlocksException { - return this.fillXZ(origin, new SingleBlockPattern(block), radius, depth, recursive); + return this.fillXZ(origin, new BlockPattern(block), radius, depth, recursive); } /** @@ -1456,7 +1442,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting (origin.getBlockY() - depth) + 1, 0), Math.min(EditSession.this.getMaximumPoint().getBlockY(), origin.getBlockY())), Masks.negate(new ExistingBlockMask(EditSession.this))); // Want to replace blocks - final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); + final BlockReplace replace = new BlockReplace(EditSession.this, pattern); // Pick how we're going to visit blocks RecursiveVisitor visitor; @@ -1514,7 +1500,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting (origin.getBlockY() - depth) + 1, 0), Math.min(EditSession.this.getMaximumPoint().getBlockY(), origin.getBlockY())), Masks.negate(new ExistingBlockMask(EditSession.this))); // Want to replace blocks - final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); + final BlockReplace replace = new BlockReplace(EditSession.this, pattern); // Pick how we're going to visit blocks RecursiveVisitor visitor; @@ -1549,7 +1535,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, height - 1, apothem - 1)); - final Pattern pattern = new SingleBlockPattern(new BaseBlock(BlockID.AIR)); + final Pattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR)); return this.setBlocks(region, pattern); } @@ -1570,7 +1556,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range position.add(-apothem + 1, 0, -apothem + 1), position.add(apothem - 1, -height + 1, apothem - 1)); - final Pattern pattern = new SingleBlockPattern(new BaseBlock(BlockID.AIR)); + final Pattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR)); return this.setBlocks(region, pattern); } @@ -1592,7 +1578,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final Vector adjustment = new Vector(1, 1, 1).multiply(apothem - 1); final Region region = new CuboidRegion(this.getWorld(), // Causes clamping of Y range position.add(adjustment.multiply(-1)), position.add(adjustment)); - final Pattern pattern = new SingleBlockPattern(new BaseBlock(BlockID.AIR)); + final Pattern pattern = new BlockPattern(new BaseBlock(BlockID.AIR)); return this.replaceBlocks(region, mask, pattern); } @@ -1643,7 +1629,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } try { if (hasExtraExtents()) { - RegionVisitor visitor = new RegionVisitor(region, new LegacyBlockReplace(extent, new SingleBlockPattern(block)), this); + RegionVisitor visitor = new RegionVisitor(region, new BlockReplace(extent, new BlockPattern(block)), this); Operations.completeBlindly(visitor); this.changes += visitor.getAffected(); } else { @@ -1662,6 +1648,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting return changes; } + public int setBlocks(final Region region, final com.sk89q.worldedit.patterns.Pattern pattern) throws MaxChangedBlocksException { + return setBlocks(region, Patterns.wrap(pattern)); + } + /** * Sets all the blocks inside a region to a given pattern. * @@ -1677,7 +1667,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting if (pattern instanceof BlockPattern) { return setBlocks(region, ((BlockPattern) pattern).getBlock()); } - final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); + final BlockReplace replace = new BlockReplace(EditSession.this, pattern); final RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); Operations.completeBlindly(visitor); return this.changes = visitor.getAffected(); @@ -1700,9 +1690,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting // return changes = region.getArea(); // } // TODO fast replace - return this.replaceBlocks(region, filter, new SingleBlockPattern(replacement)); + return this.replaceBlocks(region, filter, new BlockPattern(replacement)); } + + /** * Replaces all the blocks matching a given filter, within a given region, to a block * returned by a given pattern. @@ -1741,7 +1733,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting checkNotNull(region); checkNotNull(mask); checkNotNull(pattern); - final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); + final BlockReplace replace = new BlockReplace(EditSession.this, pattern); final RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace); final RegionVisitor visitor = new RegionVisitor(region, filter, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); Operations.completeBlindly(visitor); @@ -1779,7 +1771,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting */ @SuppressWarnings("deprecation") public int makeCuboidFaces(final Region region, final BaseBlock block) throws MaxChangedBlocksException { - return this.makeCuboidFaces(region, new SingleBlockPattern(block)); + return this.makeCuboidFaces(region, new BlockPattern(block)); } /** @@ -1811,7 +1803,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting * @throws MaxChangedBlocksException thrown if too many blocks are changed */ @SuppressWarnings("deprecation") - public int makeFaces(final Region region, final Pattern pattern) throws MaxChangedBlocksException { + public int makeFaces(final Region region, final Pattern pattern) throws WorldEditException { checkNotNull(region); checkNotNull(pattern); @@ -1833,7 +1825,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting */ @SuppressWarnings("deprecation") public int makeCuboidWalls(final Region region, final BaseBlock block) throws MaxChangedBlocksException { - return this.makeCuboidWalls(region, new SingleBlockPattern(block)); + return this.makeCuboidWalls(region, new BlockPattern(block)); } /** @@ -1866,7 +1858,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting * @throws MaxChangedBlocksException thrown if too many blocks are changed */ @SuppressWarnings("deprecation") - public int makeWalls(final Region region, final Pattern pattern) throws MaxChangedBlocksException { + public int makeWalls(final Region region, final Pattern pattern) throws WorldEditException { checkNotNull(region); checkNotNull(pattern); @@ -1877,7 +1869,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final int maxY = region.getMaximumPoint().getBlockY(); final ArbitraryShape shape = new RegionShape(region) { @Override - protected BaseBlock getMaterial(final int x, final int y, final int z, final BaseBlock defaultMaterial) { + public BaseBlock getMaterial(final int x, final int y, final int z, final BaseBlock defaultMaterial) { if ((y > maxY) || (y < minY)) { // Put holes into the floor and ceiling by telling ArbitraryShape that the shape goes on outside the region return defaultMaterial; @@ -1903,7 +1895,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting public int overlayCuboidBlocks(final Region region, final BaseBlock block) throws MaxChangedBlocksException { checkNotNull(block); - return this.overlayCuboidBlocks(region, new SingleBlockPattern(block)); + return this.overlayCuboidBlocks(region, new BlockPattern(block)); } /** @@ -1919,7 +1911,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting public int overlayCuboidBlocks(final Region region, final Pattern pattern) throws MaxChangedBlocksException { checkNotNull(region); checkNotNull(pattern); - final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); + final BlockReplace replace = new BlockReplace(EditSession.this, pattern); final RegionOffset offset = new RegionOffset(new Vector(0, 1, 0), replace); final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), offset); final LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground); @@ -2819,7 +2811,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final ArbitraryShape shape = new ArbitraryShape(region) { @Override - protected BaseBlock getMaterial(final int x, final int y, final int z, final BaseBlock defaultMaterial) { + public BaseBlock getMaterial(final int x, final int y, final int z, final BaseBlock defaultMaterial) { final Vector current = new Vector(x, y, z); environment.setCurrentBlock(current); final Vector scaled = current.subtract(zero).divide(unit); @@ -2837,7 +2829,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } }; - return shape.generate(this, pattern, hollow); + try { + return shape.generate(this, pattern, hollow); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } } public int deformRegion(final Region region, final Vector zero, final Vector unit, final String expressionString) throws ExpressionException, MaxChangedBlocksException { @@ -2941,15 +2937,21 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting outside.addAll(newOutside); } - outer: for (final BlockVector position : region) { - for (final Vector recurseDirection : this.recurseDirections) { - final BlockVector neighbor = position.add(recurseDirection).toBlockVector(); + try { + outer: + for (final BlockVector position : region) { + for (final Vector recurseDirection : this.recurseDirections) { + final BlockVector neighbor = position.add(recurseDirection).toBlockVector(); - if (outside.contains(neighbor)) { - continue outer; + if (outside.contains(neighbor)) { + continue outer; + } } + this.changes++; + pattern.apply(this.extent, position); } - this.setBlockFast(position, pattern.next(position)); + } catch (WorldEditException e) { + throw new RuntimeException(e); } return changes; @@ -3068,7 +3070,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final int tipy = (int) Math.round(tipv.getY()); final int tipz = (int) Math.round(tipv.getZ()); if (radius == 0) { - setBlock(tipx, tipy, tipz, pattern.next(tipx, tipy, tipz)); + setBlock(tipx, tipy, tipz, pattern.apply(tipx, tipy, tipz)); } else { vset.add(new Vector(tipx, tipy, tipz)); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index fbb5fd21..a689fd24 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -31,7 +31,6 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.regions.Region; @@ -123,7 +122,7 @@ public class GenerationCommands { worldEdit.checkMaxRadius(height); Vector pos = session.getPlacementPosition(player); - int affected = editSession.makeCylinder(pos, Patterns.wrap(pattern), radiusX, radiusZ, height, !hollow); + int affected = editSession.makeCylinder(pos, pattern, radiusX, radiusZ, height, !hollow); BBC.VISITOR_BLOCK.send(player, affected); } @@ -188,7 +187,7 @@ public class GenerationCommands { pos = pos.add(0, radiusY, 0); } - int affected = editSession.makeSphere(pos, Patterns.wrap(pattern), radiusX, radiusY, radiusZ, !hollow); + int affected = editSession.makeSphere(pos, pattern, radiusX, radiusY, radiusZ, !hollow); player.findFreePosition(); BBC.VISITOR_BLOCK.send(player, affected); } @@ -249,7 +248,7 @@ public class GenerationCommands { public void pyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size, @Switch('h') boolean hollow) throws WorldEditException, ParameterException { Vector pos = session.getPlacementPosition(player); worldEdit.checkMaxRadius(size); - int affected = editSession.makePyramid(pos, Patterns.wrap(pattern), size, !hollow); + int affected = editSession.makePyramid(pos, pattern, size, !hollow); player.findFreePosition(); BBC.VISITOR_BLOCK.send(player, affected); } @@ -312,7 +311,7 @@ public class GenerationCommands { } try { - final int affected = editSession.makeShape(region, zero, unit, Patterns.wrap(pattern), expression, hollow); + final int affected = editSession.makeShape(region, zero, unit, pattern, expression, hollow); player.findFreePosition(); BBC.VISITOR_BLOCK.send(player, affected); } catch (ExpressionException e) { diff --git a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 01b46165..98ee3ca3 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -50,7 +50,6 @@ import com.sk89q.worldedit.function.mask.NoiseFilter2D; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.function.visitor.LayerVisitor; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Selection; @@ -251,7 +250,7 @@ public class RegionCommands { CuboidRegion cuboidregion = (CuboidRegion) region; Vector pos1 = cuboidregion.getPos1(); Vector pos2 = cuboidregion.getPos2(); - int blocksChanged = editSession.drawLine(Patterns.wrap(pattern), pos1, pos2, thickness, !shell); + int blocksChanged = editSession.drawLine(pattern, pos1, pos2, thickness, !shell); BBC.VISITOR_BLOCK.send(player, blocksChanged); } @@ -284,7 +283,7 @@ public class RegionCommands { ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region; List vectors = new ArrayList(cpregion.getVertices()); - int blocksChanged = editSession.drawSpline(Patterns.wrap(pattern), vectors, 0, 0, 0, 10, thickness, !shell); + int blocksChanged = editSession.drawSpline(pattern, vectors, 0, 0, 0, 10, thickness, !shell); BBC.VISITOR_BLOCK.send(player, blocksChanged); } @@ -303,7 +302,7 @@ public class RegionCommands { if (from == null) { from = new ExistingBlockMask(editSession); } - int affected = editSession.replaceBlocks(region, from, Patterns.wrap(to)); + int affected = editSession.replaceBlocks(region, from, to); BBC.VISITOR_BLOCK.send(player, affected); if (!FawePlayer.wrap(player).hasPermission("fawe.tips")) BBC.TIP_REPLACE_ID.or(BBC.TIP_REPLACE_LIGHT, BBC.TIP_REPLACE_MARKER, BBC.TIP_TAB_COMPLETE).send(player); } @@ -322,7 +321,7 @@ public class RegionCommands { if (from == null) { from = new ExistingBlockMask(editSession); } - int affected = editSession.replaceBlocks(region, from, Patterns.wrap(to)); + int affected = editSession.replaceBlocks(region, from, to); BBC.VISITOR_BLOCK.send(player, affected); } @@ -340,7 +339,7 @@ public class RegionCommands { if (to instanceof BlockPattern) { affected = editSession.setBlocks(selection, ((BlockPattern) to).getBlock()); } else { - affected = editSession.setBlocks(selection, Patterns.wrap(to)); + affected = editSession.setBlocks(selection, to); } if (affected != 0) { BBC.OPERATION.send(player, affected); @@ -358,7 +357,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.overlay") @Logging(REGION) public void overlay(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { - int affected = editSession.overlayCuboidBlocks(region, Patterns.wrap(pattern)); + int affected = editSession.overlayCuboidBlocks(region, pattern); BBC.VISITOR_BLOCK.send(player, affected); } @@ -372,7 +371,7 @@ public class RegionCommands { @Logging(REGION) @CommandPermissions("worldedit.region.center") public void center(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { - int affected = editSession.center(region, Patterns.wrap(pattern)); + int affected = editSession.center(region, pattern); BBC.VISITOR_BLOCK.send(player, affected); } @@ -400,7 +399,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.walls") @Logging(REGION) public void walls(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { - int affected = editSession.makeCuboidWalls(region, Patterns.wrap(pattern)); + int affected = editSession.makeCuboidWalls(region, pattern); BBC.VISITOR_BLOCK.send(player, affected); } @@ -414,7 +413,7 @@ public class RegionCommands { @CommandPermissions("worldedit.region.faces") @Logging(REGION) public void faces(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException { - int affected = editSession.makeCuboidFaces(region, Patterns.wrap(pattern)); + int affected = editSession.makeCuboidFaces(region, pattern); BBC.VISITOR_BLOCK.send(player, affected); } @@ -650,7 +649,7 @@ public class RegionCommands { @Optional("0") @Range(min = 0) int thickness, @Optional("air") Pattern pattern) throws WorldEditException { - int affected = editSession.hollowOutRegion(region, thickness, Patterns.wrap(pattern)); + int affected = editSession.hollowOutRegion(region, thickness, pattern); BBC.VISITOR_BLOCK.send(player, affected); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index f278973b..c9096740 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -39,7 +39,7 @@ import com.sk89q.worldedit.command.tool.LongRangeBuildTool; import com.sk89q.worldedit.command.tool.QueryTool; import com.sk89q.worldedit.command.tool.TreePlanter; import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.patterns.Pattern; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.command.parametric.Optional; @@ -150,17 +150,13 @@ public class ToolCommands { max = 2 ) @CommandPermissions("worldedit.tool.flood-fill") - public void floodFill(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public void floodFill(Player player, LocalSession session, Pattern pattern, double range) throws WorldEditException { LocalConfiguration config = we.getConfiguration(); - int range = args.getInteger(1); - if (range > config.maxSuperPickaxeSize) { BBC.TOOL_RANGE_ERROR.send(player, config.maxSuperPickaxeSize); return; } - - Pattern pattern = we.getBlockPattern(player, args.getString(0)); - session.setTool(new FloodFillTool(range, pattern), player); + session.setTool(new FloodFillTool((int) range, pattern), player); BBC.TOOL_FLOOD_FILL.send(player, ItemType.toHeldName(player.getItemInHand())); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 72dd5b9f..ca097825 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -24,9 +24,17 @@ import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; import com.google.common.base.Joiner; import com.google.common.util.concurrent.AtomicDouble; -import com.sk89q.minecraft.util.commands.*; -import com.sk89q.worldedit.*; +import com.sk89q.minecraft.util.commands.Command; +import com.sk89q.minecraft.util.commands.CommandContext; +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandPermissions; +import com.sk89q.minecraft.util.commands.Logging; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.command.util.CreatureButcher; import com.sk89q.worldedit.command.util.EntityRemover; @@ -36,13 +44,15 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.function.mask.ExistingBlockMask; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operations; +import com.sk89q.worldedit.function.pattern.BlockPattern; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.visitor.EntityVisitor; import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; -import com.sk89q.worldedit.patterns.Pattern; -import com.sk89q.worldedit.patterns.SingleBlockPattern; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; @@ -51,6 +61,7 @@ import com.sk89q.worldedit.util.command.CommandMapping; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.PrimaryAliasComparator; import com.sk89q.worldedit.util.command.binding.Text; +import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.formatting.ColorCodeBuilder; import com.sk89q.worldedit.util.formatting.Style; import com.sk89q.worldedit.util.formatting.StyledFragment; @@ -58,13 +69,16 @@ import com.sk89q.worldedit.util.formatting.component.Code; import com.sk89q.worldedit.util.formatting.component.CommandListBox; import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; import com.sk89q.worldedit.world.World; - -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; + import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; /** @@ -87,21 +101,14 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fill") @Logging(PLACEMENT) - public void fill(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - Pattern pattern = we.getBlockPattern(player, args.getString(0)); - double radius = Math.max(1, args.getDouble(1)); + public void fill(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("1") double depth) throws WorldEditException { we.checkMaxRadius(radius); - int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : 1; - Vector pos = session.getPlacementPosition(player); int affected = 0; - if (pattern instanceof SingleBlockPattern) { - affected = editSession.fillXZ(pos, - ((SingleBlockPattern) pattern).getBlock(), - radius, depth, false); + if (pattern instanceof BlockPattern) { + affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, (int) depth, false); } else { - affected = editSession.fillXZ(pos, pattern, radius, depth, false); + affected = editSession.fillXZ(pos, pattern, radius, (int) depth, false); } player.print(BBC.getPrefix() + affected + " block(s) have been created."); } @@ -115,21 +122,14 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fill.recursive") @Logging(PLACEMENT) - public void fillr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - Pattern pattern = we.getBlockPattern(player, args.getString(0)); - double radius = Math.max(1, args.getDouble(1)); + public void fillr(Player player, LocalSession session, EditSession editSession, Pattern pattern, double radius, @Optional("1") double depth) throws WorldEditException { we.checkMaxRadius(radius); - int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE; - Vector pos = session.getPlacementPosition(player); int affected = 0; - if (pattern instanceof SingleBlockPattern) { - affected = editSession.fillXZ(pos, - ((SingleBlockPattern) pattern).getBlock(), - radius, depth, true); + if (pattern instanceof BlockPattern) { + affected = editSession.fillXZ(pos, ((BlockPattern) pattern).getBlock(), radius, (int) depth, true); } else { - affected = editSession.fillXZ(pos, pattern, radius, depth, true); + affected = editSession.fillXZ(pos, pattern, radius, (int) depth, true); } player.print(BBC.getPrefix() + affected + " block(s) have been created."); } @@ -143,9 +143,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.drain") @Logging(PLACEMENT) - public void drain(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - double radius = Math.max(0, args.getDouble(0)); + public void drain(Player player, LocalSession session, EditSession editSession, double radius) throws WorldEditException { we.checkMaxRadius(radius); int affected = editSession.drainArea( session.getPlacementPosition(player), radius); @@ -161,9 +159,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fixlava") @Logging(PLACEMENT) - public void fixLava(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - double radius = Math.max(0, args.getDouble(0)); + public void fixLava(Player player, LocalSession session, EditSession editSession, double radius) throws WorldEditException { we.checkMaxRadius(radius); int affected = editSession.fixLiquid( session.getPlacementPosition(player), radius, 10, 11); @@ -179,9 +175,7 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.fixwater") @Logging(PLACEMENT) - public void fixWater(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - double radius = Math.max(0, args.getDouble(0)); + public void fixWater(Player player, LocalSession session, EditSession editSession, double radius) throws WorldEditException { we.checkMaxRadius(radius); int affected = editSession.fixLiquid( session.getPlacementPosition(player), radius, 8, 9); @@ -197,15 +191,9 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removeabove") @Logging(PLACEMENT) - public void removeAbove(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1; + public void removeAbove(Player player, LocalSession session, EditSession editSession, @Optional("1") double size, @Optional("256") double height) throws WorldEditException { we.checkMaxRadius(size); - World world = player.getWorld(); - int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1); - - int affected = editSession.removeAbove( - session.getPlacementPosition(player), size, height); + int affected = editSession.removeAbove(session.getPlacementPosition(player), (int) size, (int) height); player.print(BBC.getPrefix() + affected + " block(s) have been removed."); } @@ -218,14 +206,9 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removebelow") @Logging(PLACEMENT) - public void removeBelow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1; + public void removeBelow(Player player, LocalSession session, EditSession editSession, @Optional("1") double size, @Optional("256") double height) throws WorldEditException { we.checkMaxRadius(size); - World world = player.getWorld(); - int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1); - - int affected = editSession.removeBelow(session.getPlacementPosition(player), size, height); + int affected = editSession.removeBelow(session.getPlacementPosition(player), (int) size, (int) height); player.print(BBC.getPrefix() + affected + " block(s) have been removed."); } @@ -238,13 +221,9 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.removenear") @Logging(PLACEMENT) - public void removeNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - BaseBlock block = we.getBlock(player, args.getString(0), true); - int size = Math.max(1, args.getInteger(1, 50)); + public void removeNear(Player player, LocalSession session, EditSession editSession, BaseBlock block, @Optional("50") double size) throws WorldEditException { we.checkMaxRadius(size); - - int affected = editSession.removeNear(session.getPlacementPosition(player), block.getType(), size); + int affected = editSession.removeNear(session.getPlacementPosition(player), block.getId(), (int) size); player.print(BBC.getPrefix() + affected + " block(s) have been removed."); } @@ -258,31 +237,17 @@ public class UtilityCommands { ) @CommandPermissions("worldedit.replacenear") @Logging(PLACEMENT) - public void replaceNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException { - - int size = Math.max(1, args.getInteger(0)); - int affected; - Set from; - Pattern to; - if (args.argsLength() == 2) { - from = null; - to = we.getBlockPattern(player, args.getString(1)); - } else { - from = we.getBlocks(player, args.getString(1), true, !args.hasFlag('f')); - to = we.getBlockPattern(player, args.getString(2)); + public void replaceNear(Player player, LocalSession session, EditSession editSession, double size, @Optional Mask from, Pattern to) throws WorldEditException { + if (from == null) { + from = new ExistingBlockMask(editSession); } - Vector base = session.getPlacementPosition(player); Vector min = base.subtract(size, size, size); Vector max = base.add(size, size, size); Region region = new CuboidRegion(player.getWorld(), min, max); - if (to instanceof SingleBlockPattern) { - affected = editSession.replaceBlocks(region, from, ((SingleBlockPattern) to).getBlock()); - } else { - affected = editSession.replaceBlocks(region, from, to); - } - player.print(BBC.getPrefix() + affected + " block(s) have been replaced."); + int affected = editSession.replaceBlocks(region, from, to); + BBC.VISITOR_BLOCK.send(player, affected); } @Command( diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java new file mode 100644 index 00000000..c485c6e7 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/FloodFillTool.java @@ -0,0 +1,117 @@ +/* + * 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 Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.command.tool; + +import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; +import java.util.HashSet; +import java.util.Set; + +/** + * A tool that flood fills blocks. + */ +public class FloodFillTool implements BlockTool { + + private int range; + private Pattern pattern; + + public FloodFillTool(int range, com.sk89q.worldedit.patterns.Pattern pattern) { + this(range, (Pattern) pattern); + } + + public FloodFillTool(int range, Pattern pattern) { + this.range = range; + this.pattern = pattern; + } + + @Override + public boolean canUse(Actor player) { + return player.hasPermission("worldedit.tool.flood-fill"); + } + + @Override + public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) { + World world = (World) clicked.getExtent(); + + int initialType = world.getBlockType(clicked.toVector()); + + if (initialType == BlockID.AIR) { + return true; + } + + if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) { + return true; + } + + EditSession editSession = session.createEditSession(player); + + try { + recurse(server, editSession, world, clicked.toVector().toBlockVector(), + clicked.toVector(), range, initialType, new HashSet()); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } + return true; + } + + private void recurse(Platform server, EditSession editSession, World world, BlockVector pos, Vector origin, int size, int initialType, + Set visited) throws WorldEditException { + + if (origin.distance(pos) > size || visited.contains(pos)) { + return; + } + + visited.add(pos); + + if (editSession.getBlock(pos).getType() == initialType) { + editSession.setBlock(pos, pattern); + } else { + return; + } + + recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(), + origin, size, initialType, visited); + recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(), + origin, size, initialType, visited); + } + + public static Class inject() { + return FloodFillTool.class; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java index 636aad5e..aff78833 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java @@ -24,6 +24,10 @@ import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.request.Request; +import com.sk89q.worldedit.world.World; +import com.sk89q.worldedit.world.biome.BaseBiome; +import com.sk89q.worldedit.world.biome.Biomes; +import com.sk89q.worldedit.world.registry.BiomeRegistry; import com.sk89q.worldedit.world.registry.BundledBlockData; import java.util.ArrayList; import java.util.List; @@ -104,6 +108,13 @@ public class HashTagPatternParser extends FaweParser { case "#data": { return new DataPattern(Request.request().getEditSession(), catchSuggestion(input, rest, context)); } + case "#biome": { + World world = context.getWorld(); + BiomeRegistry biomeRegistry = world.getWorldData().getBiomeRegistry(); + List knownBiomes = biomeRegistry.getBiomes(); + BaseBiome biome = Biomes.findBiomeByName(knownBiomes, rest, biomeRegistry); + return new BiomePattern(Request.request().getEditSession(), biome); + } case "#~": case "#r": case "#relative": diff --git a/core/src/main/java/com/sk89q/worldedit/function/block/BlockReplace.java b/core/src/main/java/com/sk89q/worldedit/function/block/BlockReplace.java new file mode 100644 index 00000000..237fab8c --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/block/BlockReplace.java @@ -0,0 +1,61 @@ +/* + * 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 Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.function.block; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.RegionFunction; +import com.sk89q.worldedit.function.pattern.Pattern; + + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Replaces blocks with a given pattern. + */ +public class BlockReplace implements RegionFunction { + + private final Extent extent; + private Pattern pattern; + + /** + * Create a new instance. + * + * @param extent an extent + * @param pattern a pattern + */ + public BlockReplace(Extent extent, Pattern pattern) { + checkNotNull(extent); + checkNotNull(pattern); + this.extent = extent; + this.pattern = pattern; + } + + @Override + public boolean apply(Vector position) throws WorldEditException { + return pattern.apply(extent, position); + } + + public static Class inject() { + return BlockReplace.class; + } + +} \ No newline at end of file diff --git a/core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java b/core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java index bd79f153..820d5335 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java +++ b/core/src/main/java/com/sk89q/worldedit/function/block/ExtentBlockCopy.java @@ -117,4 +117,8 @@ public class ExtentBlockCopy implements RegionFunction { return state; } + public static Class inject() { + return ExtentBlockCopy.class; + } + } diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java index 32b46452..3cac6896 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/BlockPattern.java @@ -20,12 +20,7 @@ public class BlockPattern extends AbstractPattern { } @Override - public BaseBlock next(int x, int y, int z) { - return block; - } - - @Override - public BaseBlock next(Vector position) { + public BaseBlock apply(int x, int y, int z) { return block; } diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java index 3ec30135..ddb36001 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java @@ -21,12 +21,14 @@ package com.sk89q.worldedit.function.pattern; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; /** * Returns a {@link BaseBlock} for a given position. */ -public interface Pattern extends com.sk89q.worldedit.patterns.Pattern { +public interface Pattern { /** * Return a {@link BaseBlock} for the given position. @@ -36,14 +38,12 @@ public interface Pattern extends com.sk89q.worldedit.patterns.Pattern { */ BaseBlock apply(Vector position); - @Override - default BaseBlock next(Vector position) { - return apply(position); + default BaseBlock apply(int x, int y, int z) { + return apply(MutableBlockVector.get(x, y, z)); } - @Override - default BaseBlock next(int x, int y, int z) { - return apply(MutableBlockVector.get(x, y, z)); + default boolean apply(Extent extent,Vector position) throws WorldEditException { + return extent.setBlock(position, apply(position)); } public static Class inject() { diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java index 008da8f6..c10af3d0 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java @@ -4,9 +4,6 @@ import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; - -import static com.google.common.base.Preconditions.checkNotNull; - /** * Utility methods related to {@link Pattern}s. */ @@ -22,16 +19,7 @@ public final class Patterns { * @return a new-style pattern */ public static Pattern wrap(final com.sk89q.worldedit.patterns.Pattern pattern) { - if (pattern instanceof Pattern) { - return (Pattern) pattern; - } - checkNotNull(pattern); - return new Pattern() { - @Override - public BaseBlock apply(Vector position) { - return pattern.next(position); - } - }; + return pattern; } /** @@ -41,7 +29,9 @@ public final class Patterns { * @return an old-style pattern */ public static com.sk89q.worldedit.patterns.Pattern wrap(final Pattern pattern) { - checkNotNull(pattern); + if (pattern instanceof com.sk89q.worldedit.patterns.Pattern) { + return (com.sk89q.worldedit.patterns.Pattern) pattern; + } return new com.sk89q.worldedit.patterns.Pattern() { private MutableBlockVector mutable = new MutableBlockVector(0, 0, 0); @Override @@ -62,5 +52,4 @@ public final class Patterns { public static Class inject() { return Patterns.class; } - } diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java index 646b0183..e035e9ee 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java @@ -2,7 +2,9 @@ package com.sk89q.worldedit.function.pattern; import com.boydti.fawe.object.collection.RandomCollection; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -40,6 +42,11 @@ public class RandomPattern extends AbstractPattern { return collection.next().apply(position); } + @Override + public boolean apply(Extent extent, Vector position) throws WorldEditException { + return collection.next().apply(extent, position); + } + private static class Chance { private Pattern pattern; private double chance; diff --git a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java b/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java new file mode 100644 index 00000000..12f098f9 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java @@ -0,0 +1,70 @@ +/* + * 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 Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.patterns; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.Extent; + +/** + * @deprecated See {@link com.sk89q.worldedit.function.pattern.Pattern} + */ +@Deprecated +public interface Pattern extends com.sk89q.worldedit.function.pattern.Pattern{ + + /** + * Get a block for a position. This return value of this method does + * not have to be consistent for the same position. + * + * @param position the position where a block is needed + * @return a block + */ + public BaseBlock next(Vector position); + + @Override + default boolean apply(Extent extent, Vector position) throws WorldEditException { + return extent.setBlock(position, apply(position)); + } + + @Override + default BaseBlock apply(Vector position) { + return next(position); + } + + @Override + default BaseBlock apply(int x, int y, int z) { + return next(x, y, z); + } + + /** + * Get a block for a position. This return value of this method does + * not have to be consistent for the same position. + * + * @param x the X coordinate + * @param y the Y coordinate + * @param z the Z coordinate + * @return a block + */ + public BaseBlock next(int x, int y, int z); + + public static Class inject() { + return Pattern.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java b/core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java new file mode 100644 index 00000000..ca9a735d --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/regions/shape/ArbitraryShape.java @@ -0,0 +1,221 @@ +/* + * 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 Lesser 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 Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.regions.shape; + +import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.function.pattern.Patterns; +import com.sk89q.worldedit.regions.Region; + +/** + * Generates solid and hollow shapes according to materials returned by the + * {@link #getMaterial} method. + */ +public abstract class ArbitraryShape { + + public final Region extent; + private int cacheOffsetX; + private int cacheOffsetY; + private int cacheOffsetZ; + @SuppressWarnings("FieldCanBeLocal") + private int cacheSizeX; + private int cacheSizeY; + private int cacheSizeZ; + + public ArbitraryShape(Region extent) { + this.extent = extent; + + Vector min = extent.getMinimumPoint(); + Vector max = extent.getMaximumPoint(); + + cacheOffsetX = min.getBlockX() - 1; + cacheOffsetY = min.getBlockY() - 1; + cacheOffsetZ = min.getBlockZ() - 1; + + cacheSizeX = (int) (max.getX() - cacheOffsetX + 2); + cacheSizeY = (int) (max.getY() - cacheOffsetY + 2); + cacheSizeZ = (int) (max.getZ() - cacheOffsetZ + 2); + + cache = new short[cacheSizeX * cacheSizeY * cacheSizeZ]; + } + + public Region getExtent() { + return extent; + } + + + /** + * Cache entries: + * 0 = unknown + * -1 = outside + * -2 = inside but type and data 0 + * > 0 = inside, value = (type | (data << 8)), not handling data < 0 + */ + private final short[] cache; + + /** + * Override this function to specify the shape to generate. + * + * @param x X coordinate to be queried + * @param y Y coordinate to be queried + * @param z Z coordinate to be queried + * @param defaultMaterial The material returned by the pattern for the current block. + * @return material to place or null to not place anything. + */ + public abstract BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial); + + private BaseBlock getMaterialCached(int x, int y, int z, Pattern pattern) { + final int index = (y - cacheOffsetY) + (z - cacheOffsetZ) * cacheSizeY + (x - cacheOffsetX) * cacheSizeY * cacheSizeZ; + + final short cacheEntry = cache[index]; + switch (cacheEntry) { + case 0: + // unknown, fetch material + final BaseBlock material = getMaterial(x, y, z, pattern.apply(new BlockVector(x, y, z))); + if (material == null) { + // outside + cache[index] = -1; + return null; + } + + short newCacheEntry = (short) (material.getType() | ((material.getData() + 1) << 8)); + if (newCacheEntry == 0) { + // type and data 0 + newCacheEntry = -2; + } + + cache[index] = newCacheEntry; + return material; + + case -1: + // outside + return null; + + case -2: + // type and data 0 + return new BaseBlock(0, 0); + } + + return new BaseBlock(cacheEntry & 255, ((cacheEntry >> 8) - 1) & 15); + } + + private boolean isInsideCached(int x, int y, int z, Pattern pattern) { + final int index = (y - cacheOffsetY) + (z - cacheOffsetZ) * cacheSizeY + (x - cacheOffsetX) * cacheSizeY * cacheSizeZ; + + switch (cache[index]) { + case 0: + // unknown block, meaning they must be outside the extent at this stage, but might still be inside the shape + return getMaterialCached(x, y, z, pattern) != null; + + case -1: + // outside + return false; + + default: + // inside + return true; + } + } + + @Deprecated + public int generate(EditSession editSession, com.sk89q.worldedit.patterns.Pattern pattern, boolean hollow) throws WorldEditException { + return generate(editSession, Patterns.wrap(pattern), hollow); + } + + /** + * Generates the shape. + * + * @param editSession The EditSession to use. + * @param pattern The pattern to generate default materials from. + * @param hollow Specifies whether to generate a hollow shape. + * @return number of affected blocks. + * @throws MaxChangedBlocksException + */ + public int generate(EditSession editSession, Pattern pattern, boolean hollow) throws WorldEditException { + int affected = 0; + + for (BlockVector position : getExtent()) { + int x = position.getBlockX(); + int y = position.getBlockY(); + int z = position.getBlockZ(); + + if (!hollow) { + final BaseBlock material = getMaterial(x, y, z, pattern.apply(position)); + if (material != null && editSession.setBlock(position, material)) { + ++affected; + } + + continue; + } + + final BaseBlock material = getMaterialCached(x, y, z, pattern); + if (material == null) { + continue; + } + + boolean draw = false; + do { + if (!isInsideCached(x + 1, y, z, pattern)) { + draw = true; + break; + } + if (!isInsideCached(x - 1, y, z, pattern)) { + draw = true; + break; + } + if (!isInsideCached(x, y, z + 1, pattern)) { + draw = true; + break; + } + if (!isInsideCached(x, y, z - 1, pattern)) { + draw = true; + break; + } + if (!isInsideCached(x, y + 1, z, pattern)) { + draw = true; + break; + } + if (!isInsideCached(x, y - 1, z, pattern)) { + draw = true; + break; + } + } while (false); + + if (!draw) { + continue; + } + + if (editSession.setBlock(position, material)) { + ++affected; + } + } + + return affected; + } + + public static Class inject() { + return ArbitraryShape.class; + } +} \ No newline at end of file