package net.minecraft.world.level.block.piston; import com.google.common.collect.Lists; import java.util.List; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.PushReaction; public class PistonStructureResolver { public static final int MAX_PUSH_DEPTH = 12; private final Level level; private final BlockPos pistonPos; private final boolean extending; private final BlockPos startPos; private final Direction pushDirection; private final List toPush = Lists.newArrayList(); private final List toDestroy = Lists.newArrayList(); private final Direction pistonDirection; public PistonStructureResolver(Level p_60418_, BlockPos p_60419_, Direction p_60420_, boolean p_60421_) { this.level = p_60418_; this.pistonPos = p_60419_; this.pistonDirection = p_60420_; this.extending = p_60421_; if (p_60421_) { this.pushDirection = p_60420_; this.startPos = p_60419_.relative(p_60420_); } else { this.pushDirection = p_60420_.getOpposite(); this.startPos = p_60419_.relative(p_60420_, 2); } } public boolean resolve() { this.toPush.clear(); this.toDestroy.clear(); BlockState blockstate = this.level.getBlockState(this.startPos); if (!PistonBaseBlock.isPushable(blockstate, this.level, this.startPos, this.pushDirection, false, this.pistonDirection)) { if (this.extending && blockstate.getPistonPushReaction() == PushReaction.DESTROY) { this.toDestroy.add(this.startPos); return true; } else { return false; } } else if (!this.addBlockLine(this.startPos, this.pushDirection)) { return false; } else { for (int i = 0; i < this.toPush.size(); i++) { BlockPos blockpos = this.toPush.get(i); if (isSticky(this.level.getBlockState(blockpos)) && !this.addBranchingBlocks(blockpos)) { return false; } } return true; } } private static boolean isSticky(BlockState p_155938_) { return p_155938_.is(Blocks.SLIME_BLOCK) || p_155938_.is(Blocks.HONEY_BLOCK); } private static boolean canStickToEachOther(BlockState p_155940_, BlockState p_155941_) { if (p_155940_.is(Blocks.HONEY_BLOCK) && p_155941_.is(Blocks.SLIME_BLOCK)) { return false; } else { return p_155940_.is(Blocks.SLIME_BLOCK) && p_155941_.is(Blocks.HONEY_BLOCK) ? false : isSticky(p_155940_) || isSticky(p_155941_); } } private boolean addBlockLine(BlockPos p_60434_, Direction p_60435_) { BlockState blockstate = this.level.getBlockState(p_60434_); if (blockstate.isAir()) { return true; } else if (!PistonBaseBlock.isPushable(blockstate, this.level, p_60434_, this.pushDirection, false, p_60435_)) { return true; } else if (p_60434_.equals(this.pistonPos)) { return true; } else if (this.toPush.contains(p_60434_)) { return true; } else { int i = 1; if (i + this.toPush.size() > 12) { return false; } else { while (isSticky(blockstate)) { BlockPos blockpos = p_60434_.relative(this.pushDirection.getOpposite(), i); BlockState blockstate1 = blockstate; blockstate = this.level.getBlockState(blockpos); if (blockstate.isAir() || !canStickToEachOther(blockstate1, blockstate) || !PistonBaseBlock.isPushable(blockstate, this.level, blockpos, this.pushDirection, false, this.pushDirection.getOpposite()) || blockpos.equals(this.pistonPos)) { break; } if (++i + this.toPush.size() > 12) { return false; } } int l = 0; for (int i1 = i - 1; i1 >= 0; i1--) { this.toPush.add(p_60434_.relative(this.pushDirection.getOpposite(), i1)); l++; } int j1 = 1; while (true) { BlockPos blockpos1 = p_60434_.relative(this.pushDirection, j1); int j = this.toPush.indexOf(blockpos1); if (j > -1) { this.reorderListAtCollision(l, j); for (int k = 0; k <= j + l; k++) { BlockPos blockpos2 = this.toPush.get(k); if (isSticky(this.level.getBlockState(blockpos2)) && !this.addBranchingBlocks(blockpos2)) { return false; } } return true; } blockstate = this.level.getBlockState(blockpos1); if (blockstate.isAir()) { return true; } if (!PistonBaseBlock.isPushable(blockstate, this.level, blockpos1, this.pushDirection, true, this.pushDirection) || blockpos1.equals(this.pistonPos)) { return false; } if (blockstate.getPistonPushReaction() == PushReaction.DESTROY) { this.toDestroy.add(blockpos1); return true; } if (this.toPush.size() >= 12) { return false; } this.toPush.add(blockpos1); l++; j1++; } } } } private void reorderListAtCollision(int p_60424_, int p_60425_) { List list = Lists.newArrayList(); List list1 = Lists.newArrayList(); List list2 = Lists.newArrayList(); list.addAll(this.toPush.subList(0, p_60425_)); list1.addAll(this.toPush.subList(this.toPush.size() - p_60424_, this.toPush.size())); list2.addAll(this.toPush.subList(p_60425_, this.toPush.size() - p_60424_)); this.toPush.clear(); this.toPush.addAll(list); this.toPush.addAll(list1); this.toPush.addAll(list2); } private boolean addBranchingBlocks(BlockPos p_60432_) { BlockState blockstate = this.level.getBlockState(p_60432_); for (Direction direction : Direction.values()) { if (direction.getAxis() != this.pushDirection.getAxis()) { BlockPos blockpos = p_60432_.relative(direction); BlockState blockstate1 = this.level.getBlockState(blockpos); if (canStickToEachOther(blockstate1, blockstate) && !this.addBlockLine(blockpos, direction)) { return false; } } } return true; } public Direction getPushDirection() { return this.pushDirection; } public List getToPush() { return this.toPush; } public List getToDestroy() { return this.toDestroy; } }