11package com.lambda.client.module.modules.movement
22
3- import com.lambda.client.commons.extension.ceilToInt
4- import com.lambda.client.commons.extension.floorToInt
3+ import com.lambda.client.event.SafeClientEvent
4+ import com.lambda.client.event.events.AddCollisionBoxToListEvent
55import com.lambda.client.event.events.PacketEvent
6- import com.lambda.client.event.events.PlayerTravelEvent
7- import com.lambda.client.mixin.extension.playerMoving
6+ import com.lambda.client.event.events.PlayerMoveEvent
7+ import com.lambda.client.manager.managers.TimerManager.modifyTimer
88import com.lambda.client.mixin.extension.playerY
99import com.lambda.client.module.Category
1010import com.lambda.client.module.Module
11- import com.lambda.client.util.BaritoneUtils
12- import com.lambda.client.util.EntityUtils
11+ import com.lambda.client.util.EntityUtils.flooredPosition
12+ import com.lambda.client.util.threads.runSafe
1313import com.lambda.client.util.threads.safeListener
14+ import com.lambda.mixin.accessor.player.AccessorEntityPlayerSP
1415import net.minecraft.block.Block
15- import net.minecraft.block.BlockLiquid
16- import net.minecraft.entity.Entity
17- import net.minecraft.entity.item.EntityBoat
16+ import net.minecraft.init.Blocks
1817import net.minecraft.network.play.client.CPacketPlayer
18+ import net.minecraft.network.play.server.SPacketPlayerPosLook
1919import net.minecraft.util.math.AxisAlignedBB
2020import net.minecraft.util.math.BlockPos
21+ import net.minecraft.util.math.BlockPos.PooledMutableBlockPos
22+ import net.minecraftforge.client.event.InputUpdateEvent
23+ import net.minecraftforge.fml.common.gameevent.TickEvent
24+ import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
25+ import kotlin.math.ceil
26+ import kotlin.math.floor
27+ import kotlin.math.hypot
28+
2129
2230object Jesus : Module(
2331 name = " Jesus" ,
2432 description = " Allows you to walk on water" ,
2533 category = Category .MOVEMENT
2634) {
27- private val mode by setting(" Mode" , Mode .SOLID )
2835
29- private enum class Mode {
30- SOLID , DOLPHIN
36+ private val mode by setting(" Mode" , Mode .STRICT )
37+
38+ enum class Mode {
39+ SOLID ,
40+ STRICT ,
41+ DOLPHIN
3142 }
3243
33- private val waterWalkBox = AxisAlignedBB (0.0 , 0.0 , 0.0 , 1.0 , 0.99 , 1.0 )
44+ private val preventJump by setting(" Prevent Jumping" , false , { mode == Mode .SOLID || mode == Mode .STRICT }, description = " Prevent jumping when using Jesus" )
45+
46+ private val bb = AxisAlignedBB (- 1.0 , - 1.0 , - 1.0 , 0.0 , 0.0 , 0.0 )
47+ private val liquids = listOf (Blocks .WATER , Blocks .FLOWING_WATER , Blocks .LAVA , Blocks .FLOWING_LAVA )
48+
49+ private var ticksEnabled = 0
50+ private var fakeY = 0.0
3451
3552 init {
36- onToggle {
37- BaritoneUtils .settings?.assumeWalkOnWater?.value = it
53+ onDisable {
54+ ticksEnabled = 0
55+ fakeY = .0
3856 }
3957
40- safeListener<PlayerTravelEvent > {
41- if (mc.gameSettings.keyBindSneak.isKeyDown || player.fallDistance > 3.0f || ! isInWater(player) ) return @safeListener
58+ safeListener<ClientTickEvent > {
59+ if (it.phase != TickEvent . Phase . START ) return @safeListener
4260
43- if (mode == Mode .DOLPHIN ) {
44- player.motionY + = 0.03999999910593033 // regular jump speed
45- } else {
46- player.motionY = 0.1
61+ ticksEnabled++
62+ }
4763
48- player.ridingEntity?.let {
49- if (it !is EntityBoat ) it.motionY = 0.3
50- }
64+ safeListener<AddCollisionBoxToListEvent > {
65+ if (mc.gameSettings.keyBindSneak.isKeyDown)
66+ return @safeListener
67+
68+ if ((mode == Mode .SOLID || mode == Mode .STRICT )
69+ && world.getBlockState(BlockPos (player.positionVector.add(.0 , - .1 + player.motionY, .0 ))).material.isLiquid
70+ ) {
71+ it.collisionBoxList.add(bb.offset(player.posX, floor(player.posY), player.posZ))
5172 }
5273 }
5374
54- safeListener<PacketEvent .Send > {
55- if (it.packet !is CPacketPlayer || ! it.packet.playerMoving) return @safeListener
56- if (mc.gameSettings.keyBindSneak.isKeyDown || player.ticksExisted % 2 != 0 ) return @safeListener
75+ safeListener<PlayerMoveEvent > { event ->
76+ (player as AccessorEntityPlayerSP ).lcSetLastReportedPosY(- 99.9 )
77+
78+ if (mc.gameSettings.keyBindSneak.isKeyDown) return @safeListener
5779
58- val entity = player.ridingEntity ? : player
80+ ( player as AccessorEntityPlayerSP ).lcSetLastReportedPosY( - 999.0 )
5981
60- if (EntityUtils .isAboveLiquid(entity, true ) && ! isInWater(entity)) {
61- it.packet.playerY + = 0.02
82+ if (player.isInWater || world.getBlockState(player.flooredPosition).material.isLiquid) {
83+ event.y = (.11 .also { player.motionY = it })
84+ }
85+
86+ if (player.onGround &&
87+ ! checkBlockCollisionNoLiquid(
88+ player.entityBoundingBox.offset(.0 , - .01 , .0 ),
89+ liquids + Blocks .AIR
90+ )
91+ ) {
92+ when (mode) {
93+ Mode .DOLPHIN -> {
94+ if (hypot(event.x, event.y) > .2873 * .9 ) {
95+ event.x * = .95
96+ event.z * = .95
97+ }
98+ }
99+ Mode .STRICT -> {
100+ val lava = ! checkBlockCollisionNoLiquid(
101+ player.entityBoundingBox.offset(.0 , - .01 , .0 ),
102+ listOf (Blocks .AIR , Blocks .LAVA , Blocks .FLOWING_LAVA )
103+ )
104+ // .38 is from lava liquid speed at max speed, 1.24 is from water liquid speed at max speed
105+ // because of the way "Lambda Client" handled its "PlayerMoveEvent" I have to use "magic numbers" to compensate
106+ event.x * = if (lava) .57 else 1.09
107+ event.z * = if (lava) .57 else 1.09
108+ }
109+
110+ else -> {}
111+ }
62112 }
63113 }
64- }
65114
66- @JvmStatic
67- fun handleAddCollisionBoxToList (pos : BlockPos , block : Block , entity : Entity ? , collidingBoxes : MutableList <AxisAlignedBB >) {
68- if (isDisabled || mode == Mode .DOLPHIN ) return
69- if (mc.gameSettings.keyBindSneak.isKeyDown) return
70- if (block !is BlockLiquid ) return
71- if (entity == null || entity is EntityBoat ) return
115+ safeListener<InputUpdateEvent > {
116+ if (preventJump &&
117+ fakeY != .0
118+ ) it.movementInput.jump = false
119+ }
72120
73- val player = mc.player ? : return
74- if (player.fallDistance > 3.0f ) return
121+ safeListener< PacketEvent . Send > { event ->
122+ if (event.packet !is CPacketPlayer ) return @safeListener
75123
76- if (entity != player && entity != player.ridingEntity) return
77- if (isInWater(entity) || entity.posY < pos.y) return
78- if (! EntityUtils .isAboveLiquid(entity)) return
124+ if (mc.gameSettings.keyBindSneak.isKeyDown) {
125+ if (mode == Mode .STRICT ) {
126+ player.posY - = fakeY
127+ }
79128
80- collidingBoxes.add(waterWalkBox.offset(pos))
81- }
129+ fakeY = 0.0
130+ return @safeListener
131+ }
132+
133+ val playerBB = player.entityBoundingBox
134+ if (player.isInWater
135+ || ! world.getBlockState(BlockPos (player.positionVector.add(.0 , - .1 + player.motionY, .0 ))).material.isLiquid
136+ || world.getCollisionBoxes(player, playerBB.offset(0.0 , - .0001 , 0.0 )).isEmpty()
137+ ) {
138+ fakeY = 0.0
139+ return @safeListener
140+ }
141+
142+ val packet = event.packet
143+
144+ when (mode) {
145+ Mode .STRICT -> {
146+ if ((- .4 ).coerceAtLeast(fakeY).also { fakeY = it } > - .4 ) {
147+ fakeY - = .08
148+ fakeY * = .98
149+ packet.playerY + = fakeY
150+ } else {
151+ packet.playerY + = fakeY - if (ticksEnabled % 2 == 0 ) .0 else - .00001
152+ }
153+
154+ if (checkBlockCollisionNoLiquid(
155+ player.entityBoundingBox.offset(.0 , packet.playerY - player.posY, .0 ),
156+ liquids + Blocks .AIR
157+ )) {
158+ packet.playerY = player.posY
159+ }
160+ }
161+ Mode .SOLID -> {
162+ fakeY = 0.0
82163
83- private fun isInWater (entity : Entity ): Boolean {
84- mc.world?.let {
85- val y = (entity.posY + 0.01 ).floorToInt()
164+ if (ticksEnabled % 2 == 0 ) packet.playerY - = .001
86165
87- for (x in entity.posX.floorToInt() until entity.posX.ceilToInt()) {
88- for (z in entity.posZ.floorToInt() until entity.posZ.ceilToInt()) {
89- val pos = BlockPos (x, y, z)
90- if (it.getBlockState(pos).block is BlockLiquid ) return true
166+ if (checkBlockCollisionNoLiquid(
167+ player.entityBoundingBox.offset(.0 , packet.playerY - player.posY, .0 ),
168+ liquids + Blocks .AIR
169+ )) {
170+ packet.playerY = player.posY
171+ }
91172 }
173+
174+ else -> {}
92175 }
93176 }
94177
95- return false
178+ safeListener<PacketEvent .Receive > {
179+ if (it.packet !is SPacketPlayerPosLook ) return @safeListener
180+
181+ fakeY = player.posY - it.packet.y
182+ }
96183 }
97184
185+ private fun SafeClientEvent.checkBlockCollisionNoLiquid (bb : AxisAlignedBB , allowed : List <Block >): Boolean {
186+ val minX = floor(bb.minX).toInt()
187+ val maxX = ceil(bb.maxX).toInt()
188+ val minY = floor(bb.minY).toInt()
189+ val maxY = ceil(bb.maxY).toInt()
190+ val minZ = floor(bb.minZ).toInt()
191+ val maxZ = ceil(bb.maxZ).toInt()
192+
193+ val mutableBlockPos = PooledMutableBlockPos .retain()
194+
195+ for (x in minX until maxX) {
196+ for (y in minY until maxY) {
197+ for (z in minZ until maxZ) {
198+ val blockState = world.getBlockState(mutableBlockPos.setPos(x, y, z))
199+
200+ if (! allowed.contains(blockState.block)) {
201+ mutableBlockPos.release()
202+ return true
203+ }
204+ }
205+ }
206+ }
207+
208+ mutableBlockPos.release()
209+ return false
210+ }
98211}
0 commit comments