Moved packages to worldedit.function.*.

This commit is contained in:
sk89q
2014-03-28 16:15:40 -07:00
parent 60b839ed09
commit 53730bfa20
19 changed files with 50 additions and 46 deletions

View File

@ -0,0 +1,39 @@
/*
* 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;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
/**
* Performs a function on points in a flat region.
*/
public interface FlatRegionFunction {
/**
* Apply the function to the given point.
*
* @param pt the point
* @return true if something was changed
* @throws WorldEditException thrown on an error
*/
public boolean apply(Vector2D pt) throws WorldEditException;
}

View File

@ -0,0 +1,62 @@
/*
* 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;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.masks.Mask2D;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Passes calls to {@link #apply(com.sk89q.worldedit.Vector2D)} to the
* delegate {@link com.sk89q.worldedit.function.FlatRegionFunction} if they
* match the given mask.
*/
public class FlatRegionMaskingFilter implements FlatRegionFunction {
private final EditSession editSession;
private final FlatRegionFunction function;
private Mask2D mask;
/**
* Create a new masking filter.
*
* @param editSession the edit session
* @param mask the mask
* @param function the delegate function to call
*/
public FlatRegionMaskingFilter(EditSession editSession, Mask2D mask, FlatRegionFunction function) {
checkNotNull(function);
checkNotNull(editSession);
checkNotNull(mask);
this.editSession = editSession;
this.mask = mask;
this.function = function;
}
@Override
public boolean apply(Vector2D position) throws WorldEditException {
return mask.matches(editSession, position) && function.apply(position);
}
}

View File

@ -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.function;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.regions.search.GroundSearch;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Accepts 2D coordinates to columns, finds the first ground block in each
* column, and applies the given {@link RegionFunction} onto the ground blocks.
*/
public class GroundFunction implements FlatRegionFunction {
private final RegionFunction function;
private GroundSearch groundSearch;
private int minY;
private int maxY;
/**
* Create a new instance.
*
* @param groundSearch the ground search implementation
* @param minY the minimum Y (inclusive)
* @param maxY the maximum Y (inclusive)
* @param function the function to apply on ground blocks
*/
public GroundFunction(GroundSearch groundSearch, int minY, int maxY, RegionFunction function) {
checkNotNull(function);
checkNotNull(groundSearch);
checkArgument(minY <= maxY, "minY <= maxY required");
this.function = function;
this.groundSearch = groundSearch;
this.minY = minY;
this.maxY = maxY;
}
@Override
public boolean apply(Vector2D pt) throws WorldEditException {
Vector ground = groundSearch.findGround(pt.toVector(maxY), minY);
return ground != null && function.apply(ground);
}
}

View File

@ -0,0 +1,39 @@
/*
* 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;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
/**
* Performs a function on points in a region.
*/
public interface RegionFunction {
/**
* Apply the function to the given position.
*
* @param position the position
* @return true if something was changed
* @throws WorldEditException thrown on an error
*/
public boolean apply(Vector position) throws WorldEditException;
}

View File

