
walkmc.StructureBox.kt Maven / Gradle / Ivy
package walkmc
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import org.bukkit.*
import org.bukkit.block.*
import org.bukkit.entity.*
import walkmc.extensions.strings.*
import kotlin.math.*
/**
* A structure box is very similar to [BoundingBox], but this is to use with areas.
*/
@Serializable(StructureBoxSerializer::class)
data class StructureBox(
var world: World,
var minX: Int,
var minY: Int,
var minZ: Int,
var maxX: Int,
var maxY: Int,
var maxZ: Int,
) : Iterable {
constructor(min: Block, max: Block) : this(min.location, max.location)
constructor(min: Entity, max: Entity) : this(min.location, max.location)
constructor(min: Location, max: Location) : this(
min.world,
min(min.blockX, max.blockX),
min(min.blockY, max.blockY),
min(min.blockZ, max.blockZ),
max(min.blockX, max.blockX),
max(min.blockY, max.blockY),
max(min.blockZ, max.blockZ),
)
/**
* Returns the minimum location representation of this structure box.
*/
val minPosition: Location
get() = Location(world, minX, minY, minZ)
/**
* Returns the maximum location representation of this structure box.
*/
val maxPosition: Location
get() = Location(world, maxX, maxY, maxZ)
/**
* Gets the volume of this structure box.
*/
val volume: Int
get() = (minX * maxX) + (minY * maxY) + (minZ * maxZ)
/**
* Gets the corners of this structure box.
*/
val corners: List
get() = buildList {
add(minPosition)
add(Location(world, minX, minY, maxZ))
add(Location(world, minX, maxY, minZ))
add(Location(world, minX, maxY, maxZ))
add(Location(world, maxX, minY, minZ))
add(Location(world, maxX, minY, maxZ))
add(Location(world, maxX, maxY, minZ))
add(maxPosition)
}
/**
* Gets a relative location of this box with the specified [x], [y] and [z].
*/
fun relative(x: Int, y: Int, z: Int): Location = Location(world, minX + x, minY + y, minZ + z)
/**
* Grows this structure box to the amount of radius.
*/
fun grow(radius: Int): StructureBox = apply {
minX -= radius
minY -= radius
minZ -= radius
maxX += radius
maxY += radius
maxZ += radius
}
/**
* Shrinks this structure box to the amount of radius.
*/
fun shrink(radius: Int): StructureBox = apply {
minX += radius
minY += radius
minZ += radius
maxX -= radius
maxY -= radius
maxZ -= radius
}
/**
* Verifies if a another box is collind with this box.
*/
fun isColliding(other: StructureBox): Boolean =
isCollidingX(other) || isCollidingY(other) || isCollidingZ(other)
/**
* Verifies if the X of a another box is collind with X of this box.
*/
fun isCollidingX(other: StructureBox): Boolean = other.maxX > minX && other.minX < maxX
/**
* Verifies if the Y of a another box is collind with Y of this box.
*/
fun isCollidingY(other: StructureBox): Boolean = other.maxY > minY && other.minY < maxY
/**
* Verifies if the Z of a another box is collind with Z of this box.
*/
fun isCollidingZ(other: StructureBox): Boolean = other.maxZ > minZ && other.minZ < maxZ
/**
* Verifies if a location is inside of this box.
*/
fun isInside(loc: Location): Boolean =
loc.blockX in minX until maxX && loc.blockY in minY until maxY && loc.blockZ in minZ until maxZ
/**
* Verifies if a block is inside of this box.
*/
fun isInside(block: Block): Boolean = isInside(block.location)
/**
* Verifies if a entity is inside of this box.
*/
fun isInside(entity: Entity): Boolean = isInside(entity.location)
/**
* Converts this box to a [BoundingBox].
*/
fun toBoundingBox() = BoundingBox(
minX.toDouble(),
minY.toDouble(),
minZ.toDouble(),
maxX.toDouble(),
maxY.toDouble(),
maxZ.toDouble()
)
override fun toString(): String = "${world.name}:$minX:$minY:$minZ:$maxX:$maxY:$maxZ"
override fun iterator(): Iterator = StructureBoxIterator(this)
companion object {
/**
* Converts a string to a structure box.
*/
fun from(string: String): StructureBox {
val split = string.split(':', limit = 7)
return StructureBox(
split[0].toWorld(),
split[1].toInt(),
split[2].toInt(),
split[3].toInt(),
split[4].toInt(),
split[5].toInt(),
split[6].toInt()
)
}
}
}
/**
* A serializer for serializing [StructureBox].
*/
object StructureBoxSerializer : KSerializer {
override val descriptor = PrimitiveSerialDescriptor("StructureBox", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): StructureBox {
return StructureBox.from(decoder.decodeString())
}
override fun serialize(encoder: Encoder, value: StructureBox) {
encoder.encodeString(value.toString())
}
}
/**
* Represents a iterator for [StructureBox].
*/
class StructureBoxIterator(val box: StructureBox) : Iterator {
var offsetX = 0
var offsetY = 0
var offsetZ = 0
val sizeX = abs(box.maxX - box.minX) + 1
val sizeY = abs(box.maxY - box.minY) + 1
val sizeZ = abs(box.maxZ - box.minZ) + 1
override fun hasNext(): Boolean = offsetX < sizeX && offsetY < sizeY && offsetZ < sizeZ
fun advance() {
if (++offsetX >= sizeX) {
offsetX = 0
if (++offsetY >= sizeY) {
offsetY = 0
offsetZ++
}
}
}
override fun next(): Block {
val block = box.relative(offsetX, offsetY, offsetZ).block
advance()
return block
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy