From b27b6add9333804247d36249eecd72c798efa919 Mon Sep 17 00:00:00 2001 From: sk89q Date: Sat, 6 Nov 2010 14:43:56 -0700 Subject: [PATCH] Added support for random block placement with //set. Made //set faster. --- src/EditSession.java | 53 +++++++++++- src/WorldEditListener.java | 52 +++++++++++- .../sk89q/worldedit/patterns/BlockChance.java | 63 ++++++++++++++ src/com/sk89q/worldedit/patterns/Pattern.java | 40 +++++++++ .../worldedit/patterns/RandomFillPattern.java | 85 +++++++++++++++++++ .../patterns/SingleBlockPattern.java | 63 ++++++++++++++ 6 files changed, 351 insertions(+), 5 deletions(-) create mode 100644 src/com/sk89q/worldedit/patterns/BlockChance.java create mode 100644 src/com/sk89q/worldedit/patterns/Pattern.java create mode 100644 src/com/sk89q/worldedit/patterns/RandomFillPattern.java create mode 100644 src/com/sk89q/worldedit/patterns/SingleBlockPattern.java diff --git a/src/EditSession.java b/src/EditSession.java index 865c3567f..ff7fcc649 100644 --- a/src/EditSession.java +++ b/src/EditSession.java @@ -21,6 +21,7 @@ import com.sk89q.worldedit.*; import com.sk89q.worldedit.regions.*; import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.data.*; +import com.sk89q.worldedit.patterns.*; import java.io.IOException; import java.util.Map; import java.util.HashMap; @@ -515,9 +516,16 @@ public class EditSession { Vector min = region.getMinimumPoint(); Vector max = region.getMaximumPoint(); - for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { - for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { - for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + int minX = min.getBlockX(); + int minY = min.getBlockY(); + int minZ = min.getBlockZ(); + int maxX = max.getBlockX(); + int maxY = max.getBlockY(); + int maxZ = max.getBlockZ(); + + for (int x = minX; x <= maxX; x++) { + for (int y = minY; y <= maxY; y++) { + for (int z = minZ; z <= maxZ; z++) { Vector pt = new Vector(x, y, z); if (setBlock(pt, block)) { @@ -537,6 +545,45 @@ public class EditSession { return affected; } + /** + * Sets all the blocks inside a region to a certain block type. + * + * @param region + * @param block + * @return number of blocks affected + * @throws MaxChangedBlocksException + */ + public int setBlocks(Region region, Pattern pattern) + throws MaxChangedBlocksException { + int affected = 0; + + if (region instanceof CuboidRegion) { + // Doing this for speed + Vector min = region.getMinimumPoint(); + Vector max = region.getMaximumPoint(); + + for (int x = min.getBlockX(); x <= max.getBlockX(); x++) { + for (int y = min.getBlockY(); y <= max.getBlockY(); y++) { + for (int z = min.getBlockZ(); z <= max.getBlockZ(); z++) { + Vector pt = new Vector(x, y, z); + + if (setBlock(pt, pattern.next(pt))) { + affected++; + } + } + } + } + } else { + for (Vector pt : region) { + if (setBlock(pt, pattern.next(pt))) { + affected++; + } + } + } + + return affected; + } + /** * Replaces all the blocks of a type inside a region to another block type. * diff --git a/src/WorldEditListener.java b/src/WorldEditListener.java index 6c4e0c323..28cefa0ce 100644 --- a/src/WorldEditListener.java +++ b/src/WorldEditListener.java @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +import java.util.List; +import java.util.ArrayList; import java.util.Map; import java.util.HashMap; import java.util.Set; @@ -31,6 +33,7 @@ import com.sk89q.worldedit.blocks.*; import com.sk89q.worldedit.data.*; import com.sk89q.worldedit.snapshots.*; import com.sk89q.worldedit.regions.*; +import com.sk89q.worldedit.patterns.*; /** * Plugin base. @@ -267,8 +270,47 @@ public class WorldEditListener extends PluginListener { return getBlock(id, false); } + /** + * Get a list of blocks as a set. This returns a Pattern. + * + * @param list + * @return pattern + */ + public Pattern getBlockPattern(String list) + throws UnknownItemException, DisallowedItemException { + + String[] items = list.split(","); + + if (items.length == 1) { + return new SingleBlockPattern(getBlock(items[0])); + } + + List blockChances = new ArrayList(); + + for (String s : items) { + BaseBlock block; + + double chance; + if (s.matches("[0-9]+(?:\\.(?:[0-9]+)?)?%.*")) { + String[] p = s.split("%"); + chance = Double.parseDouble(p[0]); + block = getBlock(p[1]); + } else { + chance = 1; + block = getBlock(s); + } + + blockChances.add(new BlockChance(block, chance)); + } + + return new RandomFillPattern(blockChances); + } + /** * Get a list of blocks as a set. + * + * @param list + * @return set */ public Set getBlockIDs(String list) throws UnknownItemException, DisallowedItemException { @@ -723,8 +765,14 @@ public class WorldEditListener extends PluginListener { // Replace all blocks in the region } else if(split[0].equalsIgnoreCase("//set")) { checkArgs(split, 1, 1, split[0]); - BaseBlock block = getBlock(split[1]); - int affected = editSession.setBlocks(session.getRegion(), block); + Pattern pattern = getBlockPattern(split[1]); + int affected; + if (pattern instanceof SingleBlockPattern) { + affected = editSession.setBlocks(session.getRegion(), + ((SingleBlockPattern)pattern).getBlock()); + } else { + affected = editSession.setBlocks(session.getRegion(), pattern); + } player.print(affected + " block(s) have been changed."); return true; diff --git a/src/com/sk89q/worldedit/patterns/BlockChance.java b/src/com/sk89q/worldedit/patterns/BlockChance.java new file mode 100644 index 000000000..e28e80e97 --- /dev/null +++ b/src/com/sk89q/worldedit/patterns/BlockChance.java @@ -0,0 +1,63 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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 . +*/ + +package com.sk89q.worldedit.patterns; + +import com.sk89q.worldedit.blocks.BaseBlock; + +/** + * Gives a block a chance. + * + * @author sk89q + */ +public class BlockChance { + /** + * Block. + */ + private BaseBlock block; + /** + * Chance. Can be any positive value. + */ + private double chance; + + /** + * Construct the object. + * + * @param block + * @param chance + */ + public BlockChance(BaseBlock block, double chance) { + this.block = block; + this.chance = chance; + } + + /** + * @return the block + */ + public BaseBlock getBlock() { + return block; + } + + /** + * @return the chance + */ + public double getChance() { + return chance; + } +} diff --git a/src/com/sk89q/worldedit/patterns/Pattern.java b/src/com/sk89q/worldedit/patterns/Pattern.java new file mode 100644 index 000000000..d5d84e4c6 --- /dev/null +++ b/src/com/sk89q/worldedit/patterns/Pattern.java @@ -0,0 +1,40 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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 . +*/ + +package com.sk89q.worldedit.patterns; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BaseBlock; + +/** + * Used to get the block to set. This can be used to implement a pattern + * for when setting a region with blocks. + * + * @author sk89q + */ +public interface Pattern { + /** + * Get a block for a position. This return value of this method does + * not have to be consistent for the same position. + * + * @param pos + * @return + */ + public BaseBlock next(Vector pos); +} diff --git a/src/com/sk89q/worldedit/patterns/RandomFillPattern.java b/src/com/sk89q/worldedit/patterns/RandomFillPattern.java new file mode 100644 index 000000000..765134e79 --- /dev/null +++ b/src/com/sk89q/worldedit/patterns/RandomFillPattern.java @@ -0,0 +1,85 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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 . +*/ + +package com.sk89q.worldedit.patterns; + +import java.util.Random; +import java.util.List; +import java.util.ArrayList; +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BaseBlock; + +/** + * Pattern proportionally fills. + * + * @author sk89q + */ +public class RandomFillPattern implements Pattern { + /** + * Random number generator. + */ + private static final Random random = new Random(); + /** + * Blocks and their proportions. + */ + private List blocks; + + /** + * Construct the object. + * + * @param blockType + */ + public RandomFillPattern(List blocks) { + double max = 0; + + for (BlockChance block : blocks) { + max += block.getChance(); + } + + List finalBlocks = new ArrayList(); + + double i = 0; + + for (BlockChance block : blocks) { + double v = block.getChance() / max; + i += v; + finalBlocks.add(new BlockChance(block.getBlock(), i)); + } + + this.blocks = finalBlocks; + } + + /** + * Get next block. + * + * @param pos + * @return + */ + public BaseBlock next(Vector pos) { + double r = random.nextDouble(); + + for (BlockChance block : blocks) { + if (r <= block.getChance()) { + return block.getBlock(); + } + } + + throw new RuntimeException("ProportionalFillPattern"); + } +} diff --git a/src/com/sk89q/worldedit/patterns/SingleBlockPattern.java b/src/com/sk89q/worldedit/patterns/SingleBlockPattern.java new file mode 100644 index 000000000..8bc996574 --- /dev/null +++ b/src/com/sk89q/worldedit/patterns/SingleBlockPattern.java @@ -0,0 +1,63 @@ +// $Id$ +/* + * WorldEdit + * Copyright (C) 2010 sk89q + * + * 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 . +*/ + +package com.sk89q.worldedit.patterns; + +import com.sk89q.worldedit.*; +import com.sk89q.worldedit.blocks.BaseBlock; + +/** + * Always returns the same block type. + * + * @author sk89q + */ +public class SingleBlockPattern implements Pattern { + /** + * Block type. + */ + private BaseBlock block; + + /** + * Construct the object. + * + * @param blockType + */ + public SingleBlockPattern(BaseBlock block) { + this.block = block; + } + + /** + * Get next block. + * + * @param pos + * @return + */ + public BaseBlock next(Vector pos) { + return block; + } + + /** + * Get the block. + * + * @return + */ + public BaseBlock getBlock() { + return block; + } +}