177 lines
8.3 KiB
Java
177 lines
8.3 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.annotations.VisibleForTesting
|
|
* org.jspecify.annotations.Nullable
|
|
*/
|
|
package net.minecraft.world.level.block;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import java.util.Optional;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.MultifaceBlock;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import org.jspecify.annotations.Nullable;
|
|
|
|
public class MultifaceSpreader {
|
|
public static final SpreadType[] DEFAULT_SPREAD_ORDER = new SpreadType[]{SpreadType.SAME_POSITION, SpreadType.SAME_PLANE, SpreadType.WRAP_AROUND};
|
|
private final SpreadConfig config;
|
|
|
|
public MultifaceSpreader(MultifaceBlock multifaceBlock) {
|
|
this(new DefaultSpreaderConfig(multifaceBlock));
|
|
}
|
|
|
|
public MultifaceSpreader(SpreadConfig config) {
|
|
this.config = config;
|
|
}
|
|
|
|
public boolean canSpreadInAnyDirection(BlockState state, BlockGetter level, BlockPos pos, Direction startingFace) {
|
|
return Direction.stream().anyMatch(spreadDirection -> this.getSpreadFromFaceTowardDirection(state, level, pos, startingFace, (Direction)spreadDirection, this.config::canSpreadInto).isPresent());
|
|
}
|
|
|
|
public Optional<SpreadPos> spreadFromRandomFaceTowardRandomDirection(BlockState state, LevelAccessor level, BlockPos pos, RandomSource random) {
|
|
return Direction.allShuffled(random).stream().filter(faceDirection -> this.config.canSpreadFrom(state, (Direction)faceDirection)).map(faceDirection -> this.spreadFromFaceTowardRandomDirection(state, level, pos, (Direction)faceDirection, random, false)).filter(Optional::isPresent).findFirst().orElse(Optional.empty());
|
|
}
|
|
|
|
public long spreadAll(BlockState state, LevelAccessor level, BlockPos pos, boolean postProcess) {
|
|
return Direction.stream().filter(faceDirection -> this.config.canSpreadFrom(state, (Direction)faceDirection)).map(faceDirection -> this.spreadFromFaceTowardAllDirections(state, level, pos, (Direction)faceDirection, postProcess)).reduce(0L, Long::sum);
|
|
}
|
|
|
|
public Optional<SpreadPos> spreadFromFaceTowardRandomDirection(BlockState state, LevelAccessor level, BlockPos pos, Direction startingFace, RandomSource random, boolean postProcess) {
|
|
return Direction.allShuffled(random).stream().map(spreadDirection -> this.spreadFromFaceTowardDirection(state, level, pos, startingFace, (Direction)spreadDirection, postProcess)).filter(Optional::isPresent).findFirst().orElse(Optional.empty());
|
|
}
|
|
|
|
private long spreadFromFaceTowardAllDirections(BlockState state, LevelAccessor level, BlockPos pos, Direction startingFace, boolean postProcess) {
|
|
return Direction.stream().map(spreadDirection -> this.spreadFromFaceTowardDirection(state, level, pos, startingFace, (Direction)spreadDirection, postProcess)).filter(Optional::isPresent).count();
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public Optional<SpreadPos> spreadFromFaceTowardDirection(BlockState state, LevelAccessor level, BlockPos pos, Direction fromFace, Direction spreadDirection, boolean postProcess) {
|
|
return this.getSpreadFromFaceTowardDirection(state, level, pos, fromFace, spreadDirection, this.config::canSpreadInto).flatMap(spreadPos -> this.spreadToFace(level, (SpreadPos)spreadPos, postProcess));
|
|
}
|
|
|
|
public Optional<SpreadPos> getSpreadFromFaceTowardDirection(BlockState state, BlockGetter level, BlockPos pos, Direction startingFace, Direction spreadDirection, SpreadPredicate canSpreadInto) {
|
|
if (spreadDirection.getAxis() == startingFace.getAxis()) {
|
|
return Optional.empty();
|
|
}
|
|
if (!(this.config.isOtherBlockValidAsSource(state) || this.config.hasFace(state, startingFace) && !this.config.hasFace(state, spreadDirection))) {
|
|
return Optional.empty();
|
|
}
|
|
for (SpreadType type : this.config.getSpreadTypes()) {
|
|
SpreadPos spreadPos = type.getSpreadPos(pos, spreadDirection, startingFace);
|
|
if (!canSpreadInto.test(level, pos, spreadPos)) continue;
|
|
return Optional.of(spreadPos);
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public Optional<SpreadPos> spreadToFace(LevelAccessor level, SpreadPos spreadPos, boolean postProcess) {
|
|
BlockState oldState = level.getBlockState(spreadPos.pos());
|
|
if (this.config.placeBlock(level, spreadPos, oldState, postProcess)) {
|
|
return Optional.of(spreadPos);
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public static class DefaultSpreaderConfig
|
|
implements SpreadConfig {
|
|
protected MultifaceBlock block;
|
|
|
|
public DefaultSpreaderConfig(MultifaceBlock block) {
|
|
this.block = block;
|
|
}
|
|
|
|
@Override
|
|
public @Nullable BlockState getStateForPlacement(BlockState oldState, BlockGetter level, BlockPos placementPos, Direction placementDirection) {
|
|
return this.block.getStateForPlacement(oldState, level, placementPos, placementDirection);
|
|
}
|
|
|
|
protected boolean stateCanBeReplaced(BlockGetter level, BlockPos sourcePos, BlockPos placementPos, Direction placementDirection, BlockState existingState) {
|
|
return existingState.isAir() || existingState.is(this.block) || existingState.is(Blocks.WATER) && existingState.getFluidState().isSource();
|
|
}
|
|
|
|
@Override
|
|
public boolean canSpreadInto(BlockGetter level, BlockPos sourcePos, SpreadPos spreadPos) {
|
|
BlockState existingState = level.getBlockState(spreadPos.pos());
|
|
return this.stateCanBeReplaced(level, sourcePos, spreadPos.pos(), spreadPos.face(), existingState) && this.block.isValidStateForPlacement(level, existingState, spreadPos.pos(), spreadPos.face());
|
|
}
|
|
}
|
|
|
|
public static interface SpreadConfig {
|
|
public @Nullable BlockState getStateForPlacement(BlockState var1, BlockGetter var2, BlockPos var3, Direction var4);
|
|
|
|
public boolean canSpreadInto(BlockGetter var1, BlockPos var2, SpreadPos var3);
|
|
|
|
default public SpreadType[] getSpreadTypes() {
|
|
return DEFAULT_SPREAD_ORDER;
|
|
}
|
|
|
|
default public boolean hasFace(BlockState state, Direction face) {
|
|
return MultifaceBlock.hasFace(state, face);
|
|
}
|
|
|
|
default public boolean isOtherBlockValidAsSource(BlockState state) {
|
|
return false;
|
|
}
|
|
|
|
default public boolean canSpreadFrom(BlockState state, Direction face) {
|
|
return this.isOtherBlockValidAsSource(state) || this.hasFace(state, face);
|
|
}
|
|
|
|
default public boolean placeBlock(LevelAccessor level, SpreadPos spreadPos, BlockState oldState, boolean postProcess) {
|
|
BlockState spreadState = this.getStateForPlacement(oldState, level, spreadPos.pos(), spreadPos.face());
|
|
if (spreadState != null) {
|
|
if (postProcess) {
|
|
level.getChunk(spreadPos.pos()).markPosForPostprocessing(spreadPos.pos());
|
|
}
|
|
return level.setBlock(spreadPos.pos(), spreadState, 2);
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@FunctionalInterface
|
|
public static interface SpreadPredicate {
|
|
public boolean test(BlockGetter var1, BlockPos var2, SpreadPos var3);
|
|
}
|
|
|
|
public static enum SpreadType {
|
|
SAME_POSITION{
|
|
|
|
@Override
|
|
public SpreadPos getSpreadPos(BlockPos pos, Direction spreadDirection, Direction fromFace) {
|
|
return new SpreadPos(pos, spreadDirection);
|
|
}
|
|
}
|
|
,
|
|
SAME_PLANE{
|
|
|
|
@Override
|
|
public SpreadPos getSpreadPos(BlockPos pos, Direction spreadDirection, Direction fromFace) {
|
|
return new SpreadPos(pos.relative(spreadDirection), fromFace);
|
|
}
|
|
}
|
|
,
|
|
WRAP_AROUND{
|
|
|
|
@Override
|
|
public SpreadPos getSpreadPos(BlockPos pos, Direction spreadDirection, Direction fromFace) {
|
|
return new SpreadPos(pos.relative(spreadDirection).relative(fromFace), spreadDirection.getOpposite());
|
|
}
|
|
};
|
|
|
|
|
|
public abstract SpreadPos getSpreadPos(BlockPos var1, Direction var2, Direction var3);
|
|
}
|
|
|
|
public record SpreadPos(BlockPos pos, Direction face) {
|
|
}
|
|
}
|
|
|