Reduce object creation (vector) on each block change
Fix getBlock in non allowed region
Fix command block nbt
Start work on anvil commands
This commit is contained in:
Jesse Boyd 2016-08-24 14:56:18 +10:00
parent 2d8020e415
commit dd181d9378
9 changed files with 384 additions and 143 deletions

View File

@ -615,6 +615,8 @@ public class FaweCache {
case 33: case 33:
case 151: case 151:
case 178: case 178:
case 210:
case 211:
return true; return true;
default: default:
return false; return false;

View File

@ -0,0 +1,55 @@
package com.boydti.fawe.command;
import com.boydti.fawe.config.BBC;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.Patterns;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.parametric.Optional;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
public class AnvilCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public AnvilCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/replaceall", "/rea", "/repall" },
usage = "[from-block] <to-block>",
desc = "Replace all blocks in the selection with another",
flags = "f",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.replace")
@Logging(REGION)
public void replace(Player player, EditSession editSession, @Selection Region region, @Optional Mask from, Pattern to) throws WorldEditException {
if (from == null) {
from = new ExistingBlockMask(editSession);
}
int affected = editSession.replaceBlocks(region, from, Patterns.wrap(to));
BBC.VISITOR_BLOCK.send(player, affected);
}
}

View File

@ -0,0 +1,4 @@
package com.boydti.fawe.jnbt.anvil;
public class AnvilRegion {
}

View File

