Changed Super Pickaxe to use EditSession.

This fixes WORLDEDIT-3102 and allows the logging of Super Pickaxe
usage via the EditSession Extent pipeline.
This commit is contained in:
sk89q 2014-04-23 00:33:00 -07:00
parent bf062298f1
commit f94be80923
7 changed files with 253 additions and 40 deletions

View File

@ -19,17 +19,17 @@
package com.sk89q.worldedit;
import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer;
import com.sk89q.worldedit.extent.cache.LastAccessExtentCache;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.event.extent.EditSessionEvent;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.extent.*;
import com.sk89q.worldedit.extent.ChangeSetExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.MaskingExtent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer;
import com.sk89q.worldedit.extent.cache.LastAccessExtentCache;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.extent.inventory.BlockBagExtent;
import com.sk89q.worldedit.extent.reorder.MultiStageReorder;
import com.sk89q.worldedit.extent.validation.BlockChangeLimiter;
@ -37,10 +37,11 @@ import com.sk89q.worldedit.extent.validation.DataValidatorExtent;
import com.sk89q.worldedit.extent.world.BlockQuirkExtent;
import com.sk89q.worldedit.extent.world.ChunkLoadingExtent;
import com.sk89q.worldedit.extent.world.FastModeExtent;
import com.sk89q.worldedit.extent.world.SurvivalModeExtent;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.RegionMaskingFilter;
import com.sk89q.worldedit.function.block.Counter;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.block.Counter;
import com.sk89q.worldedit.function.block.Naturalizer;
import com.sk89q.worldedit.function.generator.GardenPatchGenerator;
import com.sk89q.worldedit.function.mask.*;
@ -53,6 +54,9 @@ import com.sk89q.worldedit.history.UndoContext;
import com.sk89q.worldedit.history.change.BlockChange;
import com.sk89q.worldedit.history.changeset.BlockOptimizedHistory;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.RValue;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.math.interpolation.Interpolation;
import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation;
@ -70,6 +74,7 @@ import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.collection.DoubleArrayList;
import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.world.NullWorld;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable;
@ -105,6 +110,7 @@ public class EditSession implements Extent {
private final ChangeSet changeSet = new BlockOptimizedHistory();
private @Nullable FastModeExtent fastModeExtent;
private final SurvivalModeExtent survivalExtent;
private @Nullable ChunkLoadingExtent chunkLoadingExtent;
private @Nullable LastAccessExtentCache cacheExtent;
private @Nullable BlockQuirkExtent quirkExtent;
@ -160,6 +166,7 @@ public class EditSession implements Extent {
// This extents are ALWAYS used
extent = fastModeExtent = new FastModeExtent(world, false);
extent = survivalExtent = new SurvivalModeExtent(extent, world);
extent = quirkExtent = new BlockQuirkExtent(extent, world);
extent = chunkLoadingExtent = new ChunkLoadingExtent(extent, world);
extent = cacheExtent = new LastAccessExtentCache(extent);
@ -182,6 +189,7 @@ public class EditSession implements Extent {
this.bypassNone = extent;
} else {
Extent extent = new NullExtent();
extent = survivalExtent = new SurvivalModeExtent(extent, new NullWorld());
extent = blockBagExtent = new BlockBagExtent(extent, blockBag);
extent = reorderExtent = new MultiStageReorder(extent, false);
extent = maskingExtent = new MaskingExtent(extent, Masks.alwaysTrue());
@ -287,6 +295,15 @@ public class EditSession implements Extent {
}
}
/**
* Get the {@link SurvivalModeExtent}.
*
* @return the survival simulation extent
*/
public SurvivalModeExtent getSurvivalExtent() {
return survivalExtent;
}
/**
* Set whether fast mode is enabled.
* </p>

View File

@ -57,18 +57,16 @@ public class AreaPickaxe implements BlockTool {
}
EditSession editSession = session.createEditSession(player);
editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop);
try {
for (int x = ox - range; x <= ox + range; ++x) {
for (int y = oy - range; y <= oy + range; ++y) {
for (int z = oz - range; z <= oz + range; ++z) {
Vector pos = new Vector(x, y, z);
if (world.getBlockType(pos) != initialType) {
if (editSession.getBlockType(pos) != initialType) {
continue;
}
if (config.superPickaxeManyDrop) {
world.simulateBlockMine(pos);
}
world.queueBlockBreakEffect(server, pos, initialType, clicked.distanceSq(pos));
@ -79,6 +77,7 @@ public class AreaPickaxe implements BlockTool {
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
editSession.flushQueue();
session.remember(editSession);
}

View File

@ -19,13 +19,13 @@
package com.sk89q.worldedit.command.tool;
import java.util.HashSet;
import java.util.Set;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import java.util.HashSet;
import java.util.Set;
/**
* A pickaxe mode that recursively finds adjacent blocks within range of
* an initial block and of the same type.
@ -59,14 +59,15 @@ public class RecursivePickaxe implements BlockTool {
}
EditSession editSession = session.createEditSession(player);
editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop);
try {
recurse(server, editSession, world, clicked.toBlockVector(),
clicked, range, initialType, new HashSet<BlockVector>(),
config.superPickaxeManyDrop);
clicked, range, initialType, new HashSet<BlockVector>());
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
editSession.flushQueue();
session.remember(editSession);
}
@ -77,7 +78,6 @@ public class RecursivePickaxe implements BlockTool {
* Helper method.
*
* @param server
* @param superPickaxeManyDrop
* @param world
* @param pos
* @param origin
@ -88,7 +88,7 @@ public class RecursivePickaxe implements BlockTool {
private static void recurse(ServerInterface server, EditSession editSession,
LocalWorld world, BlockVector pos,
Vector origin, double size, int initialType,
Set<BlockVector> visited, boolean drop)
Set<BlockVector> visited)
throws MaxChangedBlocksException {
final double distanceSq = origin.distanceSq(pos);
@ -102,26 +102,22 @@ public class RecursivePickaxe implements BlockTool {
return;
}
if (drop) {
world.simulateBlockMine(pos);
}
world.queueBlockBreakEffect(server, pos, initialType, distanceSq);
editSession.setBlock(pos, air);
recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(),
origin, size, initialType, visited, drop);
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(),
origin, size, initialType, visited, drop);
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(),
origin, size, initialType, visited, drop);
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(),
origin, size, initialType, visited, drop);
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(),
origin, size, initialType, visited, drop);
origin, size, initialType, visited);
recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(),
origin, size, initialType, visited, drop);
origin, size, initialType, visited);
}
}

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.command.tool;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
/**
@ -43,11 +44,16 @@ public class SinglePickaxe implements BlockTool {
return true;
}
if (config.superPickaxeDrop) {
world.simulateBlockMine(clicked);
}
EditSession editSession = session.createEditSession(player);
editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop);
world.setBlockType(clicked, BlockID.AIR);
try {
editSession.setBlock(clicked, new BaseBlock(BlockID.AIR));
} catch (MaxChangedBlocksException e) {
player.printError("Max blocks change limit reached.");
} finally {
editSession.flushQueue();
}
world.playEffect(clicked, 2001, blockType);

View File

@ -0,0 +1,92 @@
/*
* 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.world;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Makes changes to the world as if a player had done so during survival mode.
* </p>
* Note that this extent may choose to not call the underlying
* extent and may instead call methods on the {@link World} that is passed
* in the constructor. For that reason, if you wish to "catch" changes, you
* should catch them before the changes reach this extent.
*/
public class SurvivalModeExtent extends AbstractDelegateExtent {
private final World world;
private boolean toolUse = false;
/**
* Create a new instance.
*
* @param extent the extent
* @param world the world
*/
public SurvivalModeExtent(Extent extent, World world) {
super(extent);
checkNotNull(world);
this.world = world;
}
/**
* Return whether changes to the world should be simulated with the
* use of game tools (such as pickaxes) whenever possible and reasonable.
* </p>
* For example, we could pretend that the act of setting a coal ore block
* to air (nothing) was the act of a player mining that coal ore block
* with a pickaxe, which would mean that a coal item would be dropped.
*
* @return true if tool use is to be simulated
*/
public boolean hasToolUse() {
return toolUse;
}
/**
* Set whether changes to the world should be simulated with the
* use of game tools (such as pickaxes) whenever possible and reasonable.
*
* @param toolUse true if tool use is to be simulated
* @see #hasToolUse() for an explanation
*/
public void setToolUse(boolean toolUse) {
this.toolUse = toolUse;
}
@Override
public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException {
if (toolUse && block.getType() == BlockID.AIR) {
world.simulateBlockMine(location);
return true;
} else {
return super.setBlock(location, block);
}
}
}

View File

@ -138,15 +138,20 @@ public abstract class AbstractWorld implements World {
public void simulateBlockMine(Vector pt) {
BaseBlock block = getLazyBlock(pt);
BaseItemStack stack = BlockType.getBlockDrop(block.getId(), (short) block.getData());
if (stack == null) {
return;
if (stack != null) {
final int amount = stack.getAmount();
if (amount > 1) {
dropItem(pt, new BaseItemStack(stack.getType(), 1, stack.getData()), amount);
} else {
dropItem(pt, stack, amount);
}
}
final int amount = stack.getAmount();
if (amount > 1) {
dropItem(pt, new BaseItemStack(stack.getType(), 1, stack.getData()), amount);
} else {
dropItem(pt, stack, amount);
try {
setBlock(pt, new BaseBlock(BlockID.AIR));
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.world;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
/**
* A null implementation of {@link World} that drops all changes and
* returns dummy data.
*/
public class NullWorld extends AbstractWorld {
@Override
public String getName() {
return "null";
}
@Override
public boolean setBlock(Vector position, BaseBlock block, boolean notifyAndLight) throws WorldEditException {
return false;
}
@Override
public int getBlockLightLevel(Vector position) {
return 0;
}
@Override
public boolean clearContainerBlockContents(Vector position) {
return false;
}
@Override
public BiomeType getBiome(Vector2D position) {
return null;
}
@Override
public void setBiome(Vector2D position, BiomeType biome) {
}
@Override
public void dropItem(Vector position, BaseItemStack item) {
}
@Override
public int killMobs(Vector origin, double radius, int flags) {
return 0;
}
@Override
public int removeEntities(EntityType type, Vector origin, int radius) {
return 0;
}
@Override
public boolean regenerate(Region region, EditSession editSession) {
return false;
}
@Override
public boolean generateTree(TreeType type, EditSession editSession, Vector position) throws MaxChangedBlocksException {
return false;
}
@Override
public BaseBlock getBlock(Vector position) {
return new BaseBlock(BlockID.AIR);
}
@Override
public BaseBlock getLazyBlock(Vector position) {
return new BaseBlock(BlockID.AIR);
}
}