Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(HoleESP): show bedrock only holes with a separate color #5414

Merged
merged 2 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs

private val distanceFade by float("DistanceFade", 0.3f, 0f..1f)

private val color1by1 by color("1x1", Color4b(0x19c15c))
private val colorBedrock by color("1x1Bedrock", Color4b(0x19c15c))
private val color1by1 by color("1x1", Color4b(0xf7381b))
private val color1by2 by color("1x2", Color4b(0x35bacc))
private val color2by2 by color("2x2", Color4b(0xf7381b))
private val color2by2 by color("2x2", Color4b(0xf7cf1b))

override fun horizontalDistance(): Int = horizontalDistance
override fun verticalDistance(): Int = verticalDistance
Expand Down Expand Up @@ -82,7 +83,7 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs

renderEnvironmentForWorld(event.matrixStack) {
HoleTracker.holes.forEach {
val (type, positions) = it
val positions = it.positions

val valOutOfRange = abs(pos.y - positions.from.y) > vDistance
val xzOutOfRange = abs(pos.x - positions.from.x) > hDistance ||
Expand All @@ -92,15 +93,15 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs
}

val fade = calculateFade(positions.from)
val baseColor = type.color().with(a = 50).fade(fade)
val baseColor = it.color().with(a = 50).fade(fade)
val box = positions.getBox()
withPositionRelativeToCamera(positions.from.toVec3d()) {
withColor(baseColor) {
drawSolidBox(box)
}

if (outline) {
val outlineColor = type.color().with(a = 100).fade(fade)
val outlineColor = it.color().with(a = 100).fade(fade)
withColor(outlineColor) {
drawOutlinedBox(box)
}
Expand Down Expand Up @@ -130,7 +131,7 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs
renderEnvironmentForWorld(event.matrixStack) {
withDisabledCull {
HoleTracker.holes.forEach {
val (type, positions) = it
val positions = it.positions

val valOutOfRange = abs(pos.y - positions.from.y) > vDistance
val xzOutOfRange = abs(pos.x - positions.from.x) > hDistance ||
Expand All @@ -140,7 +141,7 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs
}

val fade = calculateFade(positions.from)
val baseColor = type.color().with(a = 50).fade(fade)
val baseColor = it.color().with(a = 50).fade(fade)
val transparentColor = baseColor.with(a = 0)
val box = positions.getBox()
withPositionRelativeToCamera(positions.from.toVec3d()) {
Expand All @@ -149,7 +150,7 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs
}

if (outline) {
val outlineColor = type.color().with(a = 100).fade(fade)
val outlineColor = it.color().with(a = 100).fade(fade)
withColor(outlineColor) {
drawSideBox(box, Direction.DOWN, onlyOutline = true)
}
Expand All @@ -163,12 +164,11 @@ object ModuleHoleESP : ClientModule("HoleESP", Category.RENDER), HoleManagerSubs
}
}

private fun Hole.Type.color(): Color4b {
return when (this) {
Hole.Type.ONE_ONE -> color1by1
Hole.Type.ONE_TWO -> color1by2
Hole.Type.TWO_TWO -> color2by2
}
private fun Hole.color() = when {
type == Hole.Type.ONE_ONE && bedrockOnly -> colorBedrock
type == Hole.Type.ONE_TWO -> color1by2
type == Hole.Type.TWO_TWO -> color2by2
else -> color1by1
}

private fun calculateFade(pos: BlockPos): Float {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import net.minecraft.util.math.BlockPos
data class Hole(
val type: Type,
val positions: Region,
val bedrockOnly: Boolean = false,
val blockInvalidators: Region = Region(positions.from, positions.to.up(2)),
) : Comparable<Hole> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package net.ccbluex.liquidbounce.utils.block.hole
import it.unimi.dsi.fastutil.longs.Long2ByteOpenHashMap
import net.ccbluex.liquidbounce.features.module.MinecraftShortcuts
import net.ccbluex.liquidbounce.utils.block.ChunkScanner
import net.ccbluex.liquidbounce.utils.block.DIRECTIONS_EXCLUDING_UP
import net.ccbluex.liquidbounce.utils.block.Region
import net.ccbluex.liquidbounce.utils.block.getState
import net.ccbluex.liquidbounce.utils.kotlin.getValue
Expand All @@ -31,7 +32,8 @@ import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Direction
import java.util.concurrent.ConcurrentSkipListSet

private const val UNBREAKABLE = (-1).toByte()
private const val INDESTRUCTIBLE = (-2).toByte()
private const val BLAST_RESISTANT = (-1).toByte()
private const val AIR = 0.toByte()
private const val BREAKABLE = 1.toByte()

Expand All @@ -43,9 +45,12 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {

val holes = ConcurrentSkipListSet<Hole>()
private val mutable by ThreadLocal.withInitial(BlockPos::Mutable)
private val fullSurroundings = arrayOf(Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH)
private val UNBREAKABLE_BLOCKS: Set<Block> by lazy {
Registries.BLOCK.filterTo(hashSetOf()) { it.blastResistance >= 600 }
private val BLAST_RESISTANT_BLOCKS: Set<Block> by lazy {
Registries.BLOCK.filterTo(hashSetOf()) { it.blastResistance >= 600 && it.blastResistance < 3_600_000 }
}

private val INDESTRUCTIBLE_BLOCKS: Set<Block> by lazy {
Registries.BLOCK.filterTo(hashSetOf()) { it.blastResistance >= 3_600_000 }
}

override val shouldCallRecordBlockOnChunkUpdate: Boolean
Expand All @@ -70,7 +75,7 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {
holes.removeIf { it.positions.intersects(region) }
}

@Suppress("detekt:CognitiveComplexMethod")
@Suppress("CognitiveComplexMethod", "LongMethod")
fun Region.cachedUpdate() {
val buffer = BlockStateBuffer(volume)

Expand All @@ -93,16 +98,24 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {
return@forEach
}

val surroundings = fullSurroundings.filterTo(ArrayList(4)) { direction ->
buffer.cache(mutable.set(pos, direction)) == UNBREAKABLE
val surroundings = Direction.HORIZONTAL.filterTo(ArrayList(4)) { direction ->
val cached = buffer.cache(mutable.set(pos, direction))
cached == BLAST_RESISTANT || cached == INDESTRUCTIBLE
}

when (surroundings.size) {
// 1*1
4 -> holes += Hole(Hole.Type.ONE_ONE, Region.from(pos))
4 -> {
val bedrockOnly = DIRECTIONS_EXCLUDING_UP.all { direction ->
val cached = buffer.cache(mutable.set(pos, direction))
cached == INDESTRUCTIBLE
}

holes += Hole(Hole.Type.ONE_ONE, Region.from(pos), bedrockOnly)
}
// 1*2
3 -> {
val airDirection = fullSurroundings.first { it !in surroundings }
val airDirection = Direction.HORIZONTAL.first { it !in surroundings }
val another = pos.offset(airDirection)

if (!buffer.checkSameXZ(another)) {
Expand All @@ -112,8 +125,8 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {
val airOpposite = airDirection.opposite
var idx = 0
val checkDirections = Array(3) {
val value = fullSurroundings[idx++]
if (value === airOpposite) fullSurroundings[idx++] else value
val value = Direction.HORIZONTAL[idx++]
if (value === airOpposite) Direction.HORIZONTAL[idx++] else value
}

if (buffer.checkSurroundings(another, checkDirections)) {
Expand All @@ -122,7 +135,7 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {
}
// 2*2
2 -> {
val (direction1, direction2) = fullSurroundings.filterTo(ArrayList(2)) { it !in surroundings }
val (direction1, direction2) = Direction.HORIZONTAL.filterTo(ArrayList(2)) { it !in surroundings }

if (!buffer.checkState(mutableLocal.set(pos, direction1), direction1, direction2.opposite)) {
return@forEach
Expand Down Expand Up @@ -150,7 +163,8 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {
val state = blockPos.getState() ?: return AIR
val result = when {
state.isAir -> AIR
state.block in UNBREAKABLE_BLOCKS -> UNBREAKABLE
state.block in BLAST_RESISTANT_BLOCKS -> BLAST_RESISTANT
state.block in INDESTRUCTIBLE_BLOCKS -> INDESTRUCTIBLE
else -> BREAKABLE
}
put(longValue, result)
Expand All @@ -160,7 +174,8 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {

private fun BlockStateBuffer.checkSameXZ(blockPos: BlockPos): Boolean {
mutable.set(blockPos.x, blockPos.y - 1, blockPos.z)
if (cache(mutable) != UNBREAKABLE) {
val cached = cache(mutable)
if (cached != BLAST_RESISTANT && cached != INDESTRUCTIBLE) {
return false
}

Expand All @@ -178,7 +193,10 @@ object HoleTracker : ChunkScanner.BlockChangeSubscriber, MinecraftShortcuts {
blockPos: BlockPos,
directions: Array<out Direction>
): Boolean {
return directions.all { cache(mutable.set(blockPos, it)) == UNBREAKABLE }
return directions.all {
val cached = cache(mutable.set(blockPos, it))
cached == BLAST_RESISTANT || cached == INDESTRUCTIBLE
}
}

private fun BlockStateBuffer.checkState(
Expand Down
Loading