@@ -37,6 +37,7 @@ import com.lambda.module.tag.ModuleTag
3737import com.lambda.util.BlockUtils.blockState
3838import com.lambda.util.world.raycast.InteractionMask
3939import net.minecraft.util.math.BlockPos
40+ import java.util.*
4041import java.util.concurrent.ConcurrentLinkedQueue
4142
4243object PacketMine : Module(
@@ -52,14 +53,19 @@ object PacketMine : Module(
5253 private val interact = InteractionSettings (this , InteractionMask .Block ) { page == Page .Interaction }
5354 private val inventory = InventorySettings (this ) { page == Page .Inventory }
5455 private val hotbar = HotbarSettings (this ) { page == Page .Hotbar }
56+
5557 private val reBreakMode by setting(" ReBreak Mode" , ReBreakMode .Manual , " The method used to re-break blocks after they've been broken once" ) { breakConfig.reBreak }
58+ private val queue by setting(" Queue" , false , " Queues blocks to break so you can select multiple at once" )
59+ .onValueChange { _, to -> if (! to) queuePositions.clear() }
5660
5761 private val pendingInteractionsList = ConcurrentLinkedQueue <BuildContext >()
5862
5963 private var breaks = 0
6064 private var itemDrops = 0
6165
62- private val breakingPositions = arrayOfNulls<BlockPos >(2 )
66+ private val breakPositions = arrayOfNulls<BlockPos >(2 )
67+ private val queuePositions = LinkedList <BlockPos >()
68+
6369 private var reBreakPos: BlockPos ? = null
6470
6571 private var attackedThisTick = false
@@ -73,47 +79,61 @@ object PacketMine : Module(
7379 listen<TickEvent .Pre > {
7480 if (! breakConfig.reBreak || (reBreakMode != ReBreakMode .Auto && reBreakMode != ReBreakMode .AutoConstant )) return @listen
7581 val reBreak = reBreakPos ? : return @listen
76- requestBreakManager(reBreak)
82+ requestBreakManager(listOf ( reBreak), true )
7783 }
7884
7985 listen<PlayerEvent .Attack .Block > { it.cancel() }
8086 listen<PlayerEvent .Breaking .Update > { event ->
8187 event.cancel()
82- if (breakingPositions.any { it == event.pos }) return @listen
83- val secondary = if (breakConfig.doubleBreak) {
84- breakingPositions[1 ] ? : breakingPositions[0 ]
85- } else null
86- requestBreakManager(event.pos, secondary)
88+ if ((breakPositions + queuePositions).any { it == event.pos }) return @listen
89+ val activeBreaking = if (queue) {
90+ queuePositions.addLast(event.pos)
91+ breakPositions + queuePositions
92+ } else {
93+ arrayOf<BlockPos ?>(event.pos) + if (breakConfig.doubleBreak) {
94+ breakPositions[1 ] ? : breakPositions[0 ]
95+ } else null
96+ }
97+ requestBreakManager(activeBreaking.toList())
8798 attackedThisTick = true
8899 }
89100
90101 listen<TickEvent .Input .Post > {
91- if (! attackedThisTick) requestBreakManager(* breakingPositions.toList().toTypedArray ())
102+ if (! attackedThisTick) requestBreakManager((breakPositions + queuePositions).toList ())
92103 }
93104
94105 onDisable {
95- breakingPositions[0 ] = null
96- breakingPositions[1 ] = null
106+ breakPositions[0 ] = null
107+ breakPositions[1 ] = null
108+ queuePositions.clear()
97109 reBreakPos = null
98110 attackedThisTick = false
99111 }
100112 }
101113
102- private fun SafeContext.requestBreakManager (vararg requestPositions : BlockPos ? ) {
114+ private fun SafeContext.requestBreakManager (requestPositions : Collection < BlockPos ?>, reBreaking : Boolean = false ) {
103115 if (requestPositions.isEmpty()) return
116+ val breakContexts = breakContexts(requestPositions)
117+ if (! reBreaking) {
118+ breakPositions.forEachIndexed { index, breakPos ->
119+ if (breakContexts.none { it.expectedPos == breakPos }) {
120+ breakPositions[index] = null
121+ }
122+ }
123+ queuePositions.removeIf { queuePos ->
124+ breakContexts.none { it.expectedPos == queuePos }
125+ }
126+ }
104127 val request = BreakRequest (
105- breakContexts(requestPositions.filterNotNull()) , build, rotation, hotbar, pendingInteractions = pendingInteractionsList,
128+ breakContexts, build, rotation, hotbar, pendingInteractions = pendingInteractionsList,
106129 onAccept = {
107- if (breakConfig.doubleBreak && breakingPositions[1 ] == null ) {
108- breakingPositions[1 ] = breakingPositions[0 ]
109- }
110- breakingPositions[0 ] = it
111- reBreakPos = null
130+ addBreak(it)
131+ queuePositions.remove(it)
112132 },
113- onCancel = { nullifyBreakPos (it, true ) },
133+ onCancel = { removeBreak (it, true ) },
114134 onBreak = {
115135 breaks++
116- nullifyBreakPos (it)
136+ removeBreak (it)
117137 },
118138 onReBreakStart = { reBreakPos = it },
119139 onReBreak = { reBreakPos = it },
@@ -122,20 +142,9 @@ object PacketMine : Module(
122142 breakConfig.request(request)
123143 }
124144
125- private fun nullifyBreakPos (pos : BlockPos , includeReBreak : Boolean = false) {
126- breakingPositions.forEachIndexed { index, breakPos ->
127- if (breakPos == pos) {
128- breakingPositions[index] = null
129- }
130- }
131- if (includeReBreak && pos == reBreakPos) {
132- reBreakPos = null
133- return
134- }
135- }
136-
137- private fun SafeContext.breakContexts (breakPositions : Collection <BlockPos >) =
138- breakPositions
145+ private fun SafeContext.breakContexts (positions : Collection <BlockPos ?>) =
146+ positions
147+ .filterNotNull()
139148 .associateWith { TargetState .State (blockState(it).fluidState.blockState) }
140149 .toBlueprint()
141150 .simulate(
@@ -148,6 +157,25 @@ object PacketMine : Module(
148157 .filterIsInstance<BreakResult .Break >()
149158 .map { it.context }
150159
160+ private fun addBreak (pos : BlockPos ) {
161+ if (breakConfig.doubleBreak && breakPositions[1 ] == null ) {
162+ breakPositions[1 ] = breakPositions[0 ]
163+ }
164+ breakPositions[0 ] = pos
165+ reBreakPos = null
166+ }
167+
168+ private fun removeBreak (pos : BlockPos , includeReBreak : Boolean = false) {
169+ breakPositions.forEachIndexed { index, breakPos ->
170+ if (breakPos == pos) {
171+ breakPositions[index] = null
172+ }
173+ }
174+ if (includeReBreak && pos == reBreakPos) {
175+ reBreakPos = null
176+ }
177+ }
178+
151179 enum class Page {
152180 Build , Rotation , Interaction , Inventory , Hotbar
153181 }
0 commit comments