mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-11-02 19:06:07 +00:00
Broke up EditSession into many Extents.
This commit is contained in:
parent
10e672a94a
commit
e7fe787b20
File diff suppressed because it is too large
Load Diff
@ -25,9 +25,11 @@ import com.sk89q.worldedit.foundation.Block;
|
||||
import com.sk89q.worldedit.foundation.World;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.PriorityQueue;
|
||||
import java.util.Random;
|
||||
|
||||
@ -618,4 +620,9 @@ public abstract class LocalWorld implements World, Extent {
|
||||
new BaseBlock(BlockID.WATER, -1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Operation commit() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
120
src/main/java/com/sk89q/worldedit/extent/BlockBagExtent.java
Normal file
120
src/main/java/com/sk89q/worldedit/extent/BlockBagExtent.java
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bags.BlockBag;
|
||||
import com.sk89q.worldedit.bags.BlockBagException;
|
||||
import com.sk89q.worldedit.bags.UnplaceableBlockException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Applies a {@link BlockBag} to operations.
|
||||
*/
|
||||
public class BlockBagExtent extends ExtentDelegate {
|
||||
|
||||
private final LocalWorld world;
|
||||
private Map<Integer, Integer> missingBlocks = new HashMap<Integer, Integer>();
|
||||
private BlockBag blockBag;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param world the world
|
||||
* @param blockBag the block bag
|
||||
*/
|
||||
public BlockBagExtent(Extent extent, LocalWorld world, @Nullable BlockBag blockBag) {
|
||||
super(extent);
|
||||
checkNotNull(world);
|
||||
this.world = world;
|
||||
this.blockBag = blockBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the block bag.
|
||||
*
|
||||
* @return a block bag, which may be null if none is used
|
||||
*/
|
||||
public @Nullable BlockBag getBlockBag() {
|
||||
return blockBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block bag.
|
||||
*
|
||||
* @param blockBag a block bag, which may be null if none is used
|
||||
*/
|
||||
public void setBlockBag(@Nullable BlockBag blockBag) {
|
||||
this.blockBag = blockBag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of missing blocks and clears the list for the next
|
||||
* operation.
|
||||
*
|
||||
* @return a map of missing blocks
|
||||
*/
|
||||
public Map<Integer, Integer> popMissing() {
|
||||
Map<Integer, Integer> missingBlocks = this.missingBlocks;
|
||||
this.missingBlocks = new HashMap<Integer, Integer>();
|
||||
return missingBlocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
if (blockBag != null) {
|
||||
final int type = block.getType();
|
||||
final int existing = world.getBlockType(location);
|
||||
|
||||
if (type > 0) {
|
||||
try {
|
||||
blockBag.fetchPlacedBlock(type, 0);
|
||||
} catch (UnplaceableBlockException e) {
|
||||
return false;
|
||||
} catch (BlockBagException e) {
|
||||
if (!missingBlocks.containsKey(type)) {
|
||||
missingBlocks.put(type, 1);
|
||||
} else {
|
||||
missingBlocks.put(type, missingBlocks.get(type) + 1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing > 0) {
|
||||
try {
|
||||
blockBag.storeDroppedBlock(existing, world.getBlockData(location));
|
||||
} catch (BlockBagException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* Limits the number of blocks that can be changed before a
|
||||
* {@link MaxChangedBlocksException} is thrown.
|
||||
*/
|
||||
public class BlockChangeLimiter extends ExtentDelegate {
|
||||
|
||||
private int limit;
|
||||
private int count = 0;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param limit the limit (>= 0) or -1 for no limit
|
||||
*/
|
||||
public BlockChangeLimiter(Extent extent, int limit) {
|
||||
super(extent);
|
||||
setLimit(limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the limit.
|
||||
*
|
||||
* @return the limit (>= 0) or -1 for no limit
|
||||
*/
|
||||
public int getLimit() {
|
||||
return limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the limit.
|
||||
*
|
||||
* @param limit the limit (>= 0) or -1 for no limit
|
||||
*/
|
||||
public void setLimit(int limit) {
|
||||
checkArgument(limit >= -1, "limit >= -1 required");
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of blocks that have been counted so far.
|
||||
*
|
||||
* @return the number of blocks
|
||||
*/
|
||||
public int getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
if (limit >= 0) {
|
||||
if (count >= limit) {
|
||||
throw new MaxChangedBlocksException(limit);
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
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.blocks.BlockType;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Handles various quirks when setting blocks, such as ice turning
|
||||
* into water or containers dropping their contents.
|
||||
*/
|
||||
public class BlockQuirkExtent extends ExtentDelegate {
|
||||
|
||||
private final LocalWorld world;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param world the world
|
||||
*/
|
||||
public BlockQuirkExtent(Extent extent, LocalWorld world) {
|
||||
super(extent);
|
||||
checkNotNull(world);
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
final int existing = world.getBlockType(location);
|
||||
|
||||
if (BlockType.isContainerBlock(existing)) {
|
||||
world.clearContainerBlockContents(location); // Clear the container block so that it doesn't drop items
|
||||
} else if (existing == BlockID.ICE) {
|
||||
world.setBlockType(location, BlockID.AIR); // Ice turns until water so this has to be done first
|
||||
}
|
||||
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Stores changes to a {@link ChangeSet}.
|
||||
*/
|
||||
public class ChangeSetExtent extends ExtentDelegate {
|
||||
|
||||
private final ChangeSet changeSet;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param changeSet the change set
|
||||
*/
|
||||
public ChangeSetExtent(Extent extent, ChangeSet changeSet) {
|
||||
super(extent);
|
||||
checkNotNull(changeSet);
|
||||
this.changeSet = changeSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
BaseBlock previous = getBlock(location);
|
||||
changeSet.add(new BlockChange(location.toBlockVector(), previous, block));
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Automatically loads chunks when blocks are accessed.
|
||||
*/
|
||||
public class ChunkLoadingExtent extends ExtentDelegate {
|
||||
|
||||
private final LocalWorld world;
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param world the world
|
||||
* @param enabled true to enable
|
||||
*/
|
||||
public ChunkLoadingExtent(Extent extent, LocalWorld world, boolean enabled) {
|
||||
super(extent);
|
||||
checkNotNull(world);
|
||||
this.enabled = enabled;
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with chunk loading enabled.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param world the world
|
||||
*/
|
||||
public ChunkLoadingExtent(Extent extent, LocalWorld world) {
|
||||
this(extent, world, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
world.checkLoadedChunk(location);
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Validates set data to prevent creating invalid blocks and such.
|
||||
*/
|
||||
public class DataValidatorExtent extends ExtentDelegate {
|
||||
|
||||
private final LocalWorld world;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param world the world
|
||||
*/
|
||||
public DataValidatorExtent(Extent extent, LocalWorld world) {
|
||||
super(extent);
|
||||
checkNotNull(world);
|
||||
this.world = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
final int y = location.getBlockY();
|
||||
final int type = block.getType();
|
||||
if (y < 0 || y > world.getMaxY()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// No invalid blocks
|
||||
if (!world.isValidBlockType(type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
}
|
@ -22,6 +22,9 @@ package com.sk89q.worldedit.extent;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* A world, portion of a world, clipboard, or other object that can have blocks set or
|
||||
@ -76,4 +79,12 @@ public interface Extent {
|
||||
*/
|
||||
boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException;
|
||||
|
||||
/**
|
||||
* Return an {@link Operation} that should be called to tie up loose ends
|
||||
* (such as to commit changes in a buffer).
|
||||
*
|
||||
* @return an operation or null if there is none to execute
|
||||
*/
|
||||
@Nullable Operation commit();
|
||||
|
||||
}
|
||||
|
96
src/main/java/com/sk89q/worldedit/extent/ExtentDelegate.java
Normal file
96
src/main/java/com/sk89q/worldedit/extent/ExtentDelegate.java
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.OperationQueue;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* A base class for {@link Extent}s that merely passes extents onto another.
|
||||
*/
|
||||
public class ExtentDelegate implements Extent {
|
||||
|
||||
private final Extent extent;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
*/
|
||||
public ExtentDelegate(Extent extent) {
|
||||
checkNotNull(extent);
|
||||
this.extent = extent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extent.
|
||||
*
|
||||
* @return the extent
|
||||
*/
|
||||
public Extent getExtent() {
|
||||
return extent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlock(Vector location) {
|
||||
return extent.getBlock(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockType(Vector location) {
|
||||
return extent.getBlockType(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockData(Vector location) {
|
||||
return extent.getBlockData(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
return extent.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
108
src/main/java/com/sk89q/worldedit/extent/FastModeExtent.java
Normal file
108
src/main/java/com/sk89q/worldedit/extent/FastModeExtent.java
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Implements "fast mode" which may skip physics, lighting, etc.
|
||||
*/
|
||||
public class FastModeExtent extends ExtentDelegate {
|
||||
|
||||
private final LocalWorld world;
|
||||
private final Set<BlockVector2D> dirtyChunks = new HashSet<BlockVector2D>();
|
||||
private boolean enabled = true;
|
||||
|
||||
/**
|
||||
* Create a new instance with fast mode enabled.
|
||||
*
|
||||
* @param world the world
|
||||
*/
|
||||
public FastModeExtent(LocalWorld world) {
|
||||
this(world, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param world the world
|
||||
* @param enabled true to enable fast mode
|
||||
*/
|
||||
public FastModeExtent(LocalWorld world, boolean enabled) {
|
||||
super(world);
|
||||
checkNotNull(world);
|
||||
this.world = world;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether fast mode is enabled.
|
||||
*
|
||||
* @return true if fast mode is enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fast mode enable status.
|
||||
*
|
||||
* @param enabled true to enable fast mode
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
dirtyChunks.add(new BlockVector2D(location.getBlockX() >> 4, location.getBlockZ() >> 4));
|
||||
return super.setBlock(location, block, notifyAdjacent || enabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Operation commitBefore() {
|
||||
if (dirtyChunks.size() > 0) {
|
||||
return new Operation() {
|
||||
@Override
|
||||
public Operation resume() throws WorldEditException {
|
||||
world.fixAfterFastMode(dirtyChunks);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -38,14 +38,16 @@ import java.util.Map;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Buffers changes to an {@link Extent} and allows later retrieval of buffered
|
||||
* changes for actual setting.
|
||||
* Buffers changes to an {@link Extent} and allows later retrieval for
|
||||
* actual application of the changes.
|
||||
* </p>
|
||||
* This buffer will not attempt to return results from the buffer when
|
||||
* accessor methods (such as {@link #getBlock(Vector)}) are called.
|
||||
*/
|
||||
public class ExtentBuffer implements Extent, Pattern {
|
||||
public class ForgetfulExtentBuffer extends ExtentDelegate implements Pattern {
|
||||
|
||||
private static final BaseBlock AIR = new BaseBlock(BlockID.AIR);
|
||||
|
||||
private final Extent delegate;
|
||||
private final Map<BlockVector, BaseBlock> buffer = new LinkedHashMap<BlockVector, BaseBlock>();
|
||||
private final Mask mask;
|
||||
private Vector min = null;
|
||||
@ -56,7 +58,7 @@ public class ExtentBuffer implements Extent, Pattern {
|
||||
*
|
||||
* @param delegate the delegate extent for {@link Extent#getBlock(Vector)}, etc. calls
|
||||
*/
|
||||
public ExtentBuffer(Extent delegate) {
|
||||
public ForgetfulExtentBuffer(Extent delegate) {
|
||||
this(delegate, Masks.alwaysTrue());
|
||||
}
|
||||
|
||||
@ -67,28 +69,13 @@ public class ExtentBuffer implements Extent, Pattern {
|
||||
* @param delegate the delegate extent for {@link Extent#getBlock(Vector)}, etc. calls
|
||||
* @param mask the mask
|
||||
*/
|
||||
public ExtentBuffer(Extent delegate, Mask mask) {
|
||||
public ForgetfulExtentBuffer(Extent delegate, Mask mask) {
|
||||
super(delegate);
|
||||
checkNotNull(delegate);
|
||||
checkNotNull(mask);
|
||||
this.delegate = delegate;
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseBlock getBlock(Vector location) {
|
||||
return delegate.getBlock(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockType(Vector location) {
|
||||
return delegate.getBlockType(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockData(Vector location) {
|
||||
return delegate.getBlockData(location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
// Update minimum
|
||||
@ -110,7 +97,7 @@ public class ExtentBuffer implements Extent, Pattern {
|
||||
buffer.put(blockVector, block);
|
||||
return true;
|
||||
} else {
|
||||
return delegate.setBlock(location, block, notifyAdjacent);
|
||||
return getExtent().setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
}
|
||||
|
73
src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java
Normal file
73
src/main/java/com/sk89q/worldedit/extent/MaskingExtent.java
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class MaskingExtent extends ExtentDelegate {
|
||||
|
||||
private Mask mask;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param mask the mask
|
||||
*/
|
||||
public MaskingExtent(Extent extent, Mask mask) {
|
||||
super(extent);
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mask.
|
||||
*
|
||||
* @return the mask
|
||||
*/
|
||||
public Mask getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a mask.
|
||||
*
|
||||
* @param mask a mask
|
||||
*/
|
||||
public void setMask(Mask mask) {
|
||||
checkNotNull(mask);
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
if (mask.test(location)) {
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.extent.reorder;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.extent.ExtentDelegate;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.OperationQueue;
|
||||
import com.sk89q.worldedit.function.visitor.BlockMapEntryVisitor;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Re-orders blocks into several stages.
|
||||
*/
|
||||
public class SimpleBlockReorder extends ExtentDelegate {
|
||||
|
||||
private DoubleArrayList<BlockVector, BaseBlock> stage1 = new DoubleArrayList<BlockVector, BaseBlock>(false);
|
||||
private DoubleArrayList<BlockVector, BaseBlock> stage2 = new DoubleArrayList<BlockVector, BaseBlock>(false);
|
||||
private DoubleArrayList<BlockVector, BaseBlock> stage3 = new DoubleArrayList<BlockVector, BaseBlock>(false);
|
||||
private boolean enabled;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param extent the extent
|
||||
* @param enabled true to enable
|
||||
*/
|
||||
public SimpleBlockReorder(Extent extent, boolean enabled) {
|
||||
super(extent);
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance when the re-ordering is enabled.
|
||||
*
|
||||
* @param extent the extent
|
||||
*/
|
||||
public SimpleBlockReorder(Extent extent) {
|
||||
this(extent, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether re-ordering is enabled.
|
||||
*
|
||||
* @return true if re-ordering is enabled
|
||||
*/
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether re-ordering is enabled.
|
||||
*
|
||||
* @param enabled true if re-ordering is enabled
|
||||
*/
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(Vector location, BaseBlock block, boolean notifyAdjacent) throws WorldEditException {
|
||||
if (!enabled) {
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
}
|
||||
|
||||
if (BlockType.shouldPlaceLast(block.getType())) {
|
||||
// Place torches, etc. last
|
||||
stage2.put(location.toBlockVector(), block);
|
||||
return !(getBlockType(location) == block.getType() && getBlockData(location) == block.getData());
|
||||
} else if (BlockType.shouldPlaceFinal(block.getType())) {
|
||||
// Place signs, reed, etc even later
|
||||
stage3.put(location.toBlockVector(), block);
|
||||
return !(getBlockType(location) == block.getType() && getBlockData(location) == block.getData());
|
||||
} else if (BlockType.shouldPlaceLast(getBlockType(location))) {
|
||||
// Destroy torches, etc. first
|
||||
super.setBlock(location, new BaseBlock(BlockID.AIR), notifyAdjacent);
|
||||
return super.setBlock(location, block, notifyAdjacent);
|
||||
} else {
|
||||
stage1.put(location.toBlockVector(), block);
|
||||
return !(getBlockType(location) == block.getType() && getBlockData(location) == block.getData());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation commitBefore() {
|
||||
return new OperationQueue(
|
||||
new BlockMapEntryVisitor(
|
||||
getExtent(),
|
||||
Iterators.concat(stage1.iterator(), stage2.iterator())),
|
||||
new Stage3Committer());
|
||||
}
|
||||
|
||||
private class Stage3Committer implements Operation {
|
||||
|
||||
@Override
|
||||
public Operation resume() throws WorldEditException {
|
||||
Extent extent = getExtent();
|
||||
|
||||
final Set<BlockVector> blocks = new HashSet<BlockVector>();
|
||||
final Map<BlockVector, BaseBlock> blockTypes = new HashMap<BlockVector, BaseBlock>();
|
||||
for (Map.Entry<BlockVector, BaseBlock> entry : stage3) {
|
||||
final BlockVector pt = entry.getKey();
|
||||
blocks.add(pt);
|
||||
blockTypes.put(pt, entry.getValue());
|
||||
}
|
||||
|
||||
while (!blocks.isEmpty()) {
|
||||
BlockVector current = blocks.iterator().next();
|
||||
if (!blocks.contains(current)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Deque<BlockVector> walked = new LinkedList<BlockVector>();
|
||||
|
||||
while (true) {
|
||||
walked.addFirst(current);
|
||||
|
||||
assert (blockTypes.containsKey(current));
|
||||
|
||||
final BaseBlock baseBlock = blockTypes.get(current);
|
||||
|
||||
final int type = baseBlock.getType();
|
||||
final int data = baseBlock.getData();
|
||||
|
||||
switch (type) {
|
||||
case BlockID.WOODEN_DOOR:
|
||||
case BlockID.IRON_DOOR:
|
||||
if ((data & 0x8) == 0) {
|
||||
// Deal with lower door halves being attached to the floor AND the upper half
|
||||
BlockVector upperBlock = current.add(0, 1, 0).toBlockVector();
|
||||
if (blocks.contains(upperBlock) && !walked.contains(upperBlock)) {
|
||||
walked.addFirst(upperBlock);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case BlockID.MINECART_TRACKS:
|
||||
case BlockID.POWERED_RAIL:
|
||||
case BlockID.DETECTOR_RAIL:
|
||||
case BlockID.ACTIVATOR_RAIL:
|
||||
// Here, rails are hardcoded to be attached to the block below them.
|
||||
// They're also attached to the block they're ascending towards via BlockType.getAttachment.
|
||||
BlockVector lowerBlock = current.add(0, -1, 0).toBlockVector();
|
||||
if (blocks.contains(lowerBlock) && !walked.contains(lowerBlock)) {
|
||||
walked.addFirst(lowerBlock);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
final PlayerDirection attachment = BlockType.getAttachment(type, data);
|
||||
if (attachment == null) {
|
||||
// Block is not attached to anything => we can place it
|
||||
break;
|
||||
}
|
||||
|
||||
current = current.add(attachment.vector()).toBlockVector();
|
||||
|
||||
if (!blocks.contains(current)) {
|
||||
// We ran outside the remaing set => assume we can place blocks on this
|
||||
break;
|
||||
}
|
||||
|
||||
if (walked.contains(current)) {
|
||||
// Cycle detected => This will most likely go wrong, but there's nothing we can do about it.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (BlockVector pt : walked) {
|
||||
extent.setBlock(pt, blockTypes.get(pt), true);
|
||||
blocks.remove(pt);
|
||||
}
|
||||
}
|
||||
|
||||
stage1.clear();
|
||||
stage2.clear();
|
||||
stage3.clear();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.function.visitor;
|
||||
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
public class BlockMapEntryVisitor implements Operation {
|
||||
|
||||
private final Extent extent;
|
||||
private final Iterator<Map.Entry<BlockVector, BaseBlock>> iterator;
|
||||
|
||||
public BlockMapEntryVisitor(Extent extent, Iterator<Map.Entry<BlockVector, BaseBlock>> iterator) {
|
||||
checkNotNull(extent);
|
||||
checkNotNull(iterator);
|
||||
this.extent = extent;
|
||||
this.iterator = iterator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation resume() throws WorldEditException {
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<BlockVector, BaseBlock> entry = iterator.next();
|
||||
extent.setBlock(entry.getKey(), entry.getValue(), true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user