@file:Suppress("MemberVisibilityCanBePrivate") package net.axay.kspigot.structures import net.axay.kspigot.extensions.geometry.SimpleLocation2D import net.axay.kspigot.extensions.geometry.SimpleLocation3D import net.axay.kspigot.particles.KSpigotParticle import org.bukkit.Material import org.bukkit.entity.EntityType private fun circleEdgeLocations(radius: Number) = HashSet().apply { val currentRadius = radius.toDouble() var d = -currentRadius var x = currentRadius var y = 0 while (y <= x) { addSimpleLoc2D(x, y) addSimpleLoc2D(x, -y) addSimpleLoc2D(-x, y) addSimpleLoc2D(-x, -y) addSimpleLoc2D(y, x) addSimpleLoc2D(y, -x) addSimpleLoc2D(-y, x) addSimpleLoc2D(-y, -x) d += 2 * y + 1 y++ if (d > 0) { d += -2 * x + 2 x-- } } } private fun MutableSet.addSimpleLoc2D(first: Number, second: Number) { this += SimpleLocation2D(first, second) } abstract class Circle(val radius: Number) { protected abstract val data: StructureData val fillLocations by lazy { var currentRadius = radius.toDouble() HashSet().apply { while (currentRadius >= 0) { this += circleEdgeLocations(currentRadius).mapTo(HashSet()) { mutableSetOf(it).apply { this += SimpleLocation2D( it.x + when { it.x >= 1 -> -1; it.x <= -1 -> 1; else -> 0 }, it.y ) this += SimpleLocation2D( it.x, it.y + when { it.y >= 1 -> -1; it.y <= -1 -> 1; else -> 0 } ) } }.flatten() currentRadius-- } } } val edgeLocations by lazy { circleEdgeLocations(radius) } val filledStructure by lazy { structure(true) } val edgeStructure by lazy { structure(false) } fun structure(filled: Boolean) = Structure( HashSet().apply { val locations = if (filled) fillLocations else edgeLocations for (it in locations) this += SingleStructureData(SimpleLocation3D(it.x, 0, it.y), data) } ) } class MaterialCircle(radius: Number, material: Material) : Circle(radius) { override val data = StructureDataMaterial(material) } class ParticleCircle(radius: Number, particle: KSpigotParticle) : Circle(radius) { override val data = StructureDataParticle(particle) } class EntityCircle(radius: Number, entityType: EntityType) : Circle(radius) { override val data = StructureDataEntity(entityType) }