Fix some chunk loading issues

Affected 1.8/1.7
Also improves performance for various operations
This commit is contained in:
Jesse Boyd 2017-02-13 02:55:19 +11:00
parent 897d86b5cb
commit 47999d323b
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
24 changed files with 762 additions and 279 deletions

View File

@ -193,7 +193,7 @@ public class BukkitQueue17 extends BukkitQueue_0<net.minecraft.server.v1_7_R4.Ch
net.minecraft.server.v1_7_R4.Chunk chunk; net.minecraft.server.v1_7_R4.Chunk chunk;
net.minecraft.server.v1_7_R4.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_7_R4.CraftWorld) world).getHandle().chunkProviderServer; net.minecraft.server.v1_7_R4.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_7_R4.CraftWorld) world).getHandle().chunkProviderServer;
if (generate) { if (generate) {
return provider.getOrCreateChunk(x, z); return provider.originalGetChunkAt(x, z);
} else { } else {
return provider.loadChunk(x, z); return provider.loadChunk(x, z);
} }

View File

@ -193,7 +193,7 @@ public class BukkitQueue18R3 extends BukkitQueue_0<net.minecraft.server.v1_8_R3.
net.minecraft.server.v1_8_R3.Chunk chunk; net.minecraft.server.v1_8_R3.Chunk chunk;
net.minecraft.server.v1_8_R3.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_8_R3.CraftWorld) world).getHandle().chunkProviderServer; net.minecraft.server.v1_8_R3.ChunkProviderServer provider = ((org.bukkit.craftbukkit.v1_8_R3.CraftWorld) world).getHandle().chunkProviderServer;
if (generate) { if (generate) {
return provider.getOrCreateChunk(x, z); return provider.originalGetChunkAt(x, z);
} else { } else {
return provider.loadChunk(x, z); return provider.loadChunk(x, z);
} }

View File

@ -32,7 +32,7 @@ import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorCompletionService;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public abstract class FaweQueue { public abstract class FaweQueue implements HasFaweQueue {
private World weWorld; private World weWorld;
private String world; private String world;
@ -70,6 +70,11 @@ public abstract class FaweQueue {
ALL, ALL,
} }
@Override
public FaweQueue getQueue() {
return this;
}
public Settings getSettings() { public Settings getSettings() {
return settings; return settings;
} }
@ -386,6 +391,7 @@ public abstract class FaweQueue {
try { try {
return getCombinedId4Data(x, y, z); return getCombinedId4Data(x, y, z);
} catch (FaweException ignore) { } catch (FaweException ignore) {
ignore.printStackTrace();
return def; return def;
} }
} }

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.brush; package com.boydti.fawe.object.brush;
import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -12,7 +13,7 @@ import java.io.InputStream;
public class FlattenBrush extends HeightBrush { public class FlattenBrush extends HeightBrush {
public FlattenBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) { public FlattenBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
super(stream, rotation, yscale, tool, clipboard); super(stream, rotation, yscale, tool, clipboard, ScalableHeightMap.Shape.CYLINDER);
} }
@Override @Override

View File

@ -21,6 +21,10 @@ public class HeightBrush implements DoubleActionBrush {
public final DoubleActionBrushTool tool; public final DoubleActionBrushTool tool;
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) { public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
this(stream, rotation, yscale, tool, clipboard, ScalableHeightMap.Shape.CONE);
}
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) {
this.tool = tool; this.tool = tool;
this.rotation = (rotation / 90) % 4; this.rotation = (rotation / 90) % 4;
this.yscale = yscale; this.yscale = yscale;
@ -33,7 +37,7 @@ public class HeightBrush implements DoubleActionBrush {
} else if (clipboard != null) { } else if (clipboard != null) {
heightMap = ScalableHeightMap.fromClipboard(clipboard); heightMap = ScalableHeightMap.fromClipboard(clipboard);
} else { } else {
heightMap = new ScalableHeightMap(); heightMap = ScalableHeightMap.fromShape(shape);
} }
} }

View File

@ -0,0 +1,17 @@
package com.boydti.fawe.object.brush.heightmap;
public class FlatScalableHeightMap extends ScalableHeightMap {
public FlatScalableHeightMap() {
super();
}
public double getHeight(int x, int z) {
int dx = Math.abs(x);
int dz = Math.abs(z);
int d2 = dx * dx + dz * dz;
if (d2 > size2) {
return 0;
}
return size;
}
}

View File

