aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features/slayer/EndermanSlayerBeacon.kt
blob: 970a7f1dca45fe899859a4e2bca9c15bf8ef7b8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package at.hannibal2.skyhanni.features.slayer

import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.events.CheckRenderEntityEvent
import at.hannibal2.skyhanni.events.PacketEvent
import at.hannibal2.skyhanni.events.RenderMobColoredEvent
import at.hannibal2.skyhanni.events.withAlpha
import at.hannibal2.skyhanni.features.damageindicator.BossType
import at.hannibal2.skyhanni.features.damageindicator.DamageIndicatorManager
import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.RenderUtils.drawColor
import at.hannibal2.skyhanni.utils.RenderUtils.drawString
import net.minecraft.entity.item.EntityArmorStand
import net.minecraft.entity.monster.EntityEnderman
import net.minecraft.init.Blocks
import net.minecraft.network.play.server.S23PacketBlockChange
import net.minecraftforge.client.event.RenderWorldLastEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent

class EndermanSlayerBeacon {

    private val endermenWithBeacons = mutableListOf<EntityEnderman>()
    private val flyingBeacons = mutableListOf<EntityArmorStand>()
    private val sittingBeacon = mutableListOf<LorenzVec>()
    private val logger = LorenzLogger("slayer/voildgloom_beacon")

    @SubscribeEvent
    fun onCheckRender(event: CheckRenderEntityEvent<*>) {
        val entity = event.entity
        if (entity in endermenWithBeacons || entity in flyingBeacons) return

        if (entity is EntityEnderman) {
            if (hasBeaconInHand(entity) && canSee(LocationUtils.playerEyeLocation(), entity.getLorenzVec())) {
                endermenWithBeacons.add(entity)
                logger.log("Added enderman with beacon at ${entity.getLorenzVec()}")
            }
        }

        if (entity is EntityArmorStand) {
            val stack = entity.inventory[4] ?: return
            if (stack.name == "Beacon" && canSee(LocationUtils.playerEyeLocation(), entity.getLorenzVec())) {
                flyingBeacons.add(entity)
                logger.log("Added flying beacons at ${entity.getLorenzVec()}")
            }
        }
    }

    private fun hasBeaconInHand(entity: EntityEnderman): Boolean {
        val heldBlockState = entity.heldBlockState ?: return false
        val block = heldBlockState.block ?: return false
        return block == Blocks.beacon
    }

    private fun canSee(a: LorenzVec, b: LorenzVec): Boolean = LocationUtils.canSee(a, b) || a.distance(b) < 15

    @SubscribeEvent
    fun onRenderMobColored(event: RenderMobColoredEvent) {
        if (!isEnabled()) return

        if (event.entity in flyingBeacons) {
            event.color = LorenzColor.DARK_RED.toColor().withAlpha(1)
        }
    }

    @SubscribeEvent(priority = EventPriority.HIGH)
    fun onWorldRender(event: RenderWorldLastEvent) {
        if (!isEnabled()) return

        endermenWithBeacons.removeIf { it.isDead || !hasBeaconInHand(it) }

        endermenWithBeacons.map { it.getLorenzVec().add(-0.5, 0.2, -0.5) }
            .forEach { event.drawColor(it, LorenzColor.DARK_RED, alpha = 1f) }

        for (location in sittingBeacon.toMutableList()) {
            event.drawColor(location, LorenzColor.DARK_RED, alpha = 1f)
            event.drawString(location.add(0.5, 0.5, 0.5), "§4Beacon", true)
        }
    }

    @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
    fun onPacketReceive(event: PacketEvent.ReceiveEvent) {
        if (!isEnabled()) return

        val packet = event.packet
        if (packet is S23PacketBlockChange) {
            val location = packet.blockPosition.toLorenzVec()
            if (packet.blockState?.block == Blocks.beacon) {
                val armorStand = flyingBeacons.find { location.distance(it.getLorenzVec()) < 3 }
                if (armorStand != null) {
                    flyingBeacons.remove(armorStand)
                    sittingBeacon.add(location)
                    logger.log("Replaced flying beacon with sitting beacon at $location")
                }
            } else {
                if (location in sittingBeacon) {
                    logger.log("Removed sitting beacon $location")
                    sittingBeacon.remove(location)
                }
            }
        }
    }

    private fun isEnabled(): Boolean = LorenzUtils.inSkyBlock &&
            SkyHanniMod.feature.slayer.slayerEndermanBeacon &&
            LorenzUtils.skyBlockIsland == IslandType.THE_END &&
            DamageIndicatorManager.isBossSpawned(
                BossType.SLAYER_ENDERMAN_2,
                BossType.SLAYER_ENDERMAN_3,
                BossType.SLAYER_ENDERMAN_4
            )

    @SubscribeEvent
    fun onWorldChange(event: WorldEvent.Load) {
        endermenWithBeacons.clear()
        flyingBeacons.clear()
        sittingBeacon.clear()
        logger.log("Reset everything (world change)")
    }
}