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;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren