resolve conflicts

This commit is contained in:
Jesse Boyd
2019-07-18 16:56:57 +10:00
parent dd38cbe750
commit be8213d8ee
49 changed files with 1819 additions and 1722 deletions

View File

@ -38,6 +38,7 @@ import com.boydti.fawe.util.MaskTraverser;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
@ -91,6 +92,7 @@ import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Clipboard commands.
*/
@ -123,20 +125,24 @@ public class ClipboardCommands {
Mask mask, CommandContext context) throws WorldEditException {
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
FaweLimit limit = FawePlayer.wrap(player).getLimit();
if (volume >= limit.MAX_CHECKS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
throw FaweException.MAX_CHECKS;
}
fp.checkConfirmationRegion(() -> {
session.setClipboard(null);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, player.getUniqueId());
session.setClipboard(new ClipboardHolder(clipboard));
clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setCopyingEntities(!skipEntities);
copy.setCopyingBiomes(copyBiomes);
Mask sourceMask = editSession.getSourceMask();
if (sourceMask != null) {
new MaskTraverser(sourceMask).reset(editSession);
@ -204,12 +210,13 @@ public class ClipboardCommands {
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
FaweLimit limit = FawePlayer.wrap(player).getLimit();
if (volume >= limit.MAX_CHECKS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
throw FaweException.MAX_CHECKS;
}
if (volume >= limit.MAX_CHANGES) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
throw FaweException.MAX_CHANGES;
}
session.setClipboard(null);
ReadOnlyClipboard lazyClipboard = new WorldCutClipboard(editSession, region, !skipEntities, copyBiomes);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, lazyClipboard);
clipboard.setOrigin(session.getPlacementPosition(player));
@ -221,6 +228,7 @@ public class ClipboardCommands {
name = "/cut",
desc = "Cut the selection to the clipboard",
descFooter = "WARNING: Cutting and pasting entities cannot be undone!"
)
@CommandPermissions("worldedit.clipboard.cut")
@Logging(REGION)
@ -237,21 +245,24 @@ public class ClipboardCommands {
CommandContext context) throws WorldEditException {
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
FaweLimit limit = FawePlayer.wrap(player).getLimit();
if (volume >= limit.MAX_CHECKS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
throw FaweException.MAX_CHECKS;
}
if (volume >= limit.MAX_CHANGES) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
throw FaweException.MAX_CHANGES;
}
fp.checkConfirmationRegion(() -> {
session.setClipboard(null);
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, player.getUniqueId());
clipboard.setOrigin(session.getPlacementPosition(player));
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
copy.setCopyingEntities(!skipEntities);
copy.setCopyingEntities(copyEntities);
copy.setRemovingEntities(true);
copy.setCopyingBiomes(copyBiomes);
Mask sourceMask = editSession.getSourceMask();
@ -413,6 +424,7 @@ public class ClipboardCommands {
@Command(
name = "/paste",
desc = "Paste the clipboard's contents"
)
@CommandPermissions("worldedit.clipboard.paste")
@Logging(PLACEMENT)
@ -481,6 +493,7 @@ public class ClipboardCommands {
name = "/place",
desc = "Place the clipboard's contents without applying transformations (e.g. rotate)"
)
@CommandPermissions("worldedit.clipboard.place")
@Logging(PLACEMENT)
public void place(Player player, LocalSession session, final EditSession editSession,
@ -551,6 +564,7 @@ public class ClipboardCommands {
public void flip(Player player, LocalSession session,
@Arg(desc = "The direction to flip, defaults to look direction.", def = Direction.AIM)
@Direction BlockVector3 direction) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
AffineTransform transform = new AffineTransform();
transform = transform.scale(direction.abs().multiply(-2).add(1, 1, 1).toVector3());
@ -563,7 +577,7 @@ public class ClipboardCommands {
desc = "Clear your clipboard"
)
@CommandPermissions("worldedit.clipboard.clear")
public void clearClipboard(Player player, LocalSession session) throws WorldEditException {
public void clearClipboard(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
session.setClipboard(null);
BBC.CLIPBOARD_CLEARED.send(player);
}

View File

@ -205,6 +205,7 @@ public class PatternCommands extends MethodCommands {
" - Use to replace slabs or where the data values needs to be shifted instead of set"
)
public Pattern iddatamask(Actor actor, LocalSession session, Extent extent, @Range(min = 0, max = 15) int bitmask, Pattern pattern) {
return new IdDataMaskPattern(extent, pattern, bitmask);
}
@ -213,6 +214,7 @@ public class PatternCommands extends MethodCommands {
desc = "Only change the block id"
)
public Pattern id(Actor actor, LocalSession session, Extent extent, Pattern pattern) {
return new IdPattern(extent, pattern);
}
@ -221,6 +223,7 @@ public class PatternCommands extends MethodCommands {
desc = "Only change the block data"
)
public Pattern data(Actor actor, LocalSession session, Extent extent, Pattern pattern) {
return new DataPattern(extent, pattern);
}
@ -230,6 +233,7 @@ public class PatternCommands extends MethodCommands {
desc = "Set the biome"
)
public Pattern biome(Actor actor, LocalSession session, Extent extent, BiomeType biome) {
return new BiomePattern(extent, biome);
}
@ -239,6 +243,7 @@ public class PatternCommands extends MethodCommands {
desc = "Offset the pattern to where you click"
)
public Pattern relative(Actor actor, LocalSession session, Extent extent, Pattern pattern) {
return new RelativePattern(pattern);
}
@ -250,6 +255,7 @@ public class PatternCommands extends MethodCommands {
"Example: #!x[#!z[#~[#l3d[pattern]]]]"
)
public Pattern nox(Actor actor, LocalSession session, Extent extent, Pattern pattern) {
return new NoXPattern(pattern);
}
@ -259,6 +265,7 @@ public class PatternCommands extends MethodCommands {
desc = "The pattern will not be provided the y axis info"
)
public Pattern noy(Actor actor, LocalSession session, Extent extent, Pattern pattern) {
return new NoYPattern(pattern);
}
@ -268,6 +275,7 @@ public class PatternCommands extends MethodCommands {
desc = "The pattern will not be provided the z axis info"
)
public Pattern noz(Actor actor, LocalSession session, Extent extent, Pattern pattern) {
return new NoZPattern(pattern);
}
@ -285,6 +293,7 @@ public class PatternCommands extends MethodCommands {
desc = "Offset a pattern"
)
public Pattern offset(Actor actor, LocalSession session, double x, double y, double z, Pattern pattern) {
return new OffsetPattern(pattern, (int) x, (int) y, (int) z);
}
@ -293,6 +302,7 @@ public class PatternCommands extends MethodCommands {
desc = "Applies to only blocks on a surface. Selects a block from provided pattern with a given ranomized offset `[0, <distance>)`. e.g. Use `#existing` to randomly offset blocks in the world, or `#copy` to offset blocks in your clipboard"
)
public Pattern surfacespread(Actor actor, LocalSession session, double distance, Pattern pattern) {
return new SurfaceRandomOffsetPattern(pattern, (int) distance);
}
@ -301,6 +311,7 @@ public class PatternCommands extends MethodCommands {
desc = "Randomly spread solid blocks"
)
public Pattern solidspread(Actor actor, LocalSession session, double x, double y, double z, Pattern pattern) {
return new SolidRandomOffsetPattern(pattern, (int) x, (int) y, (int) z);
}
@ -310,6 +321,7 @@ public class PatternCommands extends MethodCommands {
desc = "Randomly spread blocks"
)
public Pattern spread(Actor actor, LocalSession session, double x, double y, double z, Pattern pattern) {
return new RandomOffsetPattern(pattern, (int) x, (int) y, (int) z);
}
@ -319,6 +331,7 @@ public class PatternCommands extends MethodCommands {
desc = "Sequentially set blocks from a list of patterns"
)
public Pattern linear(Actor actor, LocalSession session, Pattern other) {
if (other instanceof RandomPattern) {
Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
return new LinearBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
@ -332,6 +345,7 @@ public class PatternCommands extends MethodCommands {
desc = "Use the x,y,z coordinate to pick a block from the list"
)
public Pattern linear3d(Actor actor, LocalSession session, Pattern other) {
if (other instanceof RandomPattern) {
Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
@ -345,6 +359,7 @@ public class PatternCommands extends MethodCommands {
desc = "Use the x,z coordinate to pick a block from the list"
)
public Pattern linear2d(Actor actor, LocalSession session, Pattern other) {
if (other instanceof RandomPattern) {
Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
return new Linear2DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
@ -358,6 +373,7 @@ public class PatternCommands extends MethodCommands {
desc = "Expression pattern: http://wiki.sk89q.com/wiki/WorldEdit/Expression_syntax"
)
public Pattern expression(Actor actor, LocalSession session, Extent extent, String input) throws ExpressionException {
Expression exp = Expression.compile(input, "x", "y", "z");
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(extent, Vector3.ONE, Vector3.ZERO);
exp.setEnvironment(env);

View File

@ -29,7 +29,11 @@ import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.beta.filters.SetFilter;
import com.boydti.fawe.beta.implementation.QueueHandler;
import com.boydti.fawe.beta.filters.DistrFilter;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.example.NMSMappedFaweQueue;
import com.boydti.fawe.object.FaweLimit;
@ -54,6 +58,7 @@ import com.sk89q.worldedit.function.generator.FloraGenerator;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.NoiseFilter2D;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.LayerVisitor;
@ -76,9 +81,11 @@ import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.parametric.Optional;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.biome.Biomes;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.registry.BiomeRegistry;
import java.util.ArrayList;
@ -109,6 +116,43 @@ public class RegionCommands {
this.worldEdit = worldEdit;
}
@Command(
aliases = {"debugtest"},
usage = "",
desc = "debugtest",
help = "debugtest"
)
@CommandPermissions("fawe.admin.debug")
public void debugtest(Player player, @Selection Region region) throws WorldEditException {
QueueHandler queueHandler = Fawe.get().getQueueHandler();
World world = player.getWorld();
DistrFilter filter = new DistrFilter();
long start = System.currentTimeMillis();
queueHandler.apply(world, region, filter);
long diff = System.currentTimeMillis() - start;
System.out.println(diff);
}
@Command(
aliases = {"db2"},
usage = "",
desc = "db2",
help = "db2"
)
@CommandPermissions("fawe.admin.debug")
public void db2(Player player, @Selection Region region, String blockStr) throws WorldEditException {
QueueHandler queueHandler = Fawe.get().getQueueHandler();
World world = player.getWorld();
BlockState block = BlockState.get(blockStr);
SetFilter filter = new SetFilter(block);
long start = System.currentTimeMillis();
queueHandler.apply(world, region, filter);
long diff = System.currentTimeMillis() - start;
System.out.println(diff);
}
@Command(
name = "/fixlighting",
desc = "Get the light at a position"
@ -417,7 +461,7 @@ public class RegionCommands {
long volume = (((long) max.getX() - (long) min.getX() + 1) * ((long) max.getY() - (long) min.getY() + 1) * ((long) max.getZ() - (long) min.getZ() + 1));
FaweLimit limit = FawePlayer.wrap(player).getLimit();
if (volume >= limit.MAX_CHECKS) {
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
throw FaweException.MAX_CHECKS;
}
player.checkConfirmationRegion(() -> {
try {
@ -673,6 +717,7 @@ public class RegionCommands {
descFooter = "Hollows out the object contained in this selection.\n" +
"Optionally fills the hollowed out part with the given block.\n" +
"Thickness is measured in manhattan distance."
)
@CommandPermissions("worldedit.region.hollow")
@Logging(REGION)
@ -682,9 +727,11 @@ public class RegionCommands {
int thickness,
@Arg(desc = "The pattern of blocks to replace the hollowed area with", def = "air")
Pattern pattern,
CommandContext context) throws WorldEditException {
Mask finalMask = mask == null ? new SolidBlockMask(editSession) : mask;
player.checkConfirmationRegion(() -> {
int affected = editSession.hollowOutRegion(region, thickness, pattern);
int affected = editSession.hollowOutRegion(region, thickness, pattern, finalMask);
BBC.VISITOR_BLOCK.send(player, affected);
}, getArguments(context), region, context);
}

View File

@ -31,6 +31,7 @@ import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.chat.Message;
import com.sk89q.minecraft.util.commands.CommandContext;
@ -80,6 +81,7 @@ import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.regex.Pattern;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
@ -403,8 +405,8 @@ public class SchematicCommands {
}
if (new PlayerSaveClipboardEvent(player, clipboard, uri, f.toURI()).call()) {
try (ClipboardWriter writer = format.getWriter(fos)) {
if (writer instanceof StructureFormat) {
((StructureFormat) writer).write(target, player.getName());
if (writer instanceof MinecraftStructure) {
((MinecraftStructure) writer).write(target, player.getName());
} else {
writer.write(target);
}

View File

@ -27,6 +27,7 @@ import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.mask.IdMask;
import com.boydti.fawe.object.regions.selector.FuzzyRegionSelector;
import com.boydti.fawe.object.regions.selector.PolyhedralRegionSelector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
@ -490,7 +491,7 @@ public class SelectionCommands {
// TODO multi clipboard distribution
Clipboard clipboard = session.getClipboard().getClipboard(); // throws if missing
region = clipboard.getRegion();
editSession.setExtent(new AbstractDelegateExtent(clipboard));
new ExtentTraverser<AbstractDelegateExtent>(editSession).setNext(new AbstractDelegateExtent(clipboard));
} else {
region = session.getSelection(player.getWorld());
}
@ -499,6 +500,7 @@ public class SelectionCommands {
else
distribution = (List) editSession.getBlockDistribution(region);
if (distribution.isEmpty()) { // *Should* always be false
player.printError("No blocks counted.");
return;

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.DelegateConsumer;
@ -60,6 +61,7 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
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.math.BlockVector3;

View File

@ -75,6 +75,7 @@ public class WorldEditCommands {
FaweVersion fVer = Fawe.get().getVersion();
String fVerStr = fVer == null ? "unknown" : "-" + fVer.build;
actor.print("FastAsyncWorldEdit" + fVerStr + " created by Empire92");
if (fVer != null) {
actor.printDebug("----------- Platforms -----------");
FaweVersion version = Fawe.get().getVersion();

View File

@ -48,6 +48,7 @@ import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.MaxBrushRadiusException;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
@ -643,15 +644,16 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
Brush brush = current.getBrush();
if (brush == null) return;
FawePlayer<Object> fp = FawePlayer.wrap(player);
EditSession editSession = new EditSessionBuilder(player.getWorld())
EditSessionBuilder builder = new EditSessionBuilder(player.getWorld())
.player(fp)
.allowedRegionsEverywhere()
.autoQueue(false)
.blockBag(null)
.changeSetNull()
.combineStages(false)
.build();
VisualExtent newVisualExtent = new VisualExtent(editSession.getExtent(), editSession.getQueue());
.combineStages(false);
EditSession editSession = builder.build();
VisualExtent newVisualExtent = new VisualExtent(builder.getExtent(), builder.getQueue());
BlockVector3 position = getPosition(editSession, player);
if (position != null) {
editSession.setExtent(newVisualExtent);

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
public class GravityBrush implements Brush {
@ -43,8 +44,8 @@ public class GravityBrush implements Brush {
for (int x = position.getBlockX() + size; x > position.getBlockX() - size; --x) {
for (int z = position.getBlockZ() + size; z > position.getBlockZ() - size; --z) {
int freeSpot = startCheckY;
for (int y = startCheckY; y <= endY; ++y) {
final BlockState block = editSession.getLazyBlock(x, y, z);
for (int y = startCheckY; y <= endY; y++) {
BlockStateHolder block = editSession.getBlock(x, y, z);
if (!block.getBlockType().getMaterial().isAir()) {
if (y != freeSpot) {
editSession.setBlock(x, y, z, BlockTypes.AIR.getDefaultState());

View File

@ -47,10 +47,8 @@ import javax.annotation.Nullable;
/**
* A base class for {@link Extent}s that merely passes extents onto another.
*/
public class AbstractDelegateExtent implements LightingExtent {
private transient final Extent extent;
protected MutableBlockVector3 mutable = new MutableBlockVector3(0, 0, 0);
public class AbstractDelegateExtent implements Extent, LightingExtent {
private final Extent extent;
/**
* Create a new instance.
@ -62,126 +60,18 @@ public class AbstractDelegateExtent implements LightingExtent {
this.extent = extent;
}
public int getSkyLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getSkyLight(x, y, z);
}
return 0;
}
@Override
public int getMaxY() {
return extent.getMaxY();
}
@Override
public int getBlockLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getBlockLight(x, y, z);
}
return getBrightness(x, y, z);
}
@Override
public int getOpacity(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getOpacity(x, y, z);
}
return getLazyBlock(x, y, z).getBlockType().getMaterial().getLightOpacity();
}
@Override
public int getLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getLight(x, y, z);
}
return 0;
}
@Override
public int getBrightness(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getBrightness(x, y, z);
}
return getLazyBlock(x, y, z).getBlockType().getMaterial().getLightValue();
}
/**
* Get the extent.
*
* @return the extent
*/
public Extent getExtent() {
public final Extent getExtent() {
return extent;
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return extent.getLazyBlock(mutable.setComponents(x, y, z));
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return extent.getLazyBlock(position);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
return setBlock(mutable.setComponents(x, y, z), block);
}
@Override
public BlockState getBlock(BlockVector3 position) {
return extent.getBlock(position);
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return extent.getFullBlock(position);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block) throws WorldEditException {
return extent.setBlock(location, block);
}
@Override
@Nullable
public Entity createEntity(Location location, BaseEntity entity) {
return extent.createEntity(location, entity);
}
@Override
public List<? extends Entity> getEntities() {
return extent.getEntities();
}
@Override
public List<? extends Entity> getEntities(Region region) {
return extent.getEntities(region);
}
@Override
public BiomeType getBiome(BlockVector2 position) {
return extent.getBiome(position);
}
@Override
public boolean setBiome(BlockVector2 position, BiomeType biome) {
return extent.setBiome(position, biome);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
return extent.setBiome(x, y, z, biome);
}
@Override
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
return extent.getHighestTerrainBlock(x, z, minY, maxY);
}
/*
Bounds
*/
@Override
public BlockVector3 getMinimumPoint() {
return extent.getMinimumPoint();
@ -192,78 +82,90 @@ public class AbstractDelegateExtent implements LightingExtent {
return extent.getMaximumPoint();
}
protected Operation commitBefore() {
return null;
@Override
public int getMaxY() {
return extent.getMaxY();
}
/*
Input + Output
*/
@Override
public BlockState getBlock(int x, int y, int z) {
return extent.getBlock(x, y, z);
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return extent.getFullBlock(x, y, z);
}
@Override
public BiomeType getBiomeType(int x, int z) {
return extent.getBiomeType(x, z);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
return extent.setBiome(x, y, z, biome);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
return extent.setBlock(x, y, z, block);
}
/*
Light
*/
public int getSkyLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getSkyLight(x, y, z);
}
return 0;
}
public int getBlockLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getBlockLight(x, y, z);
}
return getBrightness(x, y, z);
}
public int getOpacity(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getOpacity(x, y, z);
}
return getBlock(x, y, z).getBlockType().getMaterial().getLightOpacity();
}
@Override
public int getLight(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getLight(x, y, z);
}
return 0;
}
public int getBrightness(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getBrightness(x, y, z);
}
return getBlock(x, y, z).getBlockType().getMaterial().getLightValue();
}
/*
Generic
*/
@Override
public String toString() {
return super.toString() + ":" + extent.toString();
}
@Override
public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceLayer(x, z, y, minY, maxY);
}
@Override
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) {
return extent.getHighestTerrainBlock(x, z, minY, maxY, filter);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, boolean ignoreAir) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, ignoreAir);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, Mask mask) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, mask);
}
@Override
public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, int failedMax, boolean ignoreAir) {
return extent.getNearestSurfaceTerrainBlock(x, z, y, minY, maxY, failedMin, failedMax, ignoreAir);
}
@Override
public void addCaves(Region region) throws WorldEditException {
extent.addCaves(region);
}
@Override
public void generate(Region region, GenBase gen) throws WorldEditException {
extent.generate(region, gen);
}
@Override
public void spawnResource(Region region, Resource gen, int rarity, int frequency) throws WorldEditException {
extent.spawnResource(region, gen, rarity, frequency);
}
@Override
public boolean contains(BlockVector3 pt) {
return extent.contains(pt);
}
@Override
public void addOre(Region region, Mask mask, Pattern material, int size, int frequency, int rarity, int minY, int maxY) throws WorldEditException {
extent.addOre(region, mask, material, size, frequency, rarity, minY, maxY);
}
@Override
public void addOres(Region region, Mask mask) throws WorldEditException {
extent.addOres(region, mask);
protected Operation commitBefore() {
return null;
}
@Override
@ -281,6 +183,4 @@ public class AbstractDelegateExtent implements LightingExtent {
return null;
}
}
}

View File

@ -22,6 +22,8 @@ package com.sk89q.worldedit.extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableBlockVector2;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -45,30 +47,13 @@ public interface InputExtent {
* @param position position of the block
* @return the block
*/
BlockState getBlock(BlockVector3 position);
default BlockState getBlock(BlockVector3 position) {
return getBlock(position.getX(), position.getY(), position.getZ());
}
/**
* Get a lazy, immutable snapshot of the block at the given location that only
* immediately contains information about the block's type (and metadata).
*
* <p>Further information (such as NBT data) will be available <strong>by the
* time of access</strong>. Therefore, it is not recommended that
* this method is used if the world is being simulated at the time of
* call. If the block needs to be stored for future use, then this method should
* definitely not be used. Moreover, the block that is returned is immutable (or
* should be), and therefore modifications should not be attempted on it. If a
* modifiable copy is required, then the block should be cloned.</p>
*
* <p>This method exists because it is sometimes important to inspect the block
* at a given location, but {@link #getBlock(BlockVector3)} may be too expensive in
* the underlying implementation. It is also not possible to implement
* caching if the returned object is mutable, so this methods allows caching
* implementations to be used.</p>
*
* @param position position of the block
* @return the block
*/
BlockState getLazyBlock(BlockVector3 position);
default BlockState getBlock(int x, int y, int z) {
return getBlock(MutableBlockVector3.get(x, y, z));
}
/**
* Get a immutable snapshot of the block at the given location.
@ -76,7 +61,13 @@ public interface InputExtent {
* @param position position of the block
* @return the block
*/
BaseBlock getFullBlock(BlockVector3 position);
default BaseBlock getFullBlock(BlockVector3 position) {
return getFullBlock(position.getX(), position.getY(), position.getZ());
}
default BaseBlock getFullBlock(int x, int y, int z) {
return getFullBlock(MutableBlockVector3.get(x, y, z));
}
/**
* Get the biome at the given location.
@ -87,6 +78,11 @@ public interface InputExtent {
* @param position the (x, z) location to check the biome at
* @return the biome at the location
*/
BiomeType getBiome(BlockVector2 position);
default BiomeType getBiome(BlockVector2 position) {
return getBiomeType(position.getX(), position.getZ());
}
default BiomeType getBiomeType(int x, int z) {
return getBiome(MutableBlockVector2.get(x, z));
}
}

View File

@ -73,16 +73,10 @@ public class NullExtent implements Extent {
return null;
}
@Override
public BlockState getBlock(BlockVector3 position) {
return BlockTypes.AIR.getDefaultState();
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return BlockTypes.AIR.getDefaultState();
}
@Override
public BaseBlock getFullBlock(BlockVector3 position) {
return getBlock(position).toBaseBlock();

View File

@ -199,9 +199,20 @@ public class SpongeSchematicReader extends NBTSchematicReader {
setupClipboard(0, uuid);
}
int[] pos = value.getIntArray("Pos");
int x = pos[0];
int y = pos[1];
int z = pos[2];
int x,y,z;
if (pos.length != 3) {
System.out.println("Invalid tile " + value);
if (!value.containsKey("x") || !value.containsKey("y") || !value.containsKey("z")) {
return;
}
x = value.getInt("x");
y = value.getInt("y");
z = value.getInt("z");
} else {
x = pos[0];
y = pos[1];
z = pos[2];
}
Map<String, Tag> values = value.getValue();
Tag id = values.get("Id");
if (id != null) {

View File

@ -51,6 +51,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
/**
@ -94,19 +95,11 @@ public class BlockTransformExtent extends ResettableExtent {
}
private static long[] adapt(Direction... dirs) {
long[] arr = new long[dirs.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = 1L << dirs[i].ordinal();
}
return arr;
return Arrays.stream(dirs).mapToLong(dir -> 1L << dir.ordinal()).toArray();
}
private static long[] adapt(Long... dirs) {
long[] arr = new long[dirs.length];
for (int i = 0; i < arr.length; i++) {
arr[i] = dirs[i];
}
return arr;
return Arrays.stream(dirs).mapToLong(dir -> dir).toArray();
}
private static long[] getDirections(AbstractProperty property) {
@ -138,7 +131,7 @@ public class BlockTransformExtent extends ResettableExtent {
case FACING: {
List<Direction> directions = new ArrayList<>();
for (Object value : values) {
directions.add(Direction.valueOf(value.toString().toUpperCase()));
directions.add(Direction.valueOf(value.toString().toUpperCase(Locale.ROOT)));
}
return adapt(directions.toArray(new Direction[0]));
}
@ -220,9 +213,7 @@ public class BlockTransformExtent extends ResettableExtent {
}
private static long notIndex(long mask, int... indexes) {
for (int index : indexes) {
mask = mask | (1L << (index + values().length));
}
mask |= Arrays.stream(indexes).mapToLong(index -> (1L << (index + values().length))).reduce(0, (a, b) -> a | b);
return mask;
}
@ -344,10 +335,10 @@ public class BlockTransformExtent extends ResettableExtent {
Object southState = tmp.getState(PropertyKey.SOUTH);
Object westState = tmp.getState(PropertyKey.WEST);
tmp = tmp.with(PropertyKey.valueOf(newNorth.name().toUpperCase()), northState);
tmp = tmp.with(PropertyKey.valueOf(newEast.name().toUpperCase()), eastState);
tmp = tmp.with(PropertyKey.valueOf(newSouth.name().toUpperCase()), southState);
tmp = tmp.with(PropertyKey.valueOf(newWest.name().toUpperCase()), westState);
tmp = tmp.with(PropertyKey.valueOf(newNorth.name().toUpperCase(Locale.ROOT)), northState);
tmp = tmp.with(PropertyKey.valueOf(newEast.name().toUpperCase(Locale.ROOT)), eastState);
tmp = tmp.with(PropertyKey.valueOf(newSouth.name().toUpperCase(Locale.ROOT)), southState);
tmp = tmp.with(PropertyKey.valueOf(newWest.name().toUpperCase(Locale.ROOT)), westState);
newMaskedId = tmp.getInternalId();
}
@ -476,7 +467,7 @@ public class BlockTransformExtent extends ResettableExtent {
return BlockState.getFromInternalId(newMaskedId);
}
public final BaseBlock transform(BlockStateHolder block) {
public final BaseBlock transform(BlockStateHolder<BaseBlock> block) {
BlockState transformed = transform(block.toImmutableState());
if (block.hasNbtData()) {
return transformBaseBlockNBT(transformed, block.getNbtData(), transform);
@ -501,13 +492,8 @@ public class BlockTransformExtent extends ResettableExtent {
}
@Override
public BlockState getLazyBlock(int x, int y, int z) {
return transform(super.getLazyBlock(x, y, z));
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return transform(super.getLazyBlock(position));
public BlockState getBlock(int x, int y, int z) {
return transform(super.getBlock(x, y, z));
}
@Override

View File

@ -19,256 +19,215 @@
package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.object.collection.FastBitSet;
import com.boydti.fawe.util.StringMan;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import java.util.function.Predicate;
/**
* A mask that checks whether blocks at the given positions are matched by
* a block in a list.
*
* <p>This mask checks for both an exact block type and state value match,
* respecting fuzzy status of the BlockState.</p>
* @deprecated use BlockMaskBuilder
*/
@Deprecated
public class BlockMask extends AbstractExtentMask {
private final long[][] bitSets;
protected final static long[] ALL = new long[0];
/**
* Create a new block mask.
*
* @param extent the extent
* @param blocks a list of blocks to match
*/
public BlockMask(Extent extent, Collection<BaseBlock> blocks) {
super(extent);
checkNotNull(blocks);
this.bitSets = new BlockMaskBuilder().addBlocks(blocks).optimize().getBits();
}
/**
* Create a new block mask.
*
* @param extent the extent
* @param block an array of blocks to match
*/
public BlockMask(Extent extent, BaseBlock... block) {
super(extent);
checkNotNull(block);
this.bitSets = new BlockMaskBuilder().addBlocks(block).optimize().getBits();
}
public class BlockMask extends ABlockMask {
private final boolean[] ordinals;
public BlockMask() {
super(NullExtent.INSTANCE);
this.bitSets = new long[BlockTypes.size()][];
this(new NullExtent());
}
protected BlockMask(Extent extent, long[][] bitSets) {
super(extent);
this.bitSets = bitSets;
public BlockMask(Extent extent) {
this(extent, new boolean[BlockTypes.states.length]);
}
public BlockMaskBuilder toBuilder() {
return new BlockMaskBuilder(this.bitSets);
public BlockMask(Extent extent, boolean[] ordinals) {
super(extent == null ? new NullExtent() : extent);
this.ordinals = ordinals;
}
/**
* @deprecated NBT not supported by this mask
*/
@Deprecated
public BlockMask(Extent extent, Collection<BaseBlock> blocks) {
this(extent);
add(blocks);
}
public BlockMask add(Predicate<BlockState> predicate) {
for (int i = 0; i < ordinals.length; i++) {
if (!ordinals[i]) {
BlockState state = BlockTypes.states[i];
if (state != null) ordinals[i] = predicate.test(state);
}
}
return this;
}
public BlockMask add(BlockState... states) {
addStates(Arrays.asList(states));
return this;
}
public BlockMask remove(BlockState... states) {
for (BlockState state : states) ordinals[state.getOrdinal()] = false;
return this;
}
public BlockMask clear() {
Arrays.fill(ordinals, false);
return this;
}
public boolean isEmpty() {
for (boolean value : ordinals) {
if (value) return false;
}
return true;
}
public BlockMask addStates(Collection<BlockState> states) {
for (BlockState state : states) ordinals[state.getOrdinal()] = true;
return this;
}
public BlockMask add(BlockType... types) {
addTypes(Arrays.asList(types));
return this;
}
public BlockMask addTypes(Collection<BlockType> types) {
for (BlockType type : types) {
for (BlockState state : type.getAllStates()) {
ordinals[state.getOrdinal()] = true;
}
}
return this;
}
/**
* @deprecated NBT not supported by this mask
*/
@Deprecated
public void add(Collection<BaseBlock> blocks) {
for (BaseBlock block : blocks) {
add(block.toBlockState());
}
}
@Override
public String toString() {
List<String> strings = new ArrayList<>();
for (int i = 0; i < bitSets.length; i++) {
if (bitSets[i] != null) {
long[] set = bitSets[i];
BlockType type = BlockTypes.get(i);
if (set == ALL) {
strings.add(type.getId());
} else {
for (BlockState state : type.getAllStates()) {
if (test(state)) {
strings.add(state.getAsString());
}
}
}
}
}
return StringMan.join(strings, ",");
public boolean test(BlockState state) {
return ordinals[state.getOrdinal()];
}
@Override
public Mask optimize() {
Map<Object, Integer> states = new HashMap<>();
int indexFound = -1;
{
int indexNull = -1;
int indexAll = -1;
for (int i = 0; i < bitSets.length; i++) {
long[] bs = bitSets[i];
if (bs == null) {
indexNull = i;
states.put(null, states.getOrDefault(null, 0) + 1);
} else if (bs.length == 0) {
indexAll = i;
states.put(ALL, states.getOrDefault(ALL, 0) + 1);
} else if (indexFound == -1) {
indexFound = i;
} else {
return this;
}
}
// Only types, no states
if (indexFound == -1) {
if (states.size() == 1) {
return states.keySet().iterator().next() == null ? Masks.alwaysFalse() : Masks.alwaysTrue();
}
if (states.get(ALL) == 1) return new SingleBlockTypeMask(getExtent(), BlockTypes.get(indexAll));
if (states.get(null) == 1)
return new SingleBlockTypeMask(getExtent(), BlockTypes.get(indexNull)).inverse();
boolean[] types = new boolean[BlockTypes.size()];
for (int i = 0; i < bitSets.length; i++) {
if (bitSets[i].length == 0) types[i] = true;
}
return new BlockTypeMask(getExtent(), types);
}
}
BlockType type = BlockTypes.get(indexFound);
Mask mask = getOptimizedMask(type, bitSets[indexFound]);
if (mask == null) { // Try with inverse
long[] newBitSet = bitSets[indexFound];
for (int i = 0; i < newBitSet.length; i++) newBitSet[i] = ~newBitSet[i];
mask = getOptimizedMask(type, bitSets[indexFound]);
if (mask != null) mask = mask.inverse();
}
return mask;
}
private Mask getOptimizedMask(BlockType type, long[] bitSet) {
boolean single = true;
int and = type.getInternalId();
List<? extends Property> properties = type.getProperties();
for (AbstractProperty prop : (List<AbstractProperty<?>>) type.getProperties()) {
List values = prop.getValues();
int numSet = 0;
for (int i = 0; i < values.size(); i++) {
int localI = i << prop.getBitOffset();
if (FastBitSet.get(bitSet, localI)) {
numSet++;
and |= prop.modify(and, i);
}
}
// Cannot optimize multiple property values - use current mask (null)
if (numSet != values.size() && numSet != 1) {
return null;
}
single = single && numSet == 1;
}
if (single)
return new SingleBlockStateMask(getExtent(), BlockState.getFromInternalId(and));
return new SingleBlockStateBitMask(getExtent(), and);
public boolean test(BlockVector3 vector) {
return ordinals[vector.getOrdinal(getExtent())];
}
@Override
public Mask and(Mask other) {
if (other instanceof BlockMask) {
long[][] otherBitSets = ((BlockMask) other).bitSets;
for (int i = 0; i < otherBitSets.length; i++) {
long[] otherBitSet = otherBitSets[i];
long[] bitSet = bitSets[i];
if (otherBitSet == null) bitSets[i] = null;
else if (otherBitSet.length == 0) continue;
else if (bitSet == null) continue;
else if (bitSet.length == 0) bitSets[i] = otherBitSet;
else for (int j = 0; j < otherBitSet.length; j++) bitSet[j] &= otherBitSet[j];
public Mask and(Mask mask) {
if (mask instanceof ABlockMask) {
ABlockMask other = (ABlockMask) mask;
for (int i = 0; i < ordinals.length; i++) {
if (ordinals[i]) {
ordinals[i] = other.test(BlockState.getFromOrdinal(i));
}
}
return this;
}
if (other instanceof SingleBlockStateMask) {
return new BlockMaskBuilder(bitSets).filter(((SingleBlockStateMask) other).getBlockState()).build(getExtent());
}
if (other instanceof SingleBlockTypeMask) {
return new BlockMaskBuilder(bitSets).filter(((SingleBlockTypeMask) other).getBlockType()).build(getExtent());
}
return null;
}
@Override
public Mask or(Mask other) {
if (other instanceof BlockMask) {
long[][] otherBitSets = ((BlockMask) other).bitSets;
for (int i = 0; i < otherBitSets.length; i++) {
long[] otherBitSet = otherBitSets[i];
long[] bitSet = bitSets[i];
if (otherBitSet == null) continue;
else if (otherBitSet.length == 0) bitSets[i] = ALL;
else if (bitSet == null) bitSets[i] = otherBitSet;
else if (bitSet.length == 0) continue;
else for (int j = 0; j < otherBitSet.length; j++) bitSet[j] |= otherBitSet[j];
public Mask or(Mask mask) {
if (mask instanceof ABlockMask) {
ABlockMask other = (ABlockMask) mask;
for (int i = 0; i < ordinals.length; i++) {
if (!ordinals[i]) {
ordinals[i] = other.test(BlockState.getFromOrdinal(i));
}
}
return this;
}
if (other instanceof SingleBlockStateMask) {
return new BlockMaskBuilder(bitSets).add(((SingleBlockStateMask) other).getBlockState()).build(getExtent());
return null;
}
@Override
public Mask optimize() {
int setStates = 0;
BlockState setState = null;
BlockState unsetState = null;
int totalStates = 0;
int setTypes = 0;
BlockType setType = null;
BlockType unsetType = null;
int totalTypes = 0;
for (BlockType type : BlockTypes.values) {
if (type != null) {
totalTypes++;
boolean hasAll = true;
boolean hasAny = false;
List<BlockState> all = type.getAllStates();
for (BlockState state : all) {
totalStates++;
hasAll &= test(state);
hasAny = true;
}
if (hasAll) {
setTypes++;
setType = type;
setStates += all.size();
setState = type.getDefaultState();
} else if (hasAny) {
for (BlockState state : all) {
if (test(state)) {
setStates++;
setState = state;
} else {
unsetState = state;
}
}
} else {
unsetType = type;
}
}
}
if (other instanceof SingleBlockTypeMask) {
return new BlockMaskBuilder(bitSets).add(((SingleBlockTypeMask) other).getBlockType()).build(getExtent());
if (setStates == 0) {
return Masks.alwaysFalse();
}
if (setStates == totalStates) {
return Masks.alwaysTrue();
}
if (setStates == 1) {
return new SingleBlockStateMask(getExtent(), setState);
}
if (setStates == totalStates - 1) {
return new InverseSingleBlockStateMask(getExtent(), unsetState);
}
if (setTypes == 1) {
return new SingleBlockTypeMask(getExtent(), setType);
}
if (setTypes == totalTypes - 1) {
return new InverseSingleBlockTypeMask(getExtent(), unsetType);
}
return null;
}
@Override
public Mask inverse() {
long[][] cloned = bitSets.clone();
for (int i = 0; i < cloned.length; i++) {
if (cloned[i] == null) cloned[i] = ALL;
else if (cloned[i] == ALL) cloned[i] = null;
else {
for (int j = 0; j < cloned[i].length; j++)
cloned[i][j] = ~cloned[i][j];
}
}
boolean[] cloned = ordinals.clone();
for (int i = 0; i < cloned.length; i++) cloned[i] = !cloned[i];
return new BlockMask(getExtent(), cloned);
}
public boolean test(BlockState block) {
long[] bitSet = bitSets[block.getInternalBlockTypeId()];
if (bitSet == null) return false;
if (bitSet.length == 0) return true;
return FastBitSet.get(bitSet, block.getInternalPropertiesId());
}
@Override
public boolean test(BlockVector3 vector) {
BlockStateHolder block = getExtent().getBlock(vector);
long[] bitSet = bitSets[block.getInternalBlockTypeId()];
if (bitSet == null) return false;
if (bitSet.length == 0) return true;
return FastBitSet.get(bitSet, block.getInternalPropertiesId());
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -10,6 +10,7 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -28,6 +29,8 @@ public class BlockMaskBuilder {
private static final Operator LESS_EQUAL = (a, b) -> a <= b;
private static final Operator NOT = (a, b) -> a != b;
private final static long[] ALL = new long[0];
private interface Operator {
boolean test(int left, int right);
}
@ -223,7 +226,7 @@ public class BlockMaskBuilder {
if (states == null) return false;
List values = prop.getValues();
int localI = index << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
return (states == BlockMask.ALL || FastBitSet.get(states, localI));
return (states == ALL || FastBitSet.get(states, localI));
}
private void suggest(String input, String property, Collection<BlockType> finalTypes) throws InputParseException {
@ -240,6 +243,7 @@ public class BlockMaskBuilder {
///// end internal /////
private long[][] bitSets;
private boolean[] ordinals;
private boolean optimizedStates = true;
@ -256,14 +260,23 @@ public class BlockMaskBuilder {
}
public BlockMaskBuilder addAll() {
Arrays.fill(bitSets, BlockMask.ALL);
optimizedStates = true;
for (int i = 0; i < bitSets.length; i++) {
bitSets[i] = ALL;
}
reset(true);
return this;
}
private void reset(boolean optimized) {
this.ordinals = null;
this.optimizedStates = optimized;
}
public BlockMaskBuilder clear() {
Arrays.fill(bitSets, null);
optimizedStates = true;
for (int i = 0; i < bitSets.length; i++) {
bitSets[i] = null;
}
reset(true);
return this;
}
@ -277,13 +290,13 @@ public class BlockMaskBuilder {
int i = type.getInternalId();
long[] states = bitSets[i];
if (states != null) {
if (states == BlockMask.ALL) {
if (states == ALL) {
bitSets[i] = states = FastBitSet.create(type.getMaxStateId() + 1);
Arrays.fill(states, -1);
}
int stateId = state.getInternalPropertiesId();
FastBitSet.clear(states, stateId);
optimizedStates = false;
reset(false);
}
return this;
}
@ -305,7 +318,7 @@ public class BlockMaskBuilder {
if (states != null) {
int stateId = state.getInternalPropertiesId();
boolean set = true;
if (states == BlockMask.ALL) {
if (states == ALL) {
bitSets[i] = states = FastBitSet.create(type.getMaxStateId() + 1);
} else {
set = FastBitSet.get(states, stateId);
@ -315,7 +328,7 @@ public class BlockMaskBuilder {
FastBitSet.set(states, stateId);
else
bitSets[i] = null;
optimizedStates = true;
reset(true);
}
return this;
}
@ -344,14 +357,14 @@ public class BlockMaskBuilder {
List values = prop.getValues();
for (int j = 0; j < values.size(); j++) {
int localI = j << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
if (states == BlockMask.ALL || FastBitSet.get(states, localI)) {
if (states == ALL || FastBitSet.get(states, localI)) {
if (!allowed.test(type, new AbstractMap.SimpleEntry(prop, values.get(j)))) {
if (states == BlockMask.ALL) {
if (states == ALL) {
bitSets[i] = states = FastBitSet.create(type.getMaxStateId() + 1);
FastBitSet.setAll(states);
}
FastBitSet.clear(states, localI);
optimizedStates = false;
reset(false);
}
}
}
@ -361,7 +374,7 @@ public class BlockMaskBuilder {
}
public BlockMaskBuilder add(BlockType type) {
bitSets[type.getInternalId()] = BlockMask.ALL;
bitSets[type.getInternalId()] = ALL;
return this;
}
@ -369,13 +382,13 @@ public class BlockMaskBuilder {
BlockType type = state.getBlockType();
int i = type.getInternalId();
long[] states = bitSets[i];
if (states != BlockMask.ALL) {
if (states != ALL) {
if (states == null) {
bitSets[i] = states = FastBitSet.create(type.getMaxStateId() + 1);
}
int stateId = state.getInternalPropertiesId();
FastBitSet.set(states, stateId);
optimizedStates = false;
reset(false);
}
return this;
}
@ -404,7 +417,7 @@ public class BlockMaskBuilder {
for (int i = 0; i < bitSets.length; i++) {
BlockType type = BlockTypes.get(i);
if (allow.test(type)) {
bitSets[i] = BlockMask.ALL;
bitSets[i] = ALL;
}
}
return this;
@ -413,7 +426,7 @@ public class BlockMaskBuilder {
public BlockMaskBuilder addAll(Predicate<BlockType> typePredicate, BiPredicate<BlockType, Map.Entry<Property<?>, ?>> propPredicate) {
for (int i = 0; i < bitSets.length; i++) {
long[] states = bitSets[i];
if (states == BlockMask.ALL) continue;
if (states == ALL) continue;
BlockType type = BlockTypes.get(i);
if (!typePredicate.test(type)) {
continue;
@ -428,7 +441,7 @@ public class BlockMaskBuilder {
bitSets[i] = states = FastBitSet.create(type.getMaxStateId() + 1);
}
FastBitSet.set(states, localI);
optimizedStates = false;
reset(false);
}
}
}
@ -440,7 +453,7 @@ public class BlockMaskBuilder {
public BlockMaskBuilder add(BlockType type, Property property, int index) {
AbstractProperty prop = (AbstractProperty) property;
long[] states = bitSets[type.getInternalId()];
if (states == BlockMask.ALL) return this;
if (states == ALL) return this;
List values = property.getValues();
int localI = index << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
@ -449,7 +462,7 @@ public class BlockMaskBuilder {
bitSets[type.getInternalId()] = states = FastBitSet.create(type.getMaxStateId() + 1);
}
set(type, states, property, index);
optimizedStates = false;
reset(false);
}
return this;
}
@ -460,13 +473,13 @@ public class BlockMaskBuilder {
if (states == null) return this;
List values = property.getValues();
int localI = index << prop.getBitOffset() >> BlockTypes.BIT_OFFSET;
if (states == BlockMask.ALL || FastBitSet.get(states, localI)) {
if (states == BlockMask.ALL) {
if (states == ALL || FastBitSet.get(states, localI)) {
if (states == ALL) {
bitSets[type.getInternalId()] = states = FastBitSet.create(type.getMaxStateId() + 1);
FastBitSet.setAll(states);
}
clear(type, states, property, index);
optimizedStates = false;
reset(false);
}
return this;
}
@ -512,7 +525,7 @@ public class BlockMaskBuilder {
if (!optimizedStates) {
for (int i = 0; i < bitSets.length; i++) {
long[] bitSet = bitSets[i];
if (bitSet == null || bitSet == BlockMask.ALL) continue;
if (bitSet == null || bitSet == ALL) continue;
BlockType type = BlockTypes.get(i);
int maxStateId = type.getMaxStateId();
if (maxStateId == 0) {
@ -520,7 +533,7 @@ public class BlockMaskBuilder {
bitSets[i] = null;
continue;
} else {
bitSets[i] = BlockMask.ALL;
bitSets[i] = ALL;
continue;
}
}
@ -535,19 +548,38 @@ public class BlockMaskBuilder {
}
}
if (set == 0) bitSets[i] = null;
else if (clear == 0) bitSets[i] = BlockMask.ALL;
else if (clear == 0) bitSets[i] = ALL;
}
optimizedStates = true;
reset(true);
}
return this;
}
protected long[][] getBits() {
return this.bitSets;
private boolean[] getOrdinals() {
if (ordinals == null) {
ordinals = new boolean[BlockTypes.states.length];
for (int i = 0; i < BlockTypes.values.length; i++) {
long[] bitSet = bitSets[i];
if (bitSet == null) continue;
BlockType type = BlockTypes.values[i];
if (bitSet == ALL) {
for (BlockState state : type.getAllStates()) {
ordinals[state.getOrdinal()] = true;
}
} else {
for (BlockState state : type.getAllStates()) {
if (FastBitSet.get(bitSet, state.getInternalPropertiesId())) {
ordinals[state.getOrdinal()] = true;
}
}
}
}
}
return ordinals;
}
public BlockMask build(Extent extent) {
optimize();
return new BlockMask(extent, bitSets);
return new BlockMask(extent, getOrdinals());
}
}

View File

@ -20,7 +20,6 @@
package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockType;
@ -37,8 +36,12 @@ import java.util.Set;
*
* <p>This mask checks for ONLY the block type. If state should also be checked,
* use {@link BlockMask}.</p>
* @deprecated use BlockMaskBuilder
*/
public class BlockTypeMask extends AbstractExtentMask {
import static com.google.common.base.Preconditions.checkNotNull;
@Deprecated
public final class BlockTypeMask extends AbstractExtentMask {
private final boolean[] types;
@ -110,12 +113,11 @@ public class BlockTypeMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return types[getExtent().getBlock(vector).getBlockType().getInternalId()];
return test(vector.getBlock(getExtent()).getBlockType());
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
public boolean test(BlockType block) {
return types[block.getInternalId()];
}
}

View File

@ -2,10 +2,11 @@ package com.sk89q.worldedit.function.mask;
import com.sk89q.worldedit.extent.Extent;
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 SingleBlockTypeMask extends AbstractExtentMask {
public class SingleBlockTypeMask extends ABlockMask {
private final int internalId;
public SingleBlockTypeMask(Extent extent, BlockType type) {
@ -15,12 +16,17 @@ public class SingleBlockTypeMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return getExtent().getBlock(vector).getBlockType().getInternalId() == internalId;
return test(vector.getBlock(getExtent()));
}
@Override
public final boolean test(BlockState state) {
return state.getBlockType().getInternalId() == internalId;
}
@Override
public Mask inverse() {
return new BlockMaskBuilder().add(BlockTypes.get(internalId)).build(getExtent()).inverse();
return new InverseSingleBlockTypeMask(getExtent(), BlockTypes.values[internalId]);
}
public BlockType getBlockType() {

View File

@ -27,10 +27,10 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nullable;
public class SolidBlockMask extends BlockTypeMask {
public class SolidBlockMask extends BlockMask {
public SolidBlockMask(Extent extent) {
super(extent, getTypes());
super(extent);
add(state -> state.getMaterial().isSolid());
}
@Override

View File

@ -22,11 +22,7 @@ package com.sk89q.worldedit.function.visitor;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.MappedFaweQueue;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HasFaweQueue;
import com.boydti.fawe.object.IntegerTrio;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
@ -38,8 +34,11 @@ import com.sk89q.worldedit.util.Direction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Performs a breadth-first search starting from points added with
* {@link #visit(BlockVector3)}. The search continues
@ -81,13 +80,12 @@ public abstract class BreadthFirstSearch implements Operation {
}
private final RegionFunction function;
private BlockVectorSet queue;
private BlockVector3[] directions;
private BlockVectorSet visited;
private BlockVectorSet queue;
private int affected = 0;
private int currentDepth = 0;
private final int maxDepth;
private List<BlockVector3> directions = new ArrayList<>();
private final MappedFaweQueue mFaweQueue;
private int maxBranch = Integer.MAX_VALUE;
/**
@ -101,33 +99,20 @@ public abstract class BreadthFirstSearch implements Operation {
}
public BreadthFirstSearch(RegionFunction function, int maxDepth) {
this(function, maxDepth, null);
checkNotNull(function);
}
public BreadthFirstSearch(RegionFunction function, int maxDepth, HasFaweQueue faweQueue) {
checkNotNull(function);
FaweQueue fq = faweQueue != null ? faweQueue.getQueue() : null;
this.mFaweQueue = fq instanceof MappedFaweQueue ? (MappedFaweQueue) fq : null;
this.queue = new BlockVectorSet();
this.visited = new BlockVectorSet();
this.function = function;
this.directions.addAll(Arrays.asList(DEFAULT_DIRECTIONS));
this.directions = DEFAULT_DIRECTIONS;
this.maxDepth = maxDepth;
}
public void setDirections(List<BlockVector3> directions) {
public void setDirections(BlockVector3... directions) {
this.directions = directions;
}
private IntegerTrio[] getIntDirections() {
IntegerTrio[] array = new IntegerTrio[directions.size()];
for (int i = 0; i < array.length; i++) {
BlockVector3 dir = directions.get(i);
array[i] = new IntegerTrio(dir.getBlockX(), dir.getBlockY(), dir.getBlockZ());
}
return array;
public void setDirections(Collection<BlockVector3> directions) {
setDirections(directions.toArray(new BlockVector3[0]));
}
/**
@ -138,34 +123,36 @@ public abstract class BreadthFirstSearch implements Operation {
* unit vectors. An example of a valid direction is
* {@code BlockVector3.at(1, 0, 1)}.</p>
*
* <p>The list of directions can be cleared.</p>
*
* @return the list of directions
*/
protected Collection<BlockVector3> getDirections() {
return directions;
public Collection<BlockVector3> getDirections() {
return Arrays.asList(directions);
}
/**
* Add the directions along the axes as directions to visit.
*/
protected void addAxes() {
directions.add(BlockVector3.UNIT_MINUS_Y);
directions.add(BlockVector3.UNIT_Y);
directions.add(BlockVector3.UNIT_MINUS_X);
directions.add(BlockVector3.UNIT_X);
directions.add(BlockVector3.UNIT_MINUS_Z);
directions.add(BlockVector3.UNIT_Z);
public void addAxes() {
HashSet<BlockVector3> set = new HashSet<>(Arrays.asList(directions));
set.add(BlockVector3.UNIT_MINUS_Y);
set.add(BlockVector3.UNIT_Y);
set.add(BlockVector3.UNIT_MINUS_X);
set.add(BlockVector3.UNIT_X);
set.add(BlockVector3.UNIT_MINUS_Z);
set.add(BlockVector3.UNIT_Z);
setDirections(set);
}
/**
* Add the diagonal directions as directions to visit.
*/
protected void addDiagonal() {
directions.add(Direction.NORTHEAST.toBlockVector());
directions.add(Direction.SOUTHEAST.toBlockVector());
directions.add(Direction.SOUTHWEST.toBlockVector());
directions.add(Direction.NORTHWEST.toBlockVector());
public void addDiagonal() {
HashSet<BlockVector3> set = new HashSet<>(Arrays.asList(directions));
set.add(Direction.NORTHEAST.toBlockVector());
set.add(Direction.SOUTHEAST.toBlockVector());
set.add(Direction.SOUTHWEST.toBlockVector());
set.add(Direction.NORTHWEST.toBlockVector());
setDirections(set);
}
/**
@ -206,21 +193,6 @@ public abstract class BreadthFirstSearch implements Operation {
public void setMaxBranch(int maxBranch) {
this.maxBranch = maxBranch;
}
/**
* Try to visit the given 'to' location.
*
* @param from the origin block
* @param to the block under question
*/
private void visit(BlockVector3 from, BlockVector3 to) {
BlockVector3 blockVector = to;
if (!visited.contains(blockVector)) {
visited.add(blockVector);
if (isVisitable(from, to)) {
queue.add(blockVector);
}
}
}
/**
* Return whether the given 'to' block should be visited, starting from the
@ -244,42 +216,22 @@ public abstract class BreadthFirstSearch implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
MutableBlockVector3 mutable = new MutableBlockVector3();
IntegerTrio[] dirs = getIntDirections();
// MutableBlockVector3 mutable2 = new MutableBlockVector3();
boolean shouldTrim = false;
BlockVector3[] dirs = directions;
BlockVectorSet tempQueue = new BlockVectorSet();
BlockVectorSet chunkLoadSet = new BlockVectorSet();
for (currentDepth = 0; !queue.isEmpty() && currentDepth <= maxDepth; currentDepth++) {
if (mFaweQueue != null && Settings.IMP.QUEUE.PRELOAD_CHUNKS > 1) {
int cx = Integer.MIN_VALUE;
int cz = Integer.MIN_VALUE;
for (BlockVector3 from : queue) {
for (IntegerTrio direction : dirs) {
int x = from.getBlockX() + direction.x;
int z = from.getBlockZ() + direction.z;
if (cx != (cx = x >> 4) || cz != (cz = z >> 4)) {
int y = from.getBlockY() + direction.y;
if (y < 0 || y >= 256) {
continue;
}
if (!visited.contains(x, y, z)) {
chunkLoadSet.add(cx, 0, cz);
}
}
}
}
for (BlockVector3 chunk : chunkLoadSet) {
mFaweQueue.queueChunkLoad(chunk.getBlockX(), chunk.getBlockZ());
}
}
for (BlockVector3 from : queue) {
if (function.apply(from)) affected++;
for (int i = 0, j = 0; i < dirs.length && j < maxBranch; i++) {
IntegerTrio direction = dirs[i];
int y = from.getBlockY() + direction.y;
BlockVector3 direction = dirs[i];
int y = from.getBlockY() + direction.getY();
if (y < 0 || y >= 256) {
continue;
}
int x = from.getBlockX() + direction.x;
int z = from.getBlockZ() + direction.z;
int x = from.getBlockX() + direction.getX();
int z = from.getBlockZ() + direction.getZ();
if (!visited.contains(x, y, z)) {
if (isVisitable(from, mutable.setComponents(x, y, z))) {
j++;

View File

@ -21,30 +21,36 @@ package com.sk89q.worldedit.math;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ComparisonChain;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import java.util.Comparator;
/**
* An immutable 3-dimensional vector.
*/
public class BlockVector3 {
public abstract class BlockVector3 {
public static final BlockVector3 ZERO = new BlockVector3(0, 0, 0);
public static final BlockVector3 UNIT_X = new BlockVector3(1, 0, 0);
public static final BlockVector3 UNIT_Y = new BlockVector3(0, 1, 0);
public static final BlockVector3 UNIT_Z = new BlockVector3(0, 0, 1);
public static final BlockVector3 UNIT_MINUS_X = new BlockVector3(-1, 0, 0);
public static final BlockVector3 UNIT_MINUS_Y = new BlockVector3(0, -1, 0);
public static final BlockVector3 UNIT_MINUS_Z = new BlockVector3(0, 0, -1);
public static final BlockVector3 ONE = new BlockVector3(1, 1, 1);
public static final BlockVector3 ZERO = BlockVector3.at(0, 0, 0);
public static final BlockVector3 UNIT_X = BlockVector3.at(1, 0, 0);
public static final BlockVector3 UNIT_Y = BlockVector3.at(0, 1, 0);
public static final BlockVector3 UNIT_Z = BlockVector3.at(0, 0, 1);
public static final BlockVector3 UNIT_MINUS_X = BlockVector3.at(-1, 0, 0);
public static final BlockVector3 UNIT_MINUS_Y = BlockVector3.at(0, -1, 0);
public static final BlockVector3 UNIT_MINUS_Z = BlockVector3.at(0, 0, -1);
public static final BlockVector3 ONE = BlockVector3.at(1, 1, 1);
public static BlockVector3 at(double x, double y, double z) {
return at((int) Math.floor(x), (int) Math.floor(y), (int) Math.floor(z));
}
public static BlockVector3 at(int x, int y, int z) {
return new BlockVector3(x, y, z);
return new BlockVector3Imp(x, y, z);
}
// thread-safe initialization idiom
@ -65,23 +71,6 @@ public class BlockVector3 {
return YzxOrderComparator.YZX_ORDER;
}
protected int x, y, z;
protected BlockVector3(){}
/**
* Construct an instance.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
*/
protected BlockVector3(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public MutableBlockVector3 setComponents(double x, double y, double z) {
return new MutableBlockVector3((int) x, (int) y, (int) z);
}
@ -91,37 +80,71 @@ public class BlockVector3 {
}
public MutableBlockVector3 mutX(double x) {
return new MutableBlockVector3((int) x, y, z);
return new MutableBlockVector3((int) x, getY(), getZ());
}
public MutableBlockVector3 mutY(double y) {
return new MutableBlockVector3(x, (int) y, z);
return new MutableBlockVector3(getX(), (int) y, getZ());
}
public MutableBlockVector3 mutZ(double z) {
return new MutableBlockVector3(x, y, (int) z);
return new MutableBlockVector3(getX(), getY(), (int) z);
}
public MutableBlockVector3 mutX(int x) {
return new MutableBlockVector3(x, y, z);
return new MutableBlockVector3(x, getY(), getZ());
}
public MutableBlockVector3 mutY(int y) {
return new MutableBlockVector3(x, y, z);
return new MutableBlockVector3(getX(), y, getZ());
}
public MutableBlockVector3 mutZ(int z) {
return new MutableBlockVector3(x, y, z);
return new MutableBlockVector3(getX(), getY(), z);
}
public BlockVector3 toImmutable() {
return BlockVector3.at(getX(), getY(), getZ());
}
// /**
// * Get the BlockVector3 to the north<br>
// * Normal use you would use north(this),
// * To avoid constructing a new Vector, pass e.g. north(some MutableBlockVector3)
// * There is no gaurantee it will use this provided vector
// * @param orDefault the vector to use as the result<br>
// * @return BlockVector3
// */
// public BlockVector3 north(BlockVector3 orDefault) {
// return orDefault.setComponents(getX(), getY(), getZ() - 1);
// }
//
// public BlockVector3 east(BlockVector3 orDefault) {
// return orDefault.setComponents(getX() + 1, getY(), getZ());
// }
//
// public BlockVector3 south(BlockVector3 orDefault) {
// return orDefault.setComponents(getX(), getY(), getZ() + 1);
// }
//
// public BlockVector3 west(BlockVector3 orDefault) {
// return orDefault.setComponents(getX() - 1, getY(), getZ());
// }
//
// public BlockVector3 up(BlockVector3 orDefault) {
// return orDefault.setComponents(getX(), getY() + 1, getZ());
// }
//
// public BlockVector3 down(BlockVector3 orDefault) {
// return orDefault.setComponents(getX(), getY() - 1, getZ());
// }
/**
* Get the X coordinate.
*
* @return the x coordinate
*/
public int getX() {
return x;
}
public abstract int getX();
/**
* Get the X coordinate.
@ -129,7 +152,7 @@ public class BlockVector3 {
* @return the x coordinate
*/
public int getBlockX() {
return x;
return getX();
}
/**
@ -139,7 +162,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 withX(int x) {
return BlockVector3.at(x, y, z);
return BlockVector3.at(x, getY(), getZ());
}
/**
@ -147,9 +170,7 @@ public class BlockVector3 {
*
* @return the y coordinate
*/
public int getY() {
return y;
}
public abstract int getY();
/**
* Get the Y coordinate.
@ -157,7 +178,7 @@ public class BlockVector3 {
* @return the y coordinate
*/
public int getBlockY() {
return y;
return getY();
}
/**
@ -167,7 +188,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 withY(int y) {
return BlockVector3.at(x, y, z);
return BlockVector3.at(getX(), y, getZ());
}
/**
@ -175,9 +196,7 @@ public class BlockVector3 {
*
* @return the z coordinate
*/
public int getZ() {
return z;
}
public abstract int getZ();
/**
* Get the Z coordinate.
@ -185,7 +204,7 @@ public class BlockVector3 {
* @return the z coordinate
*/
public int getBlockZ() {
return z;
return getZ();
}
/**
@ -195,7 +214,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 withZ(int z) {
return BlockVector3.at(x, y, z);
return BlockVector3.at(getX(), getY(), z);
}
/**
@ -205,7 +224,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 add(BlockVector3 other) {
return add(other.x, other.y, other.z);
return add(other.getX(), other.getY(), other.getZ());
}
/**
@ -217,7 +236,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 add(int x, int y, int z) {
return BlockVector3.at(this.x + x, this.y + y, this.z + z);
return BlockVector3.at(this.getX() + x, this.getY() + y, this.getZ() + z);
}
/**
@ -228,12 +247,12 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 add(BlockVector3... others) {
int newX = x, newY = y, newZ = z;
int newX = getX(), newY = getY(), newZ = getZ();
for (BlockVector3 other : others) {
newX += other.x;
newY += other.y;
newZ += other.z;
newX += other.getX();
newY += other.getY();
newZ += other.getZ();
}
return BlockVector3.at(newX, newY, newZ);
@ -247,7 +266,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 subtract(BlockVector3 other) {
return subtract(other.x, other.y, other.z);
return subtract(other.getX(), other.getY(), other.getZ());
}
/**
@ -260,7 +279,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 subtract(int x, int y, int z) {
return BlockVector3.at(this.x - x, this.y - y, this.z - z);
return BlockVector3.at(this.getX() - x, this.getY() - y, this.getZ() - z);
}
/**
@ -271,12 +290,12 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 subtract(BlockVector3... others) {
int newX = x, newY = y, newZ = z;
int newX = getX(), newY = getY(), newZ = getZ();
for (BlockVector3 other : others) {
newX -= other.x;
newY -= other.y;
newZ -= other.z;
newX -= other.getX();
newY -= other.getY();
newZ -= other.getZ();
}
return BlockVector3.at(newX, newY, newZ);
@ -289,7 +308,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 multiply(BlockVector3 other) {
return multiply(other.x, other.y, other.z);
return multiply(other.getX(), other.getY(), other.getZ());
}
/**
@ -301,7 +320,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 multiply(int x, int y, int z) {
return BlockVector3.at(this.x * x, this.y * y, this.z * z);
return BlockVector3.at(this.getX() * x, this.getY() * y, this.getZ() * z);
}
/**
@ -311,12 +330,12 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 multiply(BlockVector3... others) {
int newX = x, newY = y, newZ = z;
int newX = getX(), newY = getY(), newZ = getZ();
for (BlockVector3 other : others) {
newX *= other.x;
newY *= other.y;
newZ *= other.z;
newX *= other.getX();
newY *= other.getY();
newZ *= other.getZ();
}
return BlockVector3.at(newX, newY, newZ);
@ -339,7 +358,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 divide(BlockVector3 other) {
return divide(other.x, other.y, other.z);
return divide(other.getX(), other.getY(), other.getZ());
}
/**
@ -351,7 +370,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 divide(int x, int y, int z) {
return BlockVector3.at(this.x / x, this.y / y, this.z / z);
return BlockVector3.at(this.getX() / x, this.getY() / y, this.getZ() / z);
}
/**
@ -423,7 +442,7 @@ public class BlockVector3 {
* @return length, squared
*/
public int lengthSq() {
return x * x + y * y + z * z;
return getX() * getX() + getY() * getY() + getZ() * getZ();
}
/**
@ -443,9 +462,9 @@ public class BlockVector3 {
* @return distance
*/
public int distanceSq(BlockVector3 other) {
int dx = other.x - x;
int dy = other.y - y;
int dz = other.z - z;
int dx = other.getX() - getX();
int dy = other.getY() - getY();
int dz = other.getZ() - getZ();
return dx * dx + dy * dy + dz * dz;
}
@ -457,9 +476,9 @@ public class BlockVector3 {
*/
public BlockVector3 normalize() {
double len = length();
double x = this.x / len;
double y = this.y / len;
double z = this.z / len;
double x = this.getX() / len;
double y = this.getY() / len;
double z = this.getZ() / len;
return BlockVector3.at(x, y, z);
}
@ -470,7 +489,7 @@ public class BlockVector3 {
* @return the dot product of this and the other vector
*/
public double dot(BlockVector3 other) {
return x * other.x + y * other.y + z * other.z;
return getX() * other.getX() + getY() * other.getY() + getZ() * other.getZ();
}
/**
@ -480,10 +499,10 @@ public class BlockVector3 {
* @return the cross product of this and the other vector
*/
public BlockVector3 cross(BlockVector3 other) {
return new BlockVector3(
y * other.z - z * other.y,
z * other.x - x * other.z,
x * other.y - y * other.x
return new BlockVector3Imp(
getY() * other.getZ() - getZ() * other.getY(),
getZ() * other.getX() - getX() * other.getZ(),
getX() * other.getY() - getY() * other.getX()
);
}
@ -495,7 +514,7 @@ public class BlockVector3 {
* @return true if the vector is contained
*/
public boolean containedWithin(BlockVector3 min, BlockVector3 max) {
return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z;
return getX() >= min.getX() && getX() <= max.getX() && getY() >= min.getY() && getY() <= max.getY() && getZ() >= min.getZ() && getZ() <= max.getZ();
}
/**
@ -507,11 +526,11 @@ public class BlockVector3 {
*/
public BlockVector3 clampY(int min, int max) {
checkArgument(min <= max, "minimum cannot be greater than maximum");
if (y < min) {
return BlockVector3.at(x, min, z);
if (getY() < min) {
return BlockVector3.at(getX(), min, getZ());
}
if (y > max) {
return BlockVector3.at(x, max, z);
if (getY() > max) {
return BlockVector3.at(getX(), max, getZ());
}
return this;
}
@ -555,7 +574,7 @@ public class BlockVector3 {
* @return a new vector
*/
public BlockVector3 abs() {
return BlockVector3.at(Math.abs(x), Math.abs(y), Math.abs(z));
return BlockVector3.at(Math.abs(getX()), Math.abs(getY()), Math.abs(getZ()));
}
/**
@ -571,8 +590,8 @@ public class BlockVector3 {
*/
public BlockVector3 transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
angle = Math.toRadians(angle);
double x = this.x - aboutX;
double z = this.z - aboutZ;
double x = this.getX() - aboutX;
double z = this.getZ() - aboutZ;
double cos = Math.cos(angle);
double sin = Math.sin(angle);
double x2 = x * cos - z * sin;
@ -580,7 +599,7 @@ public class BlockVector3 {
return BlockVector3.at(
x2 + aboutX + translateX,
y,
getY(),
z2 + aboutZ + translateZ
);
}
@ -626,10 +645,10 @@ public class BlockVector3 {
* @return minimum
*/
public BlockVector3 getMinimum(BlockVector3 v2) {
return new BlockVector3(
Math.min(x, v2.x),
Math.min(y, v2.y),
Math.min(z, v2.z)
return new BlockVector3Imp(
Math.min(getX(), v2.getX()),
Math.min(getY(), v2.getY()),
Math.min(getZ(), v2.getZ())
);
}
@ -640,44 +659,110 @@ public class BlockVector3 {
* @return maximum
*/
public BlockVector3 getMaximum(BlockVector3 v2) {
return new BlockVector3(
Math.max(x, v2.x),
Math.max(y, v2.y),
Math.max(z, v2.z)
return new BlockVector3Imp(
Math.max(getX(), v2.getX()),
Math.max(getY(), v2.getY()),
Math.max(getZ(), v2.getZ())
);
}
/*
Methods for getting/setting blocks
Why are these methods here?
- Getting a block at a position requires various operations
(bounds checks, cache checks, ensuring loaded chunk, get ChunkSection, etc.)
- When iterating over a region, it will provide custom BlockVector3 positions
- These override the below set/get and avoid lookups (as the iterator shifts it to the chunk level)
*/
public boolean setOrdinal(Extent orDefault, int ordinal) {
return orDefault.setBlock(this, BlockState.getFromOrdinal(ordinal));
}
public boolean setBlock(Extent orDefault, BlockState state) {
return orDefault.setBlock(this, state);
}
public boolean setFullBlock(Extent orDefault, BaseBlock block) {
return orDefault.setBlock(this, block);
}
public boolean setBiome(Extent orDefault, BiomeType biome) {
return orDefault.setBiome(getX(), getY(), getZ(), biome);
}
public int getOrdinal(Extent orDefault) {
return getBlock(orDefault).getOrdinal();
}
public char getOrdinalChar(Extent orDefault) {
return (char) getOrdinal(orDefault);
}
public BlockState getBlock(Extent orDefault) {
return orDefault.getBlock(this);
}
public BaseBlock getFullBlock(Extent orDefault) {
return orDefault.getFullBlock(this);
}
public CompoundTag getNbtData(Extent orDefault) {
return orDefault.getFullBlock(getX(), getY(), getZ()).getNbtData();
}
public BlockState getOrdinalBelow(Extent orDefault) {
return orDefault.getBlock(getX(), getY() - 1, getZ());
}
public BlockState getStateAbove(Extent orDefault) {
return orDefault.getBlock(getX(), getY() + 1, getZ());
}
public BlockState getStateRelativeY(Extent orDefault, final int y) {
return orDefault.getBlock(getX(), getY() + y, getZ());
}
/*
Adapt
*/
/**
* Creates a 2D vector by dropping the Y component from this vector.
*
* @return a new {@link BlockVector2}
*/
public BlockVector2 toBlockVector2() {
return BlockVector2.at(x, z);
return BlockVector2.at(getX(), getZ());
}
public Vector3 toVector3() {
return Vector3.at(x, y, z);
return Vector3.at(getX(), getY(), getZ());
}
@Override
public boolean equals(Object obj) {
public final boolean equals(Object obj) {
if (!(obj instanceof BlockVector3)) {
return false;
}
BlockVector3 other = (BlockVector3) obj;
return other.x == this.x && other.y == this.y && other.z == this.z;
return equals((BlockVector3) obj);
}
public final boolean equals(BlockVector3 other) {
return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ();
}
@Override
public int hashCode() {
return (x ^ (z << 12)) ^ (y << 24);
return (getX() ^ (getZ() << 12)) ^ (getY() << 24);
}
@Override
public String toString() {
return "(" + x + ", " + y + ", " + z + ")";
return "(" + getX() + ", " + getY() + ", " + getZ() + ")";
}
}

View File

@ -1,9 +1,18 @@
package com.sk89q.worldedit.math;
import com.boydti.fawe.FaweCache;
public class MutableVector3 extends Vector3 {
public MutableVector3() {
}
public static MutableVector3 get(int x, int y, int z) {
return FaweCache.MUTABLE_VECTOR3.get().setComponents(x, y, z);
}
public static MutableVector3 get(double x, double y, double z) {
return FaweCache.MUTABLE_VECTOR3.get().setComponents(x, y, z);
}
public MutableVector3(double x, double y, double z) {
super(x, y, z);
@ -77,7 +86,4 @@ public class MutableVector3 extends Vector3 {
return this;
}
public double getY() {
return y;
}
}

View File

@ -22,6 +22,11 @@ package com.sk89q.worldedit.regions;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.sk89q.worldedit.math.BlockVector2;
@ -387,7 +392,6 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
return chunks;
}
@Override
public boolean contains(int x, int y, int z) {
return x >= this.minX && x <= this.maxX && z >= this.minZ && z <= this.maxZ && y >= this.minY && y <= this.maxY;
@ -398,14 +402,6 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
return x >= this.minX && x <= this.maxX && z >= this.minZ && z <= this.maxZ;
}
@Override
public boolean contains(BlockVector3 position) {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return position.containedWithin(min, max);
}
@Override
public Iterator<BlockVector3> iterator() {
if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9 || useOldIterator) {
@ -610,4 +606,51 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
BlockVector3 size = BlockVector3.ONE.multiply(apothem);
return new CuboidRegion(origin.subtract(size), origin.add(size));
}
@Override
public int getMinY() {
return minY;
}
@Override
public int getMaxY() {
return maxY;
}
@Override
public void filter(final IChunk chunk, final Filter filter, ChunkFilterBlock block, final IChunkGet get, final IChunkSet set) {
int X = chunk.getX();
int Z = chunk.getZ();
block = block.init(X, Z, get);
if ((minX + 15) >> 4 <= X && (maxX - 15) >> 4 >= X && (minZ + 15) >> 4 <= Z && (maxZ - 15) >> 4 >= Z) {
filter(chunk, filter, block, get, set, minY, maxY);
return;
}
int localMinX = Math.max(minX, X << 4) & 15;
int localMaxX = Math.min(maxX, 15 + X << 4) & 15;
int localMinZ = Math.max(minZ, Z << 4) & 15;
int localMaxZ = Math.min(maxZ, 15 + Z << 4) & 15;
int yStart = (minY & 15);
int yEnd = (maxY & 15);
int minSection = minY >> 4;
int maxSection = maxY >> 4;
if (minSection == maxSection) {
filter(chunk, filter, block, get, set, minSection, localMinX, yStart, localMinZ, localMaxX, yEnd, localMaxZ);
return;
}
if (yStart != 0) {
filter(chunk, filter, block, get, set, minSection, localMinX, yStart, localMinZ, localMaxX, 15, localMaxZ);
minSection++;
}
if (yEnd != 15) {
filter(chunk, filter, block, get, set, minSection, localMinX, 0, localMinZ, localMaxX, 15, localMaxZ);
maxSection--;
}
for (int layer = minSection; layer < maxSection; layer++) {
filter(chunk, filter, block, get, set, layer, localMinX, yStart, localMinZ, localMaxX, yEnd, localMaxZ);
}
}
}

View File

@ -21,6 +21,11 @@ package com.sk89q.worldedit.regions;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
@ -288,26 +293,22 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
minY += changeY;
}
/**
* Checks to see if a point is inside this region.
*/
@Override
public boolean contains(BlockVector3 position) {
final int blockY = position.getBlockY();
if (blockY < minY || blockY > maxY) {
public boolean contains(int x, int y, int z) {
if (y < minY || y > maxY) {
return false;
}
//todo the following lines can possibly be removed and replaced with upstream
int px = position.getBlockX();
int pz = position.getBlockZ();
return contains(x, z);
}
double dx = Math.abs(px - center.getBlockX()) * radiusInverse.getX();
double dz = Math.abs(pz - center.getBlockZ()) * radiusInverse.getZ();
@Override
public boolean contains(int x, int z) {
double dx = Math.abs(x - center.getBlockX()) * radiusInverse.getX();
double dz = Math.abs(z - center.getBlockZ()) * radiusInverse.getZ();
return dx * dx + dz * dz <= 1;
}
/**
* Sets the height of the cylinder to fit the specified Y.
*
@ -362,6 +363,16 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
return Polygons.polygonizeCylinder(center, radius, maxPoints);
}
@Override
public int getMinY() {
return minY;
}
@Override
public int getMaxY() {
return maxY;
}
/**
* Return a new instance with the given center and radius in the X and Z
* axes with a Y that extends from the bottom of the extent to the top
@ -381,4 +392,16 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
return new CylinderRegion(center, radiusVec, minY, maxY);
}
@Override
public void filter(final IChunk chunk, final Filter filter, final ChunkFilterBlock block, final IChunkGet get, final IChunkSet set) {
int bcx = chunk.getX() >> 4;
int bcz = chunk.getZ() >> 4;
int tcx = bcx + 15;
int tcz = bcz + 15;
if (contains(bcx, bcz) && contains(tcx, tcz)) {
filter(chunk, filter, block, get, set, minY, maxY);
return;
}
super.filter(chunk, filter, block, get, set);
}
}

View File

@ -19,6 +19,13 @@
package com.sk89q.worldedit.regions;
import com.boydti.fawe.beta.ChunkFilterBlock;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
@ -44,6 +51,7 @@ public class EllipsoidRegion extends AbstractRegion {
private Vector3 radius;
private Vector3 radiusSqr;
private Vector3 inverseRadius;
private int radiusLengthSqr;
private boolean sphere;
@ -180,6 +188,12 @@ public class EllipsoidRegion extends AbstractRegion {
radiusSqr = radius.multiply(radius);
radiusLengthSqr = (int) radiusSqr.getX();
this.sphere = radius.getY() == radius.getX() && radius.getX() == radius.getZ();
if (radius.getY() == radius.getX() && radius.getX() == radius.getZ()) {
this.sphere = true;
} else {
this.sphere = false;
}
inverseRadius = Vector3.ONE.divide(radius);
}
@Override
@ -206,30 +220,50 @@ public class EllipsoidRegion extends AbstractRegion {
return chunks;
}
@Override
public boolean contains(int x, int y, int z) {
int cx = x - center.getBlockX();
int cx2 = cx * cx;
if (cx2 > radiusSqr.getBlockX()) {
return false;
}
int cz = z - center.getBlockZ();
int cz2 = cz * cz;
if (cz2 > radiusSqr.getBlockZ()) {
return false;
}
int cy = y - center.getBlockY();
int cy2 = cy * cy;
if (radiusSqr.getBlockY() < 255 && cy2 > radiusSqr.getBlockY()) {
return false;
}
if (sphere) {
return cx2 + cy2 + cz2 <= radiusLengthSqr;
}
double cxd = cx2 * inverseRadius.getX();
double cyd = cy2 * inverseRadius.getY();
double czd = cz2 * inverseRadius.getZ();
return cxd + cyd + czd <= 1;
}
@Override
public boolean contains(BlockVector3 position) {
int cx = position.getBlockX() - center.getBlockX();
public boolean contains(int x, int z) {
int cx = x - center.getBlockX();
int cx2 = cx * cx;
if (cx2 > radiusSqr.getBlockX()) {
return false;
}
int cz = position.getBlockZ() - center.getBlockZ();
int cz = z - center.getBlockZ();
int cz2 = cz * cz;
if (cz2 > radiusSqr.getBlockZ()) {
return false;
}
int cy = position.getBlockY() - center.getBlockY();
int cy2 = cy * cy;
if (radiusSqr.getBlockY() < 255 && cy2 > radiusSqr.getBlockY()) {
return false;
}
if (sphere) {
return cx2 + cy2 + cz2 <= radiusLengthSqr;
return cx2 + cz2 <= radiusLengthSqr;
}
double cxd = (double) cx / radius.getBlockX();
double cyd = (double) cy / radius.getBlockY();
double czd = (double) cz / radius.getBlockZ();
return cxd * cxd + cyd * cyd + czd * czd <= 1;
double cxd = cx2 * inverseRadius.getX();
double czd = cz2 * inverseRadius.getZ();
return cxd + czd <= 1;
}
/**
@ -252,4 +286,113 @@ public class EllipsoidRegion extends AbstractRegion {
return (EllipsoidRegion) super.clone();
}
private void filterSpherePartial(int y1, int y2, int bx, int bz, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) {
int sectionStart = y1 >> 4;
int sectionEnd = y2 >> 4;
}
private void filterSpherePartial(int layer, int y1, int y2, int bx, int bz, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) {
int cx = center.getBlockX();
int cy = center.getBlockY();
int cz = center.getBlockZ();
block.init(get, set, layer);
int by = layer << 4;
int diffY;
for (int y = y1, yy = by + y1; y <= y2; y++, yy++) {
diffY = cy - yy;
int remainderY = radiusLengthSqr - (diffY * diffY);
if (remainderY >= 0) {
for (int z = 0; z < 16; z++) {
int zz = z + bz;
int diffZ = cz - zz;
int remainderZ = remainderY - (diffZ * diffZ);
if (remainderZ >= 0) {
int diffX = MathMan.usqrt(remainderZ);
int minX = Math.max(0, cx - diffX - bx);
int maxX = Math.min(15, cx + diffX - bx);
if (minX != maxX) {
block.filter(filter, minX, y, z, maxX, y, z);
}
}
}
}
}
}
@Override
public void filter(IChunk chunk, Filter filter, ChunkFilterBlock block, IChunkGet get, IChunkSet set) {
// Check bounds
// This needs to be able to perform 50M blocks/sec otherwise it becomes a bottleneck
int cx = center.getBlockX();
int cz = center.getBlockZ();
int bx = chunk.getX() << 4;
int bz = chunk.getZ() << 4;
int tx = bx + 15;
int tz = bz + 15;
int cx1 = bx - cx;
int cx2 = tx - cx;
int cxMax, cxMin;
if (cx1 < cx2) {
cxMin = cx1;
cxMax = cx2;
} else {
cxMin = cx2;
cxMax = cx1;
}
int cxMin2 = cxMin * cxMin;
int cxMax2 = cxMax * cxMax;
int cz1 = bz - cz;
int cz2 = tz - cz;
int czMax, czMin;
if (cz1 < cz2) {
czMin = cz1;
czMax = cz2;
} else {
czMin = cz2;
czMax = cz1;
}
int czMin2 = czMin * czMin;
int czMax2 = czMax * czMax;
if (sphere) {
// Does not contain chunk
if (cxMin2 + czMin2 >= radiusLengthSqr) {
return;
}
int diffY2 = radiusLengthSqr - cxMax2 - czMax2;
// (shortcut) Contains all of certain layers
if (diffY2 >= 0) {
// Get the solid layers
int cy = center.getBlockY();
int diffYFull = MathMan.usqrt(diffY2);
int yBotFull = Math.max(0, cy - diffYFull);
int yTopFull = Math.min(255, cy + diffYFull);
// Set those layers
filter(chunk, filter, block, get, set, yBotFull, yTopFull);
// Fill the remaining layers
if (yBotFull != 0 || yTopFull != 255) {
int diffYPartial = MathMan.usqrt(radiusLengthSqr - cxMin * cxMin - czMin * czMin);
if (yBotFull != 0) {
int yBotPartial = Math.max(0, cy - diffYPartial);
filterSpherePartial(yBotPartial, yBotFull - 1, bx, bz, filter, block, get, set);
}
if (yTopFull != 255) {
int yTopPartial = Math.min(255, cy + diffYPartial);
filterSpherePartial(yTopFull + 1, yTopPartial - 1, bx, bz, filter, block, get, set);
}
}
}
} else {
super.filter(chunk, filter, block, get, set); // TODO optimize non spheres
}
}
}

View File

@ -20,17 +20,16 @@
package com.sk89q.worldedit.world;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -69,7 +68,7 @@ public abstract class AbstractWorld implements World {
@Override
public Mask createLiquidMask() {
return new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER);
return new BlockMask(this).add(BlockTypes.LAVA, BlockTypes.WATER);
}
@Override
@ -96,11 +95,6 @@ public abstract class AbstractWorld implements World {
return false;
}
@Override
public BlockState getLazyBlock(BlockVector3 position) {
return getBlock(position);
}
@Override
public boolean queueBlockBreakEffect(Platform server, BlockVector3 position, BlockType blockType, double priority) {
if (taskId == -1) {

View File

@ -26,9 +26,8 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.function.mask.BlockTypeMask;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
@ -41,6 +40,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.weather.WeatherType;
import com.sk89q.worldedit.world.weather.WeatherTypes;
import javax.annotation.Nullable;
import java.nio.file.Path;
/**
* An abstract implementation of {@link World}.
@ -59,12 +59,16 @@ public interface SimpleWorld extends World {
@Override
default BaseBlock getFullBlock(BlockVector3 position) {
return getLazyBlock(position).toBaseBlock();
return getBlock(position).toBaseBlock();
}
@Override
<B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 pt, B block) throws WorldEditException;
@Nullable @Override default Path getStoragePath() {
return null;
}
@Override
default int getMaxY() {
return getMaximumPoint().getBlockY();
@ -72,7 +76,7 @@ public interface SimpleWorld extends World {
@Override
default Mask createLiquidMask() {
return new BlockTypeMask(this, BlockTypes.LAVA, BlockTypes.WATER);
return new BlockMask(this).add(BlockTypes.LAVA, BlockTypes.WATER);
}
@Override
@ -115,11 +119,6 @@ public interface SimpleWorld extends World {
return BlockVector3.at(30000000, 255, 30000000);
}
@Override
default @Nullable Operation commit() {
return null;
}
@Override
default boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException {

View File

@ -26,6 +26,7 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.ABlockMask;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
@ -47,8 +48,8 @@ import java.util.Objects;
*/
public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
private BlockState blockState;
@Nullable protected CompoundTag nbtData;
private final BlockState blockState;
private final CompoundTag nbtData;
@Deprecated
public BaseBlock() {
@ -71,6 +72,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
*/
public BaseBlock(BlockState blockState) {
this.blockState = blockState;
nbtData = null;
}
/**
@ -181,7 +183,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
@Override
public void setNbtData(@Nullable CompoundTag nbtData) {
this.nbtData = nbtData;
throw new UnsupportedOperationException("Immutable");
}
/**
@ -233,13 +235,19 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
}
@Override
public BaseBlock toBaseBlock() {
public final char getOrdinalChar() {
return blockState.getOrdinalChar();
}
@Override
public final BaseBlock toBaseBlock() {
return this;
}
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return extent.setBlock(set, this);
set.setFullBlock(extent, this);
return true;
}
@Override
@ -280,7 +288,7 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
@Override
public int hashCode() {
return blockState.hashCode(); // stop changing this
return getOrdinal();
}
@Override
@ -291,5 +299,4 @@ public class BaseBlock implements BlockStateHolder<BaseBlock>, TileEntityBlock {
return blockState.getAsString();
// }
}
}

View File

@ -19,14 +19,11 @@
package com.sk89q.worldedit.world.block;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ImmutableList;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.SingleBlockTypeMask;
import com.sk89q.worldedit.function.pattern.FawePattern;
import com.sk89q.worldedit.math.BlockVector3;
@ -38,13 +35,16 @@ import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
public class BlockType implements FawePattern, Keyed {
private final String id;
@ -173,10 +173,15 @@ public class BlockType implements FawePattern, Keyed {
*
* @return The default state
*/
public BlockState getDefaultState() {
public final BlockState getDefaultState() {
return this.settings.defaultState;
}
/**
* @Deprecated use a Mask instead
* @return
*/
@Deprecated
public FuzzyBlockState getFuzzyMatcher() {
return new FuzzyBlockState(this);
}
@ -288,7 +293,7 @@ public class BlockType implements FawePattern, Keyed {
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
return extent.setBlock(set, this.getDefaultState());
return set.setBlock(extent, getDefaultState());
}
@Override
@ -296,7 +301,11 @@ public class BlockType implements FawePattern, Keyed {
return this.getDefaultState().toBaseBlock();
}
public Mask toMask(Extent extent) {
public SingleBlockTypeMask toMask() {
return toMask(null);
}
public SingleBlockTypeMask toMask(Extent extent) {
return new SingleBlockTypeMask(extent, this);
}

View File

@ -24,6 +24,7 @@ import com.sk89q.worldedit.world.registry.LegacyMapper;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Optional;
import java.util.Locale;
public final class ItemTypes {
@ -914,7 +915,7 @@ public final class ItemTypes {
@Nullable
public static ItemType parse(String input) {
input = input.toLowerCase();
input = input.toLowerCase(Locale.ROOT);
if (!Character.isAlphabetic(input.charAt(0))) {
try {
ItemType legacy = LegacyMapper.getInstance().getItemFromLegacy(input);