Various minor
cfi smooth image command fix perm typo fix mask typo fix random offset transform
This commit is contained in:
parent
85ff1967d7
commit
f8199a3b43
@ -405,9 +405,17 @@ public class FaweBukkit implements IFawe, Listener {
|
||||
// }
|
||||
// }
|
||||
|
||||
private boolean runChunkLoad = false;
|
||||
|
||||
@EventHandler
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
if (runChunkLoad) return;
|
||||
try {
|
||||
runChunkLoad = true;
|
||||
SetQueue.IMP.runMiscTasks();
|
||||
} finally {
|
||||
runChunkLoad = false;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.collection.LocalBlockVector2DSet;
|
||||
import com.boydti.fawe.object.collection.SummedAreaTable;
|
||||
import com.boydti.fawe.object.schematic.Schematic;
|
||||
import com.boydti.fawe.util.CachedTextureUtil;
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
@ -44,7 +45,7 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
|
||||
|
||||
private final Int2ObjectOpenHashMap<char[][][]> blocks = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
private final byte[] heights;
|
||||
public final byte[] heights;
|
||||
private final byte[] biomes;
|
||||
private final char[] floor;
|
||||
private final char[] main;
|
||||
@ -101,6 +102,72 @@ public class HeightMapMCAGenerator extends MCAWriter implements Extent {
|
||||
this.textureUtil = textureUtil;
|
||||
}
|
||||
|
||||
public void smooth(BufferedImage img, boolean white, int radius, int iterations) {
|
||||
smooth(img, null, white, radius, iterations);
|
||||
}
|
||||
|
||||
public void smooth(Mask mask, int radius, int iterations) {
|
||||
smooth(null, mask, false, radius, iterations);
|
||||
}
|
||||
|
||||
private void smooth(BufferedImage img, Mask mask, boolean white, int radius, int iterations) {
|
||||
char snow = 78 << 4;
|
||||
long[] copy = new long[heights.length];
|
||||
char[] layers = new char[heights.length];
|
||||
int width = getWidth();
|
||||
int length = getLength();
|
||||
SummedAreaTable table = new SummedAreaTable(copy, layers, width, radius);
|
||||
for (int j = 0; j < iterations; j++) {
|
||||
for (int i = 0; i < heights.length; i++) {
|
||||
char combined = floor[i];
|
||||
int id = combined >> 4;
|
||||
if (id == 78 || id == 80) {
|
||||
layers[i] = (char) (((heights[i] & 0xFF) << 3) + (floor[i] & 0x7) + 1);
|
||||
} else {
|
||||
layers[i] = (char) (((heights[i] & 0xFF) << 3) + 8);
|
||||
}
|
||||
}
|
||||
int index = 0;
|
||||
table.processSummedAreaTable();
|
||||
if (img != null) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
int height = img.getRGB(x, z) & 0xFF;
|
||||
if (height == 255 || height > 0 && !white && PseudoRandom.random.nextInt(256) <= height) {
|
||||
int newHeight = table.average(x, z, index);
|
||||
int blockHeight = (newHeight - 1) >> 3;
|
||||
int layerHeight = (newHeight - 1) & 0x7;
|
||||
heights[index] = (byte) blockHeight;
|
||||
int id = floor[index] >> 4;
|
||||
if (id == 78 || id == 80) {
|
||||
floor[index] = (char) (snow + layerHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (mask != null) {
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
mutable.mutZ(z);
|
||||
for (int x = 0; x < getWidth(); x++, index++) {
|
||||
int y = heights[index] & 0xFF;
|
||||
mutable.mutX(x);
|
||||
mutable.mutY(y);
|
||||
if (mask.test(mutable)) {
|
||||
int height = table.average(x, z, index);
|
||||
int blockHeight = (height - 1) >> 3;
|
||||
int layerHeight = (height - 1) & 0x7;
|
||||
heights[index] = (byte) blockHeight;
|
||||
int id = floor[index] >> 4;
|
||||
if (id == 78 || id == 80) {
|
||||
floor[index] = (char) (snow + layerHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setHeight(BufferedImage img) {
|
||||
int index = 0;
|
||||
for (int z = 0; z < getLength(); z++) {
|
||||
|
@ -0,0 +1,93 @@
|
||||
package com.boydti.fawe.object.collection;
|
||||
|
||||
import com.boydti.fawe.util.MathMan;
|
||||
|
||||
public class SummedAreaTable {
|
||||
private final char[] source;
|
||||
private final long[] summed;
|
||||
private final int length;
|
||||
private final int width;
|
||||
private final int area;
|
||||
private final int radius;
|
||||
private final float areaInverse;
|
||||
|
||||
public SummedAreaTable(long[] buffer, char[] matrix, int width, int radius) {
|
||||
this.source = matrix;
|
||||
this.summed = buffer;
|
||||
this.width = width;
|
||||
this.length = buffer.length / width;
|
||||
this.radius = radius;
|
||||
this.area = MathMan.sqr(radius * 2 + 1);
|
||||
this.areaInverse = 1f/area;
|
||||
}
|
||||
|
||||
public void processSummedAreaTable() {
|
||||
int rowSize = source.length / width;
|
||||
int colSize = width;
|
||||
int index = 0;
|
||||
for (int i=0; i<rowSize; i++) {
|
||||
for (int j=0; j<colSize; j++, index++) {
|
||||
summed[index] = getVal(i, j, index, source[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private long getSum(int index) {
|
||||
if (index < 0) return 0;
|
||||
return summed[index];
|
||||
}
|
||||
|
||||
public int average(int x, int z, int index) {
|
||||
long centerHeight = source[index];
|
||||
int minX = Math.max(0, x - radius) - x;
|
||||
int minZ = Math.max(0, z - radius) - z;
|
||||
int maxX = Math.min(width - 1, x + radius) - x;
|
||||
int maxZ = Math.min(length - 1, z + radius) - z;
|
||||
int maxzw = maxZ * width;
|
||||
int XZ = index + maxzw + maxX;
|
||||
int area = (maxX - minX + 1) * (maxZ - minZ + 1);
|
||||
|
||||
long total = getSum(XZ);
|
||||
|
||||
int minzw = minZ * width;
|
||||
int Z = index + minzw + maxX;
|
||||
if (x > radius) {
|
||||
int X = index + minX + maxzw;
|
||||
int M = index + minzw + minX;
|
||||
total -= summed[X - 1];
|
||||
total += getSum(M - width - 1);
|
||||
}
|
||||
total -= getSum(Z - width);
|
||||
if (area == this.area) {
|
||||
return (int) (total * areaInverse);
|
||||
} else {
|
||||
return MathMan.lossyFastDivide((int) total, area);
|
||||
}
|
||||
}
|
||||
|
||||
private long getVal(int row, int col, int index, long curr) {
|
||||
long leftSum; // sub matrix sum of left matrix
|
||||
long topSum; // sub matrix sum of top matrix
|
||||
long topLeftSum; // sub matrix sum of top left matrix
|
||||
/* top left value is itself */
|
||||
if (index == 0) {
|
||||
return curr;
|
||||
}
|
||||
/* top row */
|
||||
else if (row == 0 && col != 0) {
|
||||
leftSum = summed[index - 1];
|
||||
return curr + leftSum;
|
||||
}
|
||||
/* left-most column */
|
||||
else if (row !=0 && col == 0) {
|
||||
topSum = summed[index - width];
|
||||
return curr + topSum;
|
||||
}
|
||||
else {
|
||||
leftSum = summed[index - 1];
|
||||
topSum = summed[index - width];
|
||||
topLeftSum = summed[index - width - 1]; // overlap between leftSum and topSum
|
||||
return curr + leftSum + topSum - topLeftSum;
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ public class RandomOffsetTransform extends ResettableExtent {
|
||||
public boolean setBiome(Vector2D pos, BaseBiome biome) {
|
||||
int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx;
|
||||
int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz;
|
||||
return super.setBiome(mutable.setComponents(x, z), biome);
|
||||
return getExtent().setBiome(mutable.setComponents(x, z), biome);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -34,7 +34,7 @@ public class RandomOffsetTransform extends ResettableExtent {
|
||||
int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx;
|
||||
int y = pos.getBlockY() + random.nextInt(1 + (dy << 1)) - dy;
|
||||
int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz;
|
||||
return super.setBlock(x, y, z, block);
|
||||
return getExtent().setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -42,7 +42,7 @@ public class RandomOffsetTransform extends ResettableExtent {
|
||||
x = x + random.nextInt(1 + (dx << 1)) - dx;
|
||||
y = y + random.nextInt(1 + (dy << 1)) - dy;
|
||||
z = z + random.nextInt(1 + (dz << 1)) - dz;
|
||||
return super.setBlock(x, y, z, block);
|
||||
return getExtent().setBlock(x, y, z, block);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -149,6 +149,7 @@ public class CreateFromImage extends Command {
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi ore[s]");
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi schem [url] <mask> <schem> <rarity> <distance> <rotate>");
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi height <image-url|height>");
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi smooth <url|mask> <radius> <iterations> [whiteonly]");
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi waterHeight <height>");
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi waterId <number-id>");
|
||||
fp.sendMessage(BBC.getPrefix() + "/2 cfi color <image-url>");
|
||||
@ -433,6 +434,25 @@ public class CreateFromImage extends Command {
|
||||
player.sendMessage(BBC.getPrefix() + "Set biome, what's next?");
|
||||
return;
|
||||
}
|
||||
case "smooth": {
|
||||
int id;
|
||||
if (argList.size() < 4) {
|
||||
C.COMMAND_SYNTAX.send(player, "/2 cfi " + argList.get(0) + " <url|mask> <radius> <iterations> [whiteonly]");
|
||||
return;
|
||||
}
|
||||
int radius = Integer.parseInt(argList.get(2));
|
||||
int iterations = Integer.parseInt(argList.get(3));
|
||||
BufferedImage img = getImgurImage(argList.get(1), fp);
|
||||
if (img != null) {
|
||||
boolean whiteOnly = argList.size() == 5 && Boolean.parseBoolean(argList.get(4));
|
||||
generator.smooth(img, whiteOnly, radius, iterations);
|
||||
} else {
|
||||
Mask mask = we.getMaskFactory().parseFromInput(argList.get(1), context);
|
||||
generator.smooth(mask, radius, iterations);
|
||||
}
|
||||
player.sendMessage(BBC.getPrefix() + "Smoothed terrain, what's next?");
|
||||
return;
|
||||
}
|
||||
case "overlay":
|
||||
case "setoverlay": {
|
||||
Pattern id;
|
||||
@ -552,7 +572,7 @@ public class CreateFromImage extends Command {
|
||||
player.sendMessage(BBC.getPrefix() + "Cancelled!");
|
||||
return;
|
||||
default:
|
||||
C.COMMAND_SYNTAX.send(player, "/2 cfi <setBiome|setOverlay|setMain|setFloor|setColumn|addCaves|addOre[s]|addSchems|setHeight|setColor|setGlassColor|setBiomeColor|setBlockAndBiomeColor|setColorPaletteComplexity|setColorPaletteRandomization|setColorPaletteBlocks|biomepriority|done|cancel|>");
|
||||
C.COMMAND_SYNTAX.send(player, "/2 cfi <setBiome|setOverlay|setMain|setFloor|setColumn|addCaves|addOre[s]|addSchems|setHeight|setColor|setGlassColor|setBiomeColor|setBlockAndBiomeColor|setColorPaletteComplexity|setColorPaletteRandomization|setColorPaletteBlocks|biomepriority|smooth|done|cancel|>");
|
||||
return;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -81,6 +81,10 @@ public class MathMan {
|
||||
return floatNumber > (float) floor ? floor + 1 : floor;
|
||||
}
|
||||
|
||||
public static int sqr(int val) {
|
||||
return val * val;
|
||||
}
|
||||
|
||||
public static int clamp(int check, int min, int max) {
|
||||
return check > max ? max : (check < min ? min : check);
|
||||
}
|
||||
|
@ -19,22 +19,32 @@
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.command.FawePrimitiveBinding;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.jnbt.anvil.generator.CavesGen;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.boydti.fawe.util.TextureUtil;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MutableBlockVector;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.RegionFunction;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.RegionVisitor;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
@ -44,6 +54,10 @@ import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.util.command.parametric.ParameterException;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -92,13 +106,54 @@ public class GenerationCommands {
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.cylinder")
|
||||
@CommandPermissions("worldedit.generation.ore")
|
||||
@Logging(PLACEMENT)
|
||||
public void ores(Player player, LocalSession session, EditSession editSession, @Selection Region region, Mask mask) throws WorldEditException, ParameterException {
|
||||
editSession.addOres(region, mask);
|
||||
BBC.VISITOR_BLOCK.send(player, editSession.getBlockChangeCount());
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/image" },
|
||||
desc = "Generate an image",
|
||||
usage = "<imgur> [randomize=true] [complexity=100]",
|
||||
min = 1,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.image")
|
||||
@Logging(PLACEMENT)
|
||||
public void image(Player player, LocalSession session, EditSession editSession, String arg, @Optional("true") boolean randomize, @Optional("100") int threshold) throws WorldEditException, ParameterException, IOException {
|
||||
TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold);
|
||||
URL url = new URL(arg);
|
||||
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
|
||||
throw new IOException("Only i.imgur.com links are allowed!");
|
||||
}
|
||||
FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
BufferedImage image = MainUtil.toRGB(ImageIO.read(url));
|
||||
MutableBlockVector pos1 = new MutableBlockVector(player.getPosition());
|
||||
MutableBlockVector pos2 = new MutableBlockVector(pos1.add(image.getWidth() - 1, 0, image.getHeight() - 1));
|
||||
CuboidRegion region = new CuboidRegion(pos1, pos2);
|
||||
int[] count = new int[1];
|
||||
RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() {
|
||||
@Override
|
||||
public boolean apply(Vector pos) throws WorldEditException {
|
||||
try {
|
||||
int x = pos.getBlockX() - pos1.getBlockX();
|
||||
int z = pos.getBlockZ() - pos1.getBlockZ();
|
||||
int color = image.getRGB(x, z);
|
||||
BaseBlock block = tu.getNearestBlock(color);
|
||||
count[0]++;
|
||||
return editSession.setBlockFast(pos, block);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, editSession);
|
||||
Operations.completeBlindly(visitor);
|
||||
BBC.VISITOR_BLOCK.send(player, editSession.getBlockChangeCount());
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/ore" },
|
||||
usage = "<mask> <pattern> <size> <freq> <rarity> <minY> <maxY>",
|
||||
@ -107,7 +162,7 @@ public class GenerationCommands {
|
||||
min = 7,
|
||||
max = 7
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.cylinder")
|
||||
@CommandPermissions("worldedit.generation.ore")
|
||||
@Logging(PLACEMENT)
|
||||
public void ore(Player player, LocalSession session, EditSession editSession, @Selection Region region, Mask mask, Pattern material, int size, int freq, int rarity, int minY, int maxY) throws WorldEditException, ParameterException {
|
||||
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
|
||||
|
@ -158,7 +158,7 @@ public class MaskCommands extends MethodCommands {
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"#existing"},
|
||||
aliases = {"#solid"},
|
||||
desc = "If there is a solid block"
|
||||
)
|
||||
public Mask solid(EditSession extent) {
|
||||
|
Loading…
Reference in New Issue
Block a user