Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/main/kotlin/com/lambda/config/groups/BreakSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ class BreakSettings(

// Fixes / Delays
override val breakThreshold by c.setting("Break Threshold", 0.70f, 0.1f..1.0f, 0.01f, "The break amount at which the block is considered broken", visibility = vis).group(groupPath, Group.General)
override val fudgeFactor by c.setting("Fudge Factor", 2, 0..5, 1, "The amount of ticks to give double, aka secondary breaks extra for the server to recognise the break", visibility = vis).group(groupPath, Group.General)
override val fudgeFactor by c.setting("Fudge Factor", 1, 0..5, 1, "The number of ticks to add to the break time, usually to account for server lag", visibility = vis).group(groupPath, Group.General)
override val serverSwapTicks by c.setting("Server Swap", 2, 0..5, 1, "The number of ticks to give the server time to recognize the player attributes on the swapped item", " tick(s)", visibility = vis).group(groupPath, Group.General)
// override val desyncFix by c.setting("Desync Fix", false, "Predicts if the players breaking will be slowed next tick as block break packets are processed using the players next position") { vis() && page == Page.General }
override val breakDelay by c.setting("Break Delay", 0, 0..6, 1, "The delay between breaking blocks", " ticks", visibility = vis).group(groupPath, Group.General)
override val breakDelay by c.setting("Break Delay", 0, 0..6, 1, "The delay between breaking blocks", " tick(s)", visibility = vis).group(groupPath, Group.General)

// Timing
override val breakStageMask by c.setting("Break Stage Mask", setOf(TickEvent.Input.Post, TickEvent.Player.Post), description = "The sub-tick timing at which break actions can be performed", visibility = vis).group(groupPath, Group.General)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import com.lambda.interaction.material.StackSelection.Companion.selectStack
import com.lambda.interaction.material.container.ContainerManager.containerWithMaterial
import com.lambda.interaction.material.container.MaterialContainer
import com.lambda.interaction.request.breaking.BreakConfig
import com.lambda.interaction.request.breaking.BreakManager
import com.lambda.interaction.request.inventory.InventoryConfig
import com.lambda.interaction.request.placing.PlaceConfig
import com.lambda.interaction.request.rotating.Rotation.Companion.rotation
Expand Down Expand Up @@ -850,7 +849,6 @@ object BuildSimulator {
val swapStack = swapCandidates.map { it.matchingStacks(stackSelection) }
.asSequence()
.flatten()
.filter { BreakManager.currentStackSelection.filterStack(it) }
.let { containerStacks ->
var bestStack = ItemStack.EMPTY
var bestBreakDelta = -1f
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ import java.awt.Color
interface BreakConfig : RequestConfig {
val breakMode: BreakMode
val sorter: SortMode
val breakThreshold: Float
val rebreak: Boolean

val doubleBreak: Boolean
val unsafeCancels: Boolean

val breakThreshold: Float
val fudgeFactor: Int
val serverSwapTicks: Int
//ToDo: Needs a more advanced player simulation implementation to predict the next ticks onGround / submerged status
// abstract val desyncFix: Boolean
val breakDelay: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package com.lambda.interaction.request.breaking

import com.lambda.interaction.construction.context.BreakContext
import com.lambda.interaction.request.ActionInfo
import com.lambda.interaction.request.breaking.BreakInfo.BreakType.Primary
import com.lambda.interaction.request.breaking.BreakInfo.BreakType.Rebreak
import com.lambda.util.BlockUtils.calcItemBlockBreakingDelta
import com.lambda.util.Describable
import com.lambda.util.NamedEnum
Expand All @@ -31,7 +33,6 @@ import net.minecraft.entity.player.PlayerEntity
import net.minecraft.item.ItemStack
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket
import net.minecraft.network.packet.c2s.play.PlayerActionC2SPacket.Action
import net.minecraft.world.BlockView

data class BreakInfo(
override var context: BreakContext,
Expand All @@ -44,10 +45,9 @@ data class BreakInfo(

// Pre Processing
var shouldProgress = false
var couldReBreak by OneSetPerTick(value = RebreakManager.RebreakPotential.None, throwOnLimitBreach = true)
var shouldSwap by OneSetPerTick(value = false, throwOnLimitBreach = true)
var rebreakPotential by OneSetPerTick(value = RebreakManager.RebreakPotential.None, throwOnLimitBreach = true)
var swapInfo by OneSetPerTick(value = SwapInfo.EMPTY, throwOnLimitBreach = true)
var swapStack: ItemStack by OneSetPerTick(ItemStack.EMPTY, true)
var minSwapTicks by OneSetPerTick(0, true)

// BreakInfo Specific
var updatedThisTick by OneSetPerTick(false, resetAfterTick = true).apply { set(true) }
Expand All @@ -60,7 +60,7 @@ data class BreakInfo(
var breakingTicks by OneSetPerTick(0, true)
var soundsCooldown by OneSetPerTick(0f, true)
var vanillaInstantBreakable = false
val rebreakable get() = !vanillaInstantBreakable && type == BreakType.Primary
val rebreakable get() = !vanillaInstantBreakable && type == Primary

enum class BreakType(
override val displayName: String,
Expand All @@ -70,12 +70,6 @@ data class BreakInfo(
Secondary("Secondary", "A second block broken at the same time (when double‑break is enabled)."),
RedundantSecondary("Redundant Secondary", "A previously started secondary break that’s now ignored/monitored only (no new actions)."),
Rebreak("Rebreak", "A previously broken block which new breaks in the same position can compound progression on. Often rebreaking instantly.");

fun getBreakThreshold(breakConfig: BreakConfig) =
when (this) {
Primary -> breakConfig.breakThreshold
else -> 1.0f
}
}

// Post Processing
Expand Down Expand Up @@ -113,20 +107,6 @@ data class BreakInfo(
item = null
}

fun shouldSwap(player: ClientPlayerEntity, world: BlockView): Boolean {
val breakDelta = context.cachedState.calcItemBlockBreakingDelta(player, world, context.blockPos, swapStack)
val breakProgress = breakDelta * (breakingTicks + 1)
return if (couldReBreak == RebreakManager.RebreakPotential.Instant)
breakConfig.swapMode.isEnabled()
else when (breakConfig.swapMode) {
BreakConfig.SwapMode.None -> false
BreakConfig.SwapMode.Start -> !breaking
BreakConfig.SwapMode.End -> breakProgress >= getBreakThreshold()
BreakConfig.SwapMode.StartAndEnd -> !breaking || breakProgress >= getBreakThreshold()
BreakConfig.SwapMode.Constant -> true
}
}

fun setBreakingTextureStage(
player: ClientPlayerEntity,
world: ClientWorld,
Expand All @@ -144,7 +124,12 @@ data class BreakInfo(
return if (progress > 0.0f) (progress * 10.0f).toInt().coerceAtMost(9) else -1
}

fun getBreakThreshold() = type.getBreakThreshold(breakConfig)
fun getBreakThreshold() =
when (type) {
Primary,
Rebreak-> breakConfig.breakThreshold
else -> 1.0f
}

fun startBreakPacket(world: ClientWorld, interaction: ClientPlayerInteractionManager) =
breakPacket(Action.START_DESTROY_BLOCK, world, interaction)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import com.lambda.interaction.request.breaking.BrokenBlockHandler.destroyBlock
import com.lambda.interaction.request.breaking.BrokenBlockHandler.pendingActions
import com.lambda.interaction.request.breaking.BrokenBlockHandler.setPendingConfigs
import com.lambda.interaction.request.breaking.BrokenBlockHandler.startPending
import com.lambda.interaction.request.breaking.SwapInfo.Companion.getSwapInfo
import com.lambda.interaction.request.interacting.InteractionManager
import com.lambda.interaction.request.placing.PlaceManager
import com.lambda.interaction.request.rotating.RotationRequest
Expand Down Expand Up @@ -138,15 +139,15 @@ object BreakManager : RequestHandler<BreakRequest>(
private var rotationRequest: RotationRequest? = null
private val rotated get() = rotationRequest?.done != false

var swappedThisTick = false
var heldTicks = 0
var swappedStack: ItemStack = ItemStack.EMPTY
var currentStack: ItemStack = ItemStack.EMPTY
set(value) {
if (value != field)
heldTicks = 0
swappedThisTick = true
field = value
}
var heldTicks = 0
var swappedThisTick = false
private var breakCooldown = 0
var breaksThisTick = 0
private var maxBreaksThisTick = 0
Expand All @@ -173,7 +174,7 @@ object BreakManager : RequestHandler<BreakRequest>(

listen<TickEvent.Post>(priority = Int.MIN_VALUE) {
if (!swappedThisTick) {
swappedStack = player.mainHandStack
currentStack = player.mainHandStack
}
swappedThisTick = false
heldTicks++
Expand Down Expand Up @@ -314,9 +315,12 @@ object BreakManager : RequestHandler<BreakRequest>(
* @see updateBreakProgress
*/
private fun SafeContext.processRequest(breakRequest: BreakRequest?) {
breakRequest?.let { request ->
if (request.fresh) populateFrom(request)
}

repeat(2) {
breakRequest?.let { request ->
if (request.fresh) populateFrom(request)
if (performInstantBreaks(request)) {
processNewBreaks(request)
}
Expand Down Expand Up @@ -421,12 +425,12 @@ object BreakManager : RequestHandler<BreakRequest>(
infos.forEach { it.updatePreProcessing(player, world) }

infos.firstOrNull()?.let { info ->
infos.lastOrNull { it.shouldSwap && it.shouldProgress }?.let { last ->
val minSwapTicks = max(info.minSwapTicks, last.minSwapTicks)
infos.lastOrNull { it.swapInfo.swap && it.shouldProgress }?.let { last ->
val minSwapTicks = max(info.swapInfo.minKeepTicks, last.swapInfo.minKeepTicks)
if (!info.context.requestSwap(info.request, minSwapTicks))
return false
if (minSwapTicks > 0)
swappedStack = info.swapStack
currentStack = info.swapStack
}
}
}
Expand Down Expand Up @@ -603,31 +607,8 @@ object BreakManager : RequestHandler<BreakRequest>(
updatedPreProcessingThisTick = true

swapStack = player.inventory.getStack(context.hotbarIndex)
couldReBreak = RebreakManager.couldRebreak(this, player, world)
shouldSwap = shouldSwap(player, world)

val cachedState = context.cachedState

val breakTicks = (breakingTicks + 1 - breakConfig.fudgeFactor).coerceAtLeast(1)
val breakAmount = cachedState.calcBreakDelta(
player,
world,
context.blockPos,
breakConfig,
swapStack
) * breakTicks
val breakAmountNoEfficiency = cachedState.calcBreakDelta(
player,
world,
context.blockPos,
breakConfig,
swapStack,
ignoreEfficiency = true
) * breakTicks

minSwapTicks = if ((breakAmount >= getBreakThreshold() || couldReBreak == RebreakManager.RebreakPotential.Instant) &&
(breakAmountNoEfficiency < getBreakThreshold() || type == Secondary)) 1
else 0
rebreakPotential = RebreakManager.getRebreakPotential(this, player, world)
swapInfo = getSwapInfo(this, player, world)
}

/**
Expand Down Expand Up @@ -737,8 +718,6 @@ object BreakManager : RequestHandler<BreakRequest>(
config
) * (info.breakingTicks - config.fudgeFactor)

val overBreakThreshold = progress >= info.getBreakThreshold()

if (config.sounds) {
if (info.soundsCooldown % 4.0f == 0.0f) {
val blockSoundGroup = blockState.soundGroup
Expand All @@ -765,7 +744,7 @@ object BreakManager : RequestHandler<BreakRequest>(
}

val swing = config.swing
if (overBreakThreshold && heldTicks + 1 >= info.breakConfig.fudgeFactor) {
if (progress >= info.getBreakThreshold() && info.swapInfo.canCompleteBreak) {
if (info.type == Primary) {
onBlockBreak(info)
info.stopBreakPacket(world, interaction)
Expand All @@ -791,7 +770,7 @@ object BreakManager : RequestHandler<BreakRequest>(
private fun SafeContext.startBreaking(info: BreakInfo): Boolean {
val ctx = info.context

if (info.couldReBreak.isPossible()) {
if (info.rebreakPotential.isPossible()) {
when (val rebreakResult = RebreakManager.handleUpdate(info.context, info.request)) {
is RebreakResult.StillBreaking -> {
primaryBreak = rebreakResult.breakInfo.apply {
Expand All @@ -801,6 +780,7 @@ object BreakManager : RequestHandler<BreakRequest>(
}

primaryBreak?.let { primary ->
if (!handlePreProcessing()) return false
updateBreakProgress(primary)
}
return true
Expand Down Expand Up @@ -832,14 +812,13 @@ object BreakManager : RequestHandler<BreakRequest>(
lastPosStarted = ctx.blockPos

val blockState = blockState(ctx.blockPos)
val notEmpty = blockState.isNotEmpty
if (notEmpty && info.breakingTicks == 0) {
if (info.breakingTicks == 0) {
blockState.onBlockBreakStart(world, ctx.blockPos, player)
}

val breakDelta = blockState.calcBreakDelta(player, world, ctx.blockPos, info.breakConfig)
info.vanillaInstantBreakable = breakDelta >= 1
if (notEmpty && breakDelta >= info.getBreakThreshold() && heldTicks + 1 >= info.breakConfig.fudgeFactor) {
val progress = blockState.calcBreakDelta(player, world, ctx.blockPos, info.breakConfig)
info.vanillaInstantBreakable = progress >= 1 && info.swapInfo.canCompleteBreak
if (progress >= info.getBreakThreshold() && info.swapInfo.canCompleteBreak) {
onBlockBreak(info)
if (!info.vanillaInstantBreakable) breakCooldown = info.breakConfig.breakDelay
} else {
Expand All @@ -859,7 +838,7 @@ object BreakManager : RequestHandler<BreakRequest>(

info.startBreakPacket(world, interaction)

if (info.type == Secondary || (!info.vanillaInstantBreakable && breakDelta >= info.breakConfig.breakThreshold)) {
if (info.type == Secondary || (!info.vanillaInstantBreakable && progress >= info.breakConfig.breakThreshold)) {
info.stopBreakPacket(world, interaction)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ object RebreakManager {
var rebreak: BreakInfo? = null

init {
listen<TickEvent.Post>(priority = Int.MIN_VALUE) {
listen<TickEvent.Post>(priority = Int.MIN_VALUE + 1) {
rebreak?.run {
if (!progressedThisTick) {
breakingTicks++
Expand Down Expand Up @@ -64,7 +64,7 @@ object RebreakManager {
rebreak = null
}

fun couldRebreak(info: BreakInfo, player: ClientPlayerEntity, world: BlockView) =
fun getRebreakPotential(info: BreakInfo, player: ClientPlayerEntity, world: BlockView) =
rebreak?.let { reBreak ->
val stack = if (info.breakConfig.swapMode.isEnabled())
info.swapStack
Expand All @@ -89,7 +89,8 @@ object RebreakManager {

val context = reBreak.context
val breakDelta = context.cachedState.calcBreakDelta(player, world, context.blockPos, reBreak.breakConfig)
return@runSafe if ((reBreak.breakingTicks - reBreak.breakConfig.fudgeFactor) * breakDelta >= reBreak.breakConfig.breakThreshold) {
val breakTicks = reBreak.breakingTicks - reBreak.breakConfig.fudgeFactor
return@runSafe if (breakTicks * breakDelta >= reBreak.getBreakThreshold() && reBreak.swapInfo.canCompleteBreak) {
if (reBreak.breakConfig.breakConfirmation != BreakConfig.BreakConfirmationMode.AwaitThenBreak) {
destroyBlock(reBreak)
}
Expand All @@ -109,6 +110,6 @@ object RebreakManager {
PartialProgress,
None;

fun isPossible() = this == Instant || this == PartialProgress
fun isPossible() = this != None
}
}
Loading