package net.minecraft.world.level.block; 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.state.BlockState; import net.minecraft.world.level.block.state.properties.RailShape; import org.jetbrains.annotations.Nullable; public class RailState { private final Level level; private final BlockPos pos; private final BaseRailBlock block; private BlockState state; private final boolean isStraight; private final List connections = Lists.newArrayList(); public RailState(Level level, BlockPos pos, BlockState state) { this.level = level; this.pos = pos; this.state = state; this.block = (BaseRailBlock)state.getBlock(); RailShape railShape = state.getValue(this.block.getShapeProperty()); this.isStraight = this.block.isStraight(); this.updateConnections(railShape); } public List getConnections() { return this.connections; } private void updateConnections(RailShape shape) { this.connections.clear(); switch (shape) { case NORTH_SOUTH: this.connections.add(this.pos.north()); this.connections.add(this.pos.south()); break; case EAST_WEST: this.connections.add(this.pos.west()); this.connections.add(this.pos.east()); break; case ASCENDING_EAST: this.connections.add(this.pos.west()); this.connections.add(this.pos.east().above()); break; case ASCENDING_WEST: this.connections.add(this.pos.west().above()); this.connections.add(this.pos.east()); break; case ASCENDING_NORTH: this.connections.add(this.pos.north().above()); this.connections.add(this.pos.south()); break; case ASCENDING_SOUTH: this.connections.add(this.pos.north()); this.connections.add(this.pos.south().above()); break; case SOUTH_EAST: this.connections.add(this.pos.east()); this.connections.add(this.pos.south()); break; case SOUTH_WEST: this.connections.add(this.pos.west()); this.connections.add(this.pos.south()); break; case NORTH_WEST: this.connections.add(this.pos.west()); this.connections.add(this.pos.north()); break; case NORTH_EAST: this.connections.add(this.pos.east()); this.connections.add(this.pos.north()); } } private void removeSoftConnections() { for (int i = 0; i < this.connections.size(); i++) { RailState railState = this.getRail((BlockPos)this.connections.get(i)); if (railState != null && railState.connectsTo(this)) { this.connections.set(i, railState.pos); } else { this.connections.remove(i--); } } } private boolean hasRail(BlockPos pos) { return BaseRailBlock.isRail(this.level, pos) || BaseRailBlock.isRail(this.level, pos.above()) || BaseRailBlock.isRail(this.level, pos.below()); } @Nullable private RailState getRail(BlockPos pos) { BlockState blockState = this.level.getBlockState(pos); if (BaseRailBlock.isRail(blockState)) { return new RailState(this.level, pos, blockState); } else { BlockPos blockPos = pos.above(); blockState = this.level.getBlockState(blockPos); if (BaseRailBlock.isRail(blockState)) { return new RailState(this.level, blockPos, blockState); } else { blockPos = pos.below(); blockState = this.level.getBlockState(blockPos); return BaseRailBlock.isRail(blockState) ? new RailState(this.level, blockPos, blockState) : null; } } } private boolean connectsTo(RailState state) { return this.hasConnection(state.pos); } private boolean hasConnection(BlockPos pos) { for (int i = 0; i < this.connections.size(); i++) { BlockPos blockPos = (BlockPos)this.connections.get(i); if (blockPos.getX() == pos.getX() && blockPos.getZ() == pos.getZ()) { return true; } } return false; } protected int countPotentialConnections() { int i = 0; for (Direction direction : Direction.Plane.HORIZONTAL) { if (this.hasRail(this.pos.relative(direction))) { i++; } } return i; } private boolean canConnectTo(RailState state) { return this.connectsTo(state) || this.connections.size() != 2; } private void connectTo(RailState state) { this.connections.add(state.pos); BlockPos blockPos = this.pos.north(); BlockPos blockPos2 = this.pos.south(); BlockPos blockPos3 = this.pos.west(); BlockPos blockPos4 = this.pos.east(); boolean bl = this.hasConnection(blockPos); boolean bl2 = this.hasConnection(blockPos2); boolean bl3 = this.hasConnection(blockPos3); boolean bl4 = this.hasConnection(blockPos4); RailShape railShape = null; if (bl || bl2) { railShape = RailShape.NORTH_SOUTH; } if (bl3 || bl4) { railShape = RailShape.EAST_WEST; } if (!this.isStraight) { if (bl2 && bl4 && !bl && !bl3) { railShape = RailShape.SOUTH_EAST; } if (bl2 && bl3 && !bl && !bl4) { railShape = RailShape.SOUTH_WEST; } if (bl && bl3 && !bl2 && !bl4) { railShape = RailShape.NORTH_WEST; } if (bl && bl4 && !bl2 && !bl3) { railShape = RailShape.NORTH_EAST; } } if (railShape == RailShape.NORTH_SOUTH) { if (BaseRailBlock.isRail(this.level, blockPos.above())) { railShape = RailShape.ASCENDING_NORTH; } if (BaseRailBlock.isRail(this.level, blockPos2.above())) { railShape = RailShape.ASCENDING_SOUTH; } } if (railShape == RailShape.EAST_WEST) { if (BaseRailBlock.isRail(this.level, blockPos4.above())) { railShape = RailShape.ASCENDING_EAST; } if (BaseRailBlock.isRail(this.level, blockPos3.above())) { railShape = RailShape.ASCENDING_WEST; } } if (railShape == null) { railShape = RailShape.NORTH_SOUTH; } this.state = this.state.setValue(this.block.getShapeProperty(), railShape); this.level.setBlock(this.pos, this.state, 3); } private boolean hasNeighborRail(BlockPos pos) { RailState railState = this.getRail(pos); if (railState == null) { return false; } else { railState.removeSoftConnections(); return railState.canConnectTo(this); } } public RailState place(boolean powered, boolean alwaysPlace, RailShape shape) { BlockPos blockPos = this.pos.north(); BlockPos blockPos2 = this.pos.south(); BlockPos blockPos3 = this.pos.west(); BlockPos blockPos4 = this.pos.east(); boolean bl = this.hasNeighborRail(blockPos); boolean bl2 = this.hasNeighborRail(blockPos2); boolean bl3 = this.hasNeighborRail(blockPos3); boolean bl4 = this.hasNeighborRail(blockPos4); RailShape railShape = null; boolean bl5 = bl || bl2; boolean bl6 = bl3 || bl4; if (bl5 && !bl6) { railShape = RailShape.NORTH_SOUTH; } if (bl6 && !bl5) { railShape = RailShape.EAST_WEST; } boolean bl7 = bl2 && bl4; boolean bl8 = bl2 && bl3; boolean bl9 = bl && bl4; boolean bl10 = bl && bl3; if (!this.isStraight) { if (bl7 && !bl && !bl3) { railShape = RailShape.SOUTH_EAST; } if (bl8 && !bl && !bl4) { railShape = RailShape.SOUTH_WEST; } if (bl10 && !bl2 && !bl4) { railShape = RailShape.NORTH_WEST; } if (bl9 && !bl2 && !bl3) { railShape = RailShape.NORTH_EAST; } } if (railShape == null) { if (bl5 && bl6) { railShape = shape; } else if (bl5) { railShape = RailShape.NORTH_SOUTH; } else if (bl6) { railShape = RailShape.EAST_WEST; } if (!this.isStraight) { if (powered) { if (bl7) { railShape = RailShape.SOUTH_EAST; } if (bl8) { railShape = RailShape.SOUTH_WEST; } if (bl9) { railShape = RailShape.NORTH_EAST; } if (bl10) { railShape = RailShape.NORTH_WEST; } } else { if (bl10) { railShape = RailShape.NORTH_WEST; } if (bl9) { railShape = RailShape.NORTH_EAST; } if (bl8) { railShape = RailShape.SOUTH_WEST; } if (bl7) { railShape = RailShape.SOUTH_EAST; } } } } if (railShape == RailShape.NORTH_SOUTH) { if (BaseRailBlock.isRail(this.level, blockPos.above())) { railShape = RailShape.ASCENDING_NORTH; } if (BaseRailBlock.isRail(this.level, blockPos2.above())) { railShape = RailShape.ASCENDING_SOUTH; } } if (railShape == RailShape.EAST_WEST) { if (BaseRailBlock.isRail(this.level, blockPos4.above())) { railShape = RailShape.ASCENDING_EAST; } if (BaseRailBlock.isRail(this.level, blockPos3.above())) { railShape = RailShape.ASCENDING_WEST; } } if (railShape == null) { railShape = shape; } this.updateConnections(railShape); this.state = this.state.setValue(this.block.getShapeProperty(), railShape); if (alwaysPlace || this.level.getBlockState(this.pos) != this.state) { this.level.setBlock(this.pos, this.state, 3); for (int i = 0; i < this.connections.size(); i++) { RailState railState = this.getRail((BlockPos)this.connections.get(i)); if (railState != null) { railState.removeSoftConnections(); if (railState.canConnectTo(this)) { railState.connectTo(this); } } } } return this; } public BlockState getState() { return this.state; } }