diff --git a/src/main/kotlin/com/github/itzilly/sbt/features/GemstoneFinder.kt b/src/main/kotlin/com/github/itzilly/sbt/features/GemstoneFinder.kt index 097832f..dd0203d 100644 --- a/src/main/kotlin/com/github/itzilly/sbt/features/GemstoneFinder.kt +++ b/src/main/kotlin/com/github/itzilly/sbt/features/GemstoneFinder.kt @@ -44,7 +44,6 @@ object GemstoneFinder { for (chunkZ in minBounds.z / 16..maxBounds.z / 16) { val chunk = world.getChunkFromChunkCoords(chunkX, chunkZ) - // Iterate through the chunk's blocks within the world bounds for (x in 0..15) { for (y in minBounds.y..maxBounds.y) { for (z in 0..15) { @@ -55,7 +54,7 @@ object GemstoneFinder { val blockPos = BlockPos(worldX, y, worldZ) val blockState = chunk.getBlockState(blockPos) val block = blockState.block - if (block == Blocks.air) { continue } + if (block == Blocks.air) continue val meta = block.getMetaFromState(blockState) val gemstoneColor = when { @@ -68,12 +67,12 @@ object GemstoneFinder { 5 -> GemstoneColors.JADE // Lime 14 -> GemstoneColors.RUBY // Red 10 -> GemstoneColors.AMETHYST // Purple - else -> null } } else -> null } + if (gemstoneColor != null && !gemstonesList(blockPos.x, blockPos.y, blockPos.z)) { gemstoneList.add(GemstoneBlock(blockPos.x, blockPos.y, blockPos.z, gemstoneColor)) } @@ -83,6 +82,49 @@ object GemstoneFinder { } } } + mergeAdjacentBlocks() + } + + private fun mergeAdjacentBlocks() { + val mergedList = ArrayList() + + while (gemstoneList.isNotEmpty()) { + val firstBlock = gemstoneList.removeAt(0) + val group = mutableListOf(firstBlock) + + val queue = ArrayDeque() + queue.add(firstBlock) + + while (queue.isNotEmpty()) { + val current = queue.removeFirst() + val neighbors = gemstoneList.filter { + it.color == current.color && isAdjacent(it, current) + } + group.addAll(neighbors) + gemstoneList.removeAll(neighbors) + queue.addAll(neighbors) + } + + mergedList.add(mergeGroup(group)) + } + + gemstoneList = mergedList + } + + private fun isAdjacent(a: GemstoneBlock, b: GemstoneBlock): Boolean { + return (a.x == b.x && a.y == b.y && (a.z == b.z + 1 || a.z == b.z - 1)) || + (a.x == b.x && (a.y == b.y + 1 || a.y == b.y - 1) && a.z == b.z) || + ((a.x == b.x + 1 || a.x == b.x - 1) && a.y == b.y && a.z == b.z) + } + + private fun mergeGroup(group: List): GemstoneBlock { + val minX = group.minOf { it.x } + val minY = group.minOf { it.y } + val minZ = group.minOf { it.z } + val maxX = group.maxOf { it.x } + val maxY = group.maxOf { it.y } + val maxZ = group.maxOf { it.z } + return GemstoneBlock(minX, minY, minZ, group.first().color, maxX, maxY, maxZ) } @SubscribeEvent @@ -90,8 +132,9 @@ object GemstoneFinder { val player = Minecraft.getMinecraft().thePlayer for (gemstone: GemstoneBlock in gemstoneList) { - val pos = BlockPos(gemstone.x, gemstone.y, gemstone.z) - RenderFuncs.drawBlockOutline(player, pos, event.partialTicks, gemstone.color.color) + val startPos = BlockPos(gemstone.x, gemstone.y, gemstone.z) + val endPos = BlockPos(gemstone.maxX, gemstone.maxY, gemstone.maxZ) + RenderFuncs.drawBlockOutline(player, startPos, endPos, event.partialTicks, gemstone.color.color) } } @@ -99,7 +142,10 @@ object GemstoneFinder { val x: Int, val y: Int, val z: Int, - val color: GemstoneColors + val color: GemstoneColors, + val maxX: Int = x, + val maxY: Int = y, + val maxZ: Int = z ) fun gemstonesList(x: Int, y: Int, z: Int): Boolean { diff --git a/src/main/kotlin/com/github/itzilly/sbt/renderer/RenderFuncs.kt b/src/main/kotlin/com/github/itzilly/sbt/renderer/RenderFuncs.kt index 8c08aed..79fa8e1 100644 --- a/src/main/kotlin/com/github/itzilly/sbt/renderer/RenderFuncs.kt +++ b/src/main/kotlin/com/github/itzilly/sbt/renderer/RenderFuncs.kt @@ -116,4 +116,52 @@ object RenderFuncs { val lineColor = Color(0xe310d5) RenderUtils.drawLine(pos1, pos2, lineColor, 2, false, partialTicks) } + + + fun drawBlockOutline(entity: Entity, startPos: BlockPos, endPos: BlockPos, partialTicks: Float, outlineColor: Int) { + val padding = 0.0020000000949949026 + + val entityX = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks + val entityY = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks + val entityZ = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks + + val minX = minOf(startPos.x.toDouble(), endPos.x.toDouble()) + val minY = minOf(startPos.y.toDouble(), endPos.y.toDouble()) + val minZ = minOf(startPos.z.toDouble(), endPos.z.toDouble()) + val maxX = maxOf(startPos.x.toDouble() + 1.0, endPos.x.toDouble() + 1.0) + val maxY = maxOf(startPos.y.toDouble() + 1.0, endPos.y.toDouble() + 1.0) + val maxZ = maxOf(startPos.z.toDouble() + 1.0, endPos.z.toDouble() + 1.0) + + val boundingBox = AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).expand(padding, padding, padding) + + // Convert integer color to r, g, b, a values + val r = (outlineColor shr 16 and 0xFF) / 255.0f + val g = (outlineColor shr 8 and 0xFF) / 255.0f + val b = (outlineColor and 0xFF) / 255.0f + val a = (outlineColor shr 24 and 0xFF) / 255.0f + + GL11.glPushMatrix() + GlStateManager.disableTexture2D() + GlStateManager.depthMask(false) + GlStateManager.disableDepth() + GL11.glEnable(GL11.GL_BLEND) + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA) + GL11.glEnable(GL11.GL_LINE_SMOOTH) + GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST) + GL11.glLineWidth(2.0f) + + // Set the color with alpha + GL11.glColor4f(r, g, b, a) + + // Draw the outline using the bounding box + RenderUtils.drawBlock(boundingBox.offset(-entityX, -entityY, -entityZ), outlineColor, outlineColor) + + GL11.glDisable(GL11.GL_LINE_SMOOTH) + GL11.glDisable(GL11.GL_BLEND) + GlStateManager.enableDepth() + GlStateManager.depthMask(true) + GlStateManager.enableAlpha() + GlStateManager.enableTexture2D() + GL11.glPopMatrix() + } } \ No newline at end of file