118 lines
3.9 KiB
Kotlin
118 lines
3.9 KiB
Kotlin
package cc.maxmc.blastingcrisis.misc
|
|
|
|
import org.bukkit.Location
|
|
import org.bukkit.Material
|
|
import org.bukkit.configuration.serialization.ConfigurationSerializable
|
|
import org.bukkit.configuration.serialization.SerializableAs
|
|
import org.bukkit.util.Vector
|
|
import taboolib.common.util.random
|
|
import kotlin.math.max
|
|
import kotlin.math.min
|
|
|
|
@SerializableAs("Area")
|
|
class Area(loc1: Location, loc2: Location) : ConfigurationSerializable {
|
|
val locTop: Location
|
|
val locMin: Location
|
|
|
|
@Suppress("unused") // Bukkit Specification
|
|
constructor(map: Map<String, Any>) : this(map["locTop"] as Location, map["locMin"] as Location)
|
|
|
|
init {
|
|
if (loc1.world != loc2.world) throw IllegalArgumentException("Locations must be of the same world.")
|
|
locTop = Location(loc1.world, max(loc1.x, loc2.x), max(loc1.y, loc2.y), max(loc1.z, loc2.z))
|
|
locMin = Location(loc1.world, min(loc1.x, loc2.x), min(loc1.y, loc2.y), min(loc1.z, loc2.z))
|
|
}
|
|
|
|
/**
|
|
* check if the given location is in this area
|
|
*
|
|
* @param location location to check
|
|
*
|
|
* @return true if the location is in this area
|
|
*/
|
|
fun contains(location: Location): Boolean {
|
|
if (location.world != locTop.world) return false
|
|
if (location.x !in (locMin.x - 1)..(locTop.x + 1)) return false
|
|
if (location.y !in locMin.y..locTop.y + 1) return false
|
|
return location.z in (locMin.z - 1)..(locTop.z + 1)
|
|
}
|
|
|
|
fun containsBlock(location: Location): Boolean {
|
|
if (location.world != locTop.world) return false
|
|
if (location.x !in locMin.x..locTop.x) return false
|
|
if (location.y !in locMin.y..locTop.y) return false
|
|
return location.z in locMin.z..locTop.z
|
|
}
|
|
|
|
/**
|
|
* get all locations of the blocks in this area
|
|
*
|
|
* @return all locations of the blocks in this area
|
|
*/
|
|
fun forBlocksInArea(): List<Location> {
|
|
val blocks = arrayListOf<Location>()
|
|
for (x in locMin.blockX..locTop.blockX) {
|
|
for (y in locMin.blockY..locTop.blockY) {
|
|
for (z in locMin.blockZ..locTop.blockZ) {
|
|
blocks.add(Location(locTop.world, x.toDouble(), y.toDouble(), z.toDouble()))
|
|
}
|
|
}
|
|
}
|
|
return blocks
|
|
}
|
|
|
|
/**
|
|
* get all locations of the non-air blocks in this area
|
|
*
|
|
* @return all locations of the non-air blocks in this area
|
|
*/
|
|
fun forBlocksWithoutAir(): List<Location> {
|
|
return forBlocksInArea().filter { it.block.type != Material.AIR }
|
|
}
|
|
|
|
fun getAirPercentage(): Double {
|
|
val blocks = forBlocksInArea()
|
|
return blocks.filter { it.block.type == Material.AIR }.size.toDouble() / blocks.size.toDouble()
|
|
}
|
|
|
|
/**
|
|
* generate a random Location that player can stand
|
|
*
|
|
* @return a random Location that player can stand
|
|
*/
|
|
tailrec fun randomLocation(): Location {
|
|
val x = random(locMin.blockX, locTop.blockX)
|
|
val z = random(locMin.blockZ, locTop.blockZ)
|
|
for (y in locMin.blockY..locTop.blockY) {
|
|
val loc = Vector(x, y, z).toLocation(locMin.world)
|
|
val add = loc.clone().add(0.0, 1.0, 0.0)
|
|
if (loc.block.type == Material.AIR && add.block.type == Material.AIR) return loc
|
|
}
|
|
return randomLocation()
|
|
}
|
|
|
|
override fun equals(other: Any?): Boolean {
|
|
if (this === other) return true
|
|
if (javaClass != other?.javaClass) return false
|
|
|
|
other as Area
|
|
|
|
if (locTop != other.locTop) return false
|
|
return locMin == other.locMin
|
|
}
|
|
|
|
|
|
override fun hashCode(): Int {
|
|
var result = locTop.hashCode()
|
|
result = 31 * result + locMin.hashCode()
|
|
return result
|
|
}
|
|
|
|
override fun serialize() = mutableMapOf<String, Any>("locTop" to locTop, "locMin" to locMin)
|
|
|
|
override fun toString(): String {
|
|
return "Area(locTop=$locTop, locMin=$locMin)"
|
|
}
|
|
|
|
}
|