Skip to content

Commit 2c65434

Browse files
committed
added dsl for pre-processing info and expanded the pre-processors; removed FacingProcessor.kt as I feel it cant be used to accurately refine the possible placement sides
1 parent bb4f6cb commit 2c65434

File tree

14 files changed

+278
-129
lines changed

14 files changed

+278
-129
lines changed

common/src/main/kotlin/com/lambda/interaction/construction/processing/PlacementProcessor.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ package com.lambda.interaction.construction.processing
2020
import net.minecraft.block.BlockState
2121

2222
abstract class PlacementProcessor {
23-
abstract fun acceptState(state: BlockState): Boolean
24-
abstract fun preProcess(state: BlockState): PreprocessingStep
23+
abstract fun acceptsState(state: BlockState): Boolean
24+
abstract fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator)
2525
}
2626

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2024 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.interaction.construction.processing
19+
20+
import com.lambda.interaction.construction.verify.SurfaceScan
21+
import net.minecraft.state.property.Property
22+
import net.minecraft.util.math.Direction
23+
24+
@DslMarker
25+
private annotation class InfoAccumulator
26+
27+
@InfoAccumulator
28+
data class PreprocessingInfoAccumulator(
29+
private var surfaceScan: SurfaceScan = SurfaceScan.DEFAULT,
30+
private val ignore: MutableSet<Property<*>> = mutableSetOf(),
31+
private val sides: MutableSet<Direction> = Direction.entries.toMutableSet(),
32+
) {
33+
@InfoAccumulator
34+
fun offerSurfaceScan(scan: SurfaceScan) {
35+
if (scan.mode.priority > surfaceScan.mode.priority) {
36+
surfaceScan = scan
37+
}
38+
}
39+
40+
@InfoAccumulator
41+
fun addIgnores(ignores: Set<Property<*>>) {
42+
ignore.addAll(ignores)
43+
}
44+
45+
@InfoAccumulator
46+
fun retainSides(predicate: (Direction) -> Boolean) {
47+
this.sides.retainAll(predicate)
48+
}
49+
50+
@InfoAccumulator
51+
fun retainSides(vararg sides: Direction) {
52+
this.sides.retainAll(sides.toSet())
53+
}
54+
55+
@InfoAccumulator
56+
fun complete() = PreprocessingInfo(surfaceScan, ignore, sides)
57+
}
58+
59+
data class PreprocessingInfo(
60+
val surfaceScan: SurfaceScan,
61+
val ignore: Set<Property<*>>,
62+
val sides: Set<Direction>
63+
) {
64+
companion object {
65+
val DEFAULT = PreprocessingInfo(SurfaceScan.DEFAULT, emptySet(), emptySet())
66+
}
67+
}

common/src/main/kotlin/com/lambda/interaction/construction/processing/PreprocessingStep.kt

Lines changed: 0 additions & 28 deletions
This file was deleted.

common/src/main/kotlin/com/lambda/interaction/construction/processing/ProcessorRegistry.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,24 @@ import com.lambda.core.Loadable
2121
import com.lambda.interaction.construction.verify.TargetState
2222
import com.lambda.util.reflections.getInstances
2323
import net.minecraft.block.BlockState
24-
import net.minecraft.block.Blocks
2524

2625
object ProcessorRegistry : Loadable {
2726
private val processors = getInstances<PlacementProcessor>()
28-
private val processorCache = mutableMapOf<BlockState, PreprocessingStep>()
27+
private val processorCache = mutableMapOf<BlockState, PreprocessingInfo>()
2928

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

32-
fun TargetState.findProcessorForState(): PreprocessingStep =
31+
fun TargetState.getProcessingInfo(): PreprocessingInfo =
3332
(this as? TargetState.State)?.let { state ->
3433
processorCache.getOrPut(state.blockState) {
35-
(processors.find { it.acceptState(state.blockState) } ?: DefaultProcessor).preProcess(state.blockState)
36-
}
37-
} ?: DefaultProcessor.preProcess(Blocks.AIR.defaultState)
34+
val infoAccumulator = PreprocessingInfoAccumulator()
35+
36+
processors.forEach {
37+
if (!it.acceptsState(state.blockState)) return@forEach
38+
it.preProcess(state.blockState, infoAccumulator)
39+
}
3840

39-
object DefaultProcessor : PlacementProcessor() {
40-
override fun acceptState(state: BlockState) = true
41-
override fun preProcess(state: BlockState) = PreprocessingStep()
42-
}
41+
return infoAccumulator.complete()
42+
}
43+
} ?: PreprocessingInfo.DEFAULT
4344
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.interaction.construction.processing.processors
19+
20+
import com.lambda.interaction.construction.processing.PlacementProcessor
21+
import com.lambda.interaction.construction.processing.PreprocessingInfoAccumulator
22+
import net.minecraft.block.BlockState
23+
import net.minecraft.block.enums.Attachment
24+
import net.minecraft.state.property.Properties
25+
import net.minecraft.util.math.Direction
26+
27+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
28+
@Suppress("unused")
29+
object AttachmentPreprocessor : PlacementProcessor() {
30+
override fun acceptsState(state: BlockState) =
31+
state.properties.contains(Properties.ATTACHMENT)
32+
33+
override fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator) {
34+
val attachment = state.get(Properties.ATTACHMENT) ?: return
35+
with (accumulator) {
36+
when (attachment) {
37+
Attachment.FLOOR -> retainSides(Direction.DOWN)
38+
Attachment.CEILING -> retainSides(Direction.UP)
39+
else -> retainSides { Direction.Type.HORIZONTAL.contains(it) }
40+
}
41+
}
42+
}
43+
}

