@@ -342,7 +342,15 @@ object BuildSimulator {
342342 val currentState = blockState(pos)
343343
344344 val statePromoting = currentState.block is SlabBlock && targetState.matches(currentState, pos, world, preProcessing.ignore)
345- if (targetState.isEmpty() || (! currentState.isReplaceable && ! statePromoting)) return acc
345+ // If the target state is air then the only possible blocks it could place are to remove liquids so we use the Solid TargetState
346+ val nextTargetState = if (targetState is TargetState .Air ) {
347+ TargetState .Solid
348+ } else if (targetState.isEmpty()) {
349+ // Otherwise if the target state is empty, there's no situation where placement would be required so we can return
350+ return acc
351+ } else targetState
352+ // For example, slabs count as state promoting because you are placing another block to promote the current state to the target state
353+ if (! currentState.isReplaceable && ! statePromoting) return acc
346354
347355 preProcessing.sides.forEach { neighbor ->
348356 val hitPos = if (! place.airPlace.isEnabled() && (currentState.isEmpty || statePromoting))
@@ -415,7 +423,7 @@ object BuildSimulator {
415423 }
416424
417425 interactionConfig.pointSelection.select(validHits)?.let { checkedHit ->
418- val optimalStack = targetState .getStack(world, pos, inventory)
426+ val optimalStack = nextTargetState .getStack(world, pos, inventory)
419427
420428 // ToDo: For each hand and sneak or not?
421429 val fakePlayer = copyPlayer(player).apply {
@@ -424,6 +432,7 @@ object BuildSimulator {
424432
425433 val checkedResult = checkedHit.hit
426434
435+ // ToDo: Override the stack used for this to account for blocks where replaceability is dependent on the held item
427436 val usageContext = ItemUsageContext (
428437 fakePlayer,
429438 Hand .MAIN_HAND ,
@@ -476,8 +485,8 @@ object BuildSimulator {
476485 resultState = blockItem.getPlacementState(context)
477486 ? : return @placeState PlaceResult .BlockedByEntity (pos)
478487
479- return @placeState if (! targetState .matches(resultState, pos, world, preProcessing.ignore))
480- PlaceResult .NoIntegrity (pos, resultState, context, (targetState as ? TargetState .State )?.blockState)
488+ return @placeState if (! nextTargetState .matches(resultState, pos, world, preProcessing.ignore))
489+ PlaceResult .NoIntegrity (pos, resultState, context, (nextTargetState as ? TargetState .State )?.blockState)
481490 else null
482491 }
483492
@@ -638,12 +647,12 @@ object BuildSimulator {
638647 if (fluidState.isEmpty || fluid !is FlowableFluid ) return @forEach
639648
640649 if (offset == Direction .UP ) {
641- accumulator.put( offsetPos, offsetState)
650+ accumulator[ offsetPos] = offsetState
642651 return @fold accumulator
643652 }
644653
645654 if (offsetState.block is Waterloggable && ! fluidState.isEmpty) {
646- accumulator.put( offsetPos, offsetState)
655+ accumulator[ offsetPos] = offsetState
647656 return @fold accumulator
648657 }
649658
@@ -663,17 +672,8 @@ object BuildSimulator {
663672 return @fold accumulator
664673 }
665674
666- /* block has liquids next to it that will leak when broken */
667675 if (affectedFluids.isNotEmpty()) {
668676 acc.add(BreakResult .BlockedByFluid (pos, state))
669- affectedFluids.entries.forEach { fluid ->
670- val submerge = if (fluid.value.isReplaceable) {
671- checkPlaceResults(fluid.key, eye, preProcessing, TargetState .Solid , build.placing, interactionConfig, rotation, inventory)
672- } else {
673- checkBreakResults(fluid.key, eye, preProcessing, breaking, interactionConfig, rotation, inventory, build)
674- }
675- acc.addAll(submerge)
676- }
677677 return acc
678678 }
679679 }
0 commit comments