544 lines
21 KiB
Java
544 lines
21 KiB
Java
package net.minecraft.world.level.block;
|
|
|
|
import com.google.common.collect.ImmutableMap;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Sets;
|
|
import com.mojang.serialization.MapCodec;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.particles.DustParticleOptions;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.level.LevelReader;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
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.EnumProperty;
|
|
import net.minecraft.world.level.block.state.properties.IntegerProperty;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
import net.minecraft.world.level.block.state.properties.RedstoneSide;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
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.Nullable;
|
|
|
|
public class RedStoneWireBlock extends Block {
|
|
public static final MapCodec<RedStoneWireBlock> CODEC = simpleCodec(RedStoneWireBlock::new);
|
|
public static final EnumProperty<RedstoneSide> NORTH = BlockStateProperties.NORTH_REDSTONE;
|
|
public static final EnumProperty<RedstoneSide> EAST = BlockStateProperties.EAST_REDSTONE;
|
|
public static final EnumProperty<RedstoneSide> SOUTH = BlockStateProperties.SOUTH_REDSTONE;
|
|
public static final EnumProperty<RedstoneSide> WEST = BlockStateProperties.WEST_REDSTONE;
|
|
public static final IntegerProperty POWER = BlockStateProperties.POWER;
|
|
public static final Map<Direction, EnumProperty<RedstoneSide>> PROPERTY_BY_DIRECTION = Maps.newEnumMap(
|
|
ImmutableMap.of(Direction.NORTH, NORTH, Direction.EAST, EAST, Direction.SOUTH, SOUTH, Direction.WEST, WEST)
|
|
);
|
|
protected static final int H = 1;
|
|
protected static final int W = 3;
|
|
protected static final int E = 13;
|
|
protected static final int N = 3;
|
|
protected static final int S = 13;
|
|
private static final VoxelShape SHAPE_DOT = Block.box(3.0, 0.0, 3.0, 13.0, 1.0, 13.0);
|
|
private static final Map<Direction, VoxelShape> SHAPES_FLOOR = Maps.newEnumMap(
|
|
ImmutableMap.of(
|
|
Direction.NORTH,
|
|
Block.box(3.0, 0.0, 0.0, 13.0, 1.0, 13.0),
|
|
Direction.SOUTH,
|
|
Block.box(3.0, 0.0, 3.0, 13.0, 1.0, 16.0),
|
|
Direction.EAST,
|
|
Block.box(3.0, 0.0, 3.0, 16.0, 1.0, 13.0),
|
|
Direction.WEST,
|
|
Block.box(0.0, 0.0, 3.0, 13.0, 1.0, 13.0)
|
|
)
|
|
);
|
|
private static final Map<Direction, VoxelShape> SHAPES_UP = Maps.newEnumMap(
|
|
ImmutableMap.of(
|
|
Direction.NORTH,
|
|
Shapes.or((VoxelShape)SHAPES_FLOOR.get(Direction.NORTH), Block.box(3.0, 0.0, 0.0, 13.0, 16.0, 1.0)),
|
|
Direction.SOUTH,
|
|
Shapes.or((VoxelShape)SHAPES_FLOOR.get(Direction.SOUTH), Block.box(3.0, 0.0, 15.0, 13.0, 16.0, 16.0)),
|
|
Direction.EAST,
|
|
Shapes.or((VoxelShape)SHAPES_FLOOR.get(Direction.EAST), Block.box(15.0, 0.0, 3.0, 16.0, 16.0, 13.0)),
|
|
Direction.WEST,
|
|
Shapes.or((VoxelShape)SHAPES_FLOOR.get(Direction.WEST), Block.box(0.0, 0.0, 3.0, 1.0, 16.0, 13.0))
|
|
)
|
|
);
|
|
private static final Map<BlockState, VoxelShape> SHAPES_CACHE = Maps.<BlockState, VoxelShape>newHashMap();
|
|
private static final Vec3[] COLORS = Util.make(new Vec3[16], vec3s -> {
|
|
for (int i = 0; i <= 15; i++) {
|
|
float f = i / 15.0F;
|
|
float g = f * 0.6F + (f > 0.0F ? 0.4F : 0.3F);
|
|
float h = Mth.clamp(f * f * 0.7F - 0.5F, 0.0F, 1.0F);
|
|
float j = Mth.clamp(f * f * 0.6F - 0.7F, 0.0F, 1.0F);
|
|
vec3s[i] = new Vec3(g, h, j);
|
|
}
|
|
});
|
|
private static final float PARTICLE_DENSITY = 0.2F;
|
|
private final BlockState crossState;
|
|
private boolean shouldSignal = true;
|
|
|
|
@Override
|
|
public MapCodec<RedStoneWireBlock> codec() {
|
|
return CODEC;
|
|
}
|
|
|
|
public RedStoneWireBlock(BlockBehaviour.Properties properties) {
|
|
super(properties);
|
|
this.registerDefaultState(
|
|
this.stateDefinition
|
|
.any()
|
|
.setValue(NORTH, RedstoneSide.NONE)
|
|
.setValue(EAST, RedstoneSide.NONE)
|
|
.setValue(SOUTH, RedstoneSide.NONE)
|
|
.setValue(WEST, RedstoneSide.NONE)
|
|
.setValue(POWER, 0)
|
|
);
|
|
this.crossState = this.defaultBlockState()
|
|
.setValue(NORTH, RedstoneSide.SIDE)
|
|
.setValue(EAST, RedstoneSide.SIDE)
|
|
.setValue(SOUTH, RedstoneSide.SIDE)
|
|
.setValue(WEST, RedstoneSide.SIDE);
|
|
|
|
for (BlockState blockState : this.getStateDefinition().getPossibleStates()) {
|
|
if ((Integer)blockState.getValue(POWER) == 0) {
|
|
SHAPES_CACHE.put(blockState, this.calculateShape(blockState));
|
|
}
|
|
}
|
|
}
|
|
|
|
private VoxelShape calculateShape(BlockState state) {
|
|
VoxelShape voxelShape = SHAPE_DOT;
|
|
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
RedstoneSide redstoneSide = state.getValue((Property<RedstoneSide>)PROPERTY_BY_DIRECTION.get(direction));
|
|
if (redstoneSide == RedstoneSide.SIDE) {
|
|
voxelShape = Shapes.or(voxelShape, (VoxelShape)SHAPES_FLOOR.get(direction));
|
|
} else if (redstoneSide == RedstoneSide.UP) {
|
|
voxelShape = Shapes.or(voxelShape, (VoxelShape)SHAPES_UP.get(direction));
|
|
}
|
|
}
|
|
|
|
return voxelShape;
|
|
}
|
|
|
|
@Override
|
|
protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
|
|
return (VoxelShape)SHAPES_CACHE.get(state.setValue(POWER, 0));
|
|
}
|
|
|
|
@Override
|
|
public BlockState getStateForPlacement(BlockPlaceContext context) {
|
|
return this.getConnectionState(context.getLevel(), this.crossState, context.getClickedPos());
|
|
}
|
|
|
|
private BlockState getConnectionState(BlockGetter level, BlockState state, BlockPos pos) {
|
|
boolean bl = isDot(state);
|
|
state = this.getMissingConnections(level, this.defaultBlockState().setValue(POWER, (Integer)state.getValue(POWER)), pos);
|
|
if (bl && isDot(state)) {
|
|
return state;
|
|
} else {
|
|
boolean bl2 = ((RedstoneSide)state.getValue(NORTH)).isConnected();
|
|
boolean bl3 = ((RedstoneSide)state.getValue(SOUTH)).isConnected();
|
|
boolean bl4 = ((RedstoneSide)state.getValue(EAST)).isConnected();
|
|
boolean bl5 = ((RedstoneSide)state.getValue(WEST)).isConnected();
|
|
boolean bl6 = !bl2 && !bl3;
|
|
boolean bl7 = !bl4 && !bl5;
|
|
if (!bl5 && bl6) {
|
|
state = state.setValue(WEST, RedstoneSide.SIDE);
|
|
}
|
|
|
|
if (!bl4 && bl6) {
|
|
state = state.setValue(EAST, RedstoneSide.SIDE);
|
|
}
|
|
|
|
if (!bl2 && bl7) {
|
|
state = state.setValue(NORTH, RedstoneSide.SIDE);
|
|
}
|
|
|
|
if (!bl3 && bl7) {
|
|
state = state.setValue(SOUTH, RedstoneSide.SIDE);
|
|
}
|
|
|
|
return state;
|
|
}
|
|
}
|
|
|
|
private BlockState getMissingConnections(BlockGetter level, BlockState state, BlockPos pos) {
|
|
boolean bl = !level.getBlockState(pos.above()).isRedstoneConductor(level, pos);
|
|
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
if (!((RedstoneSide)state.getValue((Property)PROPERTY_BY_DIRECTION.get(direction))).isConnected()) {
|
|
RedstoneSide redstoneSide = this.getConnectingSide(level, pos, direction, bl);
|
|
state = state.setValue((Property)PROPERTY_BY_DIRECTION.get(direction), redstoneSide);
|
|
}
|
|
}
|
|
|
|
return state;
|
|
}
|
|
|
|
@Override
|
|
protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
|
|
if (direction == Direction.DOWN) {
|
|
return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state;
|
|
} else if (direction == Direction.UP) {
|
|
return this.getConnectionState(level, state, pos);
|
|
} else {
|
|
RedstoneSide redstoneSide = this.getConnectingSide(level, pos, direction);
|
|
return redstoneSide.isConnected() == ((RedstoneSide)state.getValue((Property)PROPERTY_BY_DIRECTION.get(direction))).isConnected() && !isCross(state)
|
|
? state.setValue((Property)PROPERTY_BY_DIRECTION.get(direction), redstoneSide)
|
|
: this.getConnectionState(
|
|
level, this.crossState.setValue(POWER, (Integer)state.getValue(POWER)).setValue((Property)PROPERTY_BY_DIRECTION.get(direction), redstoneSide), pos
|
|
);
|
|
}
|
|
}
|
|
|
|
private static boolean isCross(BlockState state) {
|
|
return ((RedstoneSide)state.getValue(NORTH)).isConnected()
|
|
&& ((RedstoneSide)state.getValue(SOUTH)).isConnected()
|
|
&& ((RedstoneSide)state.getValue(EAST)).isConnected()
|
|
&& ((RedstoneSide)state.getValue(WEST)).isConnected();
|
|
}
|
|
|
|
private static boolean isDot(BlockState state) {
|
|
return !((RedstoneSide)state.getValue(NORTH)).isConnected()
|
|
&& !((RedstoneSide)state.getValue(SOUTH)).isConnected()
|
|
&& !((RedstoneSide)state.getValue(EAST)).isConnected()
|
|
&& !((RedstoneSide)state.getValue(WEST)).isConnected();
|
|
}
|
|
|
|
@Override
|
|
protected void updateIndirectNeighbourShapes(BlockState state, LevelAccessor level, BlockPos pos, int flags, int recursionLeft) {
|
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
|
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
RedstoneSide redstoneSide = state.getValue((Property<RedstoneSide>)PROPERTY_BY_DIRECTION.get(direction));
|
|
if (redstoneSide != RedstoneSide.NONE && !level.getBlockState(mutableBlockPos.setWithOffset(pos, direction)).is(this)) {
|
|
mutableBlockPos.move(Direction.DOWN);
|
|
BlockState blockState = level.getBlockState(mutableBlockPos);
|
|
if (blockState.is(this)) {
|
|
BlockPos blockPos = mutableBlockPos.relative(direction.getOpposite());
|
|
level.neighborShapeChanged(direction.getOpposite(), level.getBlockState(blockPos), mutableBlockPos, blockPos, flags, recursionLeft);
|
|
}
|
|
|
|
mutableBlockPos.setWithOffset(pos, direction).move(Direction.UP);
|
|
BlockState blockState2 = level.getBlockState(mutableBlockPos);
|
|
if (blockState2.is(this)) {
|
|
BlockPos blockPos2 = mutableBlockPos.relative(direction.getOpposite());
|
|
level.neighborShapeChanged(direction.getOpposite(), level.getBlockState(blockPos2), mutableBlockPos, blockPos2, flags, recursionLeft);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private RedstoneSide getConnectingSide(BlockGetter level, BlockPos pos, Direction face) {
|
|
return this.getConnectingSide(level, pos, face, !level.getBlockState(pos.above()).isRedstoneConductor(level, pos));
|
|
}
|
|
|
|
private RedstoneSide getConnectingSide(BlockGetter level, BlockPos pos, Direction direction, boolean nonNormalCubeAbove) {
|
|
BlockPos blockPos = pos.relative(direction);
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
if (nonNormalCubeAbove) {
|
|
boolean bl = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState);
|
|
if (bl && shouldConnectTo(level.getBlockState(blockPos.above()))) {
|
|
if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) {
|
|
return RedstoneSide.UP;
|
|
}
|
|
|
|
return RedstoneSide.SIDE;
|
|
}
|
|
}
|
|
|
|
return !shouldConnectTo(blockState, direction)
|
|
&& (blockState.isRedstoneConductor(level, blockPos) || !shouldConnectTo(level.getBlockState(blockPos.below())))
|
|
? RedstoneSide.NONE
|
|
: RedstoneSide.SIDE;
|
|
}
|
|
|
|
@Override
|
|
protected boolean canSurvive(BlockState state, LevelReader level, BlockPos pos) {
|
|
BlockPos blockPos = pos.below();
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
return this.canSurviveOn(level, blockPos, blockState);
|
|
}
|
|
|
|
private boolean canSurviveOn(BlockGetter level, BlockPos pos, BlockState state) {
|
|
return state.isFaceSturdy(level, pos, Direction.UP) || state.is(Blocks.HOPPER);
|
|
}
|
|
|
|
private void updatePowerStrength(Level level, BlockPos pos, BlockState state) {
|
|
int i = this.calculateTargetStrength(level, pos);
|
|
if ((Integer)state.getValue(POWER) != i) {
|
|
if (level.getBlockState(pos) == state) {
|
|
level.setBlock(pos, state.setValue(POWER, i), 2);
|
|
}
|
|
|
|
Set<BlockPos> set = Sets.<BlockPos>newHashSet();
|
|
set.add(pos);
|
|
|
|
for (Direction direction : Direction.values()) {
|
|
set.add(pos.relative(direction));
|
|
}
|
|
|
|
for (BlockPos blockPos : set) {
|
|
level.updateNeighborsAt(blockPos, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
private int calculateTargetStrength(Level level, BlockPos pos) {
|
|
this.shouldSignal = false;
|
|
int i = level.getBestNeighborSignal(pos);
|
|
this.shouldSignal = true;
|
|
int j = 0;
|
|
if (i < 15) {
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
BlockPos blockPos = pos.relative(direction);
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
j = Math.max(j, this.getWireSignal(blockState));
|
|
BlockPos blockPos2 = pos.above();
|
|
if (blockState.isRedstoneConductor(level, blockPos) && !level.getBlockState(blockPos2).isRedstoneConductor(level, blockPos2)) {
|
|
j = Math.max(j, this.getWireSignal(level.getBlockState(blockPos.above())));
|
|
} else if (!blockState.isRedstoneConductor(level, blockPos)) {
|
|
j = Math.max(j, this.getWireSignal(level.getBlockState(blockPos.below())));
|
|
}
|
|
}
|
|
}
|
|
|
|
return Math.max(i, j - 1);
|
|
}
|
|
|
|
private int getWireSignal(BlockState state) {
|
|
return state.is(this) ? (Integer)state.getValue(POWER) : 0;
|
|
}
|
|
|
|
/**
|
|
* Calls {@link net.minecraft.world.level.Level#updateNeighborsAt} for all neighboring blocks, but only if the given block is a redstone wire.
|
|
*/
|
|
private void checkCornerChangeAt(Level level, BlockPos pos) {
|
|
if (level.getBlockState(pos).is(this)) {
|
|
level.updateNeighborsAt(pos, this);
|
|
|
|
for (Direction direction : Direction.values()) {
|
|
level.updateNeighborsAt(pos.relative(direction), this);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
|
|
if (!oldState.is(state.getBlock()) && !level.isClientSide) {
|
|
this.updatePowerStrength(level, pos, state);
|
|
|
|
for (Direction direction : Direction.Plane.VERTICAL) {
|
|
level.updateNeighborsAt(pos.relative(direction), this);
|
|
}
|
|
|
|
this.updateNeighborsOfNeighboringWires(level, pos);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
|
|
if (!movedByPiston && !state.is(newState.getBlock())) {
|
|
super.onRemove(state, level, pos, newState, movedByPiston);
|
|
if (!level.isClientSide) {
|
|
for (Direction direction : Direction.values()) {
|
|
level.updateNeighborsAt(pos.relative(direction), this);
|
|
}
|
|
|
|
this.updatePowerStrength(level, pos, state);
|
|
this.updateNeighborsOfNeighboringWires(level, pos);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void updateNeighborsOfNeighboringWires(Level level, BlockPos pos) {
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
this.checkCornerChangeAt(level, pos.relative(direction));
|
|
}
|
|
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
BlockPos blockPos = pos.relative(direction);
|
|
if (level.getBlockState(blockPos).isRedstoneConductor(level, blockPos)) {
|
|
this.checkCornerChangeAt(level, blockPos.above());
|
|
} else {
|
|
this.checkCornerChangeAt(level, blockPos.below());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void neighborChanged(BlockState state, Level level, BlockPos pos, Block neighborBlock, BlockPos neighborPos, boolean movedByPiston) {
|
|
if (!level.isClientSide) {
|
|
if (state.canSurvive(level, pos)) {
|
|
this.updatePowerStrength(level, pos, state);
|
|
} else {
|
|
dropResources(state, level, pos);
|
|
level.removeBlock(pos, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected int getDirectSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
|
return !this.shouldSignal ? 0 : state.getSignal(level, pos, direction);
|
|
}
|
|
|
|
@Override
|
|
protected int getSignal(BlockState state, BlockGetter level, BlockPos pos, Direction direction) {
|
|
if (this.shouldSignal && direction != Direction.DOWN) {
|
|
int i = (Integer)state.getValue(POWER);
|
|
if (i == 0) {
|
|
return 0;
|
|
} else {
|
|
return direction != Direction.UP
|
|
&& !((RedstoneSide)this.getConnectionState(level, state, pos).getValue((Property)PROPERTY_BY_DIRECTION.get(direction.getOpposite()))).isConnected()
|
|
? 0
|
|
: i;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
protected static boolean shouldConnectTo(BlockState state) {
|
|
return shouldConnectTo(state, null);
|
|
}
|
|
|
|
protected static boolean shouldConnectTo(BlockState state, @Nullable Direction direction) {
|
|
if (state.is(Blocks.REDSTONE_WIRE)) {
|
|
return true;
|
|
} else if (state.is(Blocks.REPEATER)) {
|
|
Direction direction2 = state.getValue(RepeaterBlock.FACING);
|
|
return direction2 == direction || direction2.getOpposite() == direction;
|
|
} else {
|
|
return state.is(Blocks.OBSERVER) ? direction == state.getValue(ObserverBlock.FACING) : state.isSignalSource() && direction != null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected boolean isSignalSource(BlockState state) {
|
|
return this.shouldSignal;
|
|
}
|
|
|
|
public static int getColorForPower(int power) {
|
|
Vec3 vec3 = COLORS[power];
|
|
return Mth.color((float)vec3.x(), (float)vec3.y(), (float)vec3.z());
|
|
}
|
|
|
|
private void spawnParticlesAlongLine(
|
|
Level level, RandomSource random, BlockPos pos, Vec3 particleVec, Direction xDirection, Direction zDirection, float min, float max
|
|
) {
|
|
float f = max - min;
|
|
if (!(random.nextFloat() >= 0.2F * f)) {
|
|
float g = 0.4375F;
|
|
float h = min + f * random.nextFloat();
|
|
double d = 0.5 + 0.4375F * xDirection.getStepX() + h * zDirection.getStepX();
|
|
double e = 0.5 + 0.4375F * xDirection.getStepY() + h * zDirection.getStepY();
|
|
double i = 0.5 + 0.4375F * xDirection.getStepZ() + h * zDirection.getStepZ();
|
|
level.addParticle(new DustParticleOptions(particleVec.toVector3f(), 1.0F), pos.getX() + d, pos.getY() + e, pos.getZ() + i, 0.0, 0.0, 0.0);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
|
|
int i = (Integer)state.getValue(POWER);
|
|
if (i != 0) {
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
RedstoneSide redstoneSide = state.getValue((Property<RedstoneSide>)PROPERTY_BY_DIRECTION.get(direction));
|
|
switch (redstoneSide) {
|
|
case UP:
|
|
this.spawnParticlesAlongLine(level, random, pos, COLORS[i], direction, Direction.UP, -0.5F, 0.5F);
|
|
case SIDE:
|
|
this.spawnParticlesAlongLine(level, random, pos, COLORS[i], Direction.DOWN, direction, 0.0F, 0.5F);
|
|
break;
|
|
case NONE:
|
|
default:
|
|
this.spawnParticlesAlongLine(level, random, pos, COLORS[i], Direction.DOWN, direction, 0.0F, 0.3F);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected BlockState rotate(BlockState state, Rotation rotation) {
|
|
switch (rotation) {
|
|
case CLOCKWISE_180:
|
|
return state.setValue(NORTH, (RedstoneSide)state.getValue(SOUTH))
|
|
.setValue(EAST, (RedstoneSide)state.getValue(WEST))
|
|
.setValue(SOUTH, (RedstoneSide)state.getValue(NORTH))
|
|
.setValue(WEST, (RedstoneSide)state.getValue(EAST));
|
|
case COUNTERCLOCKWISE_90:
|
|
return state.setValue(NORTH, (RedstoneSide)state.getValue(EAST))
|
|
.setValue(EAST, (RedstoneSide)state.getValue(SOUTH))
|
|
.setValue(SOUTH, (RedstoneSide)state.getValue(WEST))
|
|
.setValue(WEST, (RedstoneSide)state.getValue(NORTH));
|
|
case CLOCKWISE_90:
|
|
return state.setValue(NORTH, (RedstoneSide)state.getValue(WEST))
|
|
.setValue(EAST, (RedstoneSide)state.getValue(NORTH))
|
|
.setValue(SOUTH, (RedstoneSide)state.getValue(EAST))
|
|
.setValue(WEST, (RedstoneSide)state.getValue(SOUTH));
|
|
default:
|
|
return state;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected BlockState mirror(BlockState state, Mirror mirror) {
|
|
switch (mirror) {
|
|
case LEFT_RIGHT:
|
|
return state.setValue(NORTH, (RedstoneSide)state.getValue(SOUTH)).setValue(SOUTH, (RedstoneSide)state.getValue(NORTH));
|
|
case FRONT_BACK:
|
|
return state.setValue(EAST, (RedstoneSide)state.getValue(WEST)).setValue(WEST, (RedstoneSide)state.getValue(EAST));
|
|
default:
|
|
return super.mirror(state, mirror);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
|
builder.add(NORTH, EAST, SOUTH, WEST, POWER);
|
|
}
|
|
|
|
@Override
|
|
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
|
|
if (!player.getAbilities().mayBuild) {
|
|
return InteractionResult.PASS;
|
|
} else {
|
|
if (isCross(state) || isDot(state)) {
|
|
BlockState blockState = isCross(state) ? this.defaultBlockState() : this.crossState;
|
|
blockState = blockState.setValue(POWER, (Integer)state.getValue(POWER));
|
|
blockState = this.getConnectionState(level, blockState, pos);
|
|
if (blockState != state) {
|
|
level.setBlock(pos, blockState, 3);
|
|
this.updatesOnShapeChange(level, pos, state, blockState);
|
|
return InteractionResult.SUCCESS;
|
|
}
|
|
}
|
|
|
|
return InteractionResult.PASS;
|
|
}
|
|
}
|
|
|
|
private void updatesOnShapeChange(Level level, BlockPos pos, BlockState oldState, BlockState newState) {
|
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
|
BlockPos blockPos = pos.relative(direction);
|
|
if (((RedstoneSide)oldState.getValue((Property)PROPERTY_BY_DIRECTION.get(direction))).isConnected()
|
|
!= ((RedstoneSide)newState.getValue((Property)PROPERTY_BY_DIRECTION.get(direction))).isConnected()
|
|
&& level.getBlockState(blockPos).isRedstoneConductor(level, blockPos)) {
|
|
level.updateNeighborsAtExceptFromFacing(blockPos, newState.getBlock(), direction.getOpposite());
|
|
}
|
|
}
|
|
}
|
|
}
|