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

Dieser Commit ist enthalten in:
TomyLobo 2011-10-31 22:03:35 +01:00
Ursprung 02a70cca4a
Commit 8a83f7f70e
2 geänderte Dateien mit 118 neuen und 22 gelöschten Zeilen

Datei anzeigen

@ -19,56 +19,151 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.patterns.Pattern; import com.sk89q.worldedit.patterns.Pattern;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
public abstract class ArbitraryShape { 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) { public ArbitraryShape(Region extent) {
this.extent = 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() { protected Region getExtent() {
return extent; 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 { public int generate(EditSession editSession, Pattern pattern, boolean hollow) throws MaxChangedBlocksException {
int affected = 0; int affected = 0;
for (BlockVector position : getExtent()) { for (BlockVector position : getExtent()) {
double x = position.getX(); int x = position.getBlockX();
double y = position.getY(); int y = position.getBlockY();
double z = position.getZ(); 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) { if (hollow) {
boolean draw = false; boolean draw = false;
do { do {
if (!isInside(x + 1, y, z)) { if (!isInsideCached(x + 1, y, z, pattern)) {
draw = true; draw = true;
break; break;
} }
if (!isInside(x - 1, y, z)) { if (!isInsideCached(x - 1, y, z, pattern)) {
draw = true; draw = true;
break; break;
} }
if (!isInside(x, y + 1, z)) { if (!isInsideCached(x, y + 1, z, pattern)) {
draw = true; draw = true;
break; break;
} }
if (!isInside(x, y - 1, z)) { if (!isInsideCached(x, y - 1, z, pattern)) {
draw = true; draw = true;
break; break;
} }
if (!isInside(x, y, z + 1)) { if (!isInsideCached(x, y, z + 1, pattern)) {
draw = true; draw = true;
break; break;
} }
if (!isInside(x, y, z - 1)) { if (!isInsideCached(x, y, z - 1, pattern)) {
draw = true; draw = true;
break; break;
} }
@ -79,7 +174,7 @@ public abstract class ArbitraryShape {
} }
} }
if (editSession.setBlock(position, pattern)) { if (editSession.setBlock(position, material)) {
++affected; ++affected;
} }
} }

Datei anzeigen

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