feat: visualizer切り出し

This commit is contained in:
Keisuke Hirata 2025-12-12 06:19:43 +09:00
parent e24484bdea
commit bc1ea79648
15 changed files with 252 additions and 201 deletions

View File

@ -1,85 +1,3 @@
import net.minecrell.pluginyml.paper.PaperPluginDescription
group = "net.hareworks.hcu"
version = "1.0"
plugins { plugins {
kotlin("jvm") version "2.2.21" // Apply plugins common to all subprojects if any, or just leave empty/basic
kotlin("plugin.serialization") version "2.2.21"
id("de.eldoria.plugin-yml.paper") version "0.8.0"
id("com.gradleup.shadow") version "9.2.2"
}
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
}
val exposedVersion = "1.0.0-rc-4"
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") {
exclude(group = "org.jetbrains.kotlin")
}
implementation("com.michael-bull.kotlin-result:kotlin-result:2.1.0")
compileOnly("net.hareworks.hcu:hcu-core")
implementation("net.hareworks:kommand-lib")
implementation("net.hareworks:permits-lib")
compileOnly("net.hareworks:GhostDisplays")
compileOnly("net.kyori:adventure-api:4.25.0")
compileOnly("net.kyori:adventure-text-minimessage:4.25.0")
compileOnly("org.postgresql:postgresql:42.7.8")
compileOnly("org.jetbrains.exposed:exposed-core:$exposedVersion")
compileOnly("org.jetbrains.exposed:exposed-dao:$exposedVersion")
compileOnly("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")
compileOnly("org.jetbrains.exposed:exposed-kotlin-datetime:$exposedVersion")
}
tasks {
withType<Jar> {
archiveBaseName.set("lands")
}
shadowJar {
archiveClassifier.set("min")
minimize {
exclude(dependency("net.hareworks:GhostDisplays"))
exclude(dependency("net.hareworks:kommand-lib"))
exclude(dependency("net.hareworks:permits-lib"))
}
dependencies {
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib"))
exclude(dependency("org.jetbrains.kotlin:kotlin-reflect"))
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk8"))
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk7"))
}
relocate("net.hareworks.kommand_lib", "net.hareworks.hcu.lands.libs.kommand_lib")
relocate("net.hareworks.permits_lib", "net.hareworks.hcu.lands.libs.permits_lib")
}
}
paper {
main = "net.hareworks.hcu.lands.App"
name = "lands"
description = "land plugin"
version = getVersion().toString()
apiVersion = "1.21.10"
serverDependencies {
register("hcu-core") {
required = true
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
register("GhostDisplays") {
required = true
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
}
authors =
listOf(
"Hare-K02",
"Kaariyaaa"
)
} }

View File

@ -0,0 +1,87 @@
import net.minecrell.pluginyml.paper.PaperPluginDescription
group = "net.hareworks.hcu"
version = "1.0"
plugins {
kotlin("jvm") version "2.2.21"
kotlin("plugin.serialization") version "2.2.21"
id("de.eldoria.plugin-yml.paper") version "0.8.0"
id("com.gradleup.shadow") version "9.2.2"
}
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
}
val exposedVersion = "1.0.0-rc-4"
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") {
exclude(group = "org.jetbrains.kotlin")
}
implementation("com.michael-bull.kotlin-result:kotlin-result:2.1.0")
compileOnly("net.hareworks.hcu:hcu-core")
implementation("net.hareworks:kommand-lib")
implementation("net.hareworks:permits-lib")
compileOnly("net.hareworks:GhostDisplays")
implementation(project(":visualizer-lib"))
compileOnly("net.kyori:adventure-api:4.25.0")
compileOnly("net.kyori:adventure-text-minimessage:4.25.0")
compileOnly("org.postgresql:postgresql:42.7.8")
compileOnly("org.jetbrains.exposed:exposed-core:$exposedVersion")
compileOnly("org.jetbrains.exposed:exposed-dao:$exposedVersion")
compileOnly("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")
compileOnly("org.jetbrains.exposed:exposed-kotlin-datetime:$exposedVersion")
}
tasks {
withType<Jar> {
archiveBaseName.set("lands")
}
shadowJar {
archiveClassifier.set("min")
minimize {
exclude(dependency("net.hareworks:GhostDisplays"))
exclude(dependency("net.hareworks:kommand-lib"))
exclude(dependency("net.hareworks:permits-lib"))
}
dependencies {
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib"))
exclude(dependency("org.jetbrains.kotlin:kotlin-reflect"))
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk8"))
exclude(dependency("org.jetbrains.kotlin:kotlin-stdlib-jdk7"))
}
relocate("net.hareworks.kommand_lib", "net.hareworks.hcu.lands.libs.kommand_lib")
relocate("net.hareworks.permits_lib", "net.hareworks.hcu.lands.libs.permits_lib")
}
}
paper {
main = "net.hareworks.hcu.lands.App"
name = "lands"
description = "land plugin"
version = getVersion().toString()
apiVersion = "1.21.10"
serverDependencies {
register("hcu-core") {
required = true
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
register("GhostDisplays") {
required = true
load = PaperPluginDescription.RelativeLoadOrder.BEFORE
}
}
authors =
listOf(
"Hare-K02",
"Kaariyaaa"
)
}

View File

@ -12,6 +12,7 @@ import org.bukkit.entity.Player
import org.bukkit.entity.TextDisplay import org.bukkit.entity.TextDisplay
import org.bukkit.util.Transformation import org.bukkit.util.Transformation
import org.bukkit.util.Vector import org.bukkit.util.Vector
import net.hareworks.hcu.visualizer.GeometryVisualizer
import org.joml.AxisAngle4f import org.joml.AxisAngle4f
import org.joml.Vector3f import org.joml.Vector3f
import java.util.UUID import java.util.UUID
@ -118,13 +119,12 @@ class VisualizerTask(
val (minCorner, maxCorner) = cuboid.getCornerBlocks() val (minCorner, maxCorner) = cuboid.getCornerBlocks()
// Draw outline of min corner block // Draw outline of min corner block
drawBlockOutline(player, minCorner.first, minCorner.second, minCorner.third, Color.LIME) GeometryVisualizer.drawBlockOutline(player, minCorner.first, minCorner.second, minCorner.third, Color.LIME)
// Draw outline of max corner block // Draw outline of max corner block
drawBlockOutline(player, maxCorner.first, maxCorner.second, maxCorner.third, Color.YELLOW) GeometryVisualizer.drawBlockOutline(player, maxCorner.first, maxCorner.second, maxCorner.third, Color.YELLOW)
// Draw edges of the cuboid using outer corners // Draw edges of the cuboid using outer corners
// Min corner is at block position, max corner extends to outer edge (+1.0)
val minX = cuboid.minX().toDouble() val minX = cuboid.minX().toDouble()
val maxX = cuboid.maxX() + 1.0 val maxX = cuboid.maxX() + 1.0
val minY = cuboid.minY().toDouble() val minY = cuboid.minY().toDouble()
@ -132,33 +132,14 @@ class VisualizerTask(
val minZ = cuboid.minZ().toDouble() val minZ = cuboid.minZ().toDouble()
val maxZ = cuboid.maxZ() + 1.0 val maxZ = cuboid.maxZ() + 1.0
val edgeColor = Particle.DustOptions(Color.fromRGB(100, 255, 100), 0.75f) GeometryVisualizer.drawCuboid(player, minX, minY, minZ, maxX, maxY, maxZ)
val step = 0.5
// Bottom face edges
drawLine(player, minX, minY, minZ, maxX, minY, minZ, edgeColor, step)
drawLine(player, maxX, minY, minZ, maxX, minY, maxZ, edgeColor, step)
drawLine(player, maxX, minY, maxZ, minX, minY, maxZ, edgeColor, step)
drawLine(player, minX, minY, maxZ, minX, minY, minZ, edgeColor, step)
// Top face edges
drawLine(player, minX, maxY, minZ, maxX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, maxY, minZ, maxX, maxY, maxZ, edgeColor, step)
drawLine(player, maxX, maxY, maxZ, minX, maxY, maxZ, edgeColor, step)
drawLine(player, minX, maxY, maxZ, minX, maxY, minZ, edgeColor, step)
// Vertical edges
drawLine(player, minX, minY, minZ, minX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, minY, minZ, maxX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, minY, maxZ, maxX, maxY, maxZ, edgeColor, step)
drawLine(player, minX, minY, maxZ, minX, maxY, maxZ, edgeColor, step)
} }
private fun drawCylinder(player: Player, cylinder: Shape.Cylinder) { private fun drawCylinder(player: Player, cylinder: Shape.Cylinder) {
val center = cylinder.getCenterBlock() val center = cylinder.getCenterBlock()
// Draw outline of center block // Draw outline of center block
drawBlockOutline(player, center.first, center.second, center.third, Color.AQUA) GeometryVisualizer.drawBlockOutline(player, center.first, center.second, center.third, Color.AQUA)
// Draw cylinder edges (top and bottom circles + vertical lines) // Draw cylinder edges (top and bottom circles + vertical lines)
// Add 0.5 to block coordinates for center on X/Z axis // Add 0.5 to block coordinates for center on X/Z axis
@ -171,44 +152,8 @@ class VisualizerTask(
// Y coordinates use block boundaries (no +0.5 offset) // Y coordinates use block boundaries (no +0.5 offset)
val bottomY = cylinder.y.toDouble() - cylinder.bottomHeight val bottomY = cylinder.y.toDouble() - cylinder.bottomHeight
val topY = cylinder.y.toDouble() + 1.0 + cylinder.topHeight val topY = cylinder.y.toDouble() + 1.0 + cylinder.topHeight
val segments = 32 GeometryVisualizer.drawCylinder(player, centerX, 0.0, centerZ, actualRadius, bottomY, topY)
val step = (Math.PI * 2) / segments
val edgeColor = Particle.DustOptions(Color.fromRGB(100, 200, 255), 0.75f)
// Bottom circle
for (i in 0 until segments) {
val angle1 = i * step
val angle2 = (i + 1) * step
val x1 = centerX + cos(angle1) * actualRadius
val z1 = centerZ + sin(angle1) * actualRadius
val x2 = centerX + cos(angle2) * actualRadius
val z2 = centerZ + sin(angle2) * actualRadius
drawLine(player, x1, bottomY, z1, x2, bottomY, z2, edgeColor, 0.25)
}
// Top circle
for (i in 0 until segments) {
val angle1 = i * step
val angle2 = (i + 1) * step
val x1 = centerX + cos(angle1) * actualRadius
val z1 = centerZ + sin(angle1) * actualRadius
val x2 = centerX + cos(angle2) * actualRadius
val z2 = centerZ + sin(angle2) * actualRadius
drawLine(player, x1, topY, z1, x2, topY, z2, edgeColor, 0.25)
}
// Vertical lines (8 cardinal directions)
val verticalSegments = 8
for (i in 0 until verticalSegments) {
val angle = i * (Math.PI * 2) / verticalSegments
val x = centerX + cos(angle) * actualRadius
val z = centerZ + sin(angle) * actualRadius
drawLine(player, x, bottomY, z, x, topY, z, edgeColor, 0.5)
}
// Draw block-aligned boundary (Red) // Draw block-aligned boundary (Red)
val faceBlocks = mutableSetOf<Pair<Int, Int>>() val faceBlocks = mutableSetOf<Pair<Int, Int>>()
@ -255,81 +200,32 @@ class VisualizerTask(
// Top edge (z- direction) // Top edge (z- direction)
val topNeighbor = Pair(bx, bz - 1) val topNeighbor = Pair(bx, bz - 1)
if (!faceBlocks.contains(topNeighbor) && !cylinder.contains(topNeighbor.first + 0.5, checkY, topNeighbor.second + 0.5)) { if (!faceBlocks.contains(topNeighbor) && !cylinder.contains(topNeighbor.first + 0.5, checkY, topNeighbor.second + 0.5)) {
drawLine(player, bx.toDouble(), y, bz.toDouble(), bx + 1.0, y, bz.toDouble(), dustOptions, 0.25) GeometryVisualizer.drawLine(player, bx.toDouble(), y, bz.toDouble(), bx + 1.0, y, bz.toDouble(), dustOptions, 0.25)
} }
// Right edge (x+ direction) // Right edge (x+ direction)
val rightNeighbor = Pair(bx + 1, bz) val rightNeighbor = Pair(bx + 1, bz)
if (!faceBlocks.contains(rightNeighbor) && !cylinder.contains(rightNeighbor.first + 0.5, checkY, rightNeighbor.second + 0.5)) { if (!faceBlocks.contains(rightNeighbor) && !cylinder.contains(rightNeighbor.first + 0.5, checkY, rightNeighbor.second + 0.5)) {
drawLine(player, bx + 1.0, y, bz.toDouble(), bx + 1.0, y, bz + 1.0, dustOptions, 0.25) GeometryVisualizer.drawLine(player, bx + 1.0, y, bz.toDouble(), bx + 1.0, y, bz + 1.0, dustOptions, 0.25)
} }
// Bottom edge (z+ direction) // Bottom edge (z+ direction)
val bottomNeighbor = Pair(bx, bz + 1) val bottomNeighbor = Pair(bx, bz + 1)
if (!faceBlocks.contains(bottomNeighbor) && !cylinder.contains(bottomNeighbor.first + 0.5, checkY, bottomNeighbor.second + 0.5)) { if (!faceBlocks.contains(bottomNeighbor) && !cylinder.contains(bottomNeighbor.first + 0.5, checkY, bottomNeighbor.second + 0.5)) {
drawLine(player, bx + 1.0, y, bz + 1.0, bx.toDouble(), y, bz + 1.0, dustOptions, 0.25) GeometryVisualizer.drawLine(player, bx + 1.0, y, bz + 1.0, bx.toDouble(), y, bz + 1.0, dustOptions, 0.25)
} }
// Left edge (x- direction) // Left edge (x- direction)
val leftNeighbor = Pair(bx - 1, bz) val leftNeighbor = Pair(bx - 1, bz)
if (!faceBlocks.contains(leftNeighbor) && !cylinder.contains(leftNeighbor.first + 0.5, checkY, leftNeighbor.second + 0.5)) { if (!faceBlocks.contains(leftNeighbor) && !cylinder.contains(leftNeighbor.first + 0.5, checkY, leftNeighbor.second + 0.5)) {
drawLine(player, bx.toDouble(), y, bz + 1.0, bx.toDouble(), y, bz.toDouble(), dustOptions, 0.25) GeometryVisualizer.drawLine(player, bx.toDouble(), y, bz + 1.0, bx.toDouble(), y, bz.toDouble(), dustOptions, 0.25)
} }
} }
} }
/**
* Draws an outline of a block using particles
*/
private fun drawBlockOutline(player: Player, x: Int, y: Int, z: Int, color: Color) {
val dustOptions = Particle.DustOptions(color, 1.0f)
val step = 0.25 // Particle spacing along edges
// Bottom face edges
drawLine(player, x.toDouble(), y.toDouble(), z.toDouble(), x + 1.0, y.toDouble(), z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z.toDouble(), x + 1.0, y.toDouble(), z + 1.0, dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z + 1.0, x.toDouble(), y.toDouble(), z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y.toDouble(), z.toDouble(), dustOptions, step)
// Top face edges
drawLine(player, x.toDouble(), y + 1.0, z.toDouble(), x + 1.0, y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y + 1.0, z.toDouble(), x + 1.0, y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x + 1.0, y + 1.0, z + 1.0, x.toDouble(), y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y + 1.0, z + 1.0, x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step)
// Vertical edges
drawLine(player, x.toDouble(), y.toDouble(), z.toDouble(), x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z.toDouble(), x + 1.0, y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z + 1.0, x + 1.0, y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y + 1.0, z + 1.0, dustOptions, step)
}
/**
* Draws a line of particles between two points
*/
private fun drawLine(
player: Player,
x1: Double, y1: Double, z1: Double,
x2: Double, y2: Double, z2: Double,
dustOptions: Particle.DustOptions,
step: Double
) {
val dx = x2 - x1
val dy = y2 - y1
val dz = z2 - z1
val distance = kotlin.math.sqrt(dx * dx + dy * dy + dz * dz)
val steps = (distance / step).toInt()
if (steps == 0) return
for (i in 0..steps) {
val t = i.toDouble() / steps
val x = x1 + dx * t
val y = y1 + dy * t
val z = z1 + dz * t
player.spawnParticle(Particle.DUST, x, y, z, 1, 0.0, 0.0, 0.0, dustOptions)
}
}
private fun createDisplayForLand(player: Player, land: net.hareworks.hcu.lands.model.Land): DisplayController<TextDisplay> { private fun createDisplayForLand(player: Player, land: net.hareworks.hcu.lands.model.Land): DisplayController<TextDisplay> {
val position = calculateBestAttachmentLocation(player, land) val position = calculateBestAttachmentLocation(player, land)

View File

@ -1,4 +1,7 @@
rootProject.name = "lands" rootProject.name = "lands-root"
include("lands-plugin")
include("visualizer-lib")
if (gradle.parent == null) { if (gradle.parent == null) {
includeBuild("hcu-core") includeBuild("hcu-core")

View File

@ -0,0 +1,13 @@
plugins {
kotlin("jvm") version "2.2.21"
}
repositories {
mavenCentral()
maven("https://repo.papermc.io/repository/maven-public/")
}
dependencies {
compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT")
implementation(kotlin("stdlib"))
}

View File

@ -0,0 +1,134 @@
package net.hareworks.hcu.visualizer
import org.bukkit.Color
import org.bukkit.Location
import org.bukkit.Particle
import org.bukkit.entity.Player
import org.bukkit.util.Vector
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
object GeometryVisualizer {
fun drawCuboid(player: Player, minX: Double, minY: Double, minZ: Double, maxX: Double, maxY: Double, maxZ: Double) {
// Draw outline of min corner block (conceptually logic from original task, but generalized)
// Original task drew specific block outlines for corners. Here we just draw the box edges?
// Original:
// drawBlockOutline(player, minCorner..., Color.LIME)
// drawBlockOutline(player, maxCorner..., Color.YELLOW)
// drawLine edges...
// For generic visualizer, maybe just draw the wireframe box.
val edgeColor = Particle.DustOptions(Color.fromRGB(100, 255, 100), 0.75f)
val step = 0.5
// Bottom face edges (minY)
drawLine(player, minX, minY, minZ, maxX, minY, minZ, edgeColor, step)
drawLine(player, maxX, minY, minZ, maxX, minY, maxZ, edgeColor, step)
drawLine(player, maxX, minY, maxZ, minX, minY, maxZ, edgeColor, step)
drawLine(player, minX, minY, maxZ, minX, minY, minZ, edgeColor, step)
// Top face edges (maxY)
drawLine(player, minX, maxY, minZ, maxX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, maxY, minZ, maxX, maxY, maxZ, edgeColor, step)
drawLine(player, maxX, maxY, maxZ, minX, maxY, maxZ, edgeColor, step)
drawLine(player, minX, maxY, maxZ, minX, maxY, minZ, edgeColor, step)
// Vertical edges
drawLine(player, minX, minY, minZ, minX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, minY, minZ, maxX, maxY, minZ, edgeColor, step)
drawLine(player, maxX, minY, maxZ, maxX, maxY, maxZ, edgeColor, step)
drawLine(player, minX, minY, maxZ, minX, maxY, maxZ, edgeColor, step)
}
fun drawCylinder(player: Player, centerX: Double, centerY: Double, centerZ: Double, radius: Double, minY: Double, maxY: Double) {
val actualRadius = radius // or radius + 0.5 if passed as block radius? Caller should decide.
val segments = 32
val step = (Math.PI * 2) / segments
val edgeColor = Particle.DustOptions(Color.fromRGB(100, 200, 255), 0.75f)
// Bottom circle
for (i in 0 until segments) {
val angle1 = i * step
val angle2 = (i + 1) * step
val x1 = centerX + cos(angle1) * actualRadius
val z1 = centerZ + sin(angle1) * actualRadius
val x2 = centerX + cos(angle2) * actualRadius
val z2 = centerZ + sin(angle2) * actualRadius
drawLine(player, x1, minY, z1, x2, minY, z2, edgeColor, 0.25)
}
// Top circle
for (i in 0 until segments) {
val angle1 = i * step
val angle2 = (i + 1) * step
val x1 = centerX + cos(angle1) * actualRadius
val z1 = centerZ + sin(angle1) * actualRadius
val x2 = centerX + cos(angle2) * actualRadius
val z2 = centerZ + sin(angle2) * actualRadius
drawLine(player, x1, maxY, z1, x2, maxY, z2, edgeColor, 0.25)
}
// Vertical lines (8 cardinal directions)
val verticalSegments = 8
for (i in 0 until verticalSegments) {
val angle = i * (Math.PI * 2) / verticalSegments
val x = centerX + cos(angle) * actualRadius
val z = centerZ + sin(angle) * actualRadius
drawLine(player, x, minY, z, x, maxY, z, edgeColor, 0.5)
}
}
fun drawBlockOutline(player: Player, x: Int, y: Int, z: Int, color: Color) {
val dustOptions = Particle.DustOptions(color, 1.0f)
val step = 0.25
// Bottom face edges
drawLine(player, x.toDouble(), y.toDouble(), z.toDouble(), x + 1.0, y.toDouble(), z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z.toDouble(), x + 1.0, y.toDouble(), z + 1.0, dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z + 1.0, x.toDouble(), y.toDouble(), z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y.toDouble(), z.toDouble(), dustOptions, step)
// Top face edges
drawLine(player, x.toDouble(), y + 1.0, z.toDouble(), x + 1.0, y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y + 1.0, z.toDouble(), x + 1.0, y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x + 1.0, y + 1.0, z + 1.0, x.toDouble(), y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y + 1.0, z + 1.0, x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step)
// Vertical edges
drawLine(player, x.toDouble(), y.toDouble(), z.toDouble(), x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z.toDouble(), x + 1.0, y + 1.0, z.toDouble(), dustOptions, step)
drawLine(player, x + 1.0, y.toDouble(), z + 1.0, x + 1.0, y + 1.0, z + 1.0, dustOptions, step)
drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y + 1.0, z + 1.0, dustOptions, step)
}
fun drawLine(
player: Player,
x1: Double, y1: Double, z1: Double,
x2: Double, y2: Double, z2: Double,
dustOptions: Particle.DustOptions,
step: Double
) {
val dx = x2 - x1
val dy = y2 - y1
val dz = z2 - z1
val distance = sqrt(dx * dx + dy * dy + dz * dz)
val steps = (distance / step).toInt()
if (steps == 0) return
for (i in 0..steps) {
val t = i.toDouble() / steps
val x = x1 + dx * t
val y = y1 + dy * t
val z = z1 + dz * t
player.spawnParticle(Particle.DUST, x, y, z, 1, 0.0, 0.0, 0.0, dustOptions)
}
}
}