Skip to content

Commit 0944e8d

Browse files
committed
Fix reach misconceptions and inventory crash
1 parent 3593075 commit 0944e8d

File tree

9 files changed

+71
-55
lines changed

9 files changed

+71
-55
lines changed

common/src/main/kotlin/com/lambda/interaction/construction/Blueprint.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ abstract class Blueprint {
1818
open fun isDone(ctx: SafeContext) =
1919
structure.all { (pos, targetState) ->
2020
with(ctx) {
21-
val state = pos.blockState(world)
22-
targetState.matches(state, pos, world) || state.block in TaskFlow.ignoredBlocks
21+
targetState.matches(pos.blockState(world), pos, world)
2322
}
2423
}
2524

common/src/main/kotlin/com/lambda/interaction/construction/result/BuildResult.kt

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import baritone.api.pathing.goals.GoalBlock
44
import baritone.api.pathing.goals.GoalNear
55
import baritone.process.BuilderProcess.GoalPlace
66
import com.lambda.context.SafeContext
7+
import com.lambda.interaction.construction.Blueprint
78
import com.lambda.interaction.construction.context.BuildContext
89
import com.lambda.interaction.material.ContainerManager.transfer
910
import com.lambda.interaction.material.StackSelection.Companion.select
@@ -28,7 +29,7 @@ abstract class BuildResult : ComparableResult<Rank>, Task<Unit>() {
2829
* The build action is done.
2930
*/
3031
data class Done(
31-
override val blockPos: BlockPos,
32+
override val blockPos: BlockPos
3233
) : BuildResult() {
3334
override val rank = Rank.DONE
3435
}
@@ -37,7 +38,7 @@ abstract class BuildResult : ComparableResult<Rank>, Task<Unit>() {
3738
* The build action is ignored.
3839
*/
3940
data class Ignored(
40-
override val blockPos: BlockPos,
41+
override val blockPos: BlockPos
4142
) : BuildResult() {
4243
override val rank = Rank.IGNORED
4344
}
@@ -236,26 +237,22 @@ abstract class BuildResult : ComparableResult<Rank>, Task<Unit>() {
236237
/**
237238
* Represents a break out of reach.
238239
* @param blockPos The position of the block that is out of reach.
239-
* @param startVec The start vector of the reach.
240-
* @param hitVec The hit vector of the reach.
241-
* @param reach The maximum reach distance.
242-
* @param side The side that is out of reach.
240+
* @param pov The point of view of the player.
241+
* @param misses The points that are out of reach.
243242
*/
244243
data class OutOfReach(
245244
override val blockPos: BlockPos,
246-
val startVec: Vec3d,
247-
val hitVec: Vec3d,
248-
val reach: Double,
249-
val side: Direction,
245+
val pov: Vec3d,
246+
val misses: Set<Vec3d>
250247
) : Navigable, Drawable, BuildResult() {
251248
override val rank = Rank.OUT_OF_REACH
252249
private val color = Color(252, 3, 207, 100)
253250

254251
val distance: Double by lazy {
255-
startVec.distanceTo(hitVec)
252+
misses.minOfOrNull { pov.distanceTo(it) } ?: 0.0
256253
}
257254

258-
override val goal = GoalNear(blockPos, 2)
255+
override val goal = GoalNear(blockPos, 3)
259256

260257
override fun SafeContext.buildRenderer() {
261258
withPos(blockPos, color)

common/src/main/kotlin/com/lambda/interaction/construction/result/Rank.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ enum class Rank {
3232
IGNORED;
3333

3434
val solvable: Boolean
35-
get() = ordinal < OUT_OF_WORLD.ordinal
35+
get() = ordinal < PLACE_NOT_ITEM_BLOCK.ordinal
3636
}

common/src/main/kotlin/com/lambda/interaction/construction/simulation/BuildSimulator.kt

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import com.lambda.util.BlockUtils
2020
import com.lambda.util.BlockUtils.blockState
2121
import com.lambda.util.BlockUtils.instantBreakable
2222
import com.lambda.util.BlockUtils.vecOf
23+
import com.lambda.util.Communication.info
24+
import com.lambda.util.Communication.warn
2325
import com.lambda.util.item.ItemStackUtils.equal
2426
import com.lambda.util.math.VecUtils.distSq
2527
import com.lambda.util.world.raycast.RayCastUtils.blockResult
@@ -42,7 +44,7 @@ object BuildSimulator {
4244
fun Blueprint.simulate(eye: Vec3d, reach: Double = TaskFlow.interact.reach) =
4345
runSafe {
4446
structure.entries.flatMap { (pos, target) ->
45-
checkRequirements(pos, target, reach)?.let {
47+
checkRequirements(pos, target)?.let {
4648
return@flatMap setOf(it)
4749
}
4850
checkPlaceResults(pos, target, eye, reach).let {
@@ -53,11 +55,12 @@ object BuildSimulator {
5355
if (it.isEmpty()) return@let
5456
return@flatMap it
5557
}
58+
warn("Nothing matched $pos $target")
5659
emptySet()
5760
}.toSet()
5861
} ?: emptySet()
5962

60-
private fun SafeContext.checkRequirements(pos: BlockPos, target: TargetState, reach: Double): BuildResult? {
63+
private fun SafeContext.checkRequirements(pos: BlockPos, target: TargetState): BuildResult? {
6164
/* the chunk is not loaded */
6265
if (!world.isChunkLoaded(pos)) {
6366
return BuildResult.ChunkNotLoaded(pos)
@@ -119,22 +122,18 @@ object BuildSimulator {
119122
if (voxelShape.isEmpty) return@forEach
120123

121124
val boxes = voxelShape.boundingBoxes.map { it.offset(hitPos) }
122-
123-
if (boxes.all { it.center.distanceTo(eye) > reach + 1 }) {
124-
acc.add(BuildResult.OutOfReach(pos, eye, hitPos.vecOf(hitSide), reach, hitSide))
125-
return@forEach
126-
}
127-
128125
val verify: HitResult.() -> Boolean = {
129126
blockResult?.blockPos == hitPos && blockResult?.side == hitSide
130127
}
131128
val validHits = mutableMapOf<Vec3d, HitResult>()
129+
val misses = mutableSetOf<Vec3d>()
132130
val reachSq = reach.pow(2)
133131

134132
boxes.forEach { box ->
135133
val res = if (TaskFlow.interact.useRayCast) interact.resolution else 2
136134
scanVisibleSurfaces(eye, box, setOf(hitSide), res) { side, vec ->
137135
if (eye distSq vec > reachSq) {
136+
misses.add(vec)
138137
return@scanVisibleSurfaces
139138
}
140139

@@ -152,11 +151,15 @@ object BuildSimulator {
152151
false
153152
)
154153
}
155-
156154
}
157155
}
158156

159157
if (validHits.isEmpty()) {
158+
if (misses.isNotEmpty()) {
159+
acc.add(BuildResult.OutOfReach(pos, eye, misses))
160+
return@forEach
161+
}
162+
160163
acc.add(BuildResult.NotVisible(pos, hitPos, hitSide, eye.distanceTo(hitPos.vecOf(hitSide))))
161164
return@forEach
162165
}
@@ -258,7 +261,11 @@ object BuildSimulator {
258261
return acc
259262
}
260263

261-
private fun SafeContext.checkBreakResults(pos: BlockPos, eye: Vec3d, reach: Double): Set<BuildResult> {
264+
private fun SafeContext.checkBreakResults(
265+
pos: BlockPos,
266+
eye: Vec3d,
267+
reach: Double
268+
): Set<BuildResult> {
262269
val acc = mutableSetOf<BuildResult>()
263270
val state = pos.blockState(world)
264271

@@ -315,15 +322,10 @@ object BuildSimulator {
315322

316323
val voxelShape = state.getOutlineShape(world, pos)
317324
voxelShape.getClosestPointTo(eye).ifPresent {
318-
// ToDo: Use closest point of shape
325+
// ToDo: Use closest point of shape of only visible faces
319326
}
320327

321328
val boxes = voxelShape.boundingBoxes.map { it.offset(pos) }
322-
if (boxes.all { it.center.distanceTo(eye) > reach + 1 }) {
323-
acc.add(BuildResult.OutOfReach(pos, eye, pos.toCenterPos(), reach, Direction.UP))
324-
return acc
325-
}
326-
327329
val verify: HitResult.() -> Boolean = { blockResult?.blockPos == pos }
328330
/* the player is buried inside the block */
329331
if (boxes.any { it.contains(eye) }) {
@@ -343,12 +345,14 @@ object BuildSimulator {
343345
}
344346

345347
val validHits = mutableMapOf<Vec3d, HitResult>()
348+
val misses = mutableSetOf<Vec3d>()
346349
val reachSq = reach.pow(2)
347350

348351
boxes.forEach { box ->
349352
val res = if (TaskFlow.interact.useRayCast) interact.resolution else 2
350353
scanVisibleSurfaces(eye, box, emptySet(), res) { side, vec ->
351354
if (eye distSq vec > reachSq) {
355+
misses.add(vec)
352356
return@scanVisibleSurfaces
353357
}
354358

@@ -369,6 +373,12 @@ object BuildSimulator {
369373
}
370374
}
371375

376+
if (validHits.isEmpty()) {
377+
// ToDo: If we can only mine exposed surfaces we need to add not visible result here
378+
acc.add(BuildResult.OutOfReach(pos, eye, misses))
379+
return acc
380+
}
381+
372382
validHits.keys.optimum?.let { optimum ->
373383
validHits.minByOrNull { optimum distSq it.key }?.let { closest ->
374384
val optimumRotation = eye.rotationTo(closest.key)
@@ -403,7 +413,6 @@ object BuildSimulator {
403413

404414
acc.add(BreakResult.Break(pos, breakContext))
405415
}
406-
407416
return acc
408417
}
409418
}

common/src/main/kotlin/com/lambda/interaction/construction/simulation/Simulation.kt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,13 @@ data class Simulation(val blueprint: Blueprint) {
4040
// }.keys
4141

4242
fun simulate(pos: FastVector): Set<BuildResult> {
43-
// runSafe {
44-
// if (!playerFitsIn(Vec3d.ofBottomCenter(pos.toBlockPos()))) return emptySet()
45-
// }
46-
// return blueprint.simulate(pos.toView()).also { cache[pos] = it }
47-
// return cache.computeIfAbsent(pos) {
48-
//// runSafe {
49-
//// if (!playerFitsIn(Vec3d.ofBottomCenter(pos.toBlockPos()))) return@computeIfAbsent emptySet()
50-
//// }
51-
// blueprint.simulate(pos.toView())
52-
// }
53-
return blueprint.simulate(pos.toView(), reach = 3.5)
43+
return cache.computeIfAbsent(pos) {
44+
runSafe {
45+
if (!playerFitsIn(Vec3d.ofBottomCenter(pos.toBlockPos()))) return@computeIfAbsent emptySet()
46+
}
47+
blueprint.simulate(pos.toView(), reach = 3.5)
48+
}
49+
// return blueprint.simulate(pos.toView(), reach = 3.5)
5450
}
5551

5652
private fun SafeContext.playerFitsIn(pos: Vec3d): Boolean {

common/src/main/kotlin/com/lambda/interaction/construction/verify/TargetState.kt

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@ import net.minecraft.item.Items
1111
import net.minecraft.util.math.BlockPos
1212
import net.minecraft.util.math.Direction
1313

14-
sealed class TargetState : StateMatcher {
15-
data object Air : TargetState() {
14+
sealed class TargetState(val type: Type) : StateMatcher {
15+
16+
enum class Type {
17+
AIR, SOLID, SUPPORT, STATE, BLOCK, STACK
18+
}
19+
20+
data object Air : TargetState(Type.AIR) {
1621
override fun matches(state: BlockState, pos: BlockPos, world: ClientWorld) =
1722
state.isAir
1823
override fun getStack(world: ClientWorld, pos: BlockPos): ItemStack =
1924
ItemStack.EMPTY
2025
}
2126

22-
data object Solid : TargetState() {
27+
data object Solid : TargetState(Type.SOLID) {
2328
override fun matches(state: BlockState, pos: BlockPos, world: ClientWorld) =
2429
state.isSolidBlock(world, pos)
2530
override fun getStack(world: ClientWorld, pos: BlockPos) =
@@ -28,7 +33,7 @@ sealed class TargetState : StateMatcher {
2833
} ?: ItemStack(Items.NETHERRACK)
2934
}
3035

31-
data class Support(val direction: Direction) : TargetState() {
36+
data class Support(val direction: Direction) : TargetState(Type.SUPPORT) {
3237
override fun matches(state: BlockState, pos: BlockPos, world: ClientWorld) =
3338
pos.offset(direction).blockState(world).isSolidBlock(world, pos.offset(direction))
3439
|| state.isSolidBlock(world, pos)
@@ -39,21 +44,21 @@ sealed class TargetState : StateMatcher {
3944
} ?: ItemStack(Items.NETHERRACK)
4045
}
4146

42-
data class State(val blockState: BlockState) : TargetState() {
47+
data class State(val blockState: BlockState) : TargetState(Type.STATE) {
4348
override fun matches(state: BlockState, pos: BlockPos, world: ClientWorld) =
4449
state == blockState
4550
override fun getStack(world: ClientWorld, pos: BlockPos): ItemStack =
4651
blockState.block.getPickStack(world, pos, blockState)
4752
}
4853

49-
data class Block(val block: net.minecraft.block.Block) : TargetState() {
54+
data class Block(val block: net.minecraft.block.Block) : TargetState(Type.BLOCK) {
5055
override fun matches(state: BlockState, pos: BlockPos, world: ClientWorld) =
5156
state.block == block
5257
override fun getStack(world: ClientWorld, pos: BlockPos): ItemStack =
5358
block.getPickStack(world, pos, block.defaultState)
5459
}
5560

56-
data class Stack(val itemStack: ItemStack) : TargetState() {
61+
data class Stack(val itemStack: ItemStack) : TargetState(Type.STACK) {
5762
private val block = itemStack.item.block
5863

5964
override fun matches(state: BlockState, pos: BlockPos, world: ClientWorld) =

common/src/main/kotlin/com/lambda/module/modules/player/HighwayTools.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ object HighwayTools : Module(
2727
private val width by setting("Width", 6, 1..30, 1)
2828
private val rimHeight by setting("Rim Height", 1, 0..6, 1)
2929
private val cornerBlock by setting("Corner Block", false, description = "Include corner blocks in the highway")
30+
private val ceiling by setting("Ceiling", false, description = "Smooth roof over the highway")
31+
private val ceilingMaterial by setting("Ceiling Material", Blocks.OBSIDIAN, description = "Material to build the ceiling with")
3032
private val distance by setting("Distance", -1, -1..1000000, 1, description = "Distance to build the highway (negative for infinite)")
3133
private val sliceSize by setting("Slice Size", 3, 1..5, 1, description = "Number of slices to build at once")
32-
private val material by setting("Material", Blocks.OBSIDIAN, description = "Material to build the highway with")
34+
private val material by setting("Highway Material", Blocks.OBSIDIAN, description = "Material to build the highway with")
3335

3436
private var octant = EightWayDirection.NORTH
3537
private var distanceMoved = 0
@@ -152,6 +154,16 @@ object HighwayTools : Module(
152154
-1,
153155
).associateWith { TargetState.Support(Direction.UP) }
154156

157+
if (ceiling) {
158+
structure += generateDirectionalTube(
159+
orthogonal,
160+
width,
161+
1,
162+
-center,
163+
height - 1,
164+
).associateWith { TargetState.Block(ceilingMaterial) }
165+
}
166+
155167
return structure
156168
}
157169
}

common/src/main/kotlin/com/lambda/task/tasks/BuildTask.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,6 @@ class BuildTask @Ta5kBuilder constructor(
8484
val result = results.minOrNull() ?: return@listener
8585
when {
8686
!result.rank.solvable -> {
87-
// info("Unsolvable: $result")
88-
if (!blueprint.isDone(this)) return@listener
8987
success(Unit)
9088
}
9189
result is BuildResult.NotVisible -> {

common/src/main/kotlin/com/lambda/task/tasks/InventoryTask.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ class InventoryTask(
2727
val selectedFrom = selector.filterSlots(from).filter { it.hasStack() }
2828
val selectedTo = to.filter { it.stack.isEmpty } + to.filter { it.stack.item.block in TaskFlow.disposables }
2929
selectedFrom.zip(selectedTo).forEach { (from, to) ->
30-
transactions.add(SlotUtils.Transaction(to.id, 0, SlotActionType.SWAP))
31-
transactions.add(SlotUtils.Transaction(from.id, 0, SlotActionType.SWAP))
30+
transactions.add(SlotUtils.Transaction(to.index, 0, SlotActionType.SWAP))
31+
transactions.add(SlotUtils.Transaction(from.index, 0, SlotActionType.SWAP))
3232

3333
// ToDo: Handle overflow of cursor for PICKUP
3434
}

0 commit comments

Comments
 (0)