@ -28,6 +28,11 @@ public class ScalableHeightMap {
public int size2; public int size2;
public int size; public int size;
public enum Shape {
CONE,
CYLINDER,
}
public ScalableHeightMap() { public ScalableHeightMap() {
setSize(5); setSize(5);
} }
@ -51,6 +56,16 @@ public class ScalableHeightMap {
return size - MathMan.sqrtApprox(d2); return size - MathMan.sqrtApprox(d2);
} }
public static ScalableHeightMap fromShape(Shape shape) {
switch (shape) {
default:
case CONE:
return new ScalableHeightMap();
case CYLINDER:
return new FlatScalableHeightMap();
}
}
public static ScalableHeightMap fromClipboard(Clipboard clipboard) { public static ScalableHeightMap fromClipboard(Clipboard clipboard) {
Vector dim = clipboard.getDimensions(); Vector dim = clipboard.getDimensions();
byte[][] heightArray = new byte[dim.getBlockX()][dim.getBlockZ()]; byte[][] heightArray = new byte[dim.getBlockX()][dim.getBlockZ()];

View File

@ -1,14 +1,19 @@
package com.boydti.fawe.object.clipboard; package com.boydti.fawe.object.clipboard;
import com.boydti.fawe.object.RunnableVal2; import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag; import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import java.util.List; import java.util.List;
@ -43,52 +48,61 @@ public class WorldCopyClipboard extends ReadOnlyClipboard {
} }
@Override @Override
public void forEach(RunnableVal2<Vector, BaseBlock> task, boolean air) { public void forEach(final RunnableVal2<Vector, BaseBlock> task, boolean air) {
MainUtil.stacktrace();
Vector min = region.getMinimumPoint(); Vector min = region.getMinimumPoint();
Vector max = region.getMaximumPoint(); Vector max = region.getMaximumPoint();
Vector pos = new Vector(); final Vector pos = new Vector();
if (region instanceof CuboidRegion) { if (region instanceof CuboidRegion) {
if (air) { if (air) {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { @Override
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { public boolean apply(Vector pos) throws WorldEditException {
BaseBlock block = getBlockAbs(x, y, z); int x = pos.getBlockX();
pos.mutX(x - mx); int y = pos.getBlockY();
pos.mutY(y - my); int z = pos.getBlockZ();
pos.mutZ(z - mz); BaseBlock block = getBlockAbs(x, y, z);
CompoundTag tag = block.getNbtData(); pos.mutX(x - mx);
if (tag != null) { pos.mutY(y - my);
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue()); pos.mutZ(z - mz);
values.put("x", new IntTag(pos.getBlockX())); CompoundTag tag = block.getNbtData();
values.put("y", new IntTag(pos.getBlockY())); if (tag != null) {
values.put("z", new IntTag(pos.getBlockZ())); Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
} values.put("x", new IntTag(pos.getBlockX()));
task.run(pos, block); values.put("y", new IntTag(pos.getBlockY()));
values.put("z", new IntTag(pos.getBlockZ()));
} }
task.run(pos, block);
return true;
} }
} }, editSession);
Operations.completeBlindly(visitor);
} else { } else {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { @Override
for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { public boolean apply(Vector pos) throws WorldEditException {
BaseBlock block = getBlockAbs(x, y, z); int x = pos.getBlockX();
if (block == EditSession.nullBlock) { int y = pos.getBlockY();
continue; int z = pos.getBlockZ();
} BaseBlock block = getBlockAbs(x, y, z);
pos.mutX(x - mx); if (block == EditSession.nullBlock) {
pos.mutY(y - my); return false;
pos.mutZ(z - mz);
CompoundTag tag = block.getNbtData();
if (tag != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("x", new IntTag(pos.getBlockX()));
values.put("y", new IntTag(pos.getBlockY()));
values.put("z", new IntTag(pos.getBlockZ()));
}
task.run(pos, block);
} }
pos.mutX(x - mx);
pos.mutY(y - my);
pos.mutZ(z - mz);
CompoundTag tag = block.getNbtData();
if (tag != null) {
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
values.put("x", new IntTag(pos.getBlockX()));
values.put("y", new IntTag(pos.getBlockY()));
values.put("z", new IntTag(pos.getBlockZ()));
}
task.run(pos, block);
return true;
} }
} }, editSession);
Operations.completeBlindly(visitor);
} }
} else { } else {
for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { for (int y = min.getBlockY(); y <= max.getBlockY(); y++) {

View File

@ -0,0 +1,29 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.boydti.fawe.object.function.block;
import com.google.common.base.Preconditions;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.patterns.Pattern;
public class LegacyBlockReplace implements RegionFunction {
private final Extent extent;
private Pattern pattern;
public LegacyBlockReplace(Extent extent, Pattern pattern) {
Preconditions.checkNotNull(extent);
Preconditions.checkNotNull(pattern);
this.extent = extent;
this.pattern = pattern;
}
public boolean apply(Vector position) throws WorldEditException {
return this.extent.setBlock(position, this.pattern.next(position));
}
}

View File

@ -0,0 +1,114 @@
package com.boydti.fawe.object.visitor;
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.util.ExtentTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.extent.Extent;
import java.util.Iterator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class Fast2DIterator implements Iterable<Vector2D> {
private final Iterable<? extends Vector2D> iterable;
private final MappedFaweQueue queue;
public Fast2DIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable EditSession extent) {
this(iter, (HasFaweQueue) extent);
}
public Fast2DIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable Extent extent) {
this(iter, (HasFaweQueue) (extent != null ? (extent instanceof HasFaweQueue ? extent : new ExtentTraverser(extent).findAndGet(HasFaweQueue.class)) : null));
}
public Fast2DIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable HasFaweQueue editSession) {
this(iter, (FaweQueue) editSession != null ? editSession.getQueue() : null);
}
public Fast2DIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable FaweQueue faweQueue) {
this.iterable = iter;
this.queue = faweQueue != null && faweQueue instanceof MappedFaweQueue ? (MappedFaweQueue) faweQueue : null;
}
public Iterable<? extends Vector2D> getIterable() {
return iterable;
}
@Override
public Iterator<Vector2D> iterator() {
if (queue == null || Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) {
return (Iterator<Vector2D>) iterable;
}
return new Iterator<Vector2D>() {
Iterator<? extends Vector2D> trailIter = iterable.iterator();
Iterator<? extends Vector2D> leadIter = iterable.iterator();
int lastTrailChunkX = Integer.MIN_VALUE;
int lastTrailChunkZ = Integer.MIN_VALUE;
int lastLeadChunkX = Integer.MIN_VALUE;
int lastLeadChunkZ = Integer.MIN_VALUE;
int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS;
int cx,cz;
@Override
public void remove() {
trailIter.remove();
}
@Override
public boolean hasNext() {
return trailIter.hasNext();
}
@Override
public Vector2D next() {
Vector2D pt = trailIter.next();
if (lastTrailChunkX != (lastTrailChunkX = pt.getBlockX() >> 4) || lastTrailChunkZ != (lastTrailChunkZ = pt.getBlockZ() >> 4)) {
if (leadIter.hasNext()) {
try {
int amount;
if (lastLeadChunkX == Integer.MIN_VALUE) {
lastLeadChunkX = cx;
lastLeadChunkZ = cz;
amount = loadingTarget;
} else {
amount = 1;
}
for (int count = 0; count < amount; ) {
Vector2D v = leadIter.next();
int vcx = v.getBlockX() >> 4;
int vcz = v.getBlockZ() >> 4;
if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) {
lastLeadChunkX = vcx;
lastLeadChunkZ = vcz;
queue.queueChunkLoad(vcx, vcz);
count++;
}
// Skip the next 15 blocks
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
}
} catch (Throwable ignore) {}
}
}
return pt;
}
};
}
}

View File

@ -0,0 +1,77 @@
package com.boydti.fawe.object.visitor;
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.util.ExtentTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.extent.Extent;
import java.util.Iterator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class FastChunkIterator implements Iterable<Vector2D> {
private final Iterable<? extends Vector2D> iterable;
private final MappedFaweQueue queue;
public FastChunkIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable EditSession extent) {
this(iter, (HasFaweQueue) extent);
}
public FastChunkIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable Extent extent) {
this(iter, (HasFaweQueue) (extent != null ? (extent instanceof HasFaweQueue ? extent : new ExtentTraverser(extent).findAndGet(HasFaweQueue.class)) : null));
}
public FastChunkIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable HasFaweQueue editSession) {
this(iter, (FaweQueue) editSession != null ? editSession.getQueue() : null);
}
public FastChunkIterator(@Nonnull Iterable<? extends Vector2D> iter, @Nullable FaweQueue faweQueue) {
this.iterable = iter;
this.queue = faweQueue != null && faweQueue instanceof MappedFaweQueue ? (MappedFaweQueue) faweQueue : null;
}
public Iterable<? extends Vector2D> getIterable() {
return iterable;
}
@Override
public Iterator<Vector2D> iterator() {
if (queue == null || Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) {
return (Iterator<Vector2D>) iterable;
}
final Iterator<? extends Vector2D> trailIter = iterable.iterator();
final Iterator<? extends Vector2D> leadIter = iterable.iterator();
int amount = Settings.IMP.QUEUE.PRELOAD_CHUNKS;
for (int i = 0; i < Settings.IMP.QUEUE.PRELOAD_CHUNKS && leadIter.hasNext(); i++) {
Vector2D toLoad = leadIter.next();
queue.queueChunkLoad(toLoad.getBlockX(), toLoad.getBlockZ());
}
if (!leadIter.hasNext()) {
return (Iterator<Vector2D>) trailIter;
}
return new Iterator<Vector2D>() {
@Override
public void remove() {
trailIter.remove();
}
@Override
public boolean hasNext() {
return trailIter.hasNext();
}
@Override
public Vector2D next() {
if (leadIter.hasNext()) {
Vector2D toLoad = leadIter.next();
queue.queueChunkLoad(toLoad.getBlockX(), toLoad.getBlockZ());
}
return trailIter.next();
}
};
}
}

