@@ -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 }
@@ -257,7 +270,7 @@ object BreakManager : RequestHandler<BreakRequest>(
257270
258271 info.context.cachedState.getOutlineShape(world, info.context.blockPos).boundingBoxes.map {
259272 it.offset(info.context.blockPos)
260- }.forEach boxes@{ box ->
273+ }.forEach boxes@ { box ->
261274 val interpolated = interpolateBox(box, interpolatedProgress, info.breakConfig)
262275 if (config.fill) event.renderer.buildFilled(interpolated, fillColor)
263276 if (config.outline) event.renderer.buildOutline(interpolated, outlineColor)
@@ -266,7 +279,8 @@ object BreakManager : RequestHandler<BreakRequest>(
266279 }
267280
268281 listenUnsafe<ConnectionEvent .Connect .Pre >(priority = Int .MIN_VALUE ) {
269- breakInfos.forEach { it?.nullify() }
282+ primaryBreak = null
283+ secondaryBreak = null
270284 breakCooldown = 0
271285 }
272286
@@ -309,9 +323,8 @@ object BreakManager : RequestHandler<BreakRequest>(
309323 // last break to be started
310324 run {
311325 if (! handlePreProcessing()) return @run
312- breakInfos
313- .filterNotNull()
314- .filter { it.type != RedundantSecondary && it.updatedThisTick }
326+ activeInfos
327+ .filter { it.updatedThisTick }
315328 .asReversed()
316329 .forEach { info ->
317330 if (info.shouldProgress)
@@ -323,7 +336,7 @@ object BreakManager : RequestHandler<BreakRequest>(
323336 if (instantBreaks.isEmpty() && breaks.isEmpty()) {
324337 activeRequest = null
325338 }
326- if (breaksThisTick > 0 || breakInfos.any { it != null && it.type != RedundantSecondary } ) {
339+ if (breaksThisTick > 0 || activeInfos.isNotEmpty() ) {
327340 activeThisTick = true
328341 }
329342 }
@@ -379,7 +392,7 @@ object BreakManager : RequestHandler<BreakRequest>(
379392 * @return if the break context can be accepted.
380393 */
381394 private fun SafeContext.canAccept (newCtx : BreakContext ): Boolean {
382- if (breakInfos .none { it? .context? .blockPos == newCtx.blockPos } && isPosBlocked(newCtx.blockPos)) return false
395+ if (activeInfos .none { it.context.blockPos == newCtx.blockPos } && isPosBlocked(newCtx.blockPos)) return false
383396
384397 if (! currentStackSelection.filterStack(player.inventory.getStack(newCtx.hotbarIndex)))
385398 return false
@@ -391,18 +404,16 @@ object BreakManager : RequestHandler<BreakRequest>(
391404 }
392405
393406 private fun SafeContext.handlePreProcessing (): Boolean {
394- breakInfos
395- .filterNotNull()
396- .filter { it.type != RedundantSecondary && it.updatedThisTick }
407+ activeInfos
408+ .filter { it.updatedThisTick }
397409 .let { infos ->
398410 rotationRequest = infos.firstOrNull { info -> info.breakConfig.rotateForBreak }
399411 ?.let { info ->
400412 val rotation = info.context.rotation
401413 rotation.submit(false )
402414 }
403415
404- if (breakInfos.none { it != null && it.type != RedundantSecondary }) {
405- swapped = false
416+ if (activeInfos.isEmpty()) {
406417 swappedStack = player.mainHandStack
407418 return true
408419 }
@@ -412,14 +423,10 @@ object BreakManager : RequestHandler<BreakRequest>(
412423 }
413424 infos.firstOrNull()?.let { info ->
414425 infos.firstOrNull { it.shouldSwap && it.shouldProgress }?.let { last ->
415- if (! info.context.requestSwap(info.request, max(info.minSwapTicks, last.minSwapTicks))) {
416- swapped = false
426+ if (! info.context.requestSwap(info.request, max(info.minSwapTicks, last.minSwapTicks)))
417427 return false
418- }
419428 swappedStack = info.swapStack
420- swapped = true
421- info.serverBreakTicks++
422- return true
429+ if (info.minSwapTicks > 0 ) info.serverBreakTicks++
423430 }
424431 }
425432 }
@@ -510,25 +517,21 @@ object BreakManager : RequestHandler<BreakRequest>(
510517
511518 private fun SafeContext.simulateAbandoned () {
512519 // Cancelled but double breaking so requires break manager to continue the simulation
513- breakInfos
514- .asSequence()
515- .filterNotNull()
516- .filter { it.abandoned && it.type != RedundantSecondary }
517- .forEach { info ->
518- with (info.request) {
519- info.context.blockPos
520- .toStructure(TargetState .Empty )
521- .toBlueprint()
522- .simulate(player.eyePos, interact, rotation, inventory, build)
523- .asSequence()
524- .filterIsInstance<BreakResult .Break >()
525- .filter { canAccept(it.context) }
526- .sorted()
527- .let { sim ->
528- info.updateInfo(sim.firstOrNull()?.context ? : return @forEach)
529- }
530- }
520+ abandonedBreak?.let { abandonedInfo ->
521+ with (abandonedInfo.request) {
522+ abandonedInfo.context.blockPos
523+ .toStructure(TargetState .Empty )
524+ .toBlueprint()
525+ .simulate(player.eyePos, interact, rotation, inventory, build)
526+ .asSequence()
527+ .filterIsInstance<BreakResult .Break >()
528+ .filter { canAccept(it.context) }
529+ .sorted()
530+ .let { sim ->
531+ abandonedInfo.updateInfo(sim.firstOrNull()?.context ? : return )
532+ }
531533 }
534+ }
532535 }
533536
534537 private fun checkForCancels () {
@@ -605,22 +608,26 @@ object BreakManager : RequestHandler<BreakRequest>(
605608 val cachedState = context.cachedState
606609 swapStack = player.inventory.getStack(context.hotbarIndex)
607610
608- val breakAmount =
609- cachedState.calcBreakDelta(player, world, context.blockPos, breakConfig, swapStack) * (breakingTicks + 1 )
611+ val breakTicks = (breakingTicks + 1 - breakConfig.fudgeFactor).coerceAtLeast(1 )
612+ val breakAmount = cachedState.calcBreakDelta(
613+ player,
614+ world,
615+ context.blockPos,
616+ breakConfig,
617+ swapStack
618+ ) * breakTicks
610619 val breakAmountNoEfficiency = cachedState.calcBreakDelta(
611620 player,
612621 world,
613622 context.blockPos,
614623 breakConfig,
615624 swapStack,
616625 ignoreEfficiency = true
617- ) * (breakingTicks + 1 )
626+ ) * breakTicks
618627
619- minSwapTicks = if (breakAmount >= getBreakThreshold() || couldReBreak) {
620- val min = if (breakAmountNoEfficiency >= getBreakThreshold()) 0 else 1
621- serverBreakTicks++
622- min
623- } else 0
628+ minSwapTicks = if ((breakAmount >= getBreakThreshold() || couldReBreak == RebreakManager .RebreakPotential .Instant ) &&
629+ (breakAmountNoEfficiency < getBreakThreshold() || type == Secondary )) 1
630+ else 0
624631 }
625632
626633 /* *
@@ -763,7 +770,7 @@ object BreakManager : RequestHandler<BreakRequest>(
763770 }
764771
765772 val swing = config.swing
766- if (overBreakThreshold && (! swapped || info.serverBreakTicks >= info.breakConfig.fudgeFactor)) {
773+ if (overBreakThreshold && (info.serverBreakTicks >= info.breakConfig.fudgeFactor || info.minSwapTicks < 1 )) {
767774 if (info.type == Primary ) {
768775 onBlockBreak(info)
769776 info.stopBreakPacket(world, interaction)
@@ -789,7 +796,7 @@ object BreakManager : RequestHandler<BreakRequest>(
789796 private fun SafeContext.startBreaking (info : BreakInfo ): Boolean {
790797 val ctx = info.context
791798
792- if (info.couldReBreak) {
799+ if (info.couldReBreak.isPossible() ) {
793800 when (val rebreakResult = RebreakManager .handleUpdate(info.context, info.request)) {
794801 is RebreakResult .StillBreaking -> {
795802 primaryBreak = rebreakResult.breakInfo.apply {
@@ -837,8 +844,7 @@ object BreakManager : RequestHandler<BreakRequest>(
837844
838845 val breakDelta = blockState.calcBreakDelta(player, world, ctx.blockPos, info.breakConfig)
839846 info.vanillaInstantBreakable = breakDelta >= 1
840- val serverSwapped = ! swapped || info.serverBreakTicks >= info.breakConfig.fudgeFactor
841- if (notEmpty && (breakDelta >= info.getBreakThreshold() && serverSwapped)) {
847+ if (notEmpty && (breakDelta >= info.getBreakThreshold() && (info.serverBreakTicks >= info.breakConfig.fudgeFactor || info.minSwapTicks < 1 ))) {
842848 onBlockBreak(info)
843849 if (! info.vanillaInstantBreakable) breakCooldown = info.breakConfig.breakDelay
844850 } else {
0 commit comments