Added support for custom materials to ArbitraryShape and adjusted //generate accordingly.

This commit is contained in:
TomyLobo 2011-10-31 22:03:35 +01:00
parent 02a70cca4a
commit 8a83f7f70e
2 changed files with 118 additions and 22 deletions

View File

@ -19,56 +19,151 @@
package com.sk89q.worldedit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.regions.Region;
public abstract class ArbitraryShape {
private Region extent;
private final Region extent;
private int cacheSizeX;
private int cacheSizeY;
private int cacheSizeZ;
private int cacheX;
private int cacheY;
private int cacheZ;
public ArbitraryShape(Region extent) {
this.extent = extent;
Vector min = extent.getMinimumPoint();
Vector max = extent.getMaximumPoint();
cacheSizeX = (int)(max.getX() - min.getX() + 1 + 2);
cacheSizeY = (int)(max.getY() - min.getY() + 1 + 2);
cacheSizeZ = (int)(max.getZ() - min.getZ() + 1 + 2);
cacheX = min.getBlockX() - 1;
cacheY = min.getBlockY() - 1;
cacheZ = min.getBlockZ() - 1;
cache = new short[cacheSizeX * cacheSizeY * cacheSizeZ];
}
protected Region getExtent() {
return extent;
}
protected abstract boolean isInside(double x, double y, double z);
/**
* Cache entries:
* 0 = unknown
* -1 = outside
* -2 = inside but type and data 0
* > 0 = inside, value = (type | (data << 8)), not handling data < -1
*/
private final short[] cache;
protected abstract BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial);
private BaseBlock getMaterialCached(int x, int y, int z, Pattern pattern) {
final int index = (y - cacheY) + (z - cacheZ) * cacheSizeY + (x - cacheX) * cacheSizeY * cacheSizeZ;
final short cacheEntry = cache[index];
switch (cacheEntry) {
case 0:
// unknown, fetch material
final BaseBlock material = getMaterial(x, y, z, pattern.next(new BlockVector(x, y, z)));
if (material == null) {
// outside
cache[index] = -1;
return null;
}
short newCacheEntry = (short) (material.getType() | ((material.getData()+1) << 8));
if (newCacheEntry == 0) {
// type and data 0
newCacheEntry = -2;
}
cache[index] = newCacheEntry;
return material;
case -1:
// outside
return null;
case -2:
// type and data 0
return new BaseBlock(0, 0);
}
return new BaseBlock(cacheEntry & 255, ((cacheEntry >> 8) - 1) & 15);
}
private boolean isInsideCached(int x, int y, int z, Pattern pattern) {
final int index = (y - cacheY) + (z - cacheZ) * cacheSizeY + (x - cacheX) * cacheSizeY * cacheSizeZ;
switch (cache[index]) {
case 0:
// unknown block, meaning they must be outside the extent at this stage, but might still be inside the shape
return getMaterialCached(x, y, z, pattern) != null;
case -1:
// outside
return false;
default:
// inside
return true;
}
}
public int generate(EditSession editSession, Pattern pattern, boolean hollow) throws MaxChangedBlocksException {
int affected = 0;
for (BlockVector position : getExtent()) {
double x = position.getX();
double y = position.getY();
double z = position.getZ();
int x = position.getBlockX();
int y = position.getBlockY();
int z = position.getBlockZ();
if (!isInside(x, y, z)) continue;
if (!hollow) {
final BaseBlock material = getMaterial(x, y, z, pattern.next(position));
if (material != null && editSession.setBlock(position, material)) {
++affected;
}
continue;
}
final BaseBlock material = getMaterialCached(x, y, z, pattern);
if (material == null) {
continue;
}
if (hollow) {
boolean draw = false;
do {
if (!isInside(x + 1, y, z)) {
if (!isInsideCached(x + 1, y, z, pattern)) {
draw = true;
break;
}
if (!isInside(x - 1, y, z)) {
if (!isInsideCached(x - 1, y, z, pattern)) {
draw = true;
break;
}
if (!isInside(x, y + 1, z)) {
if (!isInsideCached(x, y + 1, z, pattern)) {
draw = true;
break;
}
if (!isInside(x, y - 1, z)) {
if (!isInsideCached(x, y - 1, z, pattern)) {
draw = true;
break;
}
if (!isInside(x, y, z + 1)) {
if (!isInsideCached(x, y, z + 1, pattern)) {
draw = true;
break;
}
if (!isInside(x, y, z - 1)) {
if (!isInsideCached(x, y, z - 1, pattern)) {
draw = true;
break;
}
@ -79,7 +174,7 @@ public abstract class ArbitraryShape {
}
}
if (editSession.setBlock(position, pattern)) {
if (editSession.setBlock(position, material)) {
++affected;
}
}

View File

@ -25,6 +25,7 @@ import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.expression.Expression;
import com.sk89q.worldedit.expression.ExpressionException;
import com.sk89q.worldedit.patterns.Pattern;
@ -332,12 +333,12 @@ public class GenerationCommands {
if (args.hasFlag('r')) {
shape = new ArbitraryShape(region) {
@Override
protected boolean isInside(double x, double y, double z) {
protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) {
try {
return expression.evaluate(x, y, z) > 0;
return expression.evaluate(x, y, z) > 0 ? defaultMaterial : null;
} catch (Exception e) {
e.printStackTrace();
return false;
return null;
}
}
};
@ -350,12 +351,12 @@ public class GenerationCommands {
shape = new ArbitraryShape(region) {
@Override
protected boolean isInside(double x, double y, double z) {
protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) {
try {
return expression.evaluate(x - placementX, y - placementY, z - placementZ) > 0;
return expression.evaluate(x - placementX, y - placementY, z - placementZ) > 0 ? defaultMaterial : null;
} catch (Exception e) {
e.printStackTrace();
return false;
return null;
}
}
};
@ -366,14 +367,14 @@ public class GenerationCommands {
final Vector stretch = max.subtract(center);
shape = new ArbitraryShape(region) {
@Override
protected boolean isInside(double x, double y, double z) {
protected BaseBlock getMaterial(int x, int y, int z, BaseBlock defaultMaterial) {
final Vector scaled = new Vector(x, y, z).subtract(center).divide(stretch);
try {
return expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ()) > 0;
return expression.evaluate(scaled.getX(), scaled.getY(), scaled.getZ()) > 0 ? defaultMaterial : null;
} catch (Exception e) {
e.printStackTrace();
return false;
return null;
}
}
};