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 {
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<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"
)
// Apply plugins common to all subprojects if any, or just leave empty/basic
}

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.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<Pair<Int, Int>>()
@ -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<TextDisplay> {
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) {
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)
}
}
}