blob: ed2af9936633854d78e368bb1debc74a3c76937a [file] [log] [blame] [raw]
package li.cil.oc.server.component
import li.cil.oc.Settings
import li.cil.oc.api
import li.cil.oc.api.driver.EnvironmentHost
import li.cil.oc.api.machine.Arguments
import li.cil.oc.api.machine.Callback
import li.cil.oc.api.machine.Context
import li.cil.oc.api.network.Visibility
import li.cil.oc.api.prefab
import net.minecraft.block.Block
import net.minecraftforge.fluids.FluidRegistry
class Geolyzer(val host: EnvironmentHost) extends prefab.ManagedEnvironment {
override val node = api.Network.newNode(this, Visibility.Network).
withComponent("geolyzer").
withConnector().
create()
@Callback(doc = """function(x:number, z:number[, ignoreReplaceable:boolean]):table -- Analyzes the density of the column at the specified relative coordinates.""")
def scan(computer: Context, args: Arguments): Array[AnyRef] = {
val rx = args.checkInteger(0)
val rz = args.checkInteger(1)
val includeReplaceable = !(args.count > 2 && args.checkBoolean(2))
if (math.abs(rx) > Settings.get.geolyzerRange || math.abs(rz) > Settings.get.geolyzerRange) {
throw new IllegalArgumentException("location out of bounds")
}
val (x, y, z) = (math.floor(host.xPosition).toInt, math.floor(host.yPosition).toInt, math.floor(host.zPosition).toInt)
val bx = x + rx
val bz = z + rz
if (!node.tryChangeBuffer(-Settings.get.geolyzerScanCost))
return result(Unit, "not enough energy")
val count = 64
val noise = new Array[Byte](count)
host.world.rand.nextBytes(noise)
// Map to [-1, 1). The additional /33f is for normalization below.
val values = noise.map(_ / 128f / 33f)
for (ry <- 0 until count) {
val by = y + ry - 32
if (!host.world.isAirBlock(bx, by, bz)) {
val block = host.world.getBlock(bx, by, bz)
if (block != null && (includeReplaceable || isFluid(block) || !block.isReplaceable(host.world, x, y, z))) {
values(ry) = values(ry) * (math.abs(ry - 32) + 1) * Settings.get.geolyzerNoise + block.getBlockHardness(host.world, bx, by, bz)
}
}
else values(ry) = 0
}
result(values)
}
private def isFluid(block: Block) = FluidRegistry.lookupFluidForBlock(block) != null
}