Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1480c56
initial simulation separation and dependency result structure
beanbag44 Oct 19, 2025
e01b41e
dependent over dependant
beanbag44 Oct 19, 2025
196b1a3
Merge branch '1.21.5' into improvement/build-simulator
beanbag44 Oct 19, 2025
3387261
sim cleanup and improvement
beanbag44 Oct 21, 2025
5cf47e0
assign item usage context the swap stack
beanbag44 Oct 21, 2025
5424da0
check both current block and neighboring blocks to ensure potential r…
beanbag44 Oct 22, 2025
cd3dbe5
inventoryIndexOrSelected over inventoryIndex within the break manager…
beanbag44 Oct 22, 2025
eee5af4
modify fake player to sneak and therefore adjust eye position accordi…
beanbag44 Oct 23, 2025
c2dd7d7
replacement blocks for solid target state, and fixed race condition i…
beanbag44 Oct 24, 2025
aee1d80
better place rotation logic
beanbag44 Oct 24, 2025
25f1c9b
cleanup
beanbag44 Oct 25, 2025
2ba5f58
sort contextual build results by current tool, if not build context
beanbag44 Oct 25, 2025
ff78db9
reintroduce custom eye pos
beanbag44 Oct 25, 2025
54ee6e7
more cleanup
beanbag44 Oct 25, 2025
3d7a602
fix cave air edge case in isEmpty check
beanbag44 Oct 26, 2025
14080b0
sim checker dsl marker on checkRequirements check
beanbag44 Oct 26, 2025
f4605a2
efficient tools only setting for blocks that could be broken faster w…
beanbag44 Oct 26, 2025
7d7cbc3
isEmpty check after fluid checks in break checker
beanbag44 Oct 26, 2025
ea3e648
isToolRequired check in isSuitableForBreaking predicate
beanbag44 Oct 26, 2025
9bc9b11
Merge branch '1.21.5' into improvement/build-simulator
beanbag44 Oct 27, 2025
ecbd48c
use supervisor scopes' feature to only return after all child jobs ar…
beanbag44 Oct 28, 2025
a31c8df
improved entity spleef block position detection
beanbag44 Oct 28, 2025
8896172
remove BlockedBySelf build result
beanbag44 Oct 28, 2025
6d09f1e
dsl oriented sim structure. Im not sure if i like how many objects ar…
beanbag44 Oct 30, 2025
ebd0d3e
max dependency depth and reintroduce blocked by player build result
beanbag44 Oct 30, 2025
70d1b71
tiny cleanup
beanbag44 Oct 30, 2025
b59ffe8
dependency tweaks
beanbag44 Oct 30, 2025
081c84f
big refactor
beanbag44 Oct 30, 2025
5cc445a
dependent over dependable
beanbag44 Oct 31, 2025
3d5d18a
remove unused dependent sim context
beanbag44 Oct 31, 2025
8ed05b0
Merge branch '1.21.5' into improvement/build-simulator
beanbag44 Oct 31, 2025
62ed335
copy dependency stack when nesting simulation to prevent concurrency …
beanbag44 Oct 31, 2025
59cead9
inline block item getPlacementContext
beanbag44 Nov 1, 2025
659962d
Merge branch '1.21.5' into improvement/build-simulator
beanbag44 Nov 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/kotlin/com/lambda/config/groups/BreakSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@ class BreakSettings(
// Block
override val avoidLiquids by c.setting("Avoid Liquids", true, "Avoids breaking blocks that would cause liquid to spill", visibility = vis).group(baseGroup, Group.General)
override val avoidSupporting by c.setting("Avoid Supporting", true, "Avoids breaking the block supporting the player", visibility = vis).group(baseGroup, Group.General)
override val breakWeakBlocks by c.setting("Break Weak Blocks", false, "Break blocks that dont have structural integrity (e.g: grass)", visibility = vis).group(baseGroup, Group.General)
override val ignoredBlocks by c.setting("Ignored Blocks", allSigns, description = "Blocks that wont be broken", visibility = vis).group(baseGroup, Group.General)

// Tool
override val efficientOnly by c.setting("Efficient Tools Only", true, "Only use tools suitable for the given block (will get the item drop)") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General)
override val suitableToolsOnly by c.setting("Suitable Tools Only", true, "Only use tools suitable for the given block (will get the item drop)") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General)
override val forceSilkTouch by c.setting("Force Silk Touch", false, "Force silk touch when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General)
override val forceFortunePickaxe by c.setting("Force Fortune Pickaxe", false, "Force fortune pickaxe when breaking blocks") { vis() && swapMode.isEnabled() }.group(baseGroup, Group.General)
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/lambda/config/groups/BuildSettings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ class BuildSettings(

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

override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context", vis).group(*baseGroup, Group.Scan)
override val checkSideVisibility by c.setting("Visibility Check", true, "Whether to check if an AABB side is visible", vis).group(*baseGroup, Group.Scan)
override val strictRayCast by c.setting("Strict Raycast", false, "Whether to include the environment to the ray cast context", vis).group(*baseGroup, Group.Scan)
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)
override val pointSelection by c.setting("Point Selection", PointSelection.Optimum, "The strategy to select the best hit point", vis).group(*baseGroup, Group.Scan)

Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/com/lambda/context/AutomationConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ object AutomationConfig : Configurable(LambdaConfig), Automated {
val showAllEntries by setting("Show All Entries", false, "Show all entries in the task tree").group(Group.Debug)
val shrinkFactor by setting("Shrink Factor", 0.001, 0.0..1.0, 0.001).group(Group.Debug)
val ignoreItemDropWarnings by setting("Ignore Drop Warnings", false, "Hides the item drop warnings from the break manager").group(Group.Debug)
val maxSimDependencies by setting("Max Sim Dependencies", 3, 0..10, 1, "Maximum dependency build results").group(Group.Debug)

@Volatile
var drawables = listOf<Drawable>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,34 +41,34 @@ import kotlin.math.sqrt
import kotlin.random.Random

data class BreakContext(
override val result: BlockHitResult,
override val rotation: RotationRequest,
override var hotbarIndex: Int,
var itemSelection: StackSelection,
var instantBreak: Boolean,
override val hitResult: BlockHitResult,
override val rotationRequest: RotationRequest,
override val hotbarIndex: Int,
val itemSelection: StackSelection,
val instantBreak: Boolean,
override var cachedState: BlockState,
val sortMode: BreakConfig.SortMode,
private val automated: Automated
) : BuildContext(), LogContext, Automated by automated {
private val baseColor = Color(222, 0, 0, 25)
private val sideColor = Color(222, 0, 0, 100)

override val blockPos: BlockPos = result.blockPos
override val blockPos: BlockPos = hitResult.blockPos
override val expectedState = cachedState.emptyState

val random = Random.nextDouble()

override fun compareTo(other: BuildContext): Int = runSafe {
return when (other) {
is BreakContext -> compareByDescending<BreakContext> {
if (sortMode == BreakConfig.SortMode.Tool) it.hotbarIndex == HotbarManager.serverSlot
if (breakConfig.sorter == BreakConfig.SortMode.Tool)
it.hotbarIndex == HotbarManager.serverSlot
else 0
}.thenBy {
when (sortMode) {
when (breakConfig.sorter) {
BreakConfig.SortMode.Tool,
BreakConfig.SortMode.Closest -> player.eyePos.distance(it.result.pos, it.cachedState.block)
BreakConfig.SortMode.Farthest -> -player.eyePos.distance(it.result.pos, it.cachedState.block)
BreakConfig.SortMode.Rotation -> it.rotation.target.angleDistance
BreakConfig.SortMode.Closest -> player.eyePos.distance(it.hitResult.pos, it.cachedState.block)
BreakConfig.SortMode.Farthest -> -player.eyePos.distance(it.hitResult.pos, it.cachedState.block)
BreakConfig.SortMode.Rotation -> it.rotationRequest.target.angleDistance
BreakConfig.SortMode.Random -> it.random
}
}.thenByDescending {
Expand All @@ -92,19 +92,18 @@ data class BreakContext(
}

override fun ShapeBuilder.buildRenderer() {
box(blockPos, cachedState, baseColor, sideColor, DirectionMask.ALL.exclude(result.side))
box(blockPos, cachedState, baseColor, sideColor, DirectionMask.ALL.exclude(hitResult.side))
}

override fun getLogContextBuilder(): LogContextBuilder.() -> Unit = {
group("Break Context") {
text(blockPos.getLogContextBuilder())
text(result.getLogContextBuilder())
text(rotation.getLogContextBuilder())
text(hitResult.getLogContextBuilder())
text(rotationRequest.getLogContextBuilder())
value("Hotbar Index", hotbarIndex)
value("Instant Break", instantBreak)
value("Cached State", cachedState)
value("Expected State", expectedState)
value("Sort Mode", sortMode)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ import net.minecraft.util.hit.BlockHitResult
import net.minecraft.util.math.BlockPos

abstract class BuildContext : Comparable<BuildContext>, Drawable, Automated {
abstract val result: BlockHitResult
abstract val rotation: RotationRequest
abstract val hitResult: BlockHitResult
abstract val rotationRequest: RotationRequest
abstract val hotbarIndex: Int
abstract val cachedState: BlockState
abstract val expectedState: BlockState
abstract val blockPos: BlockPos

val distance by lazy {
runSafe { player.eyePos.distanceTo(result.pos) } ?: Double.MAX_VALUE
runSafe { player.eyePos.distanceTo(hitResult.pos) } ?: Double.MAX_VALUE
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import net.minecraft.util.math.BlockPos
import java.awt.Color

class InteractionContext(
override val result: BlockHitResult,
override val rotation: RotationRequest,
override val hitResult: BlockHitResult,
override val rotationRequest: RotationRequest,
override var hotbarIndex: Int,
override var cachedState: BlockState,
override val expectedState: BlockState,
Expand All @@ -45,7 +45,7 @@ class InteractionContext(
private val baseColor = Color(35, 254, 79, 25)
private val sideColor = Color(35, 254, 79, 100)

override val blockPos: BlockPos = result.blockPos
override val blockPos: BlockPos = hitResult.blockPos

override fun compareTo(other: BuildContext) =
when {
Expand All @@ -54,7 +54,7 @@ class InteractionContext(
}.thenByDescending {
it.cachedState.fluidState.level
}.thenBy {
it.rotation.target.angleDistance
it.rotationRequest.target.angleDistance
}.thenBy {
it.hotbarIndex == HotbarManager.serverSlot
}.thenBy {
Expand All @@ -65,20 +65,20 @@ class InteractionContext(
}

override fun ShapeBuilder.buildRenderer() {
box(blockPos, expectedState, baseColor, sideColor, result.side.mask)
box(blockPos, expectedState, baseColor, sideColor, hitResult.side.mask)
}

fun requestDependencies(request: InteractRequest): Boolean {
val hotbarRequest = submit(HotbarRequest(hotbarIndex, request), false)
val validRotation = if (request.interactConfig.rotate) submit(rotation, false).done else true
val validRotation = if (request.interactConfig.rotate) submit(rotationRequest, false).done else true
return hotbarRequest.done && validRotation
}

override fun getLogContextBuilder(): LogContextBuilder.() -> Unit = {
group("Interaction Context") {
text(blockPos.getLogContextBuilder())
text(result.getLogContextBuilder())
text(rotation.getLogContextBuilder())
text(hitResult.getLogContextBuilder())
text(rotationRequest.getLogContextBuilder())
value("Hotbar Index", hotbarIndex)
value("Cached State", cachedState)
value("Expected State", expectedState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ import net.minecraft.util.math.BlockPos
import java.awt.Color

data class PlaceContext(
override val result: BlockHitResult,
override val rotation: RotationRequest,
override val hitResult: BlockHitResult,
override val rotationRequest: RotationRequest,
override var hotbarIndex: Int,
override val blockPos: BlockPos,
override var cachedState: BlockState,
Expand All @@ -61,7 +61,7 @@ data class PlaceContext(
}.thenBy {
it.sneak == (mc.player?.isSneaking ?: false)
}.thenBy {
it.rotation.target.angleDistance
it.rotationRequest.target.angleDistance
}.thenBy {
it.hotbarIndex == HotbarManager.serverSlot
}.thenBy {
Expand All @@ -74,22 +74,22 @@ data class PlaceContext(
}

override fun ShapeBuilder.buildRenderer() {
box(blockPos, expectedState, baseColor, sideColor, result.side.mask)
box(blockPos, expectedState, baseColor, sideColor, hitResult.side.mask)
}

fun requestDependencies(request: PlaceRequest): Boolean {
val hotbarRequest = submit(HotbarRequest(hotbarIndex, this), false)
val validRotation = if (request.placeConfig.rotateForPlace) {
submit(rotation, false).done && currentDirIsValid
submit(rotationRequest, false).done && currentDirIsValid
} else true
return hotbarRequest.done && validRotation
}

override fun getLogContextBuilder(): LogContextBuilder.() -> Unit = {
group("Place Context") {
text(blockPos.getLogContextBuilder())
text(result.getLogContextBuilder())
text(rotation.getLogContextBuilder())
text(hitResult.getLogContextBuilder())
text(rotationRequest.getLogContextBuilder())
value("Hotbar Index", hotbarIndex)
value("Cached State", cachedState)
value("Expected State", expectedState)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,13 @@ import com.lambda.core.Loadable
import com.lambda.interaction.construction.verify.TargetState
import com.lambda.util.reflections.getInstances
import net.minecraft.block.BlockState
import net.minecraft.block.SlabBlock
import net.minecraft.block.enums.SlabType
import net.minecraft.state.property.Properties
import net.minecraft.util.math.BlockPos
import java.util.*

object ProcessorRegistry : Loadable {
private val processors = getInstances<PlacementProcessor>()
private val processorCache = mutableMapOf<BlockState, PreProcessingInfo?>()
private val processorCache = Collections.synchronizedMap<BlockState, PreProcessingInfo?>(mutableMapOf())

val postProcessedProperties = setOf(
Properties.EXTENDED,
Expand Down Expand Up @@ -107,30 +106,21 @@ object ProcessorRegistry : Loadable {

override fun load() = "Loaded ${processors.size} pre processors"

fun TargetState.getProcessingInfo(pos: BlockPos) =
if (this is TargetState.State) {
fun TargetState.getProcessingInfo(pos: BlockPos): PreProcessingInfo? =
if (this !is TargetState.State) PreProcessingInfo.DEFAULT
else {
val get: () -> PreProcessingInfo? = get@{
val infoAccumulator = PreProcessingInfoAccumulator()

processors.forEach { processor ->
if (!processor.acceptsState(blockState)) return@forEach
processor.preProcess(blockState, pos, infoAccumulator)
if (infoAccumulator.shouldBeOmitted) {
if (infoAccumulator.shouldBeOmitted)
return@get null
}
}

infoAccumulator.complete()
}
if (isExemptFromCache()) {
get()
} else {
processorCache.getOrPut(blockState, get)
}
} else {
PreProcessingInfo.DEFAULT
processorCache.getOrPut(blockState, get)
}

private fun TargetState.State.isExemptFromCache() =
blockState.block is SlabBlock && blockState.get(Properties.SLAB_TYPE) == SlabType.DOUBLE
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ object BlockHalfPreProcessor : PlacementProcessor() {
val slab = state.get(Properties.BLOCK_HALF) ?: return

val surfaceScan = when (slab) {
BlockHalf.BOTTOM -> SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.Y)
BlockHalf.TOP -> SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.Y)
BlockHalf.BOTTOM -> SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.Y)
BlockHalf.TOP -> SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.Y)
}

accumulator.offerSurfaceScan(surfaceScan)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,19 @@ object DoorHingePreProcessor : PlacementProcessor() {
val side = state.get(Properties.DOOR_HINGE) ?: return@runSafe
val scanner = when (state.get(Properties.HORIZONTAL_FACING) ?: return@runSafe) {
Direction.NORTH ->
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.X)
else SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.X)
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.X)
else SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.X)
Direction.EAST ->
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.Z)
else SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.Z)
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.Z)
else SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.Z)
Direction.SOUTH ->
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.X)
else SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.X)
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.X)
else SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.X)
Direction.DOWN,
Direction.UP,
Direction.WEST ->
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.Z)
else SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.Z)
if (side == DoorHinge.LEFT) SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.Z)
else SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.Z)
}
accumulator.offerSurfaceScan(scanner)
} ?: Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ object SlabPreProcessor : PlacementProcessor() {
val currentState = runSafe { blockState(pos) } ?: return

val surfaceScan = when (slab) {
SlabType.BOTTOM -> SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.Y)
SlabType.TOP -> SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.Y)
SlabType.BOTTOM -> SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.Y)
SlabType.TOP -> SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.Y)
SlabType.DOUBLE -> {
accumulator.addIgnores(Properties.SLAB_TYPE)
if (currentState.block !is SlabBlock) SurfaceScan.DEFAULT
else when (currentState.get(Properties.SLAB_TYPE)) {
SlabType.BOTTOM -> SurfaceScan(ScanMode.GREATER_BLOCK_HALF, Direction.Axis.Y)
else -> SurfaceScan(ScanMode.LESSER_BLOCK_HALF, Direction.Axis.Y)
SlabType.BOTTOM -> SurfaceScan(ScanMode.GreaterBlockHalf, Direction.Axis.Y)
else -> SurfaceScan(ScanMode.LesserBlockHalf, Direction.Axis.Y)
}
}
}
Expand Down
Loading
Loading