common/src/main/kotlin/com/lambda/interaction/construction/processing/processors/AxisPreprocessor.kt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,20 @@
1818
package com.lambda.interaction.construction.processing.processors
1919

2020
import com.lambda.interaction.construction.processing.PlacementProcessor
21-
import com.lambda.interaction.construction.processing.PreprocessingStep
21+
import com.lambda.interaction.construction.processing.PreprocessingInfoAccumulator
2222
import net.minecraft.block.BlockState
2323
import net.minecraft.state.property.Properties
24-
import net.minecraft.util.math.Direction
2524

25+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
26+
@Suppress("unused")
2627
object AxisPreprocessor : PlacementProcessor() {
27-
override fun acceptState(state: BlockState) =
28+
override fun acceptsState(state: BlockState) =
2829
state.getOrEmpty(Properties.AXIS).isPresent
2930

30-
override fun preProcess(state: BlockState): PreprocessingStep {
31-
val axis = state.getOrEmpty(Properties.AXIS).get()
32-
return PreprocessingStep(
33-
sides = Direction.entries.filter { it.axis == axis }.toSet()
34-
)
31+
override fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator) {
32+
val axis = state.get(Properties.AXIS)
33+
accumulator.retainSides { side ->
34+
side.axis == axis
35+
}
3536
}
3637
}

common/src/main/kotlin/com/lambda/interaction/construction/processing/processors/BlockFaceProcessor.kt

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,26 @@
1818
package com.lambda.interaction.construction.processing.processors
1919

2020
import com.lambda.interaction.construction.processing.PlacementProcessor
21-
import com.lambda.interaction.construction.processing.PreprocessingStep
21+
import com.lambda.interaction.construction.processing.PreprocessingInfoAccumulator
2222
import net.minecraft.block.BlockState
2323
import net.minecraft.block.enums.BlockFace
2424
import net.minecraft.state.property.Properties
2525
import net.minecraft.util.math.Direction
26-
import kotlin.jvm.optionals.getOrNull
2726

