Skip to content

Commit b5c565c

Browse files
authored
Feature: EndermanLook Module (#316)
1 parent 8c653c4 commit b5c565c

1 file changed

Lines changed: 102 additions & 0 deletions

File tree

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright 2026 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.module.modules.player
19+
20+
import com.lambda.config.ConfigEditor.hideAllExcept
21+
import com.lambda.config.automation.AutomationConfig.Companion.setDefaultAutomationConfig
22+
import com.lambda.config.withEdits
23+
import com.lambda.context.SafeContext
24+
import com.lambda.event.events.TickEvent
25+
import com.lambda.event.listener.SafeListener.Companion.listen
26+
import com.lambda.interaction.managers.rotating.IRotationRequest.Companion.rotationRequest
27+
import com.lambda.interaction.managers.rotating.Rotation.Companion.rotationTo
28+
import com.lambda.module.Module
29+
import com.lambda.module.tag.ModuleTag
30+
import com.lambda.util.math.distSq
31+
import net.minecraft.entity.EquipmentSlot
32+
import net.minecraft.entity.mob.EndermanEntity
33+
import net.minecraft.item.Items
34+
import net.minecraft.util.math.Vec3d
35+
36+
@Suppress("unused")
37+
object EndermanLook : Module(
38+
name = "EndermanLook",
39+
description = "Either stares at every enderman or stops you from staring at them",
40+
tag = ModuleTag.PLAYER,
41+
) {
42+
private val mode by setting("Mode", Mode.Away, "Whether to stare down endermen or avoid their gaze")
43+
private val stunHostiles by setting("Stun Hostiles", true, "Stare back at already provoked endermen to freeze them") { mode == Mode.Away }
44+
private val disableWhileGliding by setting("Disable While Gliding", true, "Disables when gliding with an elytra")
45+
46+
private const val STARE_CONE = 0.025 // vanilla to aggro endermen
47+
48+
init {
49+
setDefaultAutomationConfig()
50+
.withEdits {
51+
hideAllExcept(::rotationConfig)
52+
}
53+
54+
listen<TickEvent.Pre> {
55+
if (player.getEquippedStack(EquipmentSlot.HEAD).isOf(Items.CARVED_PUMPKIN)
56+
|| player.abilities.creativeMode
57+
|| (disableWhileGliding && player.isGliding)
58+
) return@listen
59+
60+
val endermen = world.entities
61+
.filterIsInstance<EndermanEntity>()
62+
.filter { it.isAlive && player.canSee(it) }
63+
64+
when (mode) {
65+
Mode.At -> closest(endermen.filter { !it.isAngry })
66+
?.let { stareAt(it) }
67+
68+
Mode.Away -> {
69+
val (stunnable, rest) = endermen.partition { it.isAngry && stunHostiles }
70+
71+
closest(stunnable)?.let { stareAt(it) }
72+
?: closest(rest.filter { isStaringAt(it) })?.let { lookAway() }
73+
}
74+
}
75+
}
76+
}
77+
78+
private fun SafeContext.stareAt(enderman: EndermanEntity) =
79+
rotationRequest { rotation(player.eyePos.rotationTo(enderman.eyePos)) }.submit()
80+
81+
private fun lookAway() =
82+
rotationRequest { pitch(90f) }.submit()
83+
84+
private fun SafeContext.closest(endermen: List<EndermanEntity>) =
85+
endermen.minByOrNull { it.eyePos distSq player.eyePos }
86+
87+
private fun SafeContext.isStaringAt(enderman: EndermanEntity): Boolean {
88+
val diff = Vec3d(
89+
enderman.x - player.x,
90+
enderman.eyeY - player.eyeY,
91+
enderman.z - player.z
92+
)
93+
94+
return player.getRotationVec(1f).normalize()
95+
.dotProduct(diff.normalize()) > 1.0 - STARE_CONE / diff.length()
96+
}
97+
98+
enum class Mode {
99+
At,
100+
Away
101+
}
102+
}

0 commit comments

Comments
 (0)