191 lines
7.2 KiB
Java
191 lines
7.2 KiB
Java
package net.minecraft.world.level.block;
|
|
|
|
import com.mojang.serialization.MapCodec;
|
|
import java.util.List;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.InteractionResult;
|
|
import net.minecraft.world.entity.decoration.ItemFrame;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.entity.ComparatorBlockEntity;
|
|
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.ComparatorMode;
|
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.ticks.TickPriority;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class ComparatorBlock extends DiodeBlock implements EntityBlock {
|
|
public static final MapCodec<ComparatorBlock> CODEC = simpleCodec(ComparatorBlock::new);
|
|
public static final EnumProperty<ComparatorMode> MODE = BlockStateProperties.MODE_COMPARATOR;
|
|
|
|
@Override
|
|
public MapCodec<ComparatorBlock> codec() {
|
|
return CODEC;
|
|
}
|
|
|
|
public ComparatorBlock(BlockBehaviour.Properties properties) {
|
|
super(properties);
|
|
this.registerDefaultState(this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(POWERED, false).setValue(MODE, ComparatorMode.COMPARE));
|
|
}
|
|
|
|
@Override
|
|
protected int getDelay(BlockState state) {
|
|
return 2;
|
|
}
|
|
|
|
@Override
|
|
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos pos, BlockPos neighborPos) {
|
|
return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)
|
|
? Blocks.AIR.defaultBlockState()
|
|
: super.updateShape(state, direction, neighborState, level, pos, neighborPos);
|
|
}
|
|
|
|
@Override
|
|
protected int getOutputSignal(BlockGetter level, BlockPos pos, BlockState state) {
|
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
|
return blockEntity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity)blockEntity).getOutputSignal() : 0;
|
|
}
|
|
|
|
private int calculateOutputSignal(Level level, BlockPos pos, BlockState state) {
|
|
int i = this.getInputSignal(level, pos, state);
|
|
if (i == 0) {
|
|
return 0;
|
|
} else {
|
|
int j = this.getAlternateSignal(level, pos, state);
|
|
if (j > i) {
|
|
return 0;
|
|
} else {
|
|
return state.getValue(MODE) == ComparatorMode.SUBTRACT ? i - j : i;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected boolean shouldTurnOn(Level level, BlockPos pos, BlockState state) {
|
|
int i = this.getInputSignal(level, pos, state);
|
|
if (i == 0) {
|
|
return false;
|
|
} else {
|
|
int j = this.getAlternateSignal(level, pos, state);
|
|
return i > j ? true : i == j && state.getValue(MODE) == ComparatorMode.COMPARE;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected int getInputSignal(Level level, BlockPos pos, BlockState state) {
|
|
int i = super.getInputSignal(level, pos, state);
|
|
Direction direction = state.getValue(FACING);
|
|
BlockPos blockPos = pos.relative(direction);
|
|
BlockState blockState = level.getBlockState(blockPos);
|
|
if (blockState.hasAnalogOutputSignal()) {
|
|
i = blockState.getAnalogOutputSignal(level, blockPos);
|
|
} else if (i < 15 && blockState.isRedstoneConductor(level, blockPos)) {
|
|
blockPos = blockPos.relative(direction);
|
|
blockState = level.getBlockState(blockPos);
|
|
ItemFrame itemFrame = this.getItemFrame(level, direction, blockPos);
|
|
int j = Math.max(
|
|
itemFrame == null ? Integer.MIN_VALUE : itemFrame.getAnalogOutput(),
|
|
blockState.hasAnalogOutputSignal() ? blockState.getAnalogOutputSignal(level, blockPos) : Integer.MIN_VALUE
|
|
);
|
|
if (j != Integer.MIN_VALUE) {
|
|
i = j;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
@Nullable
|
|
private ItemFrame getItemFrame(Level level, Direction facing, BlockPos pos) {
|
|
List<ItemFrame> list = level.getEntitiesOfClass(
|
|
ItemFrame.class,
|
|
new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1),
|
|
itemFrame -> itemFrame != null && itemFrame.getDirection() == facing
|
|
);
|
|
return list.size() == 1 ? (ItemFrame)list.get(0) : null;
|
|
}
|
|
|
|
@Override
|
|
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
|
|
if (!player.getAbilities().mayBuild) {
|
|
return InteractionResult.PASS;
|
|
} else {
|
|
state = state.cycle(MODE);
|
|
float f = state.getValue(MODE) == ComparatorMode.SUBTRACT ? 0.55F : 0.5F;
|
|
level.playSound(player, pos, SoundEvents.COMPARATOR_CLICK, SoundSource.BLOCKS, 0.3F, f);
|
|
level.setBlock(pos, state, 2);
|
|
this.refreshOutputState(level, pos, state);
|
|
return InteractionResult.sidedSuccess(level.isClientSide);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void checkTickOnNeighbor(Level level, BlockPos pos, BlockState state) {
|
|
if (!level.getBlockTicks().willTickThisTick(pos, this)) {
|
|
int i = this.calculateOutputSignal(level, pos, state);
|
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
|
int j = blockEntity instanceof ComparatorBlockEntity ? ((ComparatorBlockEntity)blockEntity).getOutputSignal() : 0;
|
|
if (i != j || (Boolean)state.getValue(POWERED) != this.shouldTurnOn(level, pos, state)) {
|
|
TickPriority tickPriority = this.shouldPrioritize(level, pos, state) ? TickPriority.HIGH : TickPriority.NORMAL;
|
|
level.scheduleTick(pos, this, 2, tickPriority);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void refreshOutputState(Level level, BlockPos pos, BlockState state) {
|
|
int i = this.calculateOutputSignal(level, pos, state);
|
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
|
int j = 0;
|
|
if (blockEntity instanceof ComparatorBlockEntity comparatorBlockEntity) {
|
|
j = comparatorBlockEntity.getOutputSignal();
|
|
comparatorBlockEntity.setOutputSignal(i);
|
|
}
|
|
|
|
if (j != i || state.getValue(MODE) == ComparatorMode.COMPARE) {
|
|
boolean bl = this.shouldTurnOn(level, pos, state);
|
|
boolean bl2 = (Boolean)state.getValue(POWERED);
|
|
if (bl2 && !bl) {
|
|
level.setBlock(pos, state.setValue(POWERED, false), 2);
|
|
} else if (!bl2 && bl) {
|
|
level.setBlock(pos, state.setValue(POWERED, true), 2);
|
|
}
|
|
|
|
this.updateNeighborsInFront(level, pos, state);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
|
|
this.refreshOutputState(level, pos, state);
|
|
}
|
|
|
|
@Override
|
|
protected boolean triggerEvent(BlockState state, Level level, BlockPos pos, int id, int param) {
|
|
super.triggerEvent(state, level, pos, id, param);
|
|
BlockEntity blockEntity = level.getBlockEntity(pos);
|
|
return blockEntity != null && blockEntity.triggerEvent(id, param);
|
|
}
|
|
|
|
@Override
|
|
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
|
|
return new ComparatorBlockEntity(pos, state);
|
|
}
|
|
|
|
@Override
|
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
|
|
builder.add(FACING, MODE, POWERED);
|
|
}
|
|
}
|