Skip to content

Commit 55ef7d3

Browse files
committed
Support for half slab building
1 parent e0416a7 commit 55ef7d3

File tree

5 files changed

+61
-25
lines changed

5 files changed

+61
-25
lines changed

common/src/main/kotlin/com/lambda/command/commands/BuildCommand.kt

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package com.lambda.command.commands
22

33
import com.lambda.brigadier.CommandResult
4+
import com.lambda.brigadier.argument.boolean
45
import com.lambda.brigadier.argument.identifier
56
import com.lambda.brigadier.argument.literal
67
import com.lambda.brigadier.argument.value
78
import com.lambda.brigadier.executeWithResult
9+
import com.lambda.brigadier.optional
810
import com.lambda.brigadier.required
911
import com.lambda.command.LambdaCommand
1012
import com.lambda.interaction.construction.Blueprint.Companion.toStructure
@@ -31,23 +33,25 @@ object BuildCommand : LambdaCommand(
3133

3234
builder.buildFuture()
3335
}
36+
optional(boolean("pathing")) { pathing ->
37+
executeWithResult {
38+
val id = structure().value()
39+
val path = if (pathing != null) pathing().value() else false
40+
runSafe<Unit> {
41+
StructureRegistry.loadStructure(id)?.let { template ->
42+
info("Building structure ${id.path} with dimensions ${template.size.toShortString()} by ${template.author}")
43+
template.toStructure()
44+
.move(player.blockPos)
45+
.toBlueprint()
46+
.build(pathing = path)
47+
.start(null)
3448

35-
executeWithResult {
36-
val id = structure().value()
37-
runSafe<Unit> {
38-
StructureRegistry.loadStructure(id)?.let { template ->
39-
info("Building structure ${id.path} with size ${template.size.toShortString()} by ${template.author}")
40-
template.toStructure()
41-
.move(player.blockPos)
42-
.toBlueprint()
43-
.build()
44-
.start(null)
45-
46-
return@executeWithResult CommandResult.success()
49+
return@executeWithResult CommandResult.success()
50+
}
4751
}
48-
}
4952

50-
CommandResult.failure("Structure ${id.path} not found")
53+
CommandResult.failure("Structure ${id.path} not found")
54+
}
5155
}
5256
}
5357
}

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import com.lambda.interaction.construction.verify.TargetState
1212
import com.lambda.interaction.material.ContainerManager.findBestAvailableTool
1313
import com.lambda.interaction.rotation.Rotation.Companion.rotationTo
1414
import com.lambda.interaction.rotation.RotationContext
15+
import com.lambda.interaction.visibilty.VisibilityChecker
16+
import com.lambda.interaction.visibilty.VisibilityChecker.ScanMode.Companion.scanMode
1517
import com.lambda.interaction.visibilty.VisibilityChecker.optimum
1618
import com.lambda.interaction.visibilty.VisibilityChecker.scanVisibleSurfaces
1719
import com.lambda.module.modules.client.TaskFlow
@@ -31,6 +33,7 @@ import net.minecraft.item.BlockItem
3133
import net.minecraft.item.ItemPlacementContext
3234
import net.minecraft.item.ItemUsageContext
3335
import net.minecraft.registry.RegistryKeys
36+
import net.minecraft.state.property.Properties
3437
import net.minecraft.util.Hand
3538
import net.minecraft.util.hit.BlockHitResult
3639
import net.minecraft.util.hit.HitResult
@@ -130,9 +133,12 @@ object BuildSimulator {
130133
val reachSq = reach.pow(2)
131134

132135
boxes.forEach { box ->
133-
val res = if (TaskFlow.interact.useRayCast) interact.resolution else 2
134-
// ToDo: If state has HALF property we need to scan the correct half of the block surface
135-
scanVisibleSurfaces(eye, box, setOf(hitSide), res) { side, vec ->
136+
val res = if (TaskFlow.interact.useRayCast) interact.resolution else 4
137+
val half = (target as? TargetState.State)
138+
?.blockState
139+
?.getOrEmpty(Properties.SLAB_TYPE)
140+
?.scanMode ?: VisibilityChecker.ScanMode.BOTH
141+
scanVisibleSurfaces(eye, box, setOf(hitSide), res, half) { side, vec ->
136142
if (eye distSq vec > reachSq) {
137143
misses.add(vec)
138144
return@scanVisibleSurfaces

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ data class Simulation(val blueprint: Blueprint) {
2323
private val cache: MutableMap<FastVector, Set<BuildResult>> = mutableMapOf()
2424
private fun FastVector.toView(): Vec3d = toVec3d().add(0.5, 0.62, 0.5)
2525

26-
fun simulate(pos: FastVector): Set<BuildResult> {
27-
return cache.computeIfAbsent(pos) {
26+
fun simulate(pos: FastVector) =
27+
cache.computeIfAbsent(pos) {
2828
val view = pos.toView()
2929
runSafe {
3030
if (blueprint.isOutOfBounds(view) && blueprint.getClosestPointTo(view).distanceTo(view) > 10.0) return@computeIfAbsent emptySet()
@@ -34,7 +34,6 @@ data class Simulation(val blueprint: Blueprint) {
3434
}
3535
blueprint.simulate(view, reach = TaskFlow.interact.reach - 1)
3636
}
37-
}
3837

3938
private fun SafeContext.playerFitsIn(pos: Vec3d): Boolean {
4039
val pBox = player.boundingBox

common/src/main/kotlin/com/lambda/interaction/visibilty/VisibilityChecker.kt

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import com.lambda.util.math.VecUtils.distSq
1313
import com.lambda.util.extension.component6
1414
import com.lambda.util.world.raycast.RayCastUtils.blockResult
1515
import com.lambda.util.world.raycast.RayCastUtils.entityResult
16+
import net.minecraft.block.enums.BlockHalf
17+
import net.minecraft.block.enums.SlabType
1618
import net.minecraft.entity.Entity
1719
import net.minecraft.util.hit.HitResult
1820
import net.minecraft.util.math.BlockPos
@@ -96,7 +98,8 @@ object VisibilityChecker {
9698
eyes: Vec3d,
9799
box: Box,
98100
sides: Set<Direction> = emptySet(),
99-
resolution: Int = 30,
101+
resolution: Int = 5,
102+
half: ScanMode = ScanMode.BOTH,
100103
check: (Direction, Vec3d) -> Unit,
101104
) {
102105
box.getVisibleSurfaces(eyes)
@@ -106,17 +109,41 @@ object VisibilityChecker {
106109
val stepX = (maxX - minX) / resolution
107110
val stepY = (maxY - minY) / resolution
108111
val stepZ = (maxZ - minZ) / resolution
112+
113+
val centerY = (minY + maxY) / 2
114+
val (startY, endY) = if (stepY != 0.0) {
115+
when (half) {
116+
ScanMode.TOP -> centerY + 0.01 to maxY
117+
ScanMode.BOTTOM -> minY to centerY - 0.01
118+
ScanMode.BOTH -> minY to maxY
119+
}
120+
} else minY to maxY
109121
(0..resolution).forEach { i ->
110122
val x = if (stepX != 0.0) minX + stepX * i else minX
111-
(0..resolution).forEach { j ->
112-
val y = if (stepY != 0.0) minY + stepY * j else minY
123+
(0..resolution).forEach inner@ { j ->
124+
val y = if (stepY != 0.0) startY + stepY * j else startY
125+
if (y > endY) return@inner
113126
val z = if (stepZ != 0.0) minZ + stepZ * ((if (stepX != 0.0) j else i)) else minZ
114127
check(side, Vec3d(x, y, z))
115128
}
116129
}
117130
}
118131
}
119132

133+
enum class ScanMode {
134+
BOTH, TOP, BOTTOM;
135+
136+
companion object {
137+
val Optional<SlabType>.scanMode: ScanMode
138+
get() = when (orElse(null)) {
139+
SlabType.TOP -> TOP
140+
SlabType.BOTTOM -> BOTTOM
141+
SlabType.DOUBLE -> BOTH
142+
else -> BOTH
143+
}
144+
}
145+
}
146+
120147
val Set<Vec3d>.optimum: Vec3d?
121148
get() = reduceOrNull { acc, vec3d ->
122149
acc.add(vec3d)

common/src/main/resources/lambda.mixins.common.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"entity.ClientPlayerEntityMixin",
1212
"entity.ClientPlayInteractionManagerMixin",
1313
"entity.EntityMixin",
14+
"entity.FireworkRocketEntityMixin",
1415
"entity.LivingEntityMixin",
1516
"entity.PlayerEntityMixin",
1617
"input.KeyBindingMixin",
@@ -43,8 +44,7 @@
4344
"render.WorldRendererMixin",
4445
"world.BlockCollisionSpliteratorMixin",
4546
"world.ClientChunkManagerMixin",
46-
"world.ClientWorldMixin",
47-
"entity.FireworkRocketEntityMixin"
47+
"world.ClientWorldMixin"
4848
],
4949
"injectors": {
5050
"defaultRequire": 1

0 commit comments

Comments
 (0)