View File

@ -0,0 +1,114 @@
package com.boydti.fawe.object.visitor;
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.util.ExtentTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import java.util.Iterator;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class FastIterator implements Iterable<Vector> {
private final Iterable<? extends Vector> iterable;
private final MappedFaweQueue queue;
public FastIterator(@Nonnull Iterable<? extends Vector> iter, @Nullable EditSession extent) {
this(iter, (HasFaweQueue) extent);
}
public FastIterator(@Nonnull Iterable<? extends Vector> iter, @Nullable Extent extent) {
this(iter, (HasFaweQueue) (extent != null ? (extent instanceof HasFaweQueue ? extent : new ExtentTraverser(extent).findAndGet(HasFaweQueue.class)) : null));
}
public FastIterator(@Nonnull Iterable<? extends Vector> iter, @Nullable HasFaweQueue editSession) {
this(iter, (FaweQueue) editSession != null ? editSession.getQueue() : null);
}
public FastIterator(@Nonnull Iterable<? extends Vector> iter, @Nullable FaweQueue faweQueue) {
this.iterable = iter;
this.queue = faweQueue != null && faweQueue instanceof MappedFaweQueue ? (MappedFaweQueue) faweQueue : null;
}
public Iterable<? extends Vector> getIterable() {
return iterable;
}
@Override
public Iterator<Vector> iterator() {
if (queue == null || Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) {
return (Iterator<Vector>) iterable;
}
return new Iterator<Vector>() {
Iterator<? extends Vector> trailIter = iterable.iterator();
Iterator<? extends Vector> leadIter = iterable.iterator();
int lastTrailChunkX = Integer.MIN_VALUE;
int lastTrailChunkZ = Integer.MIN_VALUE;
int lastLeadChunkX = Integer.MIN_VALUE;
int lastLeadChunkZ = Integer.MIN_VALUE;
int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS;
int cx,cz;
@Override
public void remove() {
trailIter.remove();
}
@Override
public boolean hasNext() {
return trailIter.hasNext();
}
@Override
public Vector next() {
Vector pt = trailIter.next();
if (lastTrailChunkX != (lastTrailChunkX = pt.getBlockX() >> 4) || lastTrailChunkZ != (lastTrailChunkZ = pt.getBlockZ() >> 4)) {
if (leadIter.hasNext()) {
try {
int amount;
if (lastLeadChunkX == Integer.MIN_VALUE) {
lastLeadChunkX = cx;
lastLeadChunkZ = cz;
amount = loadingTarget;
} else {
amount = 1;
}
for (int count = 0; count < amount; ) {
Vector v = leadIter.next();
int vcx = v.getBlockX() >> 4;
int vcz = v.getBlockZ() >> 4;
if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) {
lastLeadChunkX = vcx;
lastLeadChunkZ = vcz;
queue.queueChunkLoad(vcx, vcz);
count++;
}
// Skip the next 15 blocks
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
leadIter.next();
}
} catch (Throwable ignore) {}
}
}
return pt;
}
};
}
}

View File

