Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package com.junix.logicboard.blocks;
- import com.google.common.collect.ImmutableMap;
- import com.google.common.collect.Maps;
- import com.google.common.collect.Sets;
- import com.junix.logicboard.setup.Component;
- import com.junix.logicboard.setup.Registration;
- import net.minecraft.core.BlockPos;
- import net.minecraft.core.Direction;
- import net.minecraft.world.item.context.BlockPlaceContext;
- import net.minecraft.world.level.BlockGetter;
- import net.minecraft.world.level.Level;
- import net.minecraft.world.level.block.Block;
- import net.minecraft.world.level.block.state.BlockState;
- import net.minecraft.world.level.block.state.StateDefinition;
- import net.minecraft.world.level.block.state.properties.BlockStateProperties;
- import net.minecraft.world.level.block.state.properties.BooleanProperty;
- import net.minecraft.world.level.block.state.properties.IntegerProperty;
- import net.minecraft.world.phys.shapes.CollisionContext;
- import net.minecraft.world.phys.shapes.Shapes;
- import net.minecraft.world.phys.shapes.VoxelShape;
- import org.jetbrains.annotations.NotNull;
- import org.jetbrains.annotations.Nullable;
- import java.util.Map;
- import java.util.Set;
- public class Cable extends Component {
- /* Properties */
- public static final BooleanProperty NORTH = BooleanProperty.create("north");
- public static final BooleanProperty EAST = BooleanProperty.create("east");
- public static final BooleanProperty SOUTH = BooleanProperty.create("south");
- public static final BooleanProperty WEST = BooleanProperty.create("west");
- public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
- public static final IntegerProperty SOURCE_DISTANCE = IntegerProperty.create("source_distance", 0, 4096);
- /* VoxelShapes */
- private static final VoxelShape SHAPE_DOT = Block.box(5, 0, 5, 11, 1, 11);
- private static final VoxelShape SHAPE_N = Block.box(7, 0, 0, 9, 1, 5);
- private static final VoxelShape SHAPE_S = Block.box(7, 0, 11, 9, 1, 16);
- private static final VoxelShape SHAPE_W = Block.box(0, 0, 7, 5, 1, 9);
- private static final VoxelShape SHAPE_E = Block.box(11, 0, 7, 16, 1, 9);
- /* Maps */
- public static final Map<Direction, BooleanProperty> PROPERTY_BY_DIRECTION = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, NORTH, Direction.EAST, EAST, Direction.SOUTH, SOUTH, Direction.WEST, WEST));
- private static final Map<Direction, VoxelShape> SHAPE_BY_DIRECTION = Maps.newEnumMap(ImmutableMap.of(Direction.NORTH, SHAPE_N, Direction.SOUTH, SHAPE_S, Direction.WEST, SHAPE_W, Direction.EAST, SHAPE_E));
- private static final Map<BlockState, VoxelShape> SHAPES_CACHE = Maps.newHashMap();
- /* BlockStates */
- private final BlockState CROSS_STATE;
- public Cable() {
- super(Registration.CABLE_BLOCK_PROPERTIES);
- registerDefaultState(this.getStateDefinition().any()
- .setValue(NORTH, Boolean.FALSE)
- .setValue(SOUTH, Boolean.FALSE)
- .setValue(WEST, Boolean.FALSE)
- .setValue(EAST, Boolean.FALSE)
- .setValue(POWERED, Boolean.FALSE)
- .setValue(SOURCE_DISTANCE, 0));
- BlockState crossState = defaultBlockState();
- for (Direction direction: Direction.Plane.HORIZONTAL)
- crossState.setValue(PROPERTY_BY_DIRECTION.get(direction), Boolean.TRUE);
- CROSS_STATE = crossState;
- for (int north = 0; north < 2; north++)
- for (int south = 0; south < 2; south++)
- for (int west = 0; west < 2; west++)
- for (int east = 0; east < 2; east++) {
- System.out.println(north + " " + south + " " + west + " " + east);
- BlockState blockState = defaultBlockState();
- blockState.setValue(NORTH, north == 0).setValue(SOUTH, south == 0).setValue(WEST, west == 0).setValue(EAST, east == 0);
- SHAPES_CACHE.put(blockState, calculateShape(blockState));
- }
- }
- private VoxelShape calculateShape(BlockState blockState) {
- VoxelShape voxelShape = SHAPE_DOT;
- for (Direction direction: Direction.Plane.HORIZONTAL)
- if (blockState.getValue(PROPERTY_BY_DIRECTION.get(direction)))
- voxelShape = Shapes.or(voxelShape, SHAPE_BY_DIRECTION.get(direction));
- return voxelShape;
- }
- @Override
- protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
- builder.add(NORTH, SOUTH, WEST, EAST, POWERED, SOURCE_DISTANCE);
- }
- @Override
- public @NotNull VoxelShape getShape(BlockState blockState, @NotNull BlockGetter blockGetter, @NotNull BlockPos blockPos, @NotNull CollisionContext collisionContext) {
- return SHAPES_CACHE.get(blockState.setValue(POWERED, Boolean.FALSE).setValue(SOURCE_DISTANCE, 0));
- }
- @Nullable
- @Override
- public BlockState getStateForPlacement(BlockPlaceContext blockPlaceContext) {
- return getConnectionState(blockPlaceContext.getLevel(), CROSS_STATE, blockPlaceContext.getClickedPos());
- }
- private BlockState getConnectionState(BlockGetter blockGetter, BlockState blockState, BlockPos blockPos) {
- boolean dot = isDot(blockState);
- blockState = getMissingConnections(blockGetter, defaultBlockState().setValue(POWERED, Boolean.FALSE).setValue(SOURCE_DISTANCE, 0), blockPos);
- if (dot && isDot(blockState))
- return blockState;
- boolean north = blockState.getValue(NORTH), south = blockState.getValue(SOUTH), west = blockState.getValue(WEST), east = blockState.getValue(EAST);
- if (!north && !south && !west)
- blockState.setValue(WEST, Boolean.TRUE);
- if (!north && !south && !east)
- blockState.setValue(EAST, Boolean.TRUE);
- if (!north && !west && !east)
- blockState.setValue(NORTH, Boolean.TRUE);
- if (!south && !west && !east)
- blockState.setValue(SOUTH, Boolean.TRUE);
- return blockState;
- }
- private BlockState getMissingConnections(BlockGetter blockGetter, BlockState blockState, BlockPos blockPos) {
- for (Direction direction: Direction.Plane.HORIZONTAL)
- if (!blockState.getValue(PROPERTY_BY_DIRECTION.get(direction))) {
- boolean isConnecting = getConnectingSide(blockGetter, blockPos, direction);
- blockState.setValue(PROPERTY_BY_DIRECTION.get(direction), isConnecting);
- }
- return blockState;
- }
- private Boolean getConnectingSide(BlockGetter blockGetter, BlockPos blockPos, Direction direction) {
- BlockState relativeBlockState = blockGetter.getBlockState(blockPos.relative(direction));
- return relativeBlockState.getBlock() instanceof Component;
- }
- private boolean isDot(BlockState blockState) {
- boolean dot = false;
- for (Direction direction: Direction.Plane.HORIZONTAL)
- dot |= blockState.getValue(PROPERTY_BY_DIRECTION.get(direction));
- return !dot;
- }
- private void updateSourceDistance(Level level, BlockPos blockPos, BlockState blockState) {
- int i = calculateTargetStrength(level, blockPos);
- if (blockState.getValue(SOURCE_DISTANCE) != i) {
- if (level.getBlockState(blockPos) == blockState)
- level.setBlock(blockPos, blockState.setValue(SOURCE_DISTANCE, i).setValue(POWERED, i != 0), Block.UPDATE_CLIENTS);
- Set<BlockPos> blockPosSet = Sets.newHashSet();
- blockPosSet.add(blockPos);
- for (Direction direction: Direction.Plane.HORIZONTAL)
- blockPosSet.add(blockPos.relative(direction));
- for (BlockPos blockPos1: blockPosSet)
- level.updateNeighborsAt(blockPos1, this);
- }
- }
- private int calculateTargetStrength(Level level, BlockPos blockPos) {
- int i = 0;
- for (Direction direction: Direction.Plane.HORIZONTAL) {
- BlockState blockState = level.getBlockState(blockPos.relative(direction));
- if (blockState.getBlock() instanceof Component component)
- i = Math.min(i, component.getSourceDistance(blockState));
- }
- return i;
- }
- @Override
- public int getSourceDistance(BlockState blockState) {
- return blockState.getValue(SOURCE_DISTANCE);
- }
- private void checkCornerChangeAt(Level level, BlockPos blockPos) {
- if (level.getBlockState(blockPos).getBlock() instanceof Component) {
- level.updateNeighborsAt(blockPos, this);
- for (Direction direction: Direction.values())
- level.updateNeighborsAt(blockPos.relative(direction), this);
- }
- }
- @Override
- public void onPlace(BlockState blockState, Level level, BlockPos blockPos, BlockState blockState1, boolean bool) {
- if (!blockState1.is(blockState.getBlock()) && !level.isClientSide) {
- updateSourceDistance(level, blockPos, blockState);
- for (Direction direction: Direction.Plane.VERTICAL)
- level.updateNeighborsAt(blockPos.relative(direction), this);
- updateNeighborsOfNeighboringWires(level, blockPos);
- }
- }
- @Override
- public void onRemove(BlockState blockState, Level level, BlockPos blockPos, BlockState blockState1, boolean bool) {
- if (!bool && !blockState.is(blockState1.getBlock())) {
- super.onRemove(blockState, level, blockPos, blockState1, false);
- if (!level.isClientSide) {
- for (Direction direction: Direction.values())
- level.updateNeighborsAt(blockPos.relative(direction), this);
- updateSourceDistance(level, blockPos, blockState);
- updateNeighborsOfNeighboringWires(level, blockPos);
- }
- }
- }
- private void updateNeighborsOfNeighboringWires(Level level, BlockPos blockPos) {
- for (Direction direction: Direction.Plane.HORIZONTAL)
- checkCornerChangeAt(level, blockPos.relative(direction));
- }
- @Override
- public void neighborChanged(BlockState blockState, Level level, BlockPos blockPos, Block block, BlockPos blockPos1, boolean bool) {
- if (!level.isClientSide)
- updateSourceDistance(level, blockPos, blockState);
- }
- @Override
- public boolean isSignalSource(Direction direction) {
- return false;
- }
- @Override
- public boolean isConnectable(BlockState blockState, Direction direction) {
- return false;
- }
- }
Add Comment
Please, Sign In to add comment