minecraft-src/net/minecraft/world/level/block/ComparatorBlock.java
2025-07-04 01:41:11 +03:00

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);
}
}