@ -26,6 +26,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/ */
public class HistoryExtent extends AbstractDelegateExtent { public class HistoryExtent extends AbstractDelegateExtent {
private final AbstractDelegateExtent extent;
private FaweChangeSet changeSet; private FaweChangeSet changeSet;
private final FaweQueue queue; private final FaweQueue queue;
private final EditSession session; private final EditSession session;
@ -39,6 +40,7 @@ public class HistoryExtent extends AbstractDelegateExtent {
public HistoryExtent(final EditSession session, final Extent extent, final FaweChangeSet changeSet, FaweQueue queue) { public HistoryExtent(final EditSession session, final Extent extent, final FaweChangeSet changeSet, FaweQueue queue) {
super(extent); super(extent);
checkNotNull(changeSet); checkNotNull(changeSet);
this.extent = (AbstractDelegateExtent) extent;
this.queue = queue; this.queue = queue;
this.changeSet = changeSet; this.changeSet = changeSet;
this.session = session; this.session = session;
@ -53,13 +55,10 @@ public class HistoryExtent extends AbstractDelegateExtent {
} }
@Override @Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
int y = location.getBlockY();
if (y > 255 || y < 0) { if (y > 255 || y < 0) {
return false; return false;
} }
int x = location.getBlockX();
int z = location.getBlockZ();
int combined = queue.getCombinedId4DataDebug(x, y, z, 0, session); int combined = queue.getCombinedId4DataDebug(x, y, z, 0, session);
int id = (combined >> 4); int id = (combined >> 4);
if (id == block.getId()) { if (id == block.getId()) {
@ -80,13 +79,28 @@ public class HistoryExtent extends AbstractDelegateExtent {
} else { } else {
try { try {
CompoundTag tag = queue.getTileEntity(x, y, z); CompoundTag tag = queue.getTileEntity(x, y, z);
this.changeSet.add(location, new BaseBlock(id, combined & 0xF, tag), block); this.changeSet.add(x, y, z, new BaseBlock(id, combined & 0xF, tag), block);
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
this.changeSet.add(x, y, z, combined, block); this.changeSet.add(x, y, z, combined, block);
} }
} }
return super.setBlock(location, block); return extent.setBlock(x, y, z, block);
}
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
return extent.getLazyBlock(x, y, z);
}
@Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
return setBlock((int) location.x, (int) location.y, (int) location.z, block);
}
@Override
public BaseBlock getLazyBlock(Vector location) {
return getLazyBlock((int) location.x, (int) location.y, (int) location.z);
} }
@Nullable @Nullable

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.extent; package com.boydti.fawe.object.extent;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweQueue; import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.ReflectionUtils;
@ -8,7 +9,6 @@ import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag; import com.sk89q.jnbt.Tag;
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;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
@ -63,24 +63,34 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
return super.getBiome(position); return super.getBiome(position);
} }
private BaseBlock lastBlock; @Override
private BlockVector lastVector; public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
return setBlock((int) location.x, (int) location.y, (int) location.z, block);
}
@Override @Override
public BaseBlock getLazyBlock(final Vector position) { public BaseBlock getLazyBlock(Vector location) {
if ((this.lastBlock != null) && this.lastVector.equals(position.toBlockVector())) { return getLazyBlock((int) location.x, (int) location.y, (int) location.z);
return this.lastBlock; }
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
int combinedId4Data = queue.getCombinedId4Data(x, y, z, 0);
int id = FaweCache.getId(combinedId4Data);
if (!FaweCache.hasNBT(id)) {
return FaweCache.CACHE_BLOCK[combinedId4Data];
} }
if (!queue.isChunkLoaded(position.getBlockX() >> 4, position.getBlockZ() >> 4)) {
try { try {
this.lastVector = position.toBlockVector(); CompoundTag tile = queue.getTileEntity(x, y, z);
return this.lastBlock = super.getBlock(position); if (tile != null) {
} catch (final Throwable e) { return new BaseBlock(id, FaweCache.getData(combinedId4Data), tile);
return EditSession.nullBlock; } else {
return FaweCache.CACHE_BLOCK[combinedId4Data];
} }
} catch (Throwable e) {
MainUtil.handleError(e);
return FaweCache.CACHE_BLOCK[combinedId4Data];
} }
this.lastVector = position.toBlockVector();
return this.lastBlock = super.getBlock(position);
} }
@Override @Override
@ -105,8 +115,7 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
} }
@Override @Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { public boolean setBlock(int x, int y, int z, final BaseBlock block) throws WorldEditException {
final int y = (int) location.y;
switch (y) { switch (y) {
case 0: case 0:
case 1: case 1:
@ -368,8 +377,6 @@ public class FastWorldEditExtent extends AbstractDelegateExtent {
default: default:
return false; return false;
} }
final int x = (int) location.x;
final int z = (int) location.z;
final short id = (short) block.getId(); final short id = (short) block.getId();
switch (id) { switch (id) {
case 63: case 63:

View File

@ -55,6 +55,11 @@ public class NullExtent extends FaweRegionExtent {
throw new FaweException(reason); throw new FaweException(reason);
} }
@Override
public BaseBlock getLazyBlock(int x, int y, int z) {
throw new FaweException(reason);
}
@Override @Override
public Entity createEntity(final Location arg0, final BaseEntity arg1) { public Entity createEntity(final Location arg0, final BaseEntity arg1) {
throw new FaweException(reason); throw new FaweException(reason);

View File

@ -5,13 +5,14 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.util.WEManager; import com.boydti.fawe.util.WEManager;
import com.sk89q.worldedit.BlockVector; import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
@ -21,11 +22,13 @@ import java.util.List;
public class ProcessedWEExtent extends FaweRegionExtent { public class ProcessedWEExtent extends FaweRegionExtent {
private final FaweLimit limit; private final FaweLimit limit;
private final RegionWrapper[] mask; private final RegionWrapper[] mask;
private final AbstractDelegateExtent extent;
public ProcessedWEExtent(final Extent parent, final RegionWrapper[] mask, FaweLimit limit) { public ProcessedWEExtent(final Extent parent, final RegionWrapper[] mask, FaweLimit limit) {
super(parent); super(parent);
this.mask = mask; this.mask = mask;
this.limit = limit; this.limit = limit;
this.extent = (AbstractDelegateExtent) parent;
} }
@Override @Override
@ -50,14 +53,6 @@ public class ProcessedWEExtent extends FaweRegionExtent {
return super.getBiome(position); return super.getBiome(position);
} }
private BaseBlock lastBlock;
private BlockVector lastVector;
@Override
public BaseBlock getLazyBlock(final Vector position) {
return super.getLazyBlock(position);
}
@Override @Override
public List<? extends Entity> getEntities() { public List<? extends Entity> getEntities() {
return super.getEntities(); return super.getEntities();
@ -69,28 +64,64 @@ public class ProcessedWEExtent extends FaweRegionExtent {
} }
@Override @Override
public BaseBlock getBlock(final Vector position) { public BaseBlock getLazyBlock(int x, int y, int z) {
return this.getLazyBlock(position); if (WEManager.IMP.maskContains(this.mask, x, z)) {
if (!limit.MAX_CHECKS()) {
WEManager.IMP.cancelEditSafe(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
return EditSession.nullBlock;
} else {
return extent.getLazyBlock(x, y, z);
}
} else if (!limit.MAX_FAILS()) {
WEManager.IMP.cancelEditSafe(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
return EditSession.nullBlock;
} else {
return EditSession.nullBlock;
}
} }
@Override @Override
public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException { public boolean setBlock(final Vector location, final BaseBlock block) throws WorldEditException {
return setBlock((int) location.x, (int) location.y, (int) location.z, block);
}
@Override
public BaseBlock getLazyBlock(Vector location) {
return getLazyBlock((int) location.x, (int) location.y, (int) location.z);
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
if (block.hasNbtData() && FaweCache.hasNBT(block.getType())) { if (block.hasNbtData() && FaweCache.hasNBT(block.getType())) {
if (!limit.MAX_BLOCKSTATES()) { if (!limit.MAX_BLOCKSTATES()) {
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES); WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_TILES);
return false; return false;
} } else if (WEManager.IMP.maskContains(this.mask, x, z)) {
}
if (WEManager.IMP.maskContains(this.mask, (int) location.x, (int) location.z)) {
if (!limit.MAX_CHANGES()) { if (!limit.MAX_CHANGES()) {
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES); WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
return false; return false;
} }
return super.setBlock(location, block); return extent.setBlock(x, y, z, block);
} else if (!limit.MAX_FAILS()) { } else if (!limit.MAX_FAILS()) {
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS); WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
}
return false; return false;
} else {
return false;
}
}
if (WEManager.IMP.maskContains(this.mask, x, z)) {
if (!limit.MAX_CHANGES()) {
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_CHANGES);
return false;
} else {
return extent.setBlock(x, y, z, block);
}
} else if (!limit.MAX_FAILS()) {
WEManager.IMP.cancelEdit(this, BBC.WORLDEDIT_CANCEL_REASON_MAX_FAILS);
return false;
} else {
return false;
}
} }
@Override @Override

View File

@ -32,7 +32,6 @@ import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.HistoryExtent;
import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.NullChangeSet;
import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet; import com.boydti.fawe.object.changeset.CPUOptimizedChangeSet;
import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.changeset.FaweChangeSet;
@ -43,13 +42,10 @@ import com.boydti.fawe.object.extent.FaweRegionExtent;
import com.boydti.fawe.object.extent.NullExtent; import com.boydti.fawe.object.extent.NullExtent;
import com.boydti.fawe.object.extent.ProcessedWEExtent; import com.boydti.fawe.object.extent.ProcessedWEExtent;
import com.boydti.fawe.util.ExtentTraverser; import com.boydti.fawe.util.ExtentTraverser;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MemUtil; import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.Perm; import com.boydti.fawe.util.Perm;
import com.boydti.fawe.util.SetQueue; import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.WorldWrapper; import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID; import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.blocks.BlockType;
@ -118,7 +114,6 @@ import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.AbstractWorld; import com.sk89q.worldedit.world.AbstractWorld;
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 java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -158,10 +153,10 @@ public class EditSession implements Extent {
private World world; private World world;
private FaweQueue queue; private FaweQueue queue;
private Extent extent; private AbstractDelegateExtent extent;
private HistoryExtent history; private HistoryExtent history;
private Extent bypassHistory; private AbstractDelegateExtent bypassHistory;
private Extent bypassAll; private AbstractDelegateExtent bypassAll;
private FaweLimit originalLimit; private FaweLimit originalLimit;
private FaweLimit limit; private FaweLimit limit;
private FawePlayer player; private FawePlayer player;
@ -170,6 +165,8 @@ public class EditSession implements Extent {
private int changes = 0; private int changes = 0;
private BlockBag blockBag; private BlockBag blockBag;
private Vector mutable = new Vector();
public static final UUID CONSOLE = UUID.fromString("1-1-3-3-7"); public static final UUID CONSOLE = UUID.fromString("1-1-3-3-7");
public static final BaseBiome nullBiome = new BaseBiome(0); public static final BaseBiome nullBiome = new BaseBiome(0);
public static final BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0]; public static final BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
@ -424,16 +421,20 @@ public class EditSession implements Extent {
} }
@Deprecated @Deprecated
private Extent wrapExtent(final Extent extent, final EventBus eventBus, EditSessionEvent event, final Stage stage) { private AbstractDelegateExtent wrapExtent(final AbstractDelegateExtent extent, final EventBus eventBus, EditSessionEvent event, final Stage stage) {
event = event.clone(stage); event = event.clone(stage);
event.setExtent(extent); event.setExtent(extent);
eventBus.post(event); eventBus.post(event);
final Extent toReturn = event.getExtent(); final Extent toReturn = event.getExtent();
if (!(toReturn instanceof AbstractDelegateExtent)) {
Fawe.debug("Extent " + toReturn + " must be AbstractDelegateExtent");
return extent;
}
if (toReturn != extent) { if (toReturn != extent) {
String className = toReturn.getClass().getName().toLowerCase(); String className = toReturn.getClass().getName().toLowerCase();
for (String allowed : Settings.EXTENT.ALLOWED_PLUGINS) { for (String allowed : Settings.EXTENT.ALLOWED_PLUGINS) {
if (className.contains(allowed.toLowerCase())) { if (className.contains(allowed.toLowerCase())) {
return toReturn; return (AbstractDelegateExtent) toReturn;
} }
} }
if (Settings.EXTENT.DEBUG) { if (Settings.EXTENT.DEBUG) {
@ -614,7 +615,7 @@ public class EditSession implements Extent {
if (beforeHistory != null && beforeHistory.exists()) { if (beforeHistory != null && beforeHistory.exists()) {
beforeHistory.setNext(afterHistory.get()); beforeHistory.setNext(afterHistory.get());
} else { } else {
extent = afterHistory.get(); extent = (AbstractDelegateExtent) afterHistory.get();
} }
} }
} else if (traverseHistory == null || !traverseHistory.exists()) { } else if (traverseHistory == null || !traverseHistory.exists()) {
@ -690,30 +691,16 @@ public class EditSession implements Extent {
@Override @Override
public BaseBlock getLazyBlock(final Vector position) { public BaseBlock getLazyBlock(final Vector position) {
return getLazyBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ()); return getLazyBlock((int) position.x, (int) position.y, (int) position.z);
} }
public BaseBlock getLazyBlock(int x, int y, int z) { public BaseBlock getLazyBlock(int x, int y, int z) {
if (!limit.MAX_CHECKS()) { return extent.getLazyBlock(x, y, z);
throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
}
int combinedId4Data = queue.getCombinedId4DataDebug(x, y, z, 0, this);
int id = FaweCache.getId(combinedId4Data);
if (!FaweCache.hasNBT(id)) {
return FaweCache.CACHE_BLOCK[combinedId4Data];
}
try {
CompoundTag tile = queue.getTileEntity(x, y, z);
return new BaseBlock(id, FaweCache.getData(combinedId4Data), tile);
} catch (Throwable e) {
MainUtil.handleError(e);
return FaweCache.CACHE_BLOCK[combinedId4Data];
}
} }
@Override @Override
public BaseBlock getBlock(final Vector position) { public BaseBlock getBlock(final Vector position) {
return this.getLazyBlock(position); return getLazyBlock((int) position.x, (int) position.y, (int) position.z);
} }
/** /**
@ -757,7 +744,7 @@ public class EditSession implements Extent {
*/ */
@Deprecated @Deprecated
public BaseBlock rawGetBlock(final Vector position) { public BaseBlock rawGetBlock(final Vector position) {
return this.getLazyBlock(position); return bypassAll.getLazyBlock(position);
} }
/** /**
@ -784,7 +771,6 @@ public class EditSession implements Extent {
* @return height of highest block found or 'minY' * @return height of highest block found or 'minY'
*/ */
public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) { public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) {
Vector pt = new Vector(x, 0, z);
for (int y = maxY; y >= minY; --y) { for (int y = maxY; y >= minY; --y) {
BaseBlock block = getLazyBlock(x, y, z); BaseBlock block = getLazyBlock(x, y, z);
final int id = block.getId(); final int id = block.getId();
@ -939,13 +925,20 @@ public class EditSession implements Extent {
} }
} }
public boolean setBlock(int x, int y, int z, BaseBlock block) {
this.changes++;
try {
return this.extent.setBlock(x, y, z, block);
} catch (WorldEditException e) {
throw new RuntimeException("Unexpected exception", e);
}
}
@Override @Override
public boolean setBlock(final Vector position, final BaseBlock block) throws MaxChangedBlocksException { public boolean setBlock(final Vector position, final BaseBlock block) throws MaxChangedBlocksException {
this.changes++; this.changes++;
try { try {
return this.extent.setBlock(position, block); return this.extent.setBlock(position, block);
} catch (final MaxChangedBlocksException e) {
throw e;
} catch (final WorldEditException e) { } catch (final WorldEditException e) {
throw new RuntimeException("Unexpected exception", e); throw new RuntimeException("Unexpected exception", e);
} }
@ -1658,7 +1651,6 @@ public class EditSession implements Extent {
checkNotNull(dir); checkNotNull(dir);
checkArgument(distance >= 1, "distance >= 1 required"); checkArgument(distance >= 1, "distance >= 1 required");
final Vector displace = dir.multiply(distance); final Vector displace = dir.multiply(distance);
final Vector mutable = new Vector(0, 0, 0);
// Remove the original blocks // Remove the original blocks
final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR)); final com.sk89q.worldedit.function.pattern.Pattern pattern = replacement != null ? new BlockPattern(replacement) : new BlockPattern(new BaseBlock(BlockID.AIR));
final BlockReplace remove = new BlockReplace(EditSession.this, pattern) { final BlockReplace remove = new BlockReplace(EditSession.this, pattern) {
@ -2030,27 +2022,25 @@ public class EditSession implements Extent {
final int ceilRadius = (int) Math.ceil(radius); final int ceilRadius = (int) Math.ceil(radius);
for (int x = ox - ceilRadius; x <= (ox + ceilRadius); ++x) { for (int x = ox - ceilRadius; x <= (ox + ceilRadius); ++x) {
int dx = x - ox;
int dx2 = dx * dx;
for (int z = oz - ceilRadius; z <= (oz + ceilRadius); ++z) { for (int z = oz - ceilRadius; z <= (oz + ceilRadius); ++z) {
if ((new Vector(x, oy, z)).distanceSq(position) > radiusSq) { int dz = z - oz;
int dz2 = dz * dz;
if (dx2 + dz2 > radiusSq) {
continue; continue;
} }
for (int y = 255; y >= 1; --y) { for (int y = 255; y >= 1; --y) {
final Vector pt = new Vector(x, y, z); final int id = FaweCache.getId(queue.getCombinedId4Data(x, y, z));
final int id = this.getBlockType(pt);
switch (id) { switch (id) {
case BlockID.ICE: case BlockID.ICE:
this.setBlock(pt, water); this.setBlock(x, y, z, water);
break; break;
case BlockID.SNOW: case BlockID.SNOW:
this.setBlock(pt, air); this.setBlock(x, y, z, air);
break; break;
case BlockID.AIR: case BlockID.AIR:
continue; continue;
default: default:
break; break;
} }
@ -2084,22 +2074,22 @@ public class EditSession implements Extent {
final int ceilRadius = (int) Math.ceil(radius); final int ceilRadius = (int) Math.ceil(radius);
for (int x = ox - ceilRadius; x <= (ox + ceilRadius); ++x) { for (int x = ox - ceilRadius; x <= (ox + ceilRadius); ++x) {
int dx = x - ox;
int dx2 = dx * dx;
for (int z = oz - ceilRadius; z <= (oz + ceilRadius); ++z) { for (int z = oz - ceilRadius; z <= (oz + ceilRadius); ++z) {
if ((new Vector(x, oy, z)).distanceSq(position) > radiusSq) { int dz = z - oz;
int dz2 = dz * dz;
if (dx2 + dz2 > radiusSq) {
continue; continue;
} }
for (int y = 255; y >= 1; --y) { for (int y = 255; y >= 1; --y) {
final Vector pt = new Vector(x, y, z); final int id = FaweCache.getId(queue.getCombinedId4Data(x, y, z));
final int id = this.getBlockType(pt);
if (id == BlockID.AIR) { if (id == BlockID.AIR) {
continue; continue;
} }
// Ice! // Ice!
if ((id == BlockID.WATER) || (id == BlockID.STATIONARY_WATER)) { if ((id == BlockID.WATER) || (id == BlockID.STATIONARY_WATER)) {
this.setBlock(pt, ice); this.setBlock(x, y, z, ice);
break; break;
} }
@ -2114,7 +2104,7 @@ public class EditSession implements Extent {
} }
// add snow cover // add snow cover
this.setBlock(pt.add(0, 1, 0), snow); this.setBlock(x, y + 1, z, snow);
break; break;
} }
} }
@ -2158,22 +2148,25 @@ public class EditSession implements Extent {
final int ceilRadius = (int) Math.ceil(radius); final int ceilRadius = (int) Math.ceil(radius);
for (int x = ox - ceilRadius; x <= (ox + ceilRadius); ++x) { for (int x = ox - ceilRadius; x <= (ox + ceilRadius); ++x) {
int dx = x - ox;
int dx2 = dx * dx;
for (int z = oz - ceilRadius; z <= (oz + ceilRadius); ++z) { for (int z = oz - ceilRadius; z <= (oz + ceilRadius); ++z) {
if ((new Vector(x, oy, z)).distanceSq(position) > radiusSq) { int dz = z - oz;
int dz2 = dz * dz;
if (dx2 + dz2 > radiusSq) {
continue; continue;
} }
loop: for (int y = 255; y >= 1; --y) { loop: for (int y = 255; y >= 1; --y) {
final Vector pt = new Vector(x, y, z); BaseBlock block = getLazyBlock(x, y, z);
final int id = this.getBlockType(pt); final int id = block.getId();
final int data = this.getBlockData(pt); final int data = block.getData();
switch (id) { switch (id) {
case BlockID.DIRT: case BlockID.DIRT:
if (onlyNormalDirt && (data != 0)) { if (onlyNormalDirt && (data != 0)) {
break loop; break loop;
} }
this.setBlock(pt, grass); this.setBlock(x, y, z, grass);
break loop; break loop;
case BlockID.WATER: case BlockID.WATER:
@ -2237,7 +2230,7 @@ public class EditSession implements Extent {
* @throws MaxChangedBlocksException thrown if too many blocks are changed * @throws MaxChangedBlocksException thrown if too many blocks are changed
*/ */
public int makeForest(final Vector basePosition, final int size, final double density, final TreeGenerator treeGenerator) { public int makeForest(final Vector basePosition, final int size, final double density, final TreeGenerator treeGenerator) {
final ArrayDeque<Vector> trees = new ArrayDeque<>(); try {
for (int x = basePosition.getBlockX() - size; x <= (basePosition.getBlockX() + size); ++x) { for (int x = basePosition.getBlockX() - size; x <= (basePosition.getBlockX() + size); ++x) {
for (int z = basePosition.getBlockZ() - size; z <= (basePosition.getBlockZ() + size); ++z) { for (int z = basePosition.getBlockZ() - size; z <= (basePosition.getBlockZ() + size); ++z) {
// Don't want to be in the ground // Don't want to be in the ground
@ -2248,37 +2241,22 @@ public class EditSession implements Extent {
if (FaweCache.RANDOM.random(65536) >= (density * 65536)) { if (FaweCache.RANDOM.random(65536) >= (density * 65536)) {
continue; continue;
} // def 0.05 } // def 0.05
trees.add(new Vector(x, 0, z)); this.changes++;
}
}
if (trees.size() > 0) {
TaskManager.IMP.objectTask(trees, new RunnableVal<Vector>() {
@Override
public void run(Vector vector) {
try {
for (int y = basePosition.getBlockY(); y >= (basePosition.getBlockY() - 10); --y) { for (int y = basePosition.getBlockY(); y >= (basePosition.getBlockY() - 10); --y) {
vector = new Vector(vector.getX(), y, vector.getZ()); final int t = getLazyBlock(x, y, z).getType();
final int t = getBlock(vector).getType();
if ((t == BlockID.GRASS) || (t == BlockID.DIRT)) { if ((t == BlockID.GRASS) || (t == BlockID.DIRT)) {
treeGenerator.generate(EditSession.this, new Vector(vector.getX(), y + 1, vector.getZ())); treeGenerator.generate(EditSession.this, new Vector(x, y + 1, z));
break; break;
} else if (t == BlockID.SNOW) { } else if (t == BlockID.SNOW) {
setBlock(vector, nullBlock); setBlock(x, y, z, nullBlock);
} else if (t != BlockID.AIR) { // Trees won't grow on this! } else if (t != BlockID.AIR) { // Trees won't grow on this!
break; break;
} }
} }
} catch (MaxChangedBlocksException ignore) {
} }
} }
}, new Runnable() { } catch (MaxChangedBlocksException ignore) {}
@Override return this.changes;
public void run() {
queue.enqueue();
}
});
}
return this.changes = trees.size();
} }
/** /**
@ -2306,10 +2284,7 @@ public class EditSession implements Extent {
for (int x = minX; x <= maxX; ++x) { for (int x = minX; x <= maxX; ++x) {
for (int y = minY; y <= maxY; ++y) { for (int y = minY; y <= maxY; ++y) {
for (int z = minZ; z <= maxZ; ++z) { for (int z = minZ; z <= maxZ; ++z) {
final Vector pt = new Vector(x, y, z); int id = FaweCache.getId(queue.getCombinedId4Data(x, y, z));
final int id = this.getBlockType(pt);
if (map.containsKey(id)) { if (map.containsKey(id)) {
map.get(id).increment(); map.get(id).increment();
} else { } else {
@ -2323,7 +2298,6 @@ public class EditSession implements Extent {
} else { } else {
for (final Vector pt : region) { for (final Vector pt : region) {
final int id = this.getBlockType(pt); final int id = this.getBlockType(pt);
if (map.containsKey(id)) { if (map.containsKey(id)) {
map.get(id).increment(); map.get(id).increment();
} else { } else {
@ -2364,10 +2338,7 @@ public class EditSession implements Extent {
for (int x = minX; x <= maxX; ++x) { for (int x = minX; x <= maxX; ++x) {
for (int y = minY; y <= maxY; ++y) { for (int y = minY; y <= maxY; ++y) {
for (int z = minZ; z <= maxZ; ++z) { for (int z = minZ; z <= maxZ; ++z) {
final Vector pt = new Vector(x, y, z); final BaseBlock blk = getLazyBlock(x, y, z);
final BaseBlock blk = FaweCache.getBlock(this.getBlockType(pt), this.getBlockData(pt));
if (map.containsKey(blk)) { if (map.containsKey(blk)) {
map.get(blk).increment(); map.get(blk).increment();
} else { } else {

View File

@ -0,0 +1,152 @@
/*
* 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.extent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BaseBiome;
import javax.annotation.Nullable;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* A base class for {@link Extent}s that merely passes extents onto another.
*/
public abstract class AbstractDelegateExtent implements Extent {
private final Extent extent;
/**
* Create a new instance.
*
* @param extent the extent
*/
protected AbstractDelegateExtent(Extent extent) {
checkNotNull(extent);
this.extent = extent;
}
/**
* Get the extent.
*
* @return the extent
*/
public Extent getExtent() {
return extent;
}
@Override
public BaseBlock getBlock(Vector position) {
return extent.getLazyBlock(position);
}
private Vector mutable = new Vector(0,0,0);
public BaseBlock getLazyBlock(int x, int y, int z) {
mutable.x = x;
mutable.y = y;
mutable.z = z;
return extent.getLazyBlock(mutable);
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return extent.getLazyBlock(position);
}
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
mutable.x = x;
mutable.y = y;
mutable.z = z;
return extent.setBlock(mutable, block);
}
@Override
public boolean setBlock(Vector location, BaseBlock 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 BaseBiome getBiome(Vector2D position) {
return extent.getBiome(position);
}
@Override
public boolean setBiome(Vector2D position, BaseBiome biome) {
return extent.setBiome(position, biome);
}
@Override
public Vector getMinimumPoint() {
return extent.getMinimumPoint();
}
@Override
public Vector getMaximumPoint() {
return extent.getMaximumPoint();
}
protected Operation commitBefore() {
return null;
}
@Override
public final @Nullable Operation commit() {
Operation ours = commitBefore();
Operation other = extent.commit();
if (ours != null && other != null) {
return new OperationQueue(ours, other);
} else if (ours != null) {
return ours;
} else if (other != null) {
return other;
} else {
return null;
}
}
}