Code/net/minecraft/world/level/block/piston/PistonStructureResolver.java

196 lines
7.4 KiB
Java

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<BlockPos> toPush = Lists.newArrayList();
private final List<BlockPos> 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<BlockPos> list = Lists.newArrayList();
List<BlockPos> list1 = Lists.newArrayList();
List<BlockPos> 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<BlockPos> getToPush() {
return this.toPush;
}
public List<BlockPos> getToDestroy() {
return this.toDestroy;
}
}