@@ -24,9 +24,11 @@ import com.lambda.interaction.construction.result.Dependable
2424import com.lambda.interaction.construction.result.results.GenericResult
2525import com.lambda.interaction.construction.result.results.PlaceResult
2626import com.lambda.interaction.construction.simulation.ISimInfo
27+ import com.lambda.interaction.construction.simulation.ISimInfo.Companion.simInfo
2728import com.lambda.interaction.construction.simulation.SimChecker
2829import com.lambda.interaction.construction.simulation.SimCheckerDsl
2930import com.lambda.interaction.construction.simulation.SimInfo
31+ import com.lambda.interaction.construction.simulation.checks.BreakChecker.Companion.checkBreaks
3032import com.lambda.interaction.construction.simulation.checks.PlaceChecker.RotatePlaceTest.Companion.rotatePlaceTest
3133import com.lambda.interaction.construction.verify.TargetState
3234import com.lambda.interaction.material.ContainerSelection.Companion.selectContainer
@@ -43,8 +45,10 @@ import com.lambda.interaction.request.rotating.visibilty.lookAt
4345import com.lambda.interaction.request.rotating.visibilty.lookInDirection
4446import com.lambda.util.BlockUtils
4547import com.lambda.util.BlockUtils.blockState
48+ import com.lambda.util.EntityUtils.getPositionsWithinHitboxXZ
4649import com.lambda.util.item.ItemStackUtils.inventoryIndex
4750import com.lambda.util.item.ItemUtils.blockItem
51+ import com.lambda.util.math.MathUtils.floorToInt
4852import com.lambda.util.math.minus
4953import com.lambda.util.player.MovementUtils.sneaking
5054import com.lambda.util.player.copyPlayer
@@ -54,8 +58,10 @@ import kotlinx.coroutines.cancel
5458import kotlinx.coroutines.launch
5559import kotlinx.coroutines.supervisorScope
5660import net.minecraft.block.BlockState
61+ import net.minecraft.block.ShapeContext
5762import net.minecraft.block.pattern.CachedBlockPosition
5863import net.minecraft.client.network.ClientPlayerEntity
64+ import net.minecraft.entity.Entity
5965import net.minecraft.item.ItemPlacementContext
6066import net.minecraft.item.ItemStack
6167import net.minecraft.util.Hand
@@ -141,7 +147,7 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
141147 }
142148 }
143149
144- private fun AutomatedSafeContext.selectHitPos (
150+ private suspend fun AutomatedSafeContext.selectHitPos (
145151 validHits : Collection <CheckedHit >,
146152 fakePlayer : ClientPlayerEntity ,
147153 swapStack : ItemStack
@@ -203,7 +209,7 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
203209 return
204210 }
205211
206- private fun AutomatedSafeContext.simRotatePlace (
212+ private suspend fun AutomatedSafeContext.simRotatePlace (
207213 fakePlayer : ClientPlayerEntity ,
208214 checkedHit : CheckedHit ,
209215 context : ItemPlacementContext
@@ -231,18 +237,53 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
231237 return null
232238 }
233239
234- private fun AutomatedSafeContext.testPlaceState (context : ItemPlacementContext ): PlaceTest {
235- val resultState = context.stack.blockItem.getPlacementState(context) ? : run {
236- result(PlaceResult .BlockedByEntity (pos, emptyList()))
237- return PlaceTest (state, PlaceTestResult .BlockedByEntity )
238- }
240+ private suspend fun AutomatedSafeContext.testPlaceState (context : ItemPlacementContext ): PlaceTest {
241+ val resultState = context.stack.blockItem.getPlacementState(context)
242+ ? : run {
243+ val blockingEntities = handleEntityBlockage(context)
244+ result(PlaceResult .BlockedByEntity (pos, blockingEntities))
245+ return PlaceTest (state, PlaceTestResult .BlockedByEntity )
246+ }
239247
240248 return if (! targetState.matches(resultState, pos, preProcessing.ignore)) {
241249 result(PlaceResult .NoIntegrity (pos, resultState, context, (targetState as ? TargetState .State )?.blockState))
242250 PlaceTest (resultState, PlaceTestResult .NoIntegrity )
243251 } else PlaceTest (resultState, PlaceTestResult .Success )
244252 }
245253
254+ private suspend fun AutomatedSafeContext.handleEntityBlockage (context : ItemPlacementContext ): List <Entity > {
255+ val theoreticalState = context.stack.blockItem.block.getPlacementState(context)
256+ ? : return emptyList()
257+
258+ val collisionShape = theoreticalState.getCollisionShape(
259+ world,
260+ context.blockPos,
261+ ShapeContext .ofPlacement(player)
262+ ).offset(context.blockPos)
263+
264+ val collidingEntities = collisionShape.boundingBoxes.flatMap { box ->
265+ world.entities.filter { it.boundingBox.intersects(box) }
266+ }
267+
268+ if (collidingEntities.isNotEmpty()) {
269+ collidingEntities
270+ .mapNotNull { entity ->
271+ val hitbox = entity.boundingBox
272+ entity.getPositionsWithinHitboxXZ(
273+ (pos.y - (hitbox.maxY - hitbox.minY)).floorToInt(),
274+ pos.y
275+ )
276+ }
277+ .flatten()
278+ .forEach { support ->
279+ simInfo(support, blockState(support), TargetState .Empty )?.checkBreaks()
280+ }
281+ result(PlaceResult .BlockedByEntity (pos, collidingEntities))
282+ }
283+
284+ return collidingEntities
285+ }
286+
246287 private class RotatePlaceTest private constructor(
247288 val resultState : BlockState ,
248289 val currentDirIsValid : Boolean ,
0 commit comments