@@ -50,6 +50,7 @@ import com.lambda.util.item.ItemStackUtils.inventoryIndex
5050import com.lambda.util.item.ItemUtils.blockItem
5151import com.lambda.util.math.distSq
5252import com.lambda.util.math.vec3d
53+ import com.lambda.util.player.MovementUtils.sneaking
5354import com.lambda.util.player.copyPlayer
5455import com.lambda.util.world.raycast.RayCastUtils.blockResult
5556import kotlinx.coroutines.CoroutineScope
@@ -64,7 +65,6 @@ import net.minecraft.block.pattern.CachedBlockPosition
6465import net.minecraft.client.network.ClientPlayerEntity
6566import net.minecraft.item.ItemPlacementContext
6667import net.minecraft.item.ItemStack
67- import net.minecraft.item.ItemUsageContext
6868import net.minecraft.item.Items
6969import net.minecraft.util.Hand
7070import net.minecraft.util.hit.BlockHitResult
@@ -142,25 +142,34 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
142142 private suspend fun AutomatedSafeContext.testBlock (pos : BlockPos , side : Direction , supervisorScope : CoroutineScope ) {
143143 if (! world.worldBorder.contains(pos)) return
144144
145- val voxelShape = blockState(pos).getOutlineShape(world, pos).let { outlineShape ->
145+ val testBlockState = blockState(pos)
146+ val voxelShape = testBlockState.getOutlineShape(world, pos).let { outlineShape ->
146147 if (! outlineShape.isEmpty || ! placeConfig.airPlace.isEnabled) outlineShape
147148 else VoxelShapes .fullCube()
148149 }
149150 if (voxelShape.isEmpty) return
150151
151152 val boxes = voxelShape.boundingBoxes.map { it.offset(pos) }
152- val verify: CheckedHit .() -> Boolean = {
153- hit.blockResult?.blockPos == pos && hit.blockResult?.side == side
154- }
155153
156154 val validHits = mutableListOf<CheckedHit >()
157155 val misses = mutableSetOf<Vec3d >()
158156 val reachSq = buildConfig.interactReach.pow(2 )
159157
158+ // ToDo: For each hand and sneak or not?
159+ val fakePlayer = copyPlayer(player).apply {
160+ this .rotation = RotationManager .serverRotation
161+ if (testBlockState.block::class in BlockUtils .interactionBlocks) {
162+ input.sneaking = true
163+ updatePose()
164+ }
165+ }
166+
167+ val eye = fakePlayer.eyePos
168+
160169 withContext(Dispatchers .Default ) {
161170 boxes.map { box ->
162171 launch {
163- val sides = if (buildConfig.checkSideVisibility) {
172+ val sides = if (buildConfig.checkSideVisibility || buildConfig.strictRayCast ) {
164173 box.getVisibleSurfaces(eye).intersect(setOf (side))
165174 } else setOf (side)
166175
@@ -174,25 +183,14 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
174183 val newRotation = eye.rotationTo(vec)
175184
176185 val hit = if (buildConfig.strictRayCast) {
177- val rayCast = newRotation.rayCast(buildConfig.interactReach, eye)
178- when {
179- rayCast != null && (! placeConfig.airPlace.isEnabled || eye distSq rayCast.pos <= distSquared) ->
180- rayCast.blockResult
181-
182- placeConfig.airPlace.isEnabled -> {
183- val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye)
184- BlockHitResult (hitVec, side, pos, false )
185- }
186-
187- else -> null
188- }
186+ newRotation.rayCast(buildConfig.interactReach, eye)?.blockResult ? : return @scanSurfaces
189187 } else {
190- val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye)
188+ val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye) ? : return @scanSurfaces
191189 BlockHitResult (hitVec, side, pos, false )
192- } ? : return @scanSurfaces
190+ }
193191
192+ if (hit.blockPos != pos || hit.side != side) return @scanSurfaces
194193 val checked = CheckedHit (hit, newRotation, buildConfig.interactReach)
195- if (! checked.verify()) return @scanSurfaces
196194
197195 validHits.add(checked)
198196 }
@@ -215,39 +213,29 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
215213 else if (! swapStack.item.isEnabled(world.enabledFeatures)) {
216214 result(PlaceResult .BlockFeatureDisabled (pos, swapStack))
217215 supervisorScope.cancel()
218- } else selectHitPos(validHits)
216+ } else selectHitPos(validHits, fakePlayer )
219217 }
220218
221- private fun AutomatedSafeContext.selectHitPos (validHits : List <CheckedHit >) {
219+ private fun AutomatedSafeContext.selectHitPos (validHits : List <CheckedHit >, fakePlayer : ClientPlayerEntity ) {
222220 buildConfig.pointSelection.select(validHits)?.let { checkedHit ->
223- // ToDo: For each hand and sneak or not?
224- val fakePlayer = copyPlayer(player).apply {
225- this .rotation = RotationManager .serverRotation
226- }
227-
228- val blockHit = checkedHit.hit.blockResult ? : return
221+ val hitResult = checkedHit.hit.blockResult ? : return
229222
230- // ToDo: Override the stack used for this to account for blocks where replaceability is dependent on the held item
231- val usageContext = ItemUsageContext (
223+ var context = ItemPlacementContext (
232224 world,
233225 fakePlayer,
234226 Hand .MAIN_HAND ,
235227 swapStack,
236- blockHit,
237- )
238- val cachePos = CachedBlockPosition (
239- usageContext.world, usageContext.blockPos, false
228+ hitResult,
240229 )
241230
242- if (! player.abilities.allowModifyWorld && ! swapStack.canPlaceOn(cachePos) ) {
243- result(PlaceResult .IllegalUsage (pos))
231+ if (context.blockPos != pos ) {
232+ result(PlaceResult .UnexpectedPosition (pos, context.blockPos ))
244233 return
245234 }
246235
247- var context = ItemPlacementContext (usageContext)
248-
249- if (context.blockPos != pos) {
250- result(PlaceResult .UnexpectedPosition (pos, context.blockPos))
236+ val cachePos = CachedBlockPosition (context.world, context.blockPos, false )
237+ if (! player.abilities.allowModifyWorld && ! swapStack.canPlaceOn(cachePos)) {
238+ result(PlaceResult .IllegalUsage (pos))
251239 return
252240 }
253241
@@ -263,21 +251,18 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
263251
264252 if (! simRotation(fakePlayer, checkedHit, context)) return
265253
266- val hitBlock = blockState(blockHit.blockPos).block
267- val shouldSneak = hitBlock::class in BlockUtils .interactionBlocks
268-
269254 val rotationRequest = if (placeConfig.axisRotate) {
270255 lookInDirection(PlaceDirection .fromRotation(rot))
271256 } else lookAt(rot, 0.001 )
272257
273258 val placeContext = PlaceContext (
274- blockHit ,
259+ hitResult ,
275260 RotationRequest (rotationRequest, this @PlaceChecker),
276261 swapStack.inventoryIndex,
277- context.blockPos ,
278- blockState(context.blockPos) ,
262+ pos ,
263+ state ,
279264 resultState,
280- shouldSneak ,
265+ fakePlayer.isSneaking ,
281266 false ,
282267 currentDirIsValid,
283268 this @PlaceChecker
@@ -294,27 +279,27 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
294279 checkedHit : CheckedHit ,
295280 context : ItemPlacementContext
296281 ): Boolean {
297- currentDirIsValid = if (testPlaceState(pos, targetState, context) != PlaceTestResult .Success ) {
282+ currentDirIsValid = if (testPlaceState(context) != PlaceTestResult .Success ) {
298283 if (! placeConfig.rotateForPlace) return false
299284 else false
300285 } else true
301286
302287 if (! placeConfig.axisRotate) {
303288 fakePlayer.rotation = checkedHit.targetRotation
304- if (testPlaceState(pos, targetState, context) != PlaceTestResult .Success ) return false
289+ if (testPlaceState(context) != PlaceTestResult .Success ) return false
305290 rot = fakePlayer.rotation
306291 return true
307292 }
308293
309294 fakePlayer.rotation = player.rotation
310- if (testPlaceState(pos, targetState, context) == PlaceTestResult .Success ) {
295+ if (testPlaceState(context) == PlaceTestResult .Success ) {
311296 rot = fakePlayer.rotation
312297 return true
313298 }
314299
315300 PlaceDirection .entries.asReversed().forEachIndexed direction@{ index, direction ->
316301 fakePlayer.rotation = direction.rotation
317- when (testPlaceState(pos, targetState, context)) {
302+ when (testPlaceState(context)) {
318303 PlaceTestResult .BlockedByEntity -> return @direction
319304
320305 PlaceTestResult .NoIntegrity -> {
@@ -332,11 +317,7 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
332317 return true
333318 }
334319
335- private fun SafeContext.testPlaceState (
336- pos : BlockPos ,
337- targetState : TargetState ,
338- context : ItemPlacementContext
339- ): PlaceTestResult {
320+ private fun SafeContext.testPlaceState (context : ItemPlacementContext ): PlaceTestResult {
340321 resultState = blockItem.getPlacementState(context) ? : run {
341322 result(PlaceResult .BlockedByEntity (pos))
342323 return PlaceTestResult .BlockedByEntity
0 commit comments