176 lines
6.7 KiB
Kotlin

package com.github.itzilly.sbt.features
import com.github.itzilly.sbt.SkyBlockTweaks
import com.github.itzilly.sbt.renderer.RenderUtils
import java.awt.Color
import com.github.itzilly.sbt.util.Chatterbox
import com.github.itzilly.sbt.util.DelayedFunction
import com.github.itzilly.sbt.util.SimpleChatMsg
import com.github.itzilly.sbt.util.Vecd3
import net.minecraft.block.Block
import net.minecraft.client.Minecraft
import net.minecraft.client.renderer.GlStateManager
import net.minecraft.init.Blocks
import net.minecraft.util.BlockPos
import net.minecraft.entity.Entity
import net.minecraft.tileentity.TileEntityChest
import net.minecraft.util.AxisAlignedBB
import net.minecraft.util.MovingObjectPosition
import net.minecraftforge.client.event.ClientChatReceivedEvent
import net.minecraftforge.client.event.RenderWorldLastEvent
import net.minecraftforge.common.config.Configuration
import net.minecraftforge.event.entity.player.PlayerInteractEvent
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import org.lwjgl.opengl.GL11
data class ChestNode(
val x: Int,
val y: Int,
val z: Int,
)
fun chestNodeExists(x: Int, y: Int, z: Int): Boolean {
return ChestEsp.chestList.any { it.x == x && it.y == y && it.z == z }
}
object ChestEsp {
var chestList: ArrayList<ChestNode> = ArrayList()
var enabled: Boolean = SkyBlockTweaks.config.getBoolean("powderchestenable", Configuration.CATEGORY_GENERAL, true, "Enables/Disables Powder ChestESP")
@SubscribeEvent
fun chatMessageEvent(event: ClientChatReceivedEvent) {
if (!enabled) return
if (event.message.unformattedText == "You uncovered a treasure chest!") {
DelayedFunction({ highlightChests() }, 5)
}
}
@SubscribeEvent
fun renderBlockOverlay(event: RenderWorldLastEvent) {
if (!enabled) return
val player = Minecraft.getMinecraft().thePlayer
for (chest: ChestNode in chestList) {
val pos = BlockPos(chest.x, chest.y, chest.z)
drawChestOutline(player, pos, event.partialTicks)
drawChestLine(pos, event.partialTicks)
}
}
@SubscribeEvent
fun rightClickEvent(event: PlayerInteractEvent) {
if (!enabled) return
if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
val pos = event.pos
if (chestNodeExists(pos.x, pos.y, pos.z)) {
chestList.removeIf { it.x == pos.x && it.y == pos.y && it.z == pos.z }
checkChestLocations()
}
}
}
fun checkChestLocations() {
for (chest in chestList) {
if (chestNodeExists(chest.x, chest.y, chest.z)) {
chestList.removeIf { it.x == chest.x && it.y == chest.y && it.z == chest.z }
}
}
}
fun highlightChests() {
if (!enabled) return
val searchRadius = 8
val world = Minecraft.getMinecraft().thePlayer.worldObj
val posX = Minecraft.getMinecraft().thePlayer.posX
val posY = Minecraft.getMinecraft().thePlayer.posY
val posZ = Minecraft.getMinecraft().thePlayer.posZ
val boundXMax = posX + searchRadius
val boundXMin = posX - searchRadius
val boundYMax = posY + searchRadius
val boundYMin = posY - searchRadius
val boundZMax = posZ + searchRadius
val boundZMin = posZ - searchRadius
for (x in boundXMin.toInt()..boundXMax.toInt()) {
for (y in boundYMin.toInt()..boundYMax.toInt()) {
for (z in boundZMin.toInt()..boundZMax.toInt()) {
val block = world.getBlockState(BlockPos(x, y, z)).block
if (block == Blocks.chest || block == Blocks.trapped_chest || block == Blocks.ender_chest) {
val tileEntity = world.getTileEntity(BlockPos(x, y, z))
if (tileEntity is TileEntityChest) {
if (tileEntity.numPlayersUsing != 0) {
val point = ChestNode(x, y, z)
if (!chestNodeExists(x, y, z)) {
chestList.add(point)
}
}
}
}
}
}
}
checkChestLocations()
}
private fun drawChestOutline(entity: Entity, blockPos: BlockPos, partialTicks: Float) {
val padding: Double = 0.0020000000949949026
val entityX: Double = entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * partialTicks
val entityY: Double = entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * partialTicks
val entityZ: Double = entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * partialTicks
val outlineStartColor = 0xFFFFFF
val outlineEndColor = 0xFFFFFF
val world = Minecraft.getMinecraft().theWorld
val blockState = world.getBlockState(blockPos)
val block: Block = blockState.block
// Create a default bounding box for blocks that don't have one
val boundingBox: AxisAlignedBB = block.getCollisionBoundingBox(world, blockPos, blockState)
?: AxisAlignedBB(
blockPos.x.toDouble(), blockPos.y.toDouble(), blockPos.z.toDouble(),
blockPos.x + 1.0, blockPos.y + 1.0, blockPos.z + 1.0
).expand(padding, padding, padding)
GL11.glPushMatrix()
GlStateManager.disableTexture2D()
GlStateManager.depthMask(false)
GlStateManager.disableDepth()
GL11.glEnable(GL11.GL_LINE_SMOOTH)
GL11.glHint(GL11.GL_LINE_SMOOTH_HINT, GL11.GL_NICEST)
GL11.glLineWidth(2.0f)
GL11.glShadeModel(GL11.GL_SMOOTH)
RenderUtils.drawBlock(boundingBox.offset(-entityX, -entityY, -entityZ), outlineStartColor, outlineEndColor)
GL11.glLineWidth(2.0f)
GL11.glDisable(GL11.GL_LINE_SMOOTH)
GlStateManager.enableDepth()
GlStateManager.depthMask(true)
GlStateManager.enableAlpha()
GlStateManager.enableTexture2D()
GL11.glPopMatrix()
}
private fun drawChestLine(pos: BlockPos, partialTicks: Float) {
val render = Minecraft.getMinecraft().renderViewEntity
val rm = Minecraft.getMinecraft().renderManager
// TODO: Fix this not working with view bobbing enabled
val pos1 = Vecd3(rm.viewerPosX, rm.viewerPosY + render.eyeHeight, rm.viewerPosZ)
val pos2 = Vecd3(
pos.x.toDouble() + 0.5, // Center of the block
pos.y.toDouble() + 0.5, // Center of the block
pos.z.toDouble() + 0.5 // Center of the block
)
val lineColor = Color(0xe310d5)
RenderUtils.drawLine(pos1, pos2, lineColor, 2, false, partialTicks)
}
}