27+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
28+
@Suppress("unused")
2829
object BlockFaceProcessor : PlacementProcessor() {
29-
override fun acceptState(state: BlockState) =
30+
override fun acceptsState(state: BlockState) =
3031
state.getOrEmpty(Properties.BLOCK_FACE).isPresent
3132

32-
override fun preProcess(state: BlockState): PreprocessingStep {
33-
val property = state.getOrEmpty(Properties.BLOCK_FACE).getOrNull() ?: return PreprocessingStep()
34-
val sides = when (property) {
35-
BlockFace.FLOOR -> setOf(Direction.DOWN)
36-
BlockFace.CEILING -> setOf(Direction.UP)
37-
BlockFace.WALL -> Direction.Type.HORIZONTAL.stream().toList().toSet()
33+
override fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator) {
34+
val property = state.get(Properties.BLOCK_FACE) ?: return
35+
with (accumulator) {
36+
when (property) {
37+
BlockFace.FLOOR -> retainSides(Direction.DOWN)
38+
BlockFace.CEILING -> retainSides(Direction.UP)
39+
BlockFace.WALL -> retainSides { Direction.Type.HORIZONTAL.contains(it) }
40+
}
3841
}
39-
return PreprocessingStep(sides = sides)
4042
}
4143
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.interaction.construction.processing.processors
19+
20+
import com.lambda.interaction.construction.processing.PlacementProcessor
21+
import com.lambda.interaction.construction.processing.PreprocessingInfoAccumulator
22+
import com.lambda.interaction.construction.verify.ScanMode
23+
import com.lambda.interaction.construction.verify.SurfaceScan
24+
import net.minecraft.block.BlockState
25+
import net.minecraft.block.enums.BlockHalf
26+
import net.minecraft.state.property.Properties
27+
import net.minecraft.util.math.Direction
28+
29+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
30+
@Suppress("unused")
31+
object BlockHalfProcessor : PlacementProcessor() {
32+
override fun acceptsState(state: BlockState) =
33+
state.getOrEmpty(Properties.BLOCK_HALF).isPresent
34+
35+
override fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator) {
36+
val slab = state.get(Properties.BLOCK_HALF) ?: return
37+
38+
val surfaceScan = when (slab) {
39+
BlockHalf.BOTTOM -> SurfaceScan(ScanMode.LESSER_HALF, Direction.Axis.Y)
40+
BlockHalf.TOP -> SurfaceScan(ScanMode.GREATER_HALF, Direction.Axis.Y)
41+
}
42+
43+
accumulator.offerSurfaceScan(surfaceScan)
44+
}
45+
}

common/src/main/kotlin/com/lambda/interaction/construction/processing/processors/FacingProcessor.kt renamed to common/src/main/kotlin/com/lambda/interaction/construction/processing/processors/HopperFacingPreprocessor.kt

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2024 Lambda
2+
* Copyright 2025 Lambda
33
*
44
* This program is free software: you can redistribute it and/or modify
55
* it under the terms of the GNU General Public License as published by
@@ -18,18 +18,22 @@
1818
package com.lambda.interaction.construction.processing.processors
1919

2020
import com.lambda.interaction.construction.processing.PlacementProcessor
21-
import com.lambda.interaction.construction.processing.PreprocessingStep
21+
import com.lambda.interaction.construction.processing.PreprocessingInfoAccumulator
2222
import net.minecraft.block.BlockState
2323
import net.minecraft.state.property.Properties
24+
import net.minecraft.util.math.Direction
2425

25-
object FacingProcessor : PlacementProcessor() {
26-
override fun acceptState(state: BlockState) =
27-
state.getOrEmpty(Properties.FACING).isPresent
26+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
27+
@Suppress("unused")
28+
object HopperFacingPreprocessor : PlacementProcessor() {
29+
override fun acceptsState(state: BlockState) =
30+
state.properties.contains(Properties.HOPPER_FACING)
2831

29-
override fun preProcess(state: BlockState): PreprocessingStep {
30-
// Needs two sets of blocks: native and opposite!
31-
return PreprocessingStep(
32-
sides = setOf(state.getOrEmpty(Properties.FACING).get())
33-
)
32+
override fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator) {
33+
val facing = state.get(Properties.HOPPER_FACING) ?: return
34+
when {
35+
facing.axis == Direction.Axis.Y -> accumulator.retainSides { it.axis == Direction.Axis.Y }
36+
else -> accumulator.retainSides(facing)
37+
}
3438
}
3539
}

common/src/main/kotlin/com/lambda/interaction/construction/processing/processors/SlabProcessor.kt

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
package com.lambda.interaction.construction.processing.processors
1919

2020
import com.lambda.interaction.construction.processing.PlacementProcessor
21-
import com.lambda.interaction.construction.processing.PreprocessingStep
21+
import com.lambda.interaction.construction.processing.PreprocessingInfoAccumulator
2222
import com.lambda.interaction.construction.verify.ScanMode
2323
import com.lambda.interaction.construction.verify.SurfaceScan
2424
import net.minecraft.block.BlockState
@@ -27,24 +27,20 @@ import net.minecraft.block.enums.SlabType
2727
import net.minecraft.state.property.Properties
2828
import net.minecraft.util.math.Direction
2929

30+
// Collected using reflections and then accessed from a collection in ProcessorRegistry
31+
@Suppress("unused")
3032
object SlabProcessor : PlacementProcessor() {
31-
override fun acceptState(state: BlockState) = state.block is SlabBlock
33+
override fun acceptsState(state: BlockState) = state.block is SlabBlock
3234

33-
override fun preProcess(state: BlockState): PreprocessingStep {
34-
val slab = state.getOrEmpty(Properties.SLAB_TYPE).get()
35+
override fun preProcess(state: BlockState, accumulator: PreprocessingInfoAccumulator) {
36+
val slab = state.get(Properties.SLAB_TYPE) ?: return
3537

3638
val surfaceScan = when (slab) {
37-
SlabType.BOTTOM -> SurfaceScan(
38-
ScanMode.LESSER_HALF, Direction.Axis.Y
39-
)
40-
SlabType.TOP -> SurfaceScan(
41-
ScanMode.GREATER_HALF, Direction.Axis.Y
42-
)
43-
SlabType.DOUBLE -> SurfaceScan(
44-
ScanMode.FULL, Direction.Axis.Y
45-
)
39+
SlabType.BOTTOM -> SurfaceScan(ScanMode.LESSER_HALF, Direction.Axis.Y)
40+
SlabType.TOP -> SurfaceScan(ScanMode.GREATER_HALF, Direction.Axis.Y)
41+
SlabType.DOUBLE -> SurfaceScan(ScanMode.FULL, Direction.Axis.Y)
4642
}
4743

48-
return PreprocessingStep(surfaceScan)
44+
accumulator.offerSurfaceScan(surfaceScan)
4945
}
5046
}

0 commit comments

Comments
 (0)