diff --git a/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt index 92140a5..a9feb9b 100644 --- a/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt +++ b/lands-plugin/src/main/kotlin/net/hareworks/hcu/lands/task/VisualizerTask.kt @@ -172,56 +172,28 @@ class VisualizerTask( } } - val redDust = Particle.DustOptions(Color.RED, 1.0f) - drawFaceOutline(player, faceBlocks, bottomY, redDust, cylinder) - drawFaceOutline(player, faceBlocks, topY, redDust, cylinder) - } - - /** - * Draws only the outer edges of a face outline (excluding inner holes). - */ - private fun drawFaceOutline( - player: Player, - faceBlocks: Set>, - y: Double, - dustOptions: Particle.DustOptions, - cylinder: Shape.Cylinder - ) { - // Use the cylinder's vertical center for the 'contains' check to ensure we are within Y bounds - // This effectively checks if the neighbor is outside the radius laterally + val red = Color.RED val checkY = cylinder.y + 0.5 - // For each block in the face, check which edges face outward (not toward inner holes) - for ((bx, bz) in faceBlocks) { - // Check each of the 4 edges - // An edge should be drawn if the adjacent block is NOT in the face - // AND is outside the cylinder (not an inner hole) - - // 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)) { - 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)) { - 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)) { - 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)) { - GeometryVisualizer.drawLine(player, bx.toDouble(), y, bz + 1.0, bx.toDouble(), y, bz.toDouble(), dustOptions, 0.25) - } - } + GeometryVisualizer.drawBlockSurfaceOutline( + player, + bottomY, + faceBlocks, + { x, y, z -> cylinder.contains(x, y, z) }, + red, + checkY + ) + + GeometryVisualizer.drawBlockSurfaceOutline( + player, + topY, + faceBlocks, + { x, y, z -> cylinder.contains(x, y, z) }, + red, + checkY + ) } + 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 index 3f2af67..bca4ff0 100644 --- a/visualizer-lib/src/main/kotlin/net/hareworks/hcu/visualizer/GeometryVisualizer.kt +++ b/visualizer-lib/src/main/kotlin/net/hareworks/hcu/visualizer/GeometryVisualizer.kt @@ -13,24 +13,16 @@ 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) + // 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 (maxY) + // 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) @@ -44,7 +36,7 @@ object GeometryVisualizer { } 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 actualRadius = radius val segments = 32 val step = (Math.PI * 2) / segments @@ -84,6 +76,47 @@ object GeometryVisualizer { drawLine(player, x, minY, z, x, maxY, z, edgeColor, 0.5) } } + + /** + * Draws the outline of a set of blocks that form a horizontal surface. + * Useful for visualizing the exact block-grid coverage of a shape. + */ + fun drawBlockSurfaceOutline( + player: Player, + surfaceY: Double, + blocks: Set>, + predicate: (Double, Double, Double) -> Boolean, + color: Color, + checkY: Double + ) { + val dustOptions = Particle.DustOptions(color, 1.0f) + + for ((bx, bz) in blocks) { + // Top (Z-) + val topNeighbor = Pair(bx, bz - 1) + if (!blocks.contains(topNeighbor) && !predicate(topNeighbor.first + 0.5, checkY, topNeighbor.second + 0.5)) { + drawLine(player, bx.toDouble(), surfaceY, bz.toDouble(), bx + 1.0, surfaceY, bz.toDouble(), dustOptions, 0.25) + } + + // Right (X+) + val rightNeighbor = Pair(bx + 1, bz) + if (!blocks.contains(rightNeighbor) && !predicate(rightNeighbor.first + 0.5, checkY, rightNeighbor.second + 0.5)) { + drawLine(player, bx + 1.0, surfaceY, bz.toDouble(), bx + 1.0, surfaceY, bz + 1.0, dustOptions, 0.25) + } + + // Bottom (Z+) + val bottomNeighbor = Pair(bx, bz + 1) + if (!blocks.contains(bottomNeighbor) && !predicate(bottomNeighbor.first + 0.5, checkY, bottomNeighbor.second + 0.5)) { + drawLine(player, bx + 1.0, surfaceY, bz + 1.0, bx.toDouble(), surfaceY, bz + 1.0, dustOptions, 0.25) + } + + // Left (X-) + val leftNeighbor = Pair(bx - 1, bz) + if (!blocks.contains(leftNeighbor) && !predicate(leftNeighbor.first + 0.5, checkY, leftNeighbor.second + 0.5)) { + drawLine(player, bx.toDouble(), surfaceY, bz + 1.0, bx.toDouble(), surfaceY, bz.toDouble(), dustOptions, 0.25) + } + } + } fun drawBlockOutline(player: Player, x: Int, y: Int, z: Int, color: Color) { val dustOptions = Particle.DustOptions(color, 1.0f) @@ -105,7 +138,7 @@ object GeometryVisualizer { 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) + drawLine(player, x.toDouble(), y.toDouble(), z + 1.0, x.toDouble(), y + 1.0, z.toDouble(), dustOptions, step) } fun drawLine(