geforkt von Mirrors/FastAsyncWorldEdit
Added support for custom materials to ArbitraryShape and adjusted //generate accordingly.
Dieser Commit ist enthalten in:
Ursprung
02a70cca4a
Commit
8a83f7f70e
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren