@@ -101,39 +101,49 @@ object BreakManager : RequestHandler<BreakRequest>(
101101 onOpen = { processRequest(activeRequest); simulateAbandoned() },
102102 onClose = { checkForCancels() }
103103), PositionBlocking {
104+ private val breakInfos = arrayOfNulls<BreakInfo >(2 )
105+
106+ private val activeInfos
107+ get() = breakInfos
108+ .filterNotNull()
109+ .filter { it.type != RedundantSecondary }
110+
104111 private var primaryBreak: BreakInfo ?
105112 get() = breakInfos[0 ]
106113 set(value) { breakInfos[0 ] = value }
114+
107115 private var secondaryBreak: BreakInfo ?
108116 get() = breakInfos[1 ]
109117 set(value) { breakInfos[1 ] = value }
110- private val breakInfos = arrayOfNulls<BreakInfo >(2 )
118+
119+ private val abandonedBreak
120+ get() = breakInfos[1 ].let { secondary ->
121+ if (secondary?.abandoned == true && secondary.type != RedundantSecondary ) secondary
122+ else null
123+ }
124+
111125 val currentStackSelection
112- get() = breakInfos
126+ get() = activeInfos
113127 .lastOrNull {
114- it != null && it.type != RedundantSecondary && (it. breakConfig.doubleBreak || it.type == Secondary )
128+ it. breakConfig.doubleBreak || it.type == Secondary
115129 }?.context?.itemSelection
116130 ? : StackSelection .EVERYTHING .select()
117131
118- private val pendingBreakCount get() = breakInfos .count { it != null } + pendingActions.size
132+ private val pendingBreakCount get() = activeInfos .count() + pendingActions.size
119133 override val blockedPositions
120- get() = breakInfos.mapNotNull { it? .context? .blockPos } + pendingActions.map { it.context.blockPos }
134+ get() = activeInfos.map { it.context.blockPos } + pendingActions.map { it.context.blockPos }
121135
122136 private var activeRequest: BreakRequest ? = null
123137
124138 private var rotationRequest: RotationRequest ? = null
125139 private val rotated get() = rotationRequest?.done != false
126140
127- private var swapped = false
128- set(value) {
129- field = value
130- if (! value)
131- breakInfos.forEach { it?.serverBreakTicks = 0 }
132- }
141+ var swappedThisTick = false
133142 var swappedStack: ItemStack = ItemStack .EMPTY
134143 set(value) {
135144 if (value != field)
136145 breakInfos.forEach { it?.serverBreakTicks = 0 }
146+ swappedThisTick = true
137147 field = value
138148 }
139149 private var breakCooldown = 0
@@ -161,6 +171,9 @@ object BreakManager : RequestHandler<BreakRequest>(
161171 super .load()
162172
163173 listen<TickEvent .Post >(priority = Int .MIN_VALUE ) {
174+ if (! swappedThisTick) {
175+ swappedStack = player.mainHandStack
176+ } else swappedThisTick = false
164177 if (breakCooldown > 0 ) {
165178 breakCooldown--
166179 }
@@ -258,7 +271,8 @@ object BreakManager : RequestHandler<BreakRequest>(
258271 }
259272
260273 listenUnsafe<ConnectionEvent .Connect .Pre >(priority = Int .MIN_VALUE ) {
261- breakInfos.forEach { it?.nullify() }
274+ primaryBreak = null
275+ secondaryBreak = null
262276 breakCooldown = 0
263277 }
264278
@@ -301,9 +315,8 @@ object BreakManager : RequestHandler<BreakRequest>(
301315 // last break to be started
302316 run {
303317 if (! handlePreProcessing()) return @run
304- breakInfos
305- .filterNotNull()
306- .filter { it.type != RedundantSecondary && it.updatedThisTick }
318+ activeInfos
319+ .filter { it.updatedThisTick }
307320 .asReversed()
308321 .forEach { info ->
309322 if (info.shouldProgress)
@@ -315,7 +328,7 @@ object BreakManager : RequestHandler<BreakRequest>(
315328 if (instantBreaks.isEmpty() && breaks.isEmpty()) {
316329 activeRequest = null
317330 }
318- if (breaksThisTick > 0 || breakInfos.any { it != null && it.type != RedundantSecondary } ) {
331+ if (breaksThisTick > 0 || activeInfos.isNotEmpty() ) {
319332 activeThisTick = true
320333 }
321334 }
@@ -371,7 +384,7 @@ object BreakManager : RequestHandler<BreakRequest>(
371384 * @return if the break context can be accepted.
372385 */
373386 private fun SafeContext.canAccept (newCtx : BreakContext ): Boolean {
374- if (breakInfos .none { it? .context? .blockPos == newCtx.blockPos } && isPosBlocked(newCtx.blockPos)) return false
387+ if (activeInfos .none { it.context.blockPos == newCtx.blockPos } && isPosBlocked(newCtx.blockPos)) return false
375388
376389 if (! currentStackSelection.filterStack(player.inventory.getStack(newCtx.hotbarIndex)))
377390 return false
@@ -383,18 +396,16 @@ object BreakManager : RequestHandler<BreakRequest>(
383396 }
384397
385398 private fun SafeContext.handlePreProcessing (): Boolean {
386- breakInfos
387- .filterNotNull()
388- .filter { it.type != RedundantSecondary && it.updatedThisTick }
399+ activeInfos
400+ .filter { it.updatedThisTick }
389401 .let { infos ->
390402 rotationRequest = infos.firstOrNull { info -> info.breakConfig.rotateForBreak }
391403 ?.let { info ->
392404 val rotation = info.context.rotation
393405 rotation.submit(false )
394406 }
395407
396- if (breakInfos.none { it != null && it.type != RedundantSecondary }) {
397- swapped = false
408+ if (activeInfos.isEmpty()) {
398409 swappedStack = player.mainHandStack
399410 return true
400411 }
@@ -404,14 +415,10 @@ object BreakManager : RequestHandler<BreakRequest>(
404415 }
405416 infos.firstOrNull()?.let { info ->
406417 infos.firstOrNull { it.shouldSwap && it.shouldProgress }?.let { last ->
407- if (! info.context.requestSwap(info.request, max(info.minSwapTicks, last.minSwapTicks))) {
408- swapped = false
418+ if (! info.context.requestSwap(info.request, max(info.minSwapTicks, last.minSwapTicks)))
409419 return false
410- }
411420 swappedStack = info.swapStack
412- swapped = true
413- info.serverBreakTicks++
414- return true
421+ if (info.minSwapTicks > 0 ) info.serverBreakTicks++
415422 }
416423 }
417424 }
@@ -502,25 +509,21 @@ object BreakManager : RequestHandler<BreakRequest>(
502509
503510 private fun SafeContext.simulateAbandoned () {
504511 // Cancelled but double breaking so requires break manager to continue the simulation
505- breakInfos
506- .asSequence()
507- .filterNotNull()
508- .filter { it.abandoned && it.type != RedundantSecondary }
509- .forEach { info ->
510- with (info.request) {
511- info.context.blockPos
512- .toStructure(TargetState .Empty )
513- .toBlueprint()
514- .simulate(player.eyePos, interact, rotation, inventory, build)
515- .asSequence()
516- .filterIsInstance<BreakResult .Break >()
517- .filter { canAccept(it.context) }
518- .sorted()
519- .let { sim ->
520- info.updateInfo(sim.firstOrNull()?.context ? : return @forEach)
521- }
522- }
512+ abandonedBreak?.let { abandonedInfo ->
513+ with (abandonedInfo.request) {
514+ abandonedInfo.context.blockPos
515+ .toStructure(TargetState .Empty )
516+ .toBlueprint()
517+ .simulate(player.eyePos, interact, rotation, inventory, build)
518+ .asSequence()
519+ .filterIsInstance<BreakResult .Break >()
520+ .filter { canAccept(it.context) }
521+ .sorted()
522+ .let { sim ->
523+ abandonedInfo.updateInfo(sim.firstOrNull()?.context ? : return )
524+ }
523525 }
526+ }
524527 }
525528
526529 private fun checkForCancels () {
@@ -598,14 +601,26 @@ object BreakManager : RequestHandler<BreakRequest>(
598601 val cachedState = context.cachedState
599602 swapStack = player.inventory.getStack(context.hotbarIndex)
600603
601- val breakAmount = cachedState.calcBreakDelta(player, world, context.blockPos, breakConfig, swapStack) * (breakingTicks + 1 )
602- val breakAmountNoEfficiency = cachedState.calcBreakDelta(player, world, context.blockPos, breakConfig, swapStack, ignoreEfficiency = true ) * (breakingTicks + 1 )
603-
604- minSwapTicks = if (breakAmount >= getBreakThreshold() || couldReBreak) {
605- val min = if (breakAmountNoEfficiency >= getBreakThreshold()) 0 else 1
606- serverBreakTicks++
607- min
608- } else 0
604+ val breakTicks = (breakingTicks + 1 - breakConfig.fudgeFactor).coerceAtLeast(1 )
605+ val breakAmount = cachedState.calcBreakDelta(
606+ player,
607+ world,
608+ context.blockPos,
609+ breakConfig,
610+ swapStack
611+ ) * breakTicks
612+ val breakAmountNoEfficiency = cachedState.calcBreakDelta(
613+ player,
614+ world,
615+ context.blockPos,
616+ breakConfig,
617+ swapStack,
618+ ignoreEfficiency = true
619+ ) * breakTicks
620+
621+ minSwapTicks = if ((breakAmount >= getBreakThreshold() || couldReBreak == RebreakManager .RebreakPotential .Instant ) &&
622+ (breakAmountNoEfficiency < getBreakThreshold() || type == Secondary )) 1
623+ else 0
609624 }
610625
611626 /* *
@@ -748,7 +763,7 @@ object BreakManager : RequestHandler<BreakRequest>(
748763 }
749764
750765 val swing = config.swing
751- if (overBreakThreshold && (! swapped || info.serverBreakTicks >= info.breakConfig.fudgeFactor)) {
766+ if (overBreakThreshold && (info.serverBreakTicks >= info.breakConfig.fudgeFactor || info.minSwapTicks < 1 )) {
752767 if (info.type == Primary ) {
753768 onBlockBreak(info)
754769 info.stopBreakPacket(world, interaction)
@@ -774,7 +789,7 @@ object BreakManager : RequestHandler<BreakRequest>(
774789 private fun SafeContext.startBreaking (info : BreakInfo ): Boolean {
775790 val ctx = info.context
776791
777- if (info.couldReBreak) {
792+ if (info.couldReBreak.isPossible() ) {
778793 when (val rebreakResult = RebreakManager .handleUpdate(info.context, info.request)) {
779794 is RebreakResult .StillBreaking -> {
780795 primaryBreak = rebreakResult.breakInfo.apply {
@@ -822,8 +837,7 @@ object BreakManager : RequestHandler<BreakRequest>(
822837
823838 val breakDelta = blockState.calcBreakDelta(player, world, ctx.blockPos, info.breakConfig)
824839 info.vanillaInstantBreakable = breakDelta >= 1
825- val serverSwapped = ! swapped || info.serverBreakTicks >= info.breakConfig.fudgeFactor
826- if (notEmpty && (breakDelta >= info.getBreakThreshold() && serverSwapped)) {
840+ if (notEmpty && (breakDelta >= info.getBreakThreshold() && (info.serverBreakTicks >= info.breakConfig.fudgeFactor || info.minSwapTicks < 1 ))) {
827841 onBlockBreak(info)
828842 if (! info.vanillaInstantBreakable) breakCooldown = info.breakConfig.breakDelay
829843 } else {
0 commit comments