mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 02:12:42 -04:00
Change GeolyzerEvent.Scan
to define a bounding box instead of a column. Closes #1149.
`geolyzer.scan` can now alternatively be called with `x, z, y, width, depth, height` as first arguments to define custom bounds (old parameters still work and will continue to return columns). Layout of returned table will be such that `index = x + z*w + y*w*d`.
This commit is contained in:
parent
d6838a9455
commit
f46c22ba77
@ -36,18 +36,42 @@ public abstract class GeolyzerEvent extends Event {
|
|||||||
* the geolyzer. By default this will yield a (noisy) listing of the
|
* the geolyzer. By default this will yield a (noisy) listing of the
|
||||||
* hardness of the blocks.
|
* hardness of the blocks.
|
||||||
* <p/>
|
* <p/>
|
||||||
* Note: the y coordinate is computed as <tt>geolyzer.y - 32 + data.index</tt>.
|
* The bounds are guaranteed to not define a volume larger than 64.
|
||||||
|
* Resulting data should be written to the {@link #data} array such that
|
||||||
|
* <code>index = x + z*w + y*w*d</code>, with <code>w = maxX - minX</code>
|
||||||
|
* and <code>d = maxZ - minZ</code> (<tt>h</tt> meaning height, <tt>d</tt>
|
||||||
|
* meaning depth).
|
||||||
*/
|
*/
|
||||||
public static class Scan extends GeolyzerEvent {
|
public static class Scan extends GeolyzerEvent {
|
||||||
/**
|
/**
|
||||||
* The <em>relative</em> x coordinate of the column being scanned.
|
* The <em>relative</em> minimal x coordinate of the box being scanned (inclusive).
|
||||||
*/
|
*/
|
||||||
public final int scanX;
|
public final int minX;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <em>relative</em> z coordinate of the column being scanned.
|
* The <em>relative</em> minimal y coordinate of the box being scanned (inclusive).
|
||||||
*/
|
*/
|
||||||
public final int scanZ;
|
public final int minY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <em>relative</em> minimal z coordinate of the box being scanned (inclusive).
|
||||||
|
*/
|
||||||
|
public final int minZ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <em>relative</em> maximal x coordinate of the box being scanned (inclusive).
|
||||||
|
*/
|
||||||
|
public final int maxX;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <em>relative</em> maximal y coordinate of the box being scanned (inclusive).
|
||||||
|
*/
|
||||||
|
public final int maxY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The <em>relative</em> maximal z coordinate of the box being scanned (inclusive).
|
||||||
|
*/
|
||||||
|
public final int maxZ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data for the column of blocks being scanned, which is an
|
* The data for the column of blocks being scanned, which is an
|
||||||
@ -56,10 +80,14 @@ public abstract class GeolyzerEvent extends Event {
|
|||||||
*/
|
*/
|
||||||
public final float[] data = new float[64];
|
public final float[] data = new float[64];
|
||||||
|
|
||||||
public Scan(EnvironmentHost host, Map<?, ?> options, int scanX, int scanZ) {
|
public Scan(EnvironmentHost host, Map<?, ?> options, int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
||||||
super(host, options);
|
super(host, options);
|
||||||
this.scanX = scanX;
|
this.minX = minX;
|
||||||
this.scanZ = scanZ;
|
this.minY = minY;
|
||||||
|
this.minZ = minZ;
|
||||||
|
this.maxX = maxX;
|
||||||
|
this.maxY = maxY;
|
||||||
|
this.maxZ = maxZ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,6 @@ object GeolyzerHandler {
|
|||||||
def onGeolyzerScan(e: GeolyzerEvent.Scan) {
|
def onGeolyzerScan(e: GeolyzerEvent.Scan) {
|
||||||
val world = e.host.world
|
val world = e.host.world
|
||||||
val blockPos = BlockPosition(e.host)
|
val blockPos = BlockPosition(e.host)
|
||||||
val bx = blockPos.x + e.scanX
|
|
||||||
val bz = blockPos.z + e.scanZ
|
|
||||||
val includeReplaceable = e.options.get("includeReplaceable") match {
|
val includeReplaceable = e.options.get("includeReplaceable") match {
|
||||||
case value: java.lang.Boolean => value.booleanValue()
|
case value: java.lang.Boolean => value.booleanValue()
|
||||||
case _ => true
|
case _ => true
|
||||||
@ -27,16 +25,25 @@ object GeolyzerHandler {
|
|||||||
// Map to [-1, 1). The additional /33f is for normalization below.
|
// Map to [-1, 1). The additional /33f is for normalization below.
|
||||||
noise.map(_ / 128f / 33f).copyToArray(e.data)
|
noise.map(_ / 128f / 33f).copyToArray(e.data)
|
||||||
|
|
||||||
for (ry <- 0 until e.data.length) {
|
val w = e.maxX - e.minX + 1
|
||||||
val by = blockPos.y + ry - 32
|
val d = e.maxZ - e.minZ + 1
|
||||||
if (!world.isAirBlock(bx, by, bz)) {
|
for (ry <- e.minY to e.maxY; rz <- e.minZ to e.maxZ; rx <- e.minX to e.maxX) {
|
||||||
val block = world.getBlock(bx, by, bz)
|
val x = blockPos.x + rx
|
||||||
|
val y = blockPos.y + ry
|
||||||
|
val z = blockPos.z + rz
|
||||||
|
val index = (rx - e.minX) + ((rz - e.minZ) + (ry - e.minY) * d) * w
|
||||||
|
if (world.blockExists(x, y, z) && !world.isAirBlock(x, y, z)) {
|
||||||
|
val block = world.getBlock(x, y, z)
|
||||||
if (block != null && (includeReplaceable || isFluid(block) || !block.isReplaceable(world, blockPos.x, blockPos.y, blockPos.z))) {
|
if (block != null && (includeReplaceable || isFluid(block) || !block.isReplaceable(world, blockPos.x, blockPos.y, blockPos.z))) {
|
||||||
e.data(ry) = e.data(ry) * (math.abs(ry - 32) + 1) * Settings.get.geolyzerNoise + block.getBlockHardness(world, bx, by, bz)
|
val dx = blockPos.x - x
|
||||||
|
val dy = blockPos.y - y
|
||||||
|
val dz = blockPos.z - z
|
||||||
|
val distance = math.sqrt(dx * dx + dy * dy + dz * dz).toFloat
|
||||||
|
e.data(index) = e.data(index) * distance * Settings.get.geolyzerNoise + block.getBlockHardness(world, x, y, z)
|
||||||
}
|
}
|
||||||
else e.data(ry) = 0
|
else e.data(index) = 0
|
||||||
}
|
}
|
||||||
else e.data(ry) = 0
|
else e.data(index) = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,25 +33,48 @@ class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
|
|||||||
withConnector().
|
withConnector().
|
||||||
create()
|
create()
|
||||||
|
|
||||||
@Callback(doc = """function(x:number, z:number[, ignoreReplaceable:boolean|options:table]):table -- Analyzes the density of the column at the specified relative coordinates.""")
|
@Callback(doc = """function(x:number, z:number[, y:number, w:number, d:number, h:number][, ignoreReplaceable:boolean|options:table]):table -- Analyzes the density of the column at the specified relative coordinates.""")
|
||||||
def scan(computer: Context, args: Arguments): Array[AnyRef] = {
|
def scan(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
val rx = args.checkInteger(0)
|
val (minX, minY, minZ, maxX, maxY, maxZ, optIndex) = getScanArgs(args)
|
||||||
val rz = args.checkInteger(1)
|
val volume = (maxX - minX + 1) * (maxZ - minZ + 1) * (maxY - minY + 1)
|
||||||
val options = if (args.isBoolean(2)) mapAsJavaMap(Map("includeReplaceable" -> !args.checkBoolean(2))) else args.optTable(2, Map.empty[AnyRef, AnyRef])
|
if (volume > 64) throw new IllegalArgumentException("volume too large (maximum is 64)")
|
||||||
|
val options = if (args.isBoolean(optIndex)) mapAsJavaMap(Map("includeReplaceable" -> !args.checkBoolean(optIndex))) else args.optTable(optIndex, Map.empty[AnyRef, AnyRef])
|
||||||
if (math.abs(rx) > Settings.get.geolyzerRange || math.abs(rz) > Settings.get.geolyzerRange) {
|
if (math.abs(minX) > Settings.get.geolyzerRange || math.abs(maxX) > Settings.get.geolyzerRange ||
|
||||||
|
math.abs(minY) > Settings.get.geolyzerRange || math.abs(maxY) > Settings.get.geolyzerRange ||
|
||||||
|
math.abs(minZ) > Settings.get.geolyzerRange || math.abs(maxZ) > Settings.get.geolyzerRange) {
|
||||||
throw new IllegalArgumentException("location out of bounds")
|
throw new IllegalArgumentException("location out of bounds")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!node.tryChangeBuffer(-Settings.get.geolyzerScanCost))
|
if (!node.tryChangeBuffer(-Settings.get.geolyzerScanCost))
|
||||||
return result(Unit, "not enough energy")
|
return result(Unit, "not enough energy")
|
||||||
|
|
||||||
val event = new GeolyzerEvent.Scan(host, options, rx, rz)
|
val event = new GeolyzerEvent.Scan(host, options, minX, minY, minZ, maxX, maxY, maxZ)
|
||||||
MinecraftForge.EVENT_BUS.post(event)
|
MinecraftForge.EVENT_BUS.post(event)
|
||||||
if (event.isCanceled) result(Unit, "scan was canceled")
|
if (event.isCanceled) result(Unit, "scan was canceled")
|
||||||
else result(event.data)
|
else result(event.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private def getScanArgs(args: Arguments) = {
|
||||||
|
val minX = args.checkInteger(0)
|
||||||
|
val minZ = args.checkInteger(1)
|
||||||
|
if (args.isInteger(2) && args.isInteger(3) && args.isInteger(4) && args.isInteger(5)) {
|
||||||
|
val minY = args.checkInteger(2)
|
||||||
|
val w = args.checkInteger(3)
|
||||||
|
val d = args.checkInteger(4)
|
||||||
|
val h = args.checkInteger(5)
|
||||||
|
val maxX = minX + w - 1
|
||||||
|
val maxY = minY + h - 1
|
||||||
|
val maxZ = minZ + d - 1
|
||||||
|
|
||||||
|
(math.min(minX, maxX), math.min(minY, maxY), math.min(minZ, maxZ),
|
||||||
|
math.max(minX, maxX), math.max(minY, maxY), math.max(minZ, maxZ),
|
||||||
|
6)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
(minX, -32, minZ, minX, 31, minZ, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Callback(doc = """function(side:number[,options:table]):table -- Get some information on a directly adjacent block.""")
|
@Callback(doc = """function(side:number[,options:table]):table -- Get some information on a directly adjacent block.""")
|
||||||
def analyze(computer: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
|
def analyze(computer: Context, args: Arguments): Array[AnyRef] = if (Settings.get.allowItemStackInspection) {
|
||||||
val side = args.checkSideAny(0)
|
val side = args.checkSideAny(0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user