@@ -25,16 +25,16 @@ import com.lambda.event.events.TickEvent
2525import com.lambda.event.events.UpdateManagerEvent
2626import com.lambda.event.events.WorldEvent
2727import com.lambda.event.listener.SafeListener.Companion.listen
28+ import com.lambda.interaction.construction.context.BuildContext
2829import com.lambda.interaction.construction.context.PlaceContext
2930import com.lambda.interaction.construction.verify.TargetState
3031import com.lambda.interaction.request.PositionBlocking
3132import com.lambda.interaction.request.Priority
3233import com.lambda.interaction.request.RequestHandler
3334import com.lambda.interaction.request.breaking.BreakManager
35+ import com.lambda.interaction.request.hotbar.HotbarManager
3436import com.lambda.interaction.request.hotbar.HotbarRequest
3537import com.lambda.interaction.request.rotation.RotationManager.onRotate
36- import com.lambda.interaction.request.rotation.RotationManager.onRotatePost
37- import com.lambda.interaction.request.rotation.RotationRequest
3838import com.lambda.module.modules.client.TaskFlowModule
3939import com.lambda.util.BlockUtils.blockState
4040import com.lambda.util.BlockUtils.item
@@ -62,19 +62,18 @@ import net.minecraft.util.math.Direction
6262import net.minecraft.world.GameMode
6363
6464object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
65- private val pendingPlacements = LimitedDecayQueue <PlaceRequest >(
65+ private val pendingPlacements = LimitedDecayQueue <PlaceInfo >(
6666 TaskFlowModule .build.maxPendingInteractions, TaskFlowModule .build.interactionTimeout * 50L
6767 ) {
68- info(" ${it::class .simpleName} at ${it.placeContext .expectedPos.toShortString()} timed out" )
69- mc.world?.setBlockState(it.placeContext .expectedPos, it.placeContext .checkedState)
70- it.pendingInteractionsList.remove(it.placeContext )
68+ info(" ${it::class .simpleName} at ${it.context .expectedPos.toShortString()} timed out" )
69+ mc.world?.setBlockState(it.context .expectedPos, it.context .checkedState)
70+ it.pendingInteractionsList.remove(it.context )
7171 }
7272
73- override val blockedPositions
74- get() = pendingPlacements.map { it.placeContext.expectedPos }
73+ private var placeContexts = emptyList<PlaceContext >()
7574
76- private var rotation : RotationRequest ? = null
77- private var validRotation = false
75+ override val blockedPositions
76+ get() = pendingPlacements.map { it.context.expectedPos }
7877
7978 fun Any.onPlace (
8079 alwaysListen : Boolean = false,
@@ -95,23 +94,27 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
9594 init {
9695 listen<TickEvent .Pre >(priority = Int .MIN_VALUE ) {
9796 currentRequest?.let { request ->
98- val notSneaking = ! player.isSneaking
99- val hotbarRequest = request.hotbarConfig.request(HotbarRequest (request.placeContext.hotbarIndex))
100- if ((request.placeContext.sneak && notSneaking) || ! hotbarRequest.done || ! validRotation)
101- return @listen
102-
103- val actionResult = placeBlock(request, Hand .MAIN_HAND )
104- if (! actionResult.isAccepted) {
105- warn(" Placement interaction failed with $actionResult " )
106- }
107- activeThisTick = true
97+ placeContexts
98+ .forEach { ctx ->
99+ val notSneaking = ! player.isSneaking
100+ val hotbarRequest = request.hotbarConfig.request(HotbarRequest (ctx.hotbarIndex))
101+ if ((ctx.sneak && notSneaking) || ! hotbarRequest.done || ! ctx.rotation.done)
102+ return @listen
103+
104+ val actionResult = placeBlock(ctx, request, Hand .MAIN_HAND )
105+ if (! actionResult.isAccepted) {
106+ warn(" Placement interaction failed with $actionResult " )
107+ }
108+ activeThisTick = true
109+ }
110+ placeContexts = emptyList()
108111 }
109112 }
110113
111114 onRotate(priority = Int .MIN_VALUE ) {
112115 preEvent()
113116
114- if (! updateRequest { request -> canPlace(request.value.placeContext) } ) {
117+ if (! updateRequest() ) {
115118 postEvent()
116119 return @onRotate
117120 }
@@ -122,53 +125,56 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
122125 }
123126
124127 currentRequest?.let request@ { request ->
125- if (pendingPlacements.size >= request.buildConfig.placeSettings.maxPendingPlacements) {
126- postEvent()
127- return @onRotate
128- }
128+ pendingPlacements.setMaxSize(request.buildConfig.placeSettings.maxPendingPlacements)
129+ pendingPlacements.setDecayTime(request.buildConfig.interactionTimeout * 50L )
129130
130131 val placeConfig = request.buildConfig.placeSettings
131- rotation = if (placeConfig.rotateForPlace || placeConfig.axisRotate)
132- request.rotationConfig.request(request.placeContext.rotation)
133- else null
134132
135- pendingPlacements.setMaxSize(request.buildConfig.placeSettings.maxPendingPlacements)
136- pendingPlacements.setDecayTime(request.buildConfig.interactionTimeout * 50L )
133+ val maxPlacementsThisTick = (placeConfig.maxPendingPlacements - pendingPlacements.size).coerceAtLeast(0 )
134+ val takeCount = (placeConfig.placementsPerTick.coerceAtMost(maxPlacementsThisTick))
135+ val isSneaking = player.isSneaking
136+ val currentHotbarIndex = HotbarManager .serverSlot
137+ placeContexts = request.placeContexts
138+ .filter { canPlace(it) }
139+ .sortedBy { isSneaking == it.sneak && currentHotbarIndex == it.hotbarIndex }
140+ .take(takeCount)
141+
142+ request.placeContexts.firstOrNull()?.let { ctx ->
143+ if (placeConfig.rotateForPlace || placeConfig.axisRotate)
144+ request.rotationConfig.request(ctx.rotation)
145+ }
137146 }
138- }
139147
140- onRotatePost(priority = Int .MIN_VALUE ) {
141- validRotation = rotation?.done ? : true
142148 postEvent()
143149 }
144150
145151 listen<MovementEvent .InputUpdate > {
146- if (currentRequest?.placeContext ?.sneak == true ) it.input.sneaking = true
152+ if (placeContexts.firstOrNull() ?.sneak == true ) it.input.sneaking = true
147153 }
148154
149155 listen<WorldEvent .BlockUpdate .Server > { event ->
150156 pendingPlacements
151- .firstOrNull { it.placeContext .expectedPos == event.pos }
152- ?.let { request ->
153- removePendingPlace(request )
157+ .firstOrNull { it.context .expectedPos == event.pos }
158+ ?.let { info ->
159+ removePendingPlace(info )
154160
155161 // return if the block wasn't placed
156- if (! matchesTargetState(event.pos, request.placeContext .targetState, event.newState))
162+ if (! matchesTargetState(event.pos, info.context .targetState, event.newState))
157163 return @listen
158164
159- if (request.buildConfig.placeSettings .placeConfirmationMode == PlaceConfig .PlaceConfirmationMode .AwaitThenPlace )
160- with (request.placeContext ) {
165+ if (info.placeConfig .placeConfirmationMode == PlaceConfig .PlaceConfirmationMode .AwaitThenPlace )
166+ with (info.context ) {
161167 placeSound(expectedState.block.item as BlockItem , expectedState, expectedPos)
162168 }
163- request .onPlace()
169+ info .onPlace()
164170 return @listen
165171 }
166172 }
167173 }
168174
169175 private fun canPlace (placeContext : PlaceContext ) =
170176 pendingPlacements.none { pending ->
171- pending.placeContext .expectedPos == placeContext.expectedPos
177+ pending.context .expectedPos == placeContext.expectedPos
172178 }
173179
174180 private fun SafeContext.matchesTargetState (pos : BlockPos , targetState : TargetState , newState : BlockState ) =
@@ -178,15 +184,16 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
178184 false
179185 }
180186
181- private fun SafeContext.placeBlock (request : PlaceRequest , hand : Hand ): ActionResult {
187+ private fun SafeContext.placeBlock (placeContext : PlaceContext , request : PlaceRequest , hand : Hand ): ActionResult {
182188 interaction.syncSelectedSlot()
183- val hitResult = request. placeContext.result
189+ val hitResult = placeContext.result
184190 if (! world.worldBorder.contains(hitResult.blockPos)) return ActionResult .FAIL
185191 if (gamemode == GameMode .SPECTATOR ) return ActionResult .PASS
186- return interactBlockInternal(request, request.buildConfig.placeSettings, hand, hitResult)
192+ return interactBlockInternal(placeContext, request, request.buildConfig.placeSettings, hand, hitResult)
187193 }
188194
189195 private fun SafeContext.interactBlockInternal (
196+ placeContext : PlaceContext ,
190197 request : PlaceRequest ,
191198 placeConfig : PlaceConfig ,
192199 hand : Hand ,
@@ -212,17 +219,18 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
212219 val itemUsageContext = ItemUsageContext (player, hand, hitResult)
213220 return if (gamemode.isCreative) {
214221 val i = itemStack.count
215- useOnBlock(request, hand, hitResult, placeConfig, itemStack, itemUsageContext)
222+ useOnBlock(placeContext, request, hand, hitResult, placeConfig, itemStack, itemUsageContext)
216223 .also {
217224 itemStack.count = i
218225 }
219226 } else
220- useOnBlock(request, hand, hitResult, placeConfig, itemStack, itemUsageContext)
227+ useOnBlock(placeContext, request, hand, hitResult, placeConfig, itemStack, itemUsageContext)
221228 }
222229 return ActionResult .PASS
223230 }
224231
225232 private fun SafeContext.useOnBlock (
233+ placeContext : PlaceContext ,
226234 request : PlaceRequest ,
227235 hand : Hand ,
228236 hitResult : BlockHitResult ,
@@ -238,10 +246,11 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
238246
239247 val item = (itemStack.item as ? BlockItem ) ? : return ActionResult .PASS
240248
241- return place(request, hand, hitResult, placeConfig, item, ItemPlacementContext (context))
249+ return place(placeContext, request, hand, hitResult, placeConfig, item, ItemPlacementContext (context))
242250 }
243251
244252 private fun SafeContext.place (
253+ placeContext : PlaceContext ,
245254 request : PlaceRequest ,
246255 hand : Hand ,
247256 hitResult : BlockHitResult ,
@@ -258,10 +267,12 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
258267 val stackInHand = player.getStackInHand(hand)
259268 val stackCountPre = stackInHand.count
260269 if (placeConfig.placeConfirmationMode != PlaceConfig .PlaceConfirmationMode .None ) {
261- addPendingPlace(request)
270+ addPendingPlace(
271+ PlaceInfo (placeContext, request.onPlace, request.pendingInteractionsList, placeConfig)
272+ )
262273 }
263274
264- if (request.buildConfig.placeSettings .airPlace == PlaceConfig .AirPlaceMode .Grim ) {
275+ if (placeConfig .airPlace == PlaceConfig .AirPlaceMode .Grim ) {
265276 val placeHand = if (hand == Hand .MAIN_HAND ) Hand .OFF_HAND else Hand .MAIN_HAND
266277 airPlaceOffhandSwap()
267278 sendPlacePacket(placeHand, hitResult)
@@ -270,8 +281,8 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
270281 sendPlacePacket(hand, hitResult)
271282 }
272283
273- if (request.buildConfig.placeSettings .swing) {
274- swingHand(request.buildConfig.placeSettings .swingType, hand)
284+ if (placeConfig .swing) {
285+ swingHand(placeConfig .swingType, hand)
275286
276287 if (! stackInHand.isEmpty && (stackInHand.count != stackCountPre || interaction.hasCreativeInventory())) {
277288 mc.gameRenderer.firstPersonRenderer.resetEquipProgress(hand)
@@ -332,16 +343,23 @@ object PlaceManager : RequestHandler<PlaceRequest>(), PositionBlocking {
332343 )
333344 }
334345
335- private fun addPendingPlace (request : PlaceRequest ) {
336- pendingPlacements.add(request )
337- request .pendingInteractionsList.add(request.placeContext )
346+ private fun addPendingPlace (info : PlaceInfo ) {
347+ pendingPlacements.add(info )
348+ info .pendingInteractionsList.add(info.context )
338349 }
339350
340- private fun removePendingPlace (request : PlaceRequest ) {
341- pendingPlacements.remove(request )
342- request .pendingInteractionsList.remove(request.placeContext )
351+ private fun removePendingPlace (info : PlaceInfo ) {
352+ pendingPlacements.remove(info )
353+ info .pendingInteractionsList.remove(info.context )
343354 }
344355
356+ private data class PlaceInfo (
357+ val context : PlaceContext ,
358+ val onPlace : () -> Unit ,
359+ val pendingInteractionsList : MutableCollection <BuildContext >,
360+ val placeConfig : PlaceConfig
361+ )
362+
345363 override fun preEvent () = UpdateManagerEvent .Place .Pre ().post()
346364 override fun postEvent () = UpdateManagerEvent .Place .Post ().post()
347365}
0 commit comments