@ -50,6 +50,11 @@ public class ExtentTraverser<T extends Extent> {
} }
} }
public <U> U findAndGet(Class<U> clazz) {
ExtentTraverser<Extent> traverser = find(clazz);
return (traverser != null) ? (U) traverser.get() : null;
}
public <U extends Extent> ExtentTraverser<U> find(Class<U> clazz) { public <U extends Extent> ExtentTraverser<U> find(Class<U> clazz) {
try { try {
ExtentTraverser<T> value = this; ExtentTraverser<T> value = this;

View File

@ -72,7 +72,6 @@ public final class NBTOutputStream implements Closeable {
public void writeNamedTag(String name, Tag tag) throws IOException { public void writeNamedTag(String name, Tag tag) throws IOException {
checkNotNull(name); checkNotNull(name);
checkNotNull(tag); checkNotNull(tag);
int type = NBTUtils.getTypeCode(tag.getClass()); int type = NBTUtils.getTypeCode(tag.getClass());
writeNamedTagName(name, type); writeNamedTagName(name, type);
if (type == NBTConstants.TYPE_END) { if (type == NBTConstants.TYPE_END) {

View File

@ -52,8 +52,10 @@ import com.boydti.fawe.object.extent.ProcessedWEExtent;
import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.object.extent.SlowExtent; import com.boydti.fawe.object.extent.SlowExtent;
import com.boydti.fawe.object.extent.SourceMaskExtent; import com.boydti.fawe.object.extent.SourceMaskExtent;
import com.boydti.fawe.object.function.block.LegacyBlockReplace;
import com.boydti.fawe.object.mask.ResettableMask; import com.boydti.fawe.object.mask.ResettableMask;
import com.boydti.fawe.object.progress.DefaultProgressTracker; import com.boydti.fawe.object.progress.DefaultProgressTracker;
import com.boydti.fawe.object.visitor.FastChunkIterator;
import com.boydti.fawe.util.ExtentTraverser; import com.boydti.fawe.util.ExtentTraverser;
import com.boydti.fawe.util.MaskTraverser; import com.boydti.fawe.util.MaskTraverser;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
@ -76,6 +78,7 @@ import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent; import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter; import com.sk89q.worldedit.function.RegionMaskingFilter;
import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.block.Naturalizer; import com.sk89q.worldedit.function.block.Naturalizer;
@ -106,6 +109,7 @@ import com.sk89q.worldedit.history.change.BlockChange;
import com.sk89q.worldedit.history.changeset.ChangeSet; import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.internal.expression.runtime.RValue; import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
import com.sk89q.worldedit.math.interpolation.Node; import com.sk89q.worldedit.math.interpolation.Node;
@ -216,20 +220,6 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
player = FawePlayer.wrap(event.getActor()); player = FawePlayer.wrap(event.getActor());
} }
this.player = player; this.player = player;
if (changeSet == null) {
if (Settings.IMP.HISTORY.USE_DISK) {
UUID uuid = player == null ? CONSOLE : player.getUUID();
if (Settings.IMP.HISTORY.USE_DATABASE) {
changeSet = new RollbackOptimizedHistory(world, uuid);
} else {
changeSet = new DiskStorageHistory(world, uuid);
}
} else if (Settings.IMP.HISTORY.COMBINE_STAGES && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) {
changeSet = new CPUOptimizedChangeSet(world);
} else {
changeSet = new MemoryOptimizedHistory(world);
}
}
if (limit == null) { if (limit == null) {
if (player == null) { if (player == null) {
limit = FaweLimit.MAX; limit = FaweLimit.MAX;
@ -286,7 +276,21 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), bus, event, Stage.BEFORE_CHANGE); this.bypassAll = wrapExtent(new FastWorldEditExtent(world, queue), bus, event, Stage.BEFORE_CHANGE);
this.bypassHistory = (this.extent = wrapExtent(bypassAll, bus, event, Stage.BEFORE_REORDER)); this.bypassHistory = (this.extent = wrapExtent(bypassAll, bus, event, Stage.BEFORE_REORDER));
if (!fastmode) { if (!fastmode || changeSet != null) {
if (changeSet == null) {
if (Settings.IMP.HISTORY.USE_DISK) {
UUID uuid = player == null ? CONSOLE : player.getUUID();
if (Settings.IMP.HISTORY.USE_DATABASE) {
changeSet = new RollbackOptimizedHistory(world, uuid);
} else {
changeSet = new DiskStorageHistory(world, uuid);
}
} else if (Settings.IMP.HISTORY.COMBINE_STAGES && Settings.IMP.HISTORY.COMPRESSION_LEVEL == 0 && !(queue instanceof MCAQueue)) {
changeSet = new CPUOptimizedChangeSet(world);
} else {
changeSet = new MemoryOptimizedHistory(world);
}
}
if (limit.SPEED_REDUCTION > 0) { if (limit.SPEED_REDUCTION > 0) {
this.bypassHistory = new SlowExtent(this.bypassHistory, limit.SPEED_REDUCTION); this.bypassHistory = new SlowExtent(this.bypassHistory, limit.SPEED_REDUCTION);
} }
@ -610,6 +614,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
public void addTransform(ResettableExtent transform) { public void addTransform(ResettableExtent transform) {
wrapped = true;
if (transform == null) { if (transform == null) {
ExtentTraverser<AbstractDelegateExtent> traverser = new ExtentTraverser(this.extent).find(ResettableExtent.class); ExtentTraverser<AbstractDelegateExtent> traverser = new ExtentTraverser(this.extent).find(ResettableExtent.class);
AbstractDelegateExtent next = extent; AbstractDelegateExtent next = extent;
@ -1152,9 +1157,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
*/ */
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
private int setBlocks(final Set<Vector> vset, final Pattern pattern) throws MaxChangedBlocksException { private int setBlocks(final Set<Vector> vset, final Pattern pattern) throws MaxChangedBlocksException {
for (final Vector v : vset) { RegionVisitor visitor = new RegionVisitor(vset, new LegacyBlockReplace(extent, pattern), this);
changes += this.setBlock(v, pattern) ? 1 : 0; Operations.completeBlindly(visitor);
} changes += visitor.getAffected();
return changes; return changes;
} }
@ -1219,12 +1224,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
context.setExtent(editSession.bypassAll); context.setExtent(editSession.bypassAll);
ChangeSet changeSet = getChangeSet(); ChangeSet changeSet = getChangeSet();
editSession.getQueue().setChangeTask(null); editSession.getQueue().setChangeTask(null);
Operations.completeSmart(ChangeSetExecutor.create(changeSet, context, ChangeSetExecutor.Type.UNDO, editSession.getBlockBag(), editSession.getLimit().INVENTORY_MODE), new Runnable() { Operations.completeBlindly(ChangeSetExecutor.create(changeSet, context, ChangeSetExecutor.Type.UNDO, editSession.getBlockBag(), editSession.getLimit().INVENTORY_MODE));
@Override
public void run() {
editSession.flushQueue();
}
}, true);
editSession.changes = 1; editSession.changes = 1;
} }
@ -1238,12 +1238,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
context.setExtent(editSession.bypassAll); context.setExtent(editSession.bypassAll);
ChangeSet changeSet = getChangeSet(); ChangeSet changeSet = getChangeSet();
editSession.getQueue().setChangeTask(null); editSession.getQueue().setChangeTask(null);
Operations.completeSmart(ChangeSetExecutor.create(changeSet, context, ChangeSetExecutor.Type.REDO, editSession.getBlockBag(), editSession.getLimit().INVENTORY_MODE), new Runnable() { Operations.completeBlindly(ChangeSetExecutor.create(changeSet, context, ChangeSetExecutor.Type.REDO, editSession.getBlockBag(), editSession.getLimit().INVENTORY_MODE));
@Override
public void run() {
editSession.flushQueue();
}
}, true);
editSession.changes = 1; editSession.changes = 1;
} }
@ -1340,12 +1335,15 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return 0; return 0;
} }
if (searchIDs.size() == 1) { if (searchIDs.size() == 1) {
int count = 0; final int id = searchIDs.iterator().next();
int id = searchIDs.iterator().next(); RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
for (final Vector pt : region) { @Override
if (this.getBlockType(pt) == id) count++; public boolean apply(Vector position) throws WorldEditException {
} return getBlockType(position) == id;
return count; }
}, this);
Operations.completeBlindly(visitor);
return visitor.getAffected();
} }
final boolean[] ids = new boolean[256]; final boolean[] ids = new boolean[256];
for (final int id : searchIDs) { for (final int id : searchIDs) {
@ -1357,14 +1355,14 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
public int countBlock(final Region region, final boolean[] ids) { public int countBlock(final Region region, final boolean[] ids) {
int count = 0; RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
for (final Vector pt : region) { @Override
final int id = this.getBlockType(pt); public boolean apply(Vector position) throws WorldEditException {
if (ids[id]) { return ids[getBlockType(position)];
count++;
} }
} }, this);
return count; Operations.completeBlindly(visitor);
return visitor.getAffected();
} }
/** /**
@ -1375,42 +1373,48 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
* @return the number of blocks that matched the pattern * @return the number of blocks that matched the pattern
*/ */
public int countBlocks(final Region region, final Set<BaseBlock> searchBlocks) { public int countBlocks(final Region region, final Set<BaseBlock> searchBlocks) {
BlockMask mask = new BlockMask(extent, searchBlocks); final BlockMask mask = new BlockMask(extent, searchBlocks);
int count = 0; RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
for (final Vector pt : region) { @Override
if (mask.test(pt)) { public boolean apply(Vector position) throws WorldEditException {
count++; return mask.test(position);
} }
} }, this);
return count; Operations.completeBlindly(visitor);
return visitor.getAffected();
} }
public int fall(final Region region, boolean fullHeight, BaseBlock replace) { public int fall(final Region region, boolean fullHeight, final BaseBlock replace) {
FlatRegion flat = asFlatRegion(region); FlatRegion flat = asFlatRegion(region);
int startPerformY = region.getMinimumPoint().getBlockY(); final int startPerformY = region.getMinimumPoint().getBlockY();
int startCheckY = fullHeight ? 0 : startPerformY; final int startCheckY = fullHeight ? 0 : startPerformY;
int endY = region.getMaximumPoint().getBlockY(); final int endY = region.getMaximumPoint().getBlockY();
for (BlockVector pos : flat) { RegionVisitor visitor = new RegionVisitor(flat, new RegionFunction() {
int x = pos.getBlockX(); @Override
int z = pos.getBlockZ(); public boolean apply(Vector pos) throws WorldEditException {
int freeSpot = startCheckY; int x = pos.getBlockX();
for (int y = startCheckY; y <= endY; y++) { int z = pos.getBlockZ();
if (y < startPerformY) { int freeSpot = startCheckY;
if (getLazyBlock(x, y, z) != EditSession.nullBlock) { for (int y = startCheckY; y <= endY; y++) {
freeSpot = y + 1; if (y < startPerformY) {
if (getLazyBlock(x, y, z) != EditSession.nullBlock) {
freeSpot = y + 1;
}
continue;
} }
continue; BaseBlock block = getLazyBlock(x, y, z);
} if (block != EditSession.nullBlock) {
BaseBlock block = getLazyBlock(x, y, z); if (freeSpot != y) {
if (block != EditSession.nullBlock) { setBlock(x, freeSpot, z, block);
if (freeSpot != y) { setBlock(x, y, z, replace);
setBlock(x, freeSpot, z, block); }
setBlock(x, y, z, replace); freeSpot++;
} }
freeSpot++;
} }
return true;
} }
} }, this);
Operations.completeBlindly(visitor);
return this.changes; return this.changes;
} }
@ -1466,12 +1470,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
visitor.visit(origin); visitor.visit(origin);
// Execute // Execute
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = visitor.getAffected(); return this.changes = visitor.getAffected();
} }
@ -1565,6 +1564,10 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
return true; return true;
} }
public boolean hasExtraExtents() {
return wrapped || getMask() != null || getSourceMask() != null || history != null;
}
/** /**
* Sets all the blocks inside a region to a given block type. * Sets all the blocks inside a region to a given block type.
* *
@ -1580,11 +1583,17 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
if (canBypassAll(region, false, true) && !block.hasNbtData()) { if (canBypassAll(region, false, true) && !block.hasNbtData()) {
return changes = queue.setBlocks((CuboidRegion) region, block.getId(), block.getData()); return changes = queue.setBlocks((CuboidRegion) region, block.getId(), block.getData());
} }
Iterator<BlockVector> iter = region.iterator();
try { try {
while (iter.hasNext()) { if (hasExtraExtents()) {
if (this.extent.setBlock(iter.next(), block)) { RegionVisitor visitor = new RegionVisitor(region, new LegacyBlockReplace(extent, new SingleBlockPattern(block)), this);
changes++; Operations.completeBlindly(visitor);
this.changes += visitor.getAffected();
} else {
Iterator<BlockVector> iter = region.iterator();
while (iter.hasNext()) {
if (this.extent.setBlock(iter.next(), block)) {
changes++;
}
} }
} }
} catch (final MaxChangedBlocksException e) { } catch (final MaxChangedBlocksException e) {
@ -1612,12 +1621,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); final RegionVisitor visitor = new RegionVisitor(region, replace, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null);
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = visitor.getAffected(); return this.changes = visitor.getAffected();
} }
@ -1682,12 +1686,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern)); final BlockReplace replace = new BlockReplace(EditSession.this, Patterns.wrap(pattern));
final RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace); final RegionMaskingFilter filter = new RegionMaskingFilter(mask, replace);
final RegionVisitor visitor = new RegionVisitor(region, filter, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null); final RegionVisitor visitor = new RegionVisitor(region, filter, queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null);
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = visitor.getAffected(); return this.changes = visitor.getAffected();
} }
@ -1866,12 +1865,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final RegionOffset offset = new RegionOffset(new Vector(0, 1, 0), replace); final RegionOffset offset = new RegionOffset(new Vector(0, 1, 0), replace);
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), offset); final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), offset);
final LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground); final LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = ground.getAffected(); return this.changes = ground.getAffected();
} }
@ -1888,12 +1882,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final Naturalizer naturalizer = new Naturalizer(EditSession.this); final Naturalizer naturalizer = new Naturalizer(EditSession.this);
final FlatRegion flatRegion = Regions.asFlatRegion(region); final FlatRegion flatRegion = Regions.asFlatRegion(region);
final LayerVisitor visitor = new LayerVisitor(flatRegion, minimumBlockY(region), maximumBlockY(region), naturalizer); final LayerVisitor visitor = new LayerVisitor(flatRegion, minimumBlockY(region), maximumBlockY(region), naturalizer);
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = naturalizer.getAffected(); return this.changes = naturalizer.getAffected();
} }
@ -1925,12 +1914,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
if (!copyAir) { if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this)); copy.setSourceMask(new ExistingBlockMask(EditSession.this));
} }
Operations.completeSmart(copy, new Runnable() { Operations.completeBlindly(copy);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = copy.getAffected(); return this.changes = copy.getAffected();
} }
@ -1982,12 +1966,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
if (!copyAir) { if (!copyAir) {
copy.setSourceMask(new ExistingBlockMask(EditSession.this)); copy.setSourceMask(new ExistingBlockMask(EditSession.this));
} }
Operations.completeSmart(copy, new Runnable() { Operations.completeBlindly(copy);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = copy.getAffected(); return this.changes = copy.getAffected();
} }
@ -2044,12 +2023,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
} }
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = visitor.getAffected(); return this.changes = visitor.getAffected();
} }
@ -2108,12 +2082,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
} }
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return visitor.getAffected(); return visitor.getAffected();
} }
@ -2524,12 +2493,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), generator); final GroundFunction ground = new GroundFunction(new ExistingBlockMask(EditSession.this), generator);
final LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground); final LayerVisitor visitor = new LayerVisitor(region, minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density)); visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeSmart(visitor, new Runnable() { Operations.completeBlindly(visitor);
@Override
public void run() {
EditSession.this.flushQueue();
}
}, true);
return this.changes = ground.getAffected(); return this.changes = ground.getAffected();
} }
@ -2734,18 +2698,32 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
final RValue z = expression.getVariable("z", false); final RValue z = expression.getVariable("z", false);
final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero); final WorldEditExpressionEnvironment environment = new WorldEditExpressionEnvironment(this, unit, zero);
expression.setEnvironment(environment); expression.setEnvironment(environment);
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
for (BlockVector position : region) {
// offset, scale private MutableBlockVector mutable = new MutableBlockVector();
final Vector scaled = position.subtract(zero).divide(unit);
// transform @Override
expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ()); public boolean apply(Vector position) throws WorldEditException {
final BlockVector sourcePosition = environment.toWorld(x.getValue(), y.getValue(), z.getValue()); try {
// read block from world int mx = (position.getBlockX() - zero.getBlockX()) / unit.getBlockX();
BaseBlock material = FaweCache.CACHE_BLOCK[this.queue.getCombinedId4DataDebug(sourcePosition.getBlockX(), sourcePosition.getBlockY(), sourcePosition.getBlockZ(), 0, this)]; int my = (position.getBlockY() - zero.getBlockY()) / unit.getBlockY();
// queue operation int mz = (position.getBlockZ() - zero.getBlockZ()) / unit.getBlockZ();
this.setBlockFast(position, material); mutable.setComponents(mx, my, mz);
} // final Vector scaled = position.subtract(zero).divide(unit);
// transform
expression.evaluate(mutable.getX(), mutable.getY(), mutable.getZ());
final BlockVector sourcePosition = environment.toWorld(x.getValue(), y.getValue(), z.getValue());
// read block from world
BaseBlock material = FaweCache.CACHE_BLOCK[queue.getCombinedId4DataDebug(sourcePosition.getBlockX(), sourcePosition.getBlockY(), sourcePosition.getBlockZ(), 0, EditSession.this)];
// queue operation
return extent.setBlock(position, material);
} catch (EvaluationException e) {
throw new RuntimeException(e);
}
}
}, this);
Operations.completeBlindly(visitor);
changes += visitor.getAffected();
return changes; return changes;
} }
@ -3044,7 +3022,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
for (final Vector recurseDirection : this.recurseDirections) { for (final Vector recurseDirection : this.recurseDirections) {
queue.addLast(current.add(recurseDirection).toBlockVector()); queue.addLast(current.add(recurseDirection).toBlockVector());
} }
} // while }
} }
public int makeBiomeShape(final Region region, final Vector zero, final Vector unit, final BaseBiome biomeType, final String expressionString, final boolean hollow) throws ExpressionException, public int makeBiomeShape(final Region region, final Vector zero, final Vector unit, final BaseBiome biomeType, final String expressionString, final boolean hollow) throws ExpressionException,
@ -3160,7 +3138,7 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting
} }
} }
final Set<Vector2D> chunks = region.getChunks(); final Set<Vector2D> chunks = region.getChunks();
for (Vector2D chunk : chunks) { for (Vector2D chunk : new FastChunkIterator(chunks, this)) {
final int cx = chunk.getBlockX(); final int cx = chunk.getBlockX();
final int cz = chunk.getBlockZ(); final int cz = chunk.getBlockZ();
final int bx = cx << 4; final int bx = cx << 4;

View File

@ -439,7 +439,7 @@ public class LocalSession {
return null; return null;
} }
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) { public synchronized void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) {
// It should have already been flushed, but just in case! // It should have already been flushed, but just in case!
editSession.flushQueue(); editSession.flushQueue();
if (editSession == null || editSession.getChangeSet() == null || limitMb == 0 || ((historySize >> 20) > limitMb && !append)) { if (editSession == null || editSession.getChangeSet() == null || limitMb == 0 || ((historySize >> 20) > limitMb && !append)) {

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.command; package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.visitor.Fast2DIterator;
import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -33,23 +34,26 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.FlatRegionFunction; import com.sk89q.worldedit.function.FlatRegionFunction;
import com.sk89q.worldedit.function.FlatRegionMaskingFilter; import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.biome.BiomeReplace; import com.sk89q.worldedit.function.biome.BiomeReplace;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Mask2D; import com.sk89q.worldedit.function.mask.Mask2D;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor; import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.FlatRegion; import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.Regions; import com.sk89q.worldedit.regions.Regions;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.biome.BiomeData; import com.sk89q.worldedit.world.biome.BiomeData;
import com.sk89q.worldedit.world.registry.BiomeRegistry; import com.sk89q.worldedit.world.registry.BiomeRegistry;
import java.util.HashSet; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -124,11 +128,12 @@ public class BiomeCommands {
max = 0 max = 0
) )
@CommandPermissions("worldedit.biome.info") @CommandPermissions("worldedit.biome.info")
public void biomeInfo(Player player, LocalSession session, CommandContext args) throws WorldEditException { public void biomeInfo(Player player, LocalSession session, final EditSession editSession, CommandContext args) throws WorldEditException {
BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry(); BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
Set<BaseBiome> biomes = new HashSet<BaseBiome>(); final int[] biomes = new int[256];
String qualifier; final String qualifier;
int size = 0;
if (args.hasFlag('t')) { if (args.hasFlag('t')) {
Vector blockPosition = player.getBlockTrace(300); Vector blockPosition = player.getBlockTrace(300);
if (blockPosition == null) { if (blockPosition == null) {
@ -137,34 +142,53 @@ public class BiomeCommands {
} }
BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D()); BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
biomes.add(biome); biomes[biome.getId()]++;
size = 1;
} else if (args.hasFlag('p')) { } else if (args.hasFlag('p')) {
BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D()); BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D());
biomes.add(biome); biomes[biome.getId()]++;
size = 1;
} else { } else {
World world = player.getWorld(); World world = player.getWorld();
Region region = session.getSelection(world); Region region = session.getSelection(world);
if (region instanceof FlatRegion) { if (region instanceof FlatRegion) {
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) { for (Vector2D pt : new Fast2DIterator(((FlatRegion) region).asFlatRegion(), editSession)) {
biomes.add(world.getBiome(pt)); biomes[editSession.getBiome(pt).getId()]++;
size++;
} }
} else { } else {
for (Vector pt : region) { RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
biomes.add(world.getBiome(pt.toVector2D())); @Override
} public boolean apply(Vector position) throws WorldEditException {
biomes[editSession.getBiome(position.toVector2D()).getId()]++;
return true;
}
}, editSession);
Operations.completeBlindly(visitor);
size += visitor.getAffected();
} }
} }
BBC.BIOME_LIST_HEADER.send(player, 1, 1); BBC.BIOME_LIST_HEADER.send(player, 1, 1);
for (BaseBiome biome : biomes) {
BiomeData data = biomeRegistry.getData(biome); List<Countable<BaseBiome>> distribution = new ArrayList<>();
if (data != null) { for (int i = 0; i < biomes.length; i++) {
player.print(BBC.getPrefix() + " " + data.getName()); int count = biomes[i];
} else { if (count != 0) {
player.print(BBC.getPrefix() + " <? #" + biome.getId() + ">"); distribution.add(new Countable<BaseBiome>(new BaseBiome(i), count));
} }
} }
Collections.sort(distribution);
for (Countable<BaseBiome> c : distribution) {
BiomeData data = biomeRegistry.getData(c.getID());
String str = String.format("%-7s (%.3f%%) %s #%d",
String.valueOf(c.getAmount()),
c.getAmount() / (double) size * 100,
data == null ? "Unknown" : data.getName(),
c.getID().getId());
player.print(BBC.getPrefix() + str);
}
} }
@Command( @Command(

View File

@ -35,7 +35,6 @@ import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging; import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -48,6 +47,7 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.Masks;
@ -55,6 +55,7 @@ import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection; import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
@ -69,7 +70,6 @@ import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional; import com.sk89q.worldedit.util.command.parametric.Optional;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.Iterator;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -379,10 +379,10 @@ public class ClipboardCommands {
@CommandPermissions("worldedit.clipboard.place") @CommandPermissions("worldedit.clipboard.place")
@Logging(PLACEMENT) @Logging(PLACEMENT)
public void place(Player player, LocalSession session, final EditSession editSession, public void place(Player player, LocalSession session, final EditSession editSession,
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin, @Switch('a') final boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
@Switch('s') boolean selectPasted) throws WorldEditException { @Switch('s') boolean selectPasted) throws WorldEditException {
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard(); final Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion().clone(); Region region = clipboard.getRegion().clone();
final int maxY = editSession.getMaxY(); final int maxY = editSession.getMaxY();
@ -412,20 +412,23 @@ public class ClipboardCommands {
final int relx = to.getBlockX() - origin.getBlockX(); final int relx = to.getBlockX() - origin.getBlockX();
final int rely = to.getBlockY() - origin.getBlockY(); final int rely = to.getBlockY() - origin.getBlockY();
final int relz = to.getBlockZ() - origin.getBlockZ(); final int relz = to.getBlockZ() - origin.getBlockZ();
Iterator<BlockVector> iter = region.iterator(); RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
while (iter.hasNext()) { @Override
BlockVector mutable = iter.next(); public boolean apply(Vector mutable) throws WorldEditException {
BaseBlock block = clipboard.getBlock(mutable); BaseBlock block = clipboard.getBlock(mutable);
if (block == EditSession.nullBlock && ignoreAirBlocks) { if (block == EditSession.nullBlock && ignoreAirBlocks) {
continue; return false;
}
mutable.mutX(mutable.getX() + relx);
mutable.mutY(mutable.getY() + rely);
mutable.mutZ(mutable.getZ() + relz);
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
return editSession.setBlockFast(mutable, block);
}
return false;
} }
mutable.mutX(mutable.getX() + relx); }, editSession);
mutable.mutY(mutable.getY() + rely); Operations.completeBlindly(visitor);
mutable.mutZ(mutable.getZ() + relz);
if (mutable.getY() >= 0 && mutable.getY() <= maxY) {
editSession.setBlockFast(mutable, block);
}
}
} }
// Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin) // Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin)
final int entityOffsetX = to.getBlockX() - origin.getBlockX(); final int entityOffsetX = to.getBlockX() - origin.getBlockX();

View File

@ -204,8 +204,10 @@ public class SchematicCommands {
} }
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
e.printStackTrace();
player.printError("Unknown filename: " + filename); player.printError("Unknown filename: " + filename);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace();
player.printError("Schematic could not written: " + e.getMessage()); player.printError("Schematic could not written: " + e.getMessage());
log.log(Level.WARNING, "Failed to write a saved clipboard", e); log.log(Level.WARNING, "Failed to write a saved clipboard", e);
} }

View File

@ -32,7 +32,6 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -139,6 +138,10 @@ public class SchematicWriter implements ClipboardWriter {
} }
final DataOutputStream rawStream = outputStream.getOutputStream(); final DataOutputStream rawStream = outputStream.getOutputStream();
outputStream.writeLazyCompoundTag("Schematic", new NBTOutputStream.LazyWrite() { outputStream.writeLazyCompoundTag("Schematic", new NBTOutputStream.LazyWrite() {
private boolean hasAdd = false;
private boolean hasTile = false;
private boolean hasData = false;
@Override @Override
public void write(NBTOutputStream out) throws IOException { public void write(NBTOutputStream out) throws IOException {
int volume = width * height * length; int volume = width * height * length;
@ -154,28 +157,20 @@ public class SchematicWriter implements ClipboardWriter {
out.writeNamedTag("WEOffsetY", new IntTag(offset.getBlockY())); out.writeNamedTag("WEOffsetY", new IntTag(offset.getBlockY()));
out.writeNamedTag("WEOffsetZ", new IntTag(offset.getBlockZ())); out.writeNamedTag("WEOffsetZ", new IntTag(offset.getBlockZ()));
out.writeNamedTagName("Data", NBTConstants.TYPE_BYTE_ARRAY);
out.getOutputStream().writeInt(volume);
clipboard.IMP.streamDatas(new NBTStreamer.ByteReader() {
@Override
public void run(int index, int byteValue) {
try {
rawStream.writeByte(byteValue);
} catch (IOException e) {
e.printStackTrace();
}
}
});
out.writeNamedTagName("Blocks", NBTConstants.TYPE_BYTE_ARRAY); out.writeNamedTagName("Blocks", NBTConstants.TYPE_BYTE_ARRAY);
out.getOutputStream().writeInt(volume); out.getOutputStream().writeInt(volume);
final AtomicBoolean hasAdd = new AtomicBoolean(false);
clipboard.IMP.streamIds(new NBTStreamer.ByteReader() { clipboard.IMP.streamIds(new NBTStreamer.ByteReader() {
@Override @Override
public void run(int index, int byteValue) { public void run(int index, int byteValue) {
try { try {
if (byteValue >= 256) { if (byteValue >= 256) {
hasAdd.set(true); hasAdd = true;
}
if (FaweCache.hasData(byteValue)) {
hasData = true;
}
if (FaweCache.hasNBT(byteValue)) {
hasTile = true;
} }
rawStream.writeByte(byteValue); rawStream.writeByte(byteValue);
} catch (IOException e) { } catch (IOException e) {
@ -184,7 +179,26 @@ public class SchematicWriter implements ClipboardWriter {
} }
}); });
if (hasAdd.get()) { out.writeNamedTagName("Data", NBTConstants.TYPE_BYTE_ARRAY);
out.getOutputStream().writeInt(volume);
if (hasData) {
clipboard.IMP.streamDatas(new NBTStreamer.ByteReader() {
@Override
public void run(int index, int byteValue) {
try {
rawStream.writeByte(byteValue);
} catch (IOException e) {
e.printStackTrace();
}
}
});
} else {
for (int i = 0; i < volume; i++) {
rawStream.write(0);
}
}
if (hasAdd) {
out.writeNamedTagName("AddBlocks", NBTConstants.TYPE_BYTE_ARRAY); out.writeNamedTagName("AddBlocks", NBTConstants.TYPE_BYTE_ARRAY);
out.getOutputStream().writeInt(volume); out.getOutputStream().writeInt(volume);
clipboard.IMP.streamIds(new NBTStreamer.ByteReader() { clipboard.IMP.streamIds(new NBTStreamer.ByteReader() {
@ -199,8 +213,10 @@ public class SchematicWriter implements ClipboardWriter {
}); });
} }
final List<CompoundTag> tileEntities = clipboard.IMP.getTileEntities(); if (hasTile) {
out.writeNamedTag("TileEntities", new ListTag(CompoundTag.class, tileEntities)); final List<CompoundTag> tileEntities = clipboard.IMP.getTileEntities();
out.writeNamedTag("TileEntities", new ListTag(CompoundTag.class, tileEntities));
}
List<Tag> entities = new ArrayList<Tag>(); List<Tag> entities = new ArrayList<Tag>();
for (Entity entity : clipboard.getEntities()) { for (Entity entity : clipboard.getEntities()) {

View File

@ -23,6 +23,7 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings; import com.boydti.fawe.config.Settings;
import com.boydti.fawe.example.MappedFaweQueue; import com.boydti.fawe.example.MappedFaweQueue;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HasFaweQueue;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
@ -41,6 +42,7 @@ import java.util.List;
public class RegionVisitor implements Operation { public class RegionVisitor implements Operation {
public final Region region; public final Region region;
public final Iterable<? extends Vector> iterable;
public final RegionFunction function; public final RegionFunction function;
private final MappedFaweQueue queue; private final MappedFaweQueue queue;
public int affected = 0; public int affected = 0;
@ -60,9 +62,14 @@ public class RegionVisitor implements Operation {
} }
public RegionVisitor(Region region, RegionFunction function, FaweQueue queue) { public RegionVisitor(Region region, RegionFunction function, FaweQueue queue) {
this.region = region; this((Iterable<BlockVector>) region, function, queue);
}
public RegionVisitor(Iterable<? extends Vector> iterable, RegionFunction function, HasFaweQueue hasQueue) {
region = (iterable instanceof Region) ? (Region) iterable : null;
this.iterable = iterable;
this.function = function; this.function = function;
this.queue = queue instanceof MappedFaweQueue ? (MappedFaweQueue) queue : null; this.queue = hasQueue != null && hasQueue.getQueue() instanceof MappedFaweQueue ? (MappedFaweQueue) hasQueue.getQueue() : null;
} }
/** /**
@ -76,7 +83,7 @@ public class RegionVisitor implements Operation {
@Override @Override
public Operation resume(final RunContext run) throws WorldEditException { public Operation resume(final RunContext run) throws WorldEditException {
if (queue != null && Settings.IMP.QUEUE.PRELOAD_CHUNKS <= 1) { if (queue != null && Settings.IMP.QUEUE.PRELOAD_CHUNKS > 1) {
/* /*
* The following is done to reduce iteration cost * The following is done to reduce iteration cost
* - Preload chunks just in time * - Preload chunks just in time
@ -84,8 +91,8 @@ public class RegionVisitor implements Operation {
* - Stop iteration on exception instead of hasNext * - Stop iteration on exception instead of hasNext
* - Do not calculate the stacktrace as it is expensive * - Do not calculate the stacktrace as it is expensive
*/ */
Iterator<BlockVector> trailIter = region.iterator(); Iterator<? extends Vector> trailIter = iterable.iterator();
Iterator<BlockVector> leadIter = region.iterator(); Iterator<? extends Vector> leadIter = iterable.iterator();
int lastTrailChunkX = Integer.MIN_VALUE; int lastTrailChunkX = Integer.MIN_VALUE;
int lastTrailChunkZ = Integer.MIN_VALUE; int lastTrailChunkZ = Integer.MIN_VALUE;
int lastLeadChunkX = Integer.MIN_VALUE; int lastLeadChunkX = Integer.MIN_VALUE;
@ -93,8 +100,8 @@ public class RegionVisitor implements Operation {
int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS; int loadingTarget = Settings.IMP.QUEUE.PRELOAD_CHUNKS;
try { try {
for (;;) { for (;;) {
BlockVector pt = trailIter.next(); Vector pt = trailIter.next();
function.apply(pt); apply(pt);
int cx = pt.getBlockX() >> 4; int cx = pt.getBlockX() >> 4;
int cz = pt.getBlockZ() >> 4; int cz = pt.getBlockZ() >> 4;
if (cx != lastTrailChunkX || cz != lastTrailChunkZ) { if (cx != lastTrailChunkX || cz != lastTrailChunkZ) {
@ -109,7 +116,7 @@ public class RegionVisitor implements Operation {
amount = 1; amount = 1;
} }
for (int count = 0; count < amount;) { for (int count = 0; count < amount;) {
BlockVector v = leadIter.next(); Vector v = leadIter.next();
int vcx = v.getBlockX() >> 4; int vcx = v.getBlockX() >> 4;
int vcz = v.getBlockZ() >> 4; int vcz = v.getBlockZ() >> 4;
if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) { if (vcx != lastLeadChunkX || vcz != lastLeadChunkZ) {
@ -136,40 +143,43 @@ public class RegionVisitor implements Operation {
leadIter.next(); leadIter.next();
} }
} }
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
} }
} catch (Throwable ignore) {} } catch (Throwable ignore) {}
try { try {
for (;;) { for (;;) {
function.apply(trailIter.next()); apply(trailIter.next());
function.apply(trailIter.next()); apply(trailIter.next());
} }
} catch (Throwable ignore) {} } catch (Throwable ignore) {}
affected = region.getArea();
} else { } else {
for (Vector pt : region) { for (Vector pt : iterable) {
if (function.apply(pt)) { apply(pt);
affected++;
}
} }
} }
return null; return null;
} }
private void apply(Vector pt) throws WorldEditException {
if (function.apply(pt)) {
affected++;
}
}
@Override @Override
public void cancel() {} public void cancel() {}

