Skip to content

Commit ebdab3f

Browse files
committed
fixes the main inconsistency within the break manager on 1.21.5
1 parent a3498dd commit ebdab3f

File tree

3 files changed

+92
-65
lines changed

3 files changed

+92
-65
lines changed

src/main/kotlin/com/lambda/interaction/request/breaking/BreakInfo.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ data class BreakInfo(
4444

4545
// Pre Processing
4646
var shouldProgress = false
47-
var couldReBreak by OneSetPerTick(value = false, throwOnLimitBreach = true)
47+
var couldReBreak by OneSetPerTick(value = RebreakManager.RebreakPotential.None, throwOnLimitBreach = true)
4848
var shouldSwap by OneSetPerTick(value = false, throwOnLimitBreach = true)
4949
var swapStack: ItemStack by OneSetPerTick(ItemStack.EMPTY, true)
5050
var minSwapTicks by OneSetPerTick(0, true)
@@ -118,7 +118,7 @@ data class BreakInfo(
118118
val item = player.inventory.getStack(context.hotbarIndex)
119119
val breakDelta = context.cachedState.calcItemBlockBreakingDelta(player, world, context.blockPos, item)
120120
val breakProgress = breakDelta * (breakingTicks + 1)
121-
return if (couldReBreak)
121+
return if (couldReBreak == RebreakManager.RebreakPotential.Instant)
122122
breakConfig.swapMode.isEnabled()
123123
else when (breakConfig.swapMode) {
124124
BreakConfig.SwapMode.None -> false

src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt

Lines changed: 72 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -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 {

src/main/kotlin/com/lambda/interaction/request/breaking/RebreakManager.kt

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ object RebreakManager {
3535
var rebreak: BreakInfo? = null
3636

3737
init {
38-
listen<TickEvent.Pre>(priority = Int.MIN_VALUE) {
38+
listen<TickEvent.Post>(priority = Int.MIN_VALUE) {
3939
rebreak?.run {
4040
if (!progressedThisTick) {
4141
breakingTicks++
@@ -70,11 +70,16 @@ object RebreakManager {
7070
player.inventory.getStack(info.context.hotbarIndex)
7171
else player.mainHandStack
7272
val breakDelta = info.context.cachedState.calcItemBlockBreakingDelta(player, world, info.context.blockPos, stack)
73-
reBreak.breakConfig.rebreak &&
73+
val possible = reBreak.breakConfig.rebreak &&
7474
info.context.blockPos == reBreak.context.blockPos &&
75-
!reBreak.updatedThisTick &&
76-
((reBreak.breakingTicks - info.breakConfig.fudgeFactor) * breakDelta >= info.breakConfig.breakThreshold)
77-
} == true
75+
!reBreak.updatedThisTick
76+
val instant = (reBreak.breakingTicks - info.breakConfig.fudgeFactor) * breakDelta >= info.breakConfig.breakThreshold
77+
when {
78+
possible && instant -> RebreakPotential.Instant
79+
possible -> RebreakPotential.PartialProgress
80+
else -> RebreakPotential.None
81+
}
82+
} ?: RebreakPotential.None
7883

7984
fun handleUpdate(ctx: BreakContext, breakRequest: BreakRequest) =
8085
runSafe {
@@ -98,4 +103,12 @@ object RebreakManager {
98103
RebreakResult.StillBreaking(reBreak)
99104
}
100105
}
106+
107+
enum class RebreakPotential {
108+
Instant,
109+
PartialProgress,
110+
None;
111+
112+
fun isPossible() = this == Instant || this == PartialProgress
113+
}
101114
}

0 commit comments

Comments
 (0)