From bc1ea79648d1f8b9a08e0a209f314418a823a492 Mon Sep 17 00:00:00 2001 From: Hare Date: Fri, 12 Dec 2025 06:19:43 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20visualizer=E5=88=87=E3=82=8A=E5=87=BA?= =?UTF-8?q?=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 84 +---------- lands-plugin/build.gradle.kts | 87 ++++++++++++ .../kotlin/net/hareworks/hcu/lands/App.kt | 0 .../net/hareworks/hcu/lands/api/LandsAPI.kt | 0 .../hareworks/hcu/lands/api/LandsAPIImpl.kt | 0 .../hcu/lands/command/LandsCommand.kt | 0 .../hcu/lands/database/LandsTable.kt | 0 .../hareworks/hcu/lands/index/LandIndex.kt | 0 .../hareworks/hcu/lands/index/SpatialTypes.kt | 0 .../net/hareworks/hcu/lands/model/Land.kt | 0 .../hcu/lands/service/LandService.kt | 0 .../hcu/lands/task/VisualizerTask.kt | 130 ++--------------- settings.gradle.kts | 5 +- visualizer-lib/build.gradle.kts | 13 ++ .../hcu/visualizer/GeometryVisualizer.kt | 134 ++++++++++++++++++ 15 files changed, 252 insertions(+), 201 deletions(-) create mode 100644 lands-plugin/build.gradle.kts rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/App.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/api/LandsAPI.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/api/LandsAPIImpl.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/command/LandsCommand.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/database/LandsTable.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/index/LandIndex.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/index/SpatialTypes.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/model/Land.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/service/LandService.kt (100%) rename {src => lands-plugin/src}/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt (76%) create mode 100644 visualizer-lib/build.gradle.kts create mode 100644 visualizer-lib/src/main/kotlin/net/hareworks/hcu/visualizer/GeometryVisualizer.kt diff --git a/build.gradle.kts b/build.gradle.kts index cb90054..c00f183 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,85 +1,3 @@ -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") - - 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 { - 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" - ) + // Apply plugins common to all subprojects if any, or just leave empty/basic } diff --git a/lands-plugin/build.gradle.kts b/lands-plugin/build.gradle.kts new file mode 100644 index 0000000..71ce8cc --- /dev/null +++ b/lands-plugin/build.gradle.kts @@ -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 { + 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" + ) +} diff --git a/src/main/kotlin/net/hareworks/hcu/lands/App.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/App.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/App.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/App.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPI.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPI.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPI.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPI.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPIImpl.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPIImpl.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPIImpl.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/api/LandsAPIImpl.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/command/LandsCommand.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/command/LandsCommand.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/command/LandsCommand.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/command/LandsCommand.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/database/LandsTable.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/database/LandsTable.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/database/LandsTable.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/database/LandsTable.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/index/LandIndex.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/index/LandIndex.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/index/LandIndex.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/index/LandIndex.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/index/SpatialTypes.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/index/SpatialTypes.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/index/SpatialTypes.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/index/SpatialTypes.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/model/Land.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/model/Land.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/model/Land.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/model/Land.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/service/LandService.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/service/LandService.kt similarity index 100% rename from src/main/kotlin/net/hareworks/hcu/lands/service/LandService.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/service/LandService.kt diff --git a/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt similarity index 76% rename from src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt rename to lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt index eebe1b8..92140a5 100644 --- a/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt +++ b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt @@ -12,6 +12,7 @@ import org.bukkit.entity.Player import org.bukkit.entity.TextDisplay import org.bukkit.util.Transformation import org.bukkit.util.Vector +import net.hareworks.hcu.visualizer.GeometryVisualizer import org.joml.AxisAngle4f import org.joml.Vector3f import java.util.UUID @@ -118,13 +119,12 @@ class VisualizerTask( val (minCorner, maxCorner) = cuboid.getCornerBlocks() // 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 - 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 - // Min corner is at block position, max corner extends to outer edge (+1.0) val minX = cuboid.minX().toDouble() val maxX = cuboid.maxX() + 1.0 val minY = cuboid.minY().toDouble() @@ -132,33 +132,14 @@ class VisualizerTask( val minZ = cuboid.minZ().toDouble() val maxZ = cuboid.maxZ() + 1.0 - val edgeColor = Particle.DustOptions(Color.fromRGB(100, 255, 100), 0.75f) - 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) + GeometryVisualizer.drawCuboid(player, minX, minY, minZ, maxX, maxY, maxZ) } private fun drawCylinder(player: Player, cylinder: Shape.Cylinder) { val center = cylinder.getCenterBlock() // 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) // 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) val bottomY = cylinder.y.toDouble() - cylinder.bottomHeight val topY = cylinder.y.toDouble() + 1.0 + cylinder.topHeight - - 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, 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) - } + + GeometryVisualizer.drawCylinder(player, centerX, 0.0, centerZ, actualRadius, bottomY, topY) // Draw block-aligned boundary (Red) val faceBlocks = mutableSetOf>() @@ -255,81 +200,32 @@ class VisualizerTask( // Top edge (z- direction) val topNeighbor = Pair(bx, bz - 1) 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) val rightNeighbor = Pair(bx + 1, bz) 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) val bottomNeighbor = Pair(bx, bz + 1) 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) val leftNeighbor = Pair(bx - 1, bz) 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 { val position = calculateBestAttachmentLocation(player, land) diff --git a/settings.gradle.kts b/settings.gradle.kts index a4ef1ce..aa06851 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,4 +1,7 @@ -rootProject.name = "lands" +rootProject.name = "lands-root" + +include("lands-plugin") +include("visualizer-lib") if (gradle.parent == null) { includeBuild("hcu-core") diff --git a/visualizer-lib/build.gradle.kts b/visualizer-lib/build.gradle.kts new file mode 100644 index 0000000..058759e --- /dev/null +++ b/visualizer-lib/build.gradle.kts @@ -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")) +} diff --git a/visualizer-lib/src/main/kotlin/net/hareworks/hcu/visualizer/GeometryVisualizer.kt b/visualizer-lib/src/main/kotlin/net/hareworks/hcu/visualizer/GeometryVisualizer.kt new file mode 100644 index 0000000..3f2af67 --- /dev/null +++ b/visualizer-lib/src/main/kotlin/net/hareworks/hcu/visualizer/GeometryVisualizer.kt @@ -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) + } + } +}