@@ -46,13 +46,13 @@ import com.lambda.interaction.request.rotating.visibilty.lookInDirection
4646import com.lambda.threading.runSafeAutomated
4747import com.lambda.util.BlockUtils
4848import com.lambda.util.BlockUtils.blockState
49- import com.lambda.util.BlockUtils.isEmpty
5049import com.lambda.util.item.ItemStackUtils.inventoryIndex
5150import com.lambda.util.item.ItemUtils.blockItem
5251import com.lambda.util.math.distSq
5352import com.lambda.util.math.vec3d
5453import com.lambda.util.player.copyPlayer
5554import com.lambda.util.world.raycast.RayCastUtils.blockResult
55+ import kotlinx.coroutines.CoroutineScope
5656import kotlinx.coroutines.Dispatchers
5757import kotlinx.coroutines.cancel
5858import kotlinx.coroutines.joinAll
@@ -69,6 +69,7 @@ import net.minecraft.item.Items
6969import net.minecraft.util.Hand
7070import net.minecraft.util.hit.BlockHitResult
7171import net.minecraft.util.math.BlockPos
72+ import net.minecraft.util.math.Direction
7273import net.minecraft.util.math.Vec3d
7374import net.minecraft.util.shape.VoxelShapes
7475import kotlin.math.pow
@@ -123,91 +124,98 @@ class PlaceChecker @SimCheckerDsl private constructor(simInfo: SimInfo)
123124
124125 supervisorScope {
125126 withContext(Dispatchers .Default ) {
126- preProcessing.sides.map { neighbor ->
127+ preProcessing.sides.map { side ->
127128 launch {
128- val hitBlockPos = if (! placeConfig.airPlace.isEnabled && state.isEmpty)
129- pos.offset(neighbor) else pos
130- val hitSide = neighbor.opposite
131- if (! world.worldBorder.contains(hitBlockPos)) return @launch
132-
133- val voxelShape = blockState(hitBlockPos).getOutlineShape(world, hitBlockPos).let { outlineShape ->
134- if (! outlineShape.isEmpty || ! placeConfig.airPlace.isEnabled) outlineShape
135- else VoxelShapes .fullCube()
136- }
137- if (voxelShape.isEmpty) return @launch
129+ val neighborPos = pos.offset(side)
130+ val neighborSide = side.opposite
131+ if (! placeConfig.airPlace.isEnabled)
132+ testBlock(neighborPos, neighborSide, this @supervisorScope)
133+ testBlock(pos, side, this @supervisorScope)
134+ }
135+ }.joinAll()
136+ }
137+ }
138+
139+ return true
140+ }
141+
142+ private suspend fun AutomatedSafeContext.testBlock (pos : BlockPos , side : Direction , supervisorScope : CoroutineScope ) {
143+ if (! world.worldBorder.contains(pos)) return
144+
145+ val voxelShape = blockState(pos).getOutlineShape(world, pos).let { outlineShape ->
146+ if (! outlineShape.isEmpty || ! placeConfig.airPlace.isEnabled) outlineShape
147+ else VoxelShapes .fullCube()
148+ }
149+ if (voxelShape.isEmpty) return
150+
151+ val boxes = voxelShape.boundingBoxes.map { it.offset(pos) }
152+ val verify: CheckedHit .() -> Boolean = {
153+ hit.blockResult?.blockPos == pos && hit.blockResult?.side == side
154+ }
138155
139- val boxes = voxelShape.boundingBoxes.map { it.offset(hitBlockPos) }
140- val verify: CheckedHit .() -> Boolean = {
141- hit.blockResult?.blockPos == hitBlockPos && hit.blockResult?.side == hitSide
156+ val validHits = mutableListOf<CheckedHit >()
157+ val misses = mutableSetOf<Vec3d >()
158+ val reachSq = buildConfig.interactReach.pow(2 )
159+
160+ withContext(Dispatchers .Default ) {
161+ boxes.map { box ->
162+ launch {
163+ val sides = if (buildConfig.checkSideVisibility) {
164+ box.getVisibleSurfaces(eye).intersect(setOf (side))
165+ } else setOf (side)
166+
167+ scanSurfaces(box, sides, buildConfig.resolution, preProcessing.surfaceScan) { _, vec ->
168+ val distSquared = eye distSq vec
169+ if (distSquared > reachSq) {
170+ misses.add(vec)
171+ return @scanSurfaces
142172 }
143173
144- val validHits = mutableListOf<CheckedHit >()
145- val misses = mutableSetOf<Vec3d >()
146- val reachSq = buildConfig.interactReach.pow(2 )
147-
148- boxes.map { box ->
149- launch {
150- val sides = if (buildConfig.checkSideVisibility) {
151- box.getVisibleSurfaces(eye).intersect(setOf (hitSide))
152- } else setOf (hitSide)
153-
154- scanSurfaces(box, sides, buildConfig.resolution, preProcessing.surfaceScan) { _, vec ->
155- val distSquared = eye distSq vec
156- if (distSquared > reachSq) {
157- misses.add(vec)
158- return @scanSurfaces
159- }
160-
161- val newRotation = eye.rotationTo(vec)
162-
163- val hit = if (buildConfig.strictRayCast) {
164- val rayCast = newRotation.rayCast(buildConfig.interactReach, eye)
165- when {
166- rayCast != null && (! placeConfig.airPlace.isEnabled || eye distSq rayCast.pos <= distSquared) ->
167- rayCast.blockResult
168-
169- placeConfig.airPlace.isEnabled -> {
170- val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye)
171- BlockHitResult (hitVec, hitSide, hitBlockPos, false )
172- }
173-
174- else -> null
175- }
176- } else {
177- val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye)
178- BlockHitResult (hitVec, hitSide, hitBlockPos, false )
179- } ? : return @scanSurfaces
180-
181- val checked = CheckedHit (hit, newRotation, buildConfig.interactReach)
182- if (! checked.verify()) return @scanSurfaces
183-
184- validHits.add(checked)
174+ val newRotation = eye.rotationTo(vec)
175+
176+ 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 )
185185 }
186- }
187- }.joinAll()
188186
189- if (validHits.isEmpty()) {
190- if (misses.isNotEmpty()) {
191- result(GenericResult .OutOfReach (pos, eye, misses))
192- return @launch
187+ else -> null
193188 }
189+ } else {
190+ val hitVec = newRotation.castBox(box, buildConfig.interactReach, eye)
191+ BlockHitResult (hitVec, side, pos, false )
192+ } ? : return @scanSurfaces
194193
195- result(GenericResult .NotVisible (pos, hitBlockPos, hitSide, eye.distanceTo(hitBlockPos.offset(hitSide).vec3d)))
196- return @launch
197- }
194+ val checked = CheckedHit (hit, newRotation, buildConfig.interactReach)
195+ if (! checked.verify()) return @scanSurfaces
198196
199- if (swapStack.item == Items .AIR )
200- this @supervisorScope.cancel()
201- else if (! swapStack.item.isEnabled(world.enabledFeatures)) {
202- result(PlaceResult .BlockFeatureDisabled (pos, swapStack))
203- this @supervisorScope.cancel()
204- } else selectHitPos(validHits)
197+ validHits.add(checked)
205198 }
206- }.joinAll()
199+ }
200+ }.joinAll()
201+ }
202+
203+ if (validHits.isEmpty()) {
204+ if (misses.isNotEmpty()) {
205+ result(GenericResult .OutOfReach (pos, eye, misses))
206+ return
207207 }
208+
209+ result(GenericResult .NotVisible (pos, pos, side, eye.distanceTo(pos.offset(side).vec3d)))
210+ return
208211 }
209212
210- return true
213+ if (swapStack.item == Items .AIR )
214+ supervisorScope.cancel()
215+ else if (! swapStack.item.isEnabled(world.enabledFeatures)) {
216+ result(PlaceResult .BlockFeatureDisabled (pos, swapStack))
217+ supervisorScope.cancel()
218+ } else selectHitPos(validHits)
211219 }
212220
213221 private fun AutomatedSafeContext.selectHitPos (validHits : List <CheckedHit >) {
0 commit comments