@@ -23,7 +23,6 @@ import com.lambda.context.SafeContext
2323import com.lambda.event.EventFlow.post
2424import com.lambda.event.events.ConnectionEvent
2525import com.lambda.event.events.EntityEvent
26- import com.lambda.event.events.TickEvent
2726import com.lambda.event.events.UpdateManagerEvent
2827import com.lambda.event.events.WorldEvent
2928import com.lambda.event.listener.SafeListener.Companion.listen
@@ -113,94 +112,100 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
113112 }
114113
115114 init {
116- listen<TickEvent . Pre >(priority = Int . MIN_VALUE + 1 ) {
115+ listen<UpdateManagerEvent . Hotbar . Pre > {
117116 preEvent()
118117
119118 pendingBreaks.cleanUp()
120119 updateRequest()
121- if (isOnBreakCooldown()) {
122- blockBreakingCooldown--
123- } else if (currentRequest == null ) {
124- breakingInfos.forEach { it?.cancelBreak(player, world, interaction) }
125- } else currentRequest?.let request@ { request ->
126- val breakConfig = request.buildConfig.breakSettings
127-
128- val validNewContexts = request.contexts
129- .filter { ctx -> canAccept(ctx) }
130- .sortedWith(
131- compareByDescending<BreakContext > { it.instantBreak }
132- .thenByDescending { it.hotbarIndex == HotbarManager .serverSlot }
133- ).toMutableList()
120+ val request = currentRequest ? : breakingInfos.filterNotNull().firstOrNull()?.request ? : return @listen
121+
122+ val hotbarRequest = HotbarRequest (request.hotbarConfig) {
123+ if (isOnBreakCooldown()) {
124+ blockBreakingCooldown--
125+ } else if (currentRequest == null ) {
126+ breakingInfos.forEach { it?.cancelBreak(player, world, interaction) }
127+ } else currentRequest?.let request@ { currentRequest ->
128+ val breakConfig = currentRequest.buildConfig.breakSettings
129+ val validNewContexts = currentRequest.contexts
130+ .filter { ctx -> canAccept(ctx) }
131+ .sortedWith(
132+ compareByDescending<BreakContext > { it.instantBreak }
133+ .thenByDescending { it.hotbarIndex == HotbarManager .serverSlot }
134+ ).toMutableList()
135+
136+ breakingInfos
137+ .filterNotNull()
138+ .forEach { info ->
139+ validNewContexts.find {
140+ ctx -> ctx.expectedPos == info.context.expectedPos
141+ }?.let { ctx ->
142+ info.updateInfo(ctx, currentRequest)
143+ validNewContexts.remove(ctx)
144+ return @forEach
145+ }
146+
147+ info.cancelBreak(player, world, interaction)
148+ }
149+ if (atMaxBreakingInfos(currentRequest.buildConfig.breakSettings)) return @request
150+
151+ val maxBreaksThisTick = breakConfig.maxPendingBreaks - (breakingInfos.count { it != null } + pendingBreaks.size)
152+ if (maxBreaksThisTick <= 0 ) return @request
153+ val instantBreaks = validNewContexts
154+ .take(breakConfig.instantBreaksPerTick.coerceAtMost(maxBreaksThisTick))
155+ .filter { it.instantBreak }
156+
157+ if (instantBreaks.isNotEmpty()) {
158+ instantBreaks.forEach { ctx ->
159+ if (ctx.hotbarIndex != HotbarManager .serverSlot) {
160+ if (! swapTo(ctx.hotbarIndex)) return @request
161+ }
162+ val breakInfo = handleRequestContext(ctx, currentRequest) ? : return @request
163+ currentRequest.onAccept?.invoke(ctx.expectedPos)
164+ updateBlockBreakingProgress(breakInfo)
165+ activeThisTick = true
166+ }
167+ if (instantBreaks.size == breakConfig.instantBreaksPerTick) return @request
168+ }
134169
135- breakingInfos
136- .filterNotNull()
137- .forEach { info ->
138- validNewContexts.find {
139- ctx -> ctx.expectedPos == info.context.expectedPos
140- }?.let { ctx ->
141- info.updateInfo(ctx, request)
142- validNewContexts.remove(ctx)
143- return @forEach
170+ validNewContexts
171+ .filter { ! it.instantBreak }
172+ .forEach { ctx ->
173+ handleRequestContext(ctx, currentRequest) ? : return @request
174+ currentRequest.onAccept?.invoke(ctx.expectedPos)
175+ if (atMaxBreakingInfos(currentRequest.buildConfig.breakSettings)) return @request
144176 }
177+ }
145178
146- info.cancelBreak(player, world, interaction)
179+ breakingInfos
180+ .firstOrNull { it?.breakConfig?.rotateForBreak == true && ! it.redundant }
181+ ?.let { info ->
182+ // If the simulation cant find a valid rotation to the block,
183+ // the existing break context stays and the keep ticks deplete until rotations stop
184+ if (info.context.rotation.keepTicks <= 0 ) null
185+ else info.rotationConfig.request(info.context.rotation)
147186 }
148- if (atMaxBreakingInfos(request.buildConfig.breakSettings)) return @request
149-
150- val maxBreaksThisTick = breakConfig.maxPendingBreaks - (breakingInfos.count { it != null } + pendingBreaks.size)
151- if (maxBreaksThisTick <= 0 ) return @request
152- val instantBreaks = validNewContexts
153- .take(breakConfig.instantBreaksPerTick.coerceAtMost(maxBreaksThisTick))
154- .filter { it.instantBreak }
155-
156- if (instantBreaks.isNotEmpty()) {
157- instantBreaks.forEach { ctx ->
158- if (ctx.hotbarIndex != HotbarManager .serverSlot) {
159- if (! request.hotbarConfig.request(HotbarRequest (ctx.hotbarIndex)).done) return @request
187+ ?.let { rot ->
188+ if (! rot.done) {
189+ return @HotbarRequest
160190 }
161- val breakInfo = handleRequestContext(ctx, request) ? : return @request
162- request.onAccept?.invoke(ctx.expectedPos)
163- updateBlockBreakingProgress(breakInfo)
164- activeThisTick = true
165191 }
166- if (instantBreaks.size == breakConfig.instantBreaksPerTick) return @request
167- }
168192
169- validNewContexts
170- .filter { ! it.instantBreak }
171- .forEach { ctx ->
172- handleRequestContext(ctx, request) ? : return @request
173- request.onAccept?.invoke(ctx.expectedPos)
174- if (atMaxBreakingInfos(request.buildConfig.breakSettings)) return @request
193+ // Reversed so that the breaking order feels natural to the user as the primary break has to
194+ // be started after the secondary
195+ breakingInfos
196+ .filterNotNull()
197+ .reversed()
198+ .forEach { info ->
199+ if (! info.redundant && ! swapTo(info.context.hotbarIndex)) return @HotbarRequest
200+ updateBlockBreakingProgress(info)
201+ if (! info.redundant) activeThisTick = true
175202 }
203+ done()
176204 }
205+ request.hotbarConfig.request(hotbarRequest)
206+ }
177207
178- breakingInfos
179- .firstOrNull { it?.breakConfig?.rotateForBreak == true && ! it.redundant }
180- ?.let { info ->
181- // If the simulation cant find a valid rotation to the block,
182- // the existing break context stays and the keep ticks deplete until rotations stop
183- if (info.context.rotation.keepTicks <= 0 ) null
184- else info.rotationConfig.request(info.context.rotation)
185- }
186- ?.let { rot ->
187- if (! rot.done) {
188- postEvent()
189- return @listen
190- }
191- }
192-
193- // Reversed so that the breaking order feels natural to the user as the primary break has to
194- // be started after the secondary
195- breakingInfos
196- .filterNotNull()
197- .reversed()
198- .forEach { info ->
199- if (! info.redundant && ! info.requestHotbarSwap()) return @forEach
200- updateBlockBreakingProgress(info)
201- if (! info.redundant) activeThisTick = true
202- }
203-
208+ listen<UpdateManagerEvent .Hotbar .Post > {
204209 postEvent()
205210 }
206211
@@ -345,7 +350,7 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
345350 setBreakCooldown(info.breakConfig.breakDelay)
346351 interaction.sendSequencedPacket(world) { sequence ->
347352 onBlockBreak(info)
348- PlayerActionC2SPacket (PlayerActionC2SPacket . Action .START_DESTROY_BLOCK , ctx.expectedPos, hitResult.side, sequence)
353+ PlayerActionC2SPacket (Action .START_DESTROY_BLOCK , ctx.expectedPos, hitResult.side, sequence)
349354 }
350355 val swing = info.breakConfig.swing
351356 if (swing.isEnabled()) {
@@ -419,7 +424,7 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
419424 if (info.type == BreakType .Primary ) {
420425 interaction.sendSequencedPacket(world) { sequence ->
421426 onBlockBreak(info)
422- PlayerActionC2SPacket (PlayerActionC2SPacket . Action .STOP_DESTROY_BLOCK , ctx.expectedPos, hitResult.side, sequence)
427+ PlayerActionC2SPacket (Action .STOP_DESTROY_BLOCK , ctx.expectedPos, hitResult.side, sequence)
423428 }
424429 } else {
425430 onBlockBreak(info)
@@ -442,7 +447,7 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
442447 if (gamemode.isCreative) {
443448 interaction.sendSequencedPacket(world) { sequence: Int ->
444449 onBlockBreak(info)
445- PlayerActionC2SPacket (PlayerActionC2SPacket . Action .START_DESTROY_BLOCK , ctx.expectedPos, ctx.result.side, sequence)
450+ PlayerActionC2SPacket (Action .START_DESTROY_BLOCK , ctx.expectedPos, ctx.result.side, sequence)
446451 }
447452 setBreakCooldown(info.breakConfig.breakDelay)
448453 return true
@@ -591,9 +596,6 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
591596 }
592597 }
593598
594- fun requestHotbarSwap () =
595- request.hotbarConfig.request(HotbarRequest (context.hotbarIndex)).done
596-
597599 fun setBreakingTextureStage (
598600 player : ClientPlayerEntity ,
599601 world : ClientWorld ,
0 commit comments