@ -0,0 +1,62 @@
/*
* 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;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.masks.Mask;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Passes calls to {@link #apply(com.sk89q.worldedit.Vector)} to the
* delegate {@link com.sk89q.worldedit.function.RegionFunction} if they
* match the given mask.
*/
public class RegionMaskingFilter implements RegionFunction {
private final EditSession editSession;
private final RegionFunction function;
private Mask mask;
/**
* Create a new masking filter.
*
* @param editSession the edit session
* @param mask the mask
* @param function the function
*/
public RegionMaskingFilter(EditSession editSession, Mask mask, RegionFunction function) {
checkNotNull(function);
checkNotNull(editSession);
checkNotNull(mask);
this.editSession = editSession;
this.mask = mask;
this.function = function;
}
@Override
public boolean apply(Vector position) throws WorldEditException {
return mask.matches(editSession, position) && function.apply(position);
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.block;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
/**
* Counts the number of blocks.
*/
public class BlockCount implements RegionFunction {
private int count;
/**
* Returns the number of blocks that have been counted.
*
* @return the number of blocks
*/
public int getCount() {
return count;
}
@Override
public boolean apply(Vector position) throws WorldEditException {
count++;
return false;
}
}

View File

@ -0,0 +1,52 @@
/*
* 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.block;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.patterns.Pattern;
/**
* Replaces blocks with the given pattern.
*/
public class BlockReplace implements RegionFunction {
private final EditSession editSession;
private Pattern pattern;
/**
* Create a new instance.
*
* @param editSession the edit session
* @param pattern a pattern
*/
public BlockReplace(EditSession editSession, Pattern pattern) {
this.editSession = editSession;
this.pattern = pattern;
}
@Override
public boolean apply(Vector position) throws WorldEditException {
return editSession.setBlock(position, pattern.next(position));
}
}

View File

@ -0,0 +1,123 @@
/*
* 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.generator;
import com.sk89q.worldedit.EditSession;
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.function.RegionFunction;
import com.sk89q.worldedit.patterns.BlockChance;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.RandomFillPattern;
import java.util.ArrayList;
import java.util.List;
/**
* Generates flora (which may include tall grass, flowers, etc.).
* <p>
* The current implementation is not biome-aware, but it may become so in
* the future.
*/
public class FloraGenerator implements RegionFunction {
private final EditSession editSession;
private boolean biomeAware = false;
private final Pattern desertPattern = getDesertPattern();
private final Pattern temperatePattern = getTemperatePattern();
/**
* Create a new flora generator.
*
* @param editSession the edit session
*/
public FloraGenerator(EditSession editSession) {
this.editSession = editSession;
}
/**
* Return whether the flora generator is set to be biome-aware.
* <p>
* By default, it is currently disabled by default, but this may change.
*
* @return true if biome aware
*/
public boolean isBiomeAware() {
return biomeAware;
}
/**
* Set whether the generator is biome aware.
* <p>
* It is currently not possible to make the generator biome-aware.
*
* @param biomeAware must always be false
*/
public void setBiomeAware(boolean biomeAware) {
if (biomeAware) {
throw new IllegalArgumentException("Cannot enable biome-aware mode; not yet implemented");
}
this.biomeAware = biomeAware;
}
/**
* Get a pattern for plants to place inside a desert environment.
*
* @return a pattern that places flora
*/
public static Pattern getDesertPattern() {
List<BlockChance> chance = new ArrayList<BlockChance>();
chance.add(new BlockChance(new BaseBlock(BlockID.DEAD_BUSH), 30));
chance.add(new BlockChance(new BaseBlock(BlockID.CACTUS), 20));
chance.add(new BlockChance(new BaseBlock(BlockID.AIR), 300));
return new RandomFillPattern(chance);
}
/**
* Get a pattern for plants to place inside a temperate environment.
*
* @return a pattern that places flora
*/
public static Pattern getTemperatePattern() {
List<BlockChance> chance = new ArrayList<BlockChance>();
chance.add(new BlockChance(new BaseBlock(BlockID.LONG_GRASS, 1), 300));
chance.add(new BlockChance(new BaseBlock(BlockID.RED_FLOWER), 5));
chance.add(new BlockChance(new BaseBlock(BlockID.YELLOW_FLOWER), 5));
return new RandomFillPattern(chance);
}
@Override
public boolean apply(Vector position) throws WorldEditException {
BaseBlock block = editSession.getBlock(position);
if (block.getType() == BlockID.GRASS) {
editSession.setBlock(position.add(0, 1, 0), temperatePattern.next(position));
return true;
} else if (block.getType() == BlockID.SAND) {
editSession.setBlock(position.add(0, 1, 0), desertPattern.next(position));
return true;
}
return false;
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.generator;
import com.sk89q.worldedit.EditSession;
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.function.RegionFunction;
import com.sk89q.worldedit.util.TreeGenerator;
/**
* Generates forests by searching for the ground starting from the given upper Y
* coordinate for every column given.
*/
public class ForestGenerator implements RegionFunction {
private final TreeGenerator treeGenerator;
private final EditSession editSession;
/**
* Create a new instance.
*
* @param editSession the edit session
* @param treeGenerator a tree generator
*/
public ForestGenerator(EditSession editSession, TreeGenerator treeGenerator) {
this.editSession = editSession;
this.treeGenerator = treeGenerator;
}
@Override
public boolean apply(Vector position) throws WorldEditException {
BaseBlock block = editSession.getBlock(position);
int t = block.getType();
if (t == BlockID.GRASS || t == BlockID.DIRT) {
treeGenerator.generate(editSession, position.add(0, 1, 0));
return true;
} else if (t == BlockID.SNOW) {
editSession.setBlock(position, new BaseBlock(BlockID.AIR));
return false;
} else { // Trees won't grow on this!
return false;
}
}
}

View File

@ -0,0 +1,203 @@
/*
* 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.generator;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
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.function.RegionFunction;
import com.sk89q.worldedit.patterns.BlockChance;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.patterns.RandomFillPattern;
import com.sk89q.worldedit.patterns.SingleBlockPattern;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class GardenPatchGenerator implements RegionFunction {
private final Random random = new Random();
private final EditSession editSession;
private Pattern plant = getPumpkinPattern();
private int affected;
/**
* Create a new instance.
*
* @param editSession the edit session
*/
public GardenPatchGenerator(EditSession editSession) {
this.editSession = editSession;
}
/**
* Get the plant pattern that is placed.
*
* @return the plant pattern
*/
public Pattern getPlant() {
return plant;
}
/**
* Set the plant pattern that is placed.
*
* @param plant the plant pattern
*/
public void setPlant(Pattern plant) {
this.plant = plant;
}
/**
* Get the number of affected blocks.
*
* @return affected count
*/
public int getAffected() {
return affected;
}
/**
* Make a patch vine.
*
* @param basePos the base position
* @param pos the vine position
*/
private void placeVine(Vector basePos, Vector pos) throws MaxChangedBlocksException {
if (pos.distance(basePos) > 4) return;
if (editSession.getBlockType(pos) != 0) return;
for (int i = -1; i > -3; --i) {
Vector testPos = pos.add(0, i, 0);
if (editSession.getBlockType(testPos) == BlockID.AIR) {
pos = testPos;
} else {
break;
}
}
editSession.setBlockIfAir(pos, new BaseBlock(BlockID.LEAVES));
affected++;
int t = random.nextInt(4);
int h = random.nextInt(3) - 1;
Vector p;
BaseBlock log = new BaseBlock(BlockID.LOG);
switch (t) {
case 0:
if (random.nextBoolean()) {
placeVine(basePos, pos.add(1, 0, 0));
}
if (random.nextBoolean()) {
editSession.setBlockIfAir(pos.add(1, h, -1), log);
affected++;
}
editSession.setBlockIfAir(p = pos.add(0, 0, -1), plant.next(p));
affected++;
break;
case 1:
if (random.nextBoolean()) {
placeVine(basePos, pos.add(0, 0, 1));
}
if (random.nextBoolean()) {
editSession.setBlockIfAir(pos.add(1, h, 0), log);
affected++;
}
editSession.setBlockIfAir(p = pos.add(1, 0, 1), plant.next(p));
affected++;
break;
case 2:
if (random.nextBoolean()) {
placeVine(basePos, pos.add(0, 0, -1));
}
if (random.nextBoolean()) {
editSession.setBlockIfAir(pos.add(-1, h, 0), log);
affected++;
}
editSession.setBlockIfAir(p = pos.add(-1, 0, 1), plant.next(p));
affected++;
break;
case 3:
if (random.nextBoolean()) {
placeVine(basePos, pos.add(-1, 0, 0));
}
if (random.nextBoolean()) {
editSession.setBlockIfAir(pos.add(-1, h, -1), log);
affected++;
}
editSession.setBlockIfAir(p = pos.add(-1, 0, -1), plant.next(p));
affected++;
break;
}
}
@Override
public boolean apply(Vector position) throws WorldEditException {
if (editSession.getBlock(position).getType() != BlockID.AIR) {
position = position.add(0, 1, 0);
}
if (editSession.getBlock(position.add(0, -1, 0)).getType() != BlockID.GRASS) {
return false;
}
BaseBlock leavesBlock = new BaseBlock(BlockID.LEAVES);
editSession.setBlockIfAir(position, leavesBlock);
placeVine(position, position.add(0, 0, 1));
placeVine(position, position.add(0, 0, -1));
placeVine(position, position.add(1, 0, 0));
placeVine(position, position.add(-1, 0, 0));
return true;
}
/**
* Get a pattern that creates pumpkins with different faces.
*
* @return a pumpkin pattern
*/
public static Pattern getPumpkinPattern() {
List<BlockChance> chance = new ArrayList<BlockChance>();
for (int i = 0; i < 4; i++) {
chance.add(new BlockChance(new BaseBlock(BlockID.PUMPKIN, i), 100));
}
return new RandomFillPattern(chance);
}
/**
* Get a pattern that creates melons.
*
* @return a melon pattern
*/
public static Pattern getMelonPattern() {
return new SingleBlockPattern(new BaseBlock(BlockID.MELON_BLOCK));
}
}

View File

@ -0,0 +1,49 @@
/*
* 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.operation;
import com.sk89q.worldedit.WorldEditException;
/**
* An task that may be split into multiple steps to be run sequentially immediately
* or at a varying or fixed interval. Operations should attempt to break apart tasks
* into smaller tasks that can be completed in quicker successions.
*/
public interface Operation {
/**
* Complete the next step. If this method returns true, then the method may be
* called again in the future, or possibly never. If this method returns false,
* then this method should not be called again.
*
* @return another operation to run that operation again, or null to stop
* @throws WorldEditException an error
*/
Operation resume() throws WorldEditException;
/**
* Abort the current task. After the this method is called, {@link #resume()} should
* not be called at any point in the future. This method should not be called after
* successful completion of the operation. This method must be called if
* the operation is interrupted before completion.
*/
void cancel();
}

View File

@ -0,0 +1,81 @@
/*
* 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.operation;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.WorldEditException;
/**
* Operation helper methods.
*/
public final class OperationHelper {
private OperationHelper() {
}
/**
* Complete a given operation synchronously until it completes.
*
* @param op operation to execute
* @throws WorldEditException WorldEdit exception
*/
public static void complete(Operation op) throws WorldEditException {
while (op != null) {
op = op.resume();
}
}
/**
* Complete a given operation synchronously until it completes. Catch all
* errors that is not {@link MaxChangedBlocksException} for legacy reasons.
*
* @param op operation to execute
* @throws MaxChangedBlocksException thrown when too many blocks have been changed
*/
public static void completeLegacy(Operation op) throws MaxChangedBlocksException {
while (op != null) {
try {
op = op.resume();
} catch (MaxChangedBlocksException e) {
throw e;
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}
}
/**
* Complete a given operation synchronously until it completes. Re-throw all
* {@link com.sk89q.worldedit.WorldEditException} exceptions as
* {@link java.lang.RuntimeException}s.
*
* @param op operation to execute
*/
public static void completeBlindly(Operation op) {
while (op != null) {
try {
op = op.resume();
} catch (WorldEditException e) {
throw new RuntimeException(e);
}
}
}
}

View File

@ -0,0 +1,174 @@
/*
* 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.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.RegionFunction;
import java.util.*;
/**
* Performs a breadth-first search starting from points added with
* {@link #visit(com.sk89q.worldedit.Vector)}. The search continues
* to a certain adjacent point provided that the method
* {@link #isVisitable(com.sk89q.worldedit.Vector, com.sk89q.worldedit.Vector)}
* returns true for that point.
* </p>
* As an abstract implementation, this class can be used to implement
* functionality that starts at certain points and extends outward from
* those points.
*/
public abstract class BreadthFirstSearch implements Operation {
private final RegionFunction function;
private final Queue<BlockVector> queue = new ArrayDeque<BlockVector>();
private final Set<BlockVector> visited = new HashSet<BlockVector>();
private final List<Vector> directions = new ArrayList<Vector>();
private int affected = 0;
/**
* Create a new instance.
*
* @param function the function to apply to visited blocks
*/
public BreadthFirstSearch(RegionFunction function) {
this.function = function;
addAxes();
}
/**
* Get the list of directions will be visited.
* </p>
* Directions are {@link com.sk89q.worldedit.Vector}s that determine
* what adjacent points area available. Vectors should not be
* unit vectors. An example of a valid direction is {@code new Vector(1, 0, 1)}.
* </p>
* The list of directions can be cleared.
*
* @return the list of directions
*/
protected List<Vector> getDirections() {
return directions;
}
/**
* Add the directions along the axes as directions to visit.
*/
protected void addAxes() {
directions.add(new Vector(0, -1, 0));
directions.add(new Vector(0, 1, 0));
directions.add(new Vector(-1, 0, 0));
directions.add(new Vector(1, 0, 0));
directions.add(new Vector(0, 0, -1));
directions.add(new Vector(0, 0, 1));
}
/**
* Add the diagonal directions as directions to visit.
*/
protected void addDiagonal() {
directions.add(new Vector(1, 0, 1));
directions.add(new Vector(-1, 0, -1));
directions.add(new Vector(1, 0, -1));
directions.add(new Vector(-1, 0, 1));
}
/**
* Add the given location to the list of locations to visit, provided
* that it has not been visited. The position passed to this method
* will still be visited even if it fails
* {@link #isVisitable(com.sk89q.worldedit.Vector, com.sk89q.worldedit.Vector)}.
* </p>
* This method should be used before the search begins, because if
* the position <em>does</em> fail the test, and the search has already
* visited it (because it is connected to another root point),
* the search will mark the position as "visited" and a call to this
* method will do nothing.
*
* @param position the position
*/
public void visit(Vector position) {
BlockVector blockVector = position.toBlockVector();
if (!visited.contains(blockVector)) {
queue.add(blockVector);
visited.add(blockVector);
}
}
/**
* Try to visit the given 'to' location.
*
* @param from the origin block
* @param to the block under question
*/
private void visit(Vector from, Vector to) {
BlockVector blockVector = to.toBlockVector();
if (!visited.contains(blockVector)) {
visited.add(blockVector);
if (isVisitable(from, to)) {
queue.add(blockVector);
}
}
}
/**
* Return whether the given 'to' block should be visited, starting from the
* 'from' block.
*
* @param from the origin block
* @param to the block under question
* @return true if the 'to' block should be visited
*/
protected abstract boolean isVisitable(Vector from, Vector to);
/**
* Get the number of affected objects.
*
* @return the number of affected
*/
public int getAffected() {
return affected;
}
@Override
public Operation resume() throws WorldEditException {
Vector position;
while ((position = queue.poll()) != null) {
if (function.apply(position)) {
affected++;
}
for (Vector dir : directions) {
visit(position, position.add(dir));
}
}
return null;
}
@Override
public void cancel() {
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.function.RegionFunction;
import java.util.List;
/**
* Visits adjacent points on the same X-Z plane as long as the points
* pass the given mask, and then executes the provided region
* function on the entire column.
* </p>
* This is used by <code>//fill</code>.
*/
public class DownwardVisitor extends RecursiveVisitor {
private int baseY;
/**
* Create a new visitor.
*
* @param editSession the edit session
* @param mask the mask
* @param function the function
* @param baseY the base Y
*/
public DownwardVisitor(EditSession editSession, Mask mask, RegionFunction function, int baseY) {
super(editSession, mask, function);
this.baseY = baseY;
List<Vector> directions = getDirections();
directions.clear();
directions.add(new Vector(1, 0, 0));
directions.add(new Vector(-1, 0, 0));
directions.add(new Vector(0, 0, 1));
directions.add(new Vector(0, 0, -1));
directions.add(new Vector(0, -1, 0));
}
@Override
protected boolean isVisitable(Vector from, Vector to) {
int fromY = from.getBlockY();
return (fromY == baseY || to.subtract(from).getBlockY() < 0) && super.isVisitable(from, to);
}
}

View File

@ -0,0 +1,74 @@
/*
* 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.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.FlatRegionFunction;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.FlatRegion;
import com.sk89q.worldedit.regions.Region;
/**
* Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}.
*/
public class FlatRegionVisitor implements Operation {
private final FlatRegion flatRegion;
private final FlatRegionFunction function;
private int affected = 0;
public FlatRegionVisitor(Region region, FlatRegionFunction function) {
this.function = function;
if (region instanceof FlatRegion) {
flatRegion = (FlatRegion) region;
} else {
flatRegion = CuboidRegion.makeCuboid(region);
}
}
/**
* Get the number of affected objects.
*
* @return the number of affected
*/
public int getAffected() {
return affected;
}
@Override
public Operation resume() throws WorldEditException {
for (Vector2D pt : flatRegion.asFlatRegion()) {
if (function.apply(pt)) {
affected++;
}
}
return null;
}
@Override
public void cancel() {
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.masks.Mask;
import com.sk89q.worldedit.function.RegionFunction;
/**
* An implementation of an {@link BreadthFirstSearch} that uses a mask to
* determine where a block should be visited.
*/
public class RecursiveVisitor extends BreadthFirstSearch {
private final EditSession editSession;
private final Mask mask;
public RecursiveVisitor(EditSession editSession, Mask mask, RegionFunction function) {
super(function);
this.editSession = editSession;
this.mask = mask;
}
@Override
protected boolean isVisitable(Vector from, Vector to) {
int y = to.getBlockY();
if (y < 0 || y > editSession.getWorld().getMaxY()) {
return false;
}
return mask.matches(editSession, to);
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.regions.Region;
/**
* Utility class to apply region functions to {@link com.sk89q.worldedit.regions.Region}.
*/
public class RegionVisitor implements Operation {
private final Region region;
private final RegionFunction function;
private int affected = 0;
public RegionVisitor(Region region, RegionFunction function) {
this.region = region;
this.function = function;
}
/**
* Get the number of affected objects.
*
* @return the number of affected
*/
public int getAffected() {
return affected;
}
@Override
public Operation resume() throws WorldEditException {
for (Vector pt : region) {
if (function.apply(pt)) {
affected++;
}
}
return null;
}
@Override
public void cancel() {
}
}