View File

@ -0,0 +1,55 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.patterns;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
/**
* @deprecated See {@link com.sk89q.worldedit.function.pattern.Pattern}
*/
@Deprecated
public interface Pattern { //extends com.sk89q.worldedit.function.pattern.Pattern {
/**
* Get a block for a position. This return value of this method does
* not have to be consistent for the same position.
*
* @param position the position where a block is needed
* @return a block
*/
public BaseBlock next(Vector position);
/**
* Get a block for a position. This return value of this method does
* not have to be consistent for the same position.
*
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return a block
*/
public BaseBlock next(int x, int y, int z);
// @Override
// default BaseBlock apply(Vector position) {
// return next(position);
// }
}

View File

@ -129,7 +129,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
public Chunk loadChunk(World world, int x, int z, boolean generate) { public Chunk loadChunk(World world, int x, int z, boolean generate) {
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider(); ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
if (generate) { if (generate) {
return provider.provideChunk(x, z); return provider.originalLoadChunk(x, z);
} else { } else {
return provider.loadChunk(x, z); return provider.loadChunk(x, z);
} }

View File

@ -98,7 +98,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
public Chunk loadChunk(World world, int x, int z, boolean generate) { public Chunk loadChunk(World world, int x, int z, boolean generate) {
ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider(); ChunkProviderServer provider = (ChunkProviderServer) world.getChunkProvider();
if (generate) { if (generate) {
return provider.provideChunk(x, z); return provider.originalLoadChunk(x, z);
} else { } else {
return provider.loadChunk(x, z); return provider.loadChunk(x, z);
} }