Skip to content

Commit eee5af4

Browse files
committed
modify fake player to sneak and therefore adjust eye position accordingly if sneaking is required for placement
1 parent cd3dbe5 commit eee5af4

File tree

4 files changed

+41
-59
lines changed

4 files changed

+41
-59
lines changed

src/main/kotlin/com/lambda/config/groups/BuildSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ class BuildSettings(
4747

4848
override val scanReach: Double get() = max(attackReach, interactReach)
4949

50-
override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context", vis).group(*baseGroup, Group.Scan)
5150
override val checkSideVisibility by c.setting("Visibility Check", true, "Whether to check if an AABB side is visible", vis).group(*baseGroup, Group.Scan)
51+
override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context", vis).group(*baseGroup, Group.Scan)
5252
override val resolution by c.setting("Resolution", 5, 1..20, 1, "The amount of grid divisions per surface of the hit box", "", vis).group(*baseGroup, Group.Scan)
5353
override val pointSelection by c.setting("Point Selection", PointSelection.Optimum, "The strategy to select the best hit point", vis).group(*baseGroup, Group.Scan)
5454

src/main/kotlin/com/lambda/interaction/construction/simulation/checks/PlaceChecker.kt

Lines changed: 38 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import com.lambda.util.item.ItemStackUtils.inventoryIndex
5050
import com.lambda.util.item.ItemUtils.blockItem
5151
import com.lambda.util.math.distSq
5252
import com.lambda.util.math.vec3d
53+
import com.lambda.util.player.MovementUtils.sneaking
5354
import com.lambda.util.player.copyPlayer
5455
import com.lambda.util.world.raycast.RayCastUtils.blockResult
5556
import kotlinx.coroutines.CoroutineScope
@@ -64,7 +65,6 @@ import net.minecraft.block.pattern.CachedBlockPosition
6465
import net.minecraft.client.network.ClientPlayerEntity
6566
import net.minecraft.item.ItemPlacementContext
6667
import net.minecraft.item.ItemStack
67-
import net.minecraft.item.ItemUsageContext
6868
import net.minecraft.item.Items
6969
import net.minecraft.util.Hand
7070
import 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

src/main/kotlin/com/lambda/interaction/request/rotating/visibilty/PointSelection.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ enum class PointSelection(
4141
"Choose the point closest to the average of all candidates (balanced and stable aim).",
4242
select = { hits ->
4343
val optimum = hits
44-
.mapNotNull { it?.hit?.pos }
44+
.mapNotNull { it.hit.pos }
4545
.reduceOrNull { acc, pos -> acc.add(pos) }
4646
?.times(1 / hits.size.toDouble())
4747

src/main/resources/lambda.accesswidener

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ transitive-accessible method net/minecraft/entity/LivingEntity getHandSwingDurat
4848
transitive-accessible method net/minecraft/client/network/ClientPlayerInteractionManager syncSelectedSlot ()V
4949
transitive-accessible method net/minecraft/util/math/Direction listClosest (Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/Direction;Lnet/minecraft/util/math/Direction;)[Lnet/minecraft/util/math/Direction;
5050
transitive-accessible field net/minecraft/client/network/ClientPlayerInteractionManager gameMode Lnet/minecraft/world/GameMode;
51+
transitive-accessible method net/minecraft/entity/player/PlayerEntity updatePose ()V
5152

5253
# Camera
5354
transitive-accessible method net/minecraft/client/render/Camera setPos (DDD)V

0 commit comments

Comments
 (0)