11package com.lambda.interaction
22
3- import com.lambda.Loadable
3+ import com.lambda.core. Loadable
44import com.lambda.context.SafeContext
5- import com.lambda.event.EventFlow
5+ import com.lambda.event.EventFlow.post
6+ import com.lambda.event.EventFlow.postChecked
7+ import com.lambda.event.events.PacketEvent
68import com.lambda.event.events.PlayerPacketEvent
7- import com.lambda.interaction.rotation.Rotation
9+ import com.lambda.event.listener.SafeListener.Companion.listener
810import com.lambda.threading.runSafe
11+ import com.lambda.util.Communication.warn
12+ import com.lambda.util.collections.LimitedOrderedSet
13+ import com.lambda.util.math.VecUtils.dist
914import com.lambda.util.math.VecUtils.distSq
1015import com.lambda.util.player.MovementUtils.motionX
1116import com.lambda.util.player.MovementUtils.motionZ
1217import com.lambda.util.primitives.extension.component1
1318import com.lambda.util.primitives.extension.component2
1419import com.lambda.util.primitives.extension.component3
20+ import com.lambda.util.text.Color
21+ import com.lambda.util.text.buildText
22+ import com.lambda.util.text.color
23+ import com.lambda.util.text.literal
1524import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket
1625import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket.*
26+ import net.minecraft.network.packet.s2c.play.PlayerPositionLookS2CPacket
1727import net.minecraft.util.math.MathHelper.square
1828import net.minecraft.util.math.Vec3d
1929
2030object PlayerPacketManager : Loadable {
21- private var prevPosition: Vec3d = Vec3d .ZERO
22- private var lastPosition = Vec3d (0.0 , - 1000.0 , 0.0 )
23- private var lastRotation = Rotation (0.0 , - 10000.0 )
24- private var lastOnGround: Boolean? = null
25- private var lastSprinting: Boolean? = null
26- private var lastSneaking: Boolean? = null
31+ private val configurations = LimitedOrderedSet <PlayerPacketEvent .Pre >(100 )
2732 private var sendTicks = 0
2833
2934 @JvmStatic
3035 fun sendPlayerPackets () {
3136 runSafe {
32- EventFlow .post(
33- PlayerPacketEvent .Pre (
34- player.pos,
35- RotationManager .currentRotation,
36- player.isOnGround,
37- player.isSprinting
38- )
39- ) {
37+ PlayerPacketEvent .Pre (
38+ player.pos,
39+ RotationManager .currentRotation,
40+ player.isOnGround,
41+ player.isSprinting,
42+ player.isSneaking
43+ ).post {
4044 updatePlayerPackets(this )
4145 }
4246 }
4347 }
4448
45- private fun SafeContext. updatePlayerPackets ( event : PlayerPacketEvent . Pre ) {
46- reportSprint(event.isSprinting)
47- reportSneak(player.isSneaking)
49+ init {
50+ listener< PacketEvent . Receive . Pre > { event ->
51+ if (event.packet !is PlayerPositionLookS2CPacket ) return @listener
4852
49- if (mc.cameraEntity != player) return
53+ if (configurations.isEmpty()) {
54+ warn(" Position was reverted" , " Rubberband" )
55+ return @listener
56+ }
57+
58+ val newPos = Vec3d (event.packet.x, event.packet.y, event.packet.z)
59+ val last = configurations.minBy {
60+ it.position distSq newPos
61+ }
62+ val delta = last.position dist newPos
63+
64+ warn(buildText {
65+ literal(" Reverted position by " )
66+ color(Color .YELLOW ) {
67+ literal(" ${configurations.reversed().indexOf(last) + 1 } " )
68+ }
69+ literal(" ticks (derivation: " )
70+ color(Color .YELLOW ) {
71+ literal(" %.3f" .format(delta))
72+ }
73+ literal(" )" )
74+ }, " Rubberband" )
75+ }
76+ }
5077
51- val position = event.position
52- val rotation = event.rotation
53- val ground = event.onGround
78+ private fun SafeContext. updatePlayerPackets ( new : PlayerPacketEvent . Pre ) {
79+ val previous = configurations.lastOrNull() ? : new
80+ configurations.add(new)
5481
55- RotationManager .currentRotation = rotation
82+ reportSprint(previous, new)
83+ reportSneak(previous, new)
84+
85+ if (mc.cameraEntity != player) return
86+
87+ RotationManager .currentRotation = new.rotation
5688
5789 if (player.hasVehicle()) {
5890 connection.sendPacket(
5991 Full (
6092 player.motionX,
6193 - 999.0 ,
6294 player.motionZ,
63- rotation.yaw.toFloat(),
64- rotation.pitch.toFloat(),
65- ground
95+ new. rotation.yaw.toFloat(),
96+ new. rotation.pitch.toFloat(),
97+ new.onGround
6698 )
6799 )
68- lastRotation = rotation
69100 return
70101 }
71102
72- val updatePosition = (position.subtract(lastPosition ) distSq Vec3d .ZERO ) > square(2 .0E- 4 ) || ++ sendTicks >= 20
73- val updateRotation = rotation != lastRotation
103+ val updatePosition = (new. position.subtract(previous.position ) distSq Vec3d .ZERO ) > square(2 .0E- 4 ) || ++ sendTicks >= 20
104+ val updateRotation = new. rotation != previous.rotation
74105
75- val (x, y, z) = position
106+ val (x, y, z) = new. position
76107
77- val (yawD, pitchD) = rotation
108+ val (yawD, pitchD) = new. rotation
78109 val (yaw, pitch) = yawD.toFloat() to pitchD.toFloat()
79110
80111 val packet = when {
81112 updatePosition && updateRotation -> {
82- Full (x, y, z, yaw, pitch, ground )
113+ Full (x, y, z, yaw, pitch, new.onGround )
83114 }
84115
85116 updatePosition -> {
86- PositionAndOnGround (x, y, z, ground )
117+ PositionAndOnGround (x, y, z, new.onGround )
87118 }
88119
89120 updateRotation -> {
90- LookAndOnGround (yaw, pitch, ground )
121+ LookAndOnGround (yaw, pitch, new.onGround )
91122 }
92123
93- lastOnGround != ground -> {
94- OnGroundOnly (ground )
124+ previous.onGround != new.onGround -> {
125+ OnGroundOnly (new.onGround )
95126 }
96127
97128 else -> null
98129 }
99130
100131 if (updatePosition) {
101- prevPosition = lastPosition
102- lastPosition = position
103132 sendTicks = 0
104133 }
105- if (updateRotation) {
106- lastRotation = rotation
107- }
108-
109- lastOnGround = ground
110134
111135 packet?.let {
112- EventFlow .postChecked( PlayerPacketEvent .Post (it)) {
136+ PlayerPacketEvent .Post (it).postChecked {
113137 connection.sendPacket(this .packet)
114138 }
115139 }
116140 }
117141
118- private fun SafeContext.reportSprint (isSprinting : Boolean ) {
119- if (lastSprinting == isSprinting) return
120- lastSprinting = isSprinting
142+ private fun SafeContext.reportSprint (previous : PlayerPacketEvent .Pre , new : PlayerPacketEvent .Pre ) {
143+ if (previous.isSprinting == new.isSprinting) return
121144
122- val state = if (isSprinting) {
145+ val state = if (new. isSprinting) {
123146 ClientCommandC2SPacket .Mode .START_SPRINTING
124147 } else {
125148 ClientCommandC2SPacket .Mode .STOP_SPRINTING
@@ -128,12 +151,14 @@ object PlayerPacketManager : Loadable {
128151 connection.sendPacket(ClientCommandC2SPacket (player, state))
129152 }
130153
131- private fun SafeContext.reportSneak (flag : Boolean ) {
132- if (lastSneaking == flag) return
133- lastSneaking = flag
154+ private fun SafeContext.reportSneak (previous : PlayerPacketEvent .Pre , new : PlayerPacketEvent .Pre ) {
155+ if (previous.isSneaking == new.isSneaking) return
134156
135- val state = if (flag) ClientCommandC2SPacket .Mode .PRESS_SHIFT_KEY
136- else ClientCommandC2SPacket .Mode .RELEASE_SHIFT_KEY
157+ val state = if (new.isSneaking) {
158+ ClientCommandC2SPacket .Mode .PRESS_SHIFT_KEY
159+ } else {
160+ ClientCommandC2SPacket .Mode .RELEASE_SHIFT_KEY
161+ }
137162
138163 connection.sendPacket(ClientCommandC2SPacket (player, state))
139164 }
0 commit comments