@@ -23,6 +23,7 @@ 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.MovementEvent
2627import com.lambda.event.events.UpdateManagerEvent
2728import com.lambda.event.events.WorldEvent
2829import com.lambda.event.listener.SafeListener.Companion.listen
@@ -131,57 +132,7 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
131132 ? : breakInfos.firstOrNull { it != null }?.request?.hotbarConfig
132133 ? : return @listen
133134
134- hotbarRequest = HotbarRequest (hotbarConfig) {
135- if (isOnBreakCooldown()) {
136- blockBreakingCooldown--
137- } else if (currentRequest == null ) {
138- breakInfos.forEach { it?.cancelBreak() }
139- } else currentRequest?.let request@ { request ->
140- val breakConfig = request.buildConfig.breakSettings
141-
142- newBreaks = request.contexts
143- .filter { ctx -> canAccept(ctx) }
144- .sortedWith(
145- compareByDescending<BreakContext > { it.instantBreak }
146- .thenByDescending { it.hotbarIndex == HotbarManager .serverSlot }
147- ).toMutableList()
148-
149- refreshOrCancelBreaks(newBreaks, request)
150- if (atMaxBreakInfos(breakConfig)) return @request
151-
152- val maxBreaks = getMaxBreaks(breakConfig)
153- if (maxBreaks <= 0 ) return @request
154- val maxInstantBreaks = breakConfig.instantBreaksPerTick.coerceAtMost(maxBreaks)
155-
156- val uncappedInstantBreaks = newBreaks.filter { it.instantBreak }
157- instantBreaks = uncappedInstantBreaks.take(maxInstantBreaks)
158- excessInstantBreaks = uncappedInstantBreaks.size > instantBreaks.size
159-
160- instantBreaks.forEach { ctx ->
161- if (! swapTo(ctx.hotbarIndex)) return @request
162- val breakInfo = handleNewBreak(ctx, request) ? : return @request
163- request.onAccept?.invoke(ctx.expectedPos)
164- updateBreakProgress(breakInfo)
165- }
166- if (excessInstantBreaks) return @request
167- processNewBreaks(newBreaks, request)
168- }
169-
170- updateLiveBreakInfos()
171- rotation = liveBreakInfos.firstOrNull { it.breakConfig.rotateForBreak }?.let { info ->
172- info.rotationConfig.request(info.context.rotation)
173- }
174-
175- // Reversed so that the breaking order feels natural to the user as the primary break has to
176- // be started after the secondary
177- liveBreakInfos
178- .reversed()
179- .forEach { info ->
180- if (! swapTo(info.context.hotbarIndex) || ! validRotation) return @HotbarRequest
181- updateBreakProgress(info)
182- }
183- done()
184- }
135+ hotbarRequest = HotbarRequest (hotbarConfig) { if (update(::swapTo, tickPre = true )) done() }
185136 hotbarRequest?.let { hotbarRequest ->
186137 hotbarConfig.request(hotbarRequest)
187138 }
@@ -190,6 +141,15 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
190141 }
191142 }
192143
144+ listen<MovementEvent .Player .Post > {
145+ val sequenceMode = currentRequest?.buildConfig?.breakSettings?.sequenceMode
146+ ? : breakInfos.find { it != null }?.breakConfig?.sequenceMode
147+ ? : return @listen
148+ if (sequenceMode == BuildConfig .InteractSequenceMode .PostMovement ) {
149+ update(null )
150+ }
151+ }
152+
193153 listen<WorldEvent .BlockUpdate .Server >(priority = Int .MIN_VALUE + 1 ) { event ->
194154 pendingBreaks
195155 .firstOrNull { it.context.expectedPos == event.pos }
@@ -259,14 +219,75 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
259219 }
260220 }
261221
222+ private fun SafeContext.update (swapTo : ((slot: Int ) -> Boolean )? , tickPre : Boolean = false): Boolean {
223+ if (tickPre) {
224+ if (isOnBreakCooldown()) {
225+ blockBreakingCooldown--
226+ } else if (currentRequest == null ) {
227+ breakInfos.forEach { it?.cancelBreak() }
228+ }
229+ }
230+
231+ if (! isOnBreakCooldown()) currentRequest?.let request@ { request ->
232+ val breakConfig = request.buildConfig.breakSettings
233+
234+ if (tickPre) {
235+ newBreaks = request.contexts
236+ .filter { ctx -> canAccept(ctx) }
237+ .sortedWith(
238+ compareByDescending<BreakContext > { it.instantBreak }
239+ .thenByDescending { it.hotbarIndex == HotbarManager .serverSlot }
240+ ).toMutableList()
241+
242+ refreshOrCancelBreaks(newBreaks, request)
243+
244+ val maxBreaks = getMaxBreaks(breakConfig).coerceAtLeast(0 )
245+ val maxInstantBreaks = breakConfig.instantBreaksPerTick.coerceAtMost(maxBreaks)
246+
247+ val uncappedInstantBreaks = newBreaks.filter { it.instantBreak }
248+ instantBreaks = uncappedInstantBreaks.take(maxInstantBreaks)
249+ excessInstantBreaks = uncappedInstantBreaks.size > instantBreaks.size
250+ }
251+
252+ if (atMaxBreakInfos(breakConfig)) return @request
253+ instantBreaks.forEach { ctx ->
254+ swapTo?.invoke(ctx.hotbarIndex)
255+ val mismatchedTiming = tickPre && breakConfig.sequenceMode != BuildConfig .InteractSequenceMode .TickStart
256+ if (mismatchedTiming) return false
257+ if (! swapped) return @request
258+ val breakInfo = handleNewBreak(ctx, request) ? : return @request
259+ request.onAccept?.invoke(ctx.expectedPos)
260+ updateBreakProgress(breakInfo)
261+ }
262+ if (! excessInstantBreaks) processNewBreaks(newBreaks, request)
263+ }
264+
265+ updateLiveBreakInfos()
266+ rotation = liveBreakInfos.firstOrNull { it.breakConfig.rotateForBreak }?.let { info ->
267+ info.rotationConfig.request(info.context.rotation)
268+ }
269+
270+ // Reversed so that the breaking order feels natural to the user as the primary break has to
271+ // be started after the secondary
272+ liveBreakInfos
273+ .reversed()
274+ .forEach { info ->
275+ swapTo?.invoke(info.context.hotbarIndex)
276+ val mismatchedTiming = tickPre && info.breakConfig.sequenceMode != BuildConfig .InteractSequenceMode .TickStart
277+ if (! swapped || ! validRotation || mismatchedTiming) return false
278+ updateBreakProgress(info)
279+ }
280+
281+ return true
282+ }
283+
262284 private fun refreshOrCancelBreaks (newContexts : MutableCollection <BreakContext >, request : BreakRequest ) {
263285 breakInfos
264- .filterNotNull()
265- .forEach { info ->
286+ .forEachNotNull { info ->
266287 newContexts.find { ctx -> ctx.expectedPos == info.context.expectedPos }?.let { ctx ->
267288 info.updateInfo(ctx, request)
268289 newContexts.remove(ctx)
269- return @forEach
290+ return @forEachNotNull
270291 }
271292
272293 info.cancelBreak()
@@ -598,6 +619,10 @@ object BreakManager : RequestHandler<BreakRequest>(), PositionBlocking {
598619 else -> secondaryBreak = null
599620 }
600621
622+ private fun Array<BreakInfo?>.forEachNotNull (block : (BreakInfo ) -> Unit ) {
623+ for (info in this ) info?.run (block)
624+ }
625+
601626 override fun preEvent () = UpdateManagerEvent .Break .Pre ().post()
602627 override fun postEvent () = UpdateManagerEvent .Break .Post ().post()
603628}
0 commit comments