Code/net/minecraft/world/level/block/RedstoneTorchBlock.java

159 lines
6.4 KiB
Java

package net.minecraft.world.level.block;
import com.google.common.collect.Lists;
import com.mojang.serialization.MapCodec;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.particles.DustParticleOptions;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
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.BooleanProperty;
import net.minecraft.world.level.redstone.ExperimentalRedstoneUtils;
import net.minecraft.world.level.redstone.Orientation;
public class RedstoneTorchBlock extends BaseTorchBlock {
public static final MapCodec<RedstoneTorchBlock> CODEC = simpleCodec(RedstoneTorchBlock::new);
public static final BooleanProperty LIT = BlockStateProperties.LIT;
private static final Map<BlockGetter, List<RedstoneTorchBlock.Toggle>> RECENT_TOGGLES = new WeakHashMap<>();
public static final int RECENT_TOGGLE_TIMER = 60;
public static final int MAX_RECENT_TOGGLES = 8;
public static final int RESTART_DELAY = 160;
private static final int TOGGLE_DELAY = 2;
@Override
public MapCodec<? extends RedstoneTorchBlock> codec() {
return CODEC;
}
protected RedstoneTorchBlock(BlockBehaviour.Properties p_55678_) {
super(p_55678_);
this.registerDefaultState(this.stateDefinition.any().setValue(LIT, true));
}
@Override
protected void onPlace(BlockState p_55724_, Level p_55725_, BlockPos p_55726_, BlockState p_55727_, boolean p_55728_) {
this.notifyNeighbors(p_55725_, p_55726_, p_55724_);
}
private void notifyNeighbors(Level p_369825_, BlockPos p_369455_, BlockState p_368137_) {
Orientation orientation = this.randomOrientation(p_369825_, p_368137_);
for (Direction direction : Direction.values()) {
p_369825_.updateNeighborsAt(p_369455_.relative(direction), this, ExperimentalRedstoneUtils.withFront(orientation, direction));
}
}
@Override
protected void affectNeighborsAfterRemoval(BlockState p_396570_, ServerLevel p_391552_, BlockPos p_392704_, boolean p_397552_) {
if (!p_397552_) {
this.notifyNeighbors(p_391552_, p_392704_, p_396570_);
}
}
@Override
protected int getSignal(BlockState p_55694_, BlockGetter p_55695_, BlockPos p_55696_, Direction p_55697_) {
return p_55694_.getValue(LIT) && Direction.UP != p_55697_ ? 15 : 0;
}
protected boolean hasNeighborSignal(Level p_55681_, BlockPos p_55682_, BlockState p_55683_) {
return p_55681_.hasSignal(p_55682_.below(), Direction.DOWN);
}
@Override
protected void tick(BlockState p_221949_, ServerLevel p_221950_, BlockPos p_221951_, RandomSource p_221952_) {
boolean flag = this.hasNeighborSignal(p_221950_, p_221951_, p_221949_);
List<RedstoneTorchBlock.Toggle> list = RECENT_TOGGLES.get(p_221950_);
while (list != null && !list.isEmpty() && p_221950_.getGameTime() - list.get(0).when > 60L) {
list.remove(0);
}
if (p_221949_.getValue(LIT)) {
if (flag) {
p_221950_.setBlock(p_221951_, p_221949_.setValue(LIT, false), 3);
if (isToggledTooFrequently(p_221950_, p_221951_, true)) {
p_221950_.levelEvent(1502, p_221951_, 0);
p_221950_.scheduleTick(p_221951_, p_221950_.getBlockState(p_221951_).getBlock(), 160);
}
}
} else if (!flag && !isToggledTooFrequently(p_221950_, p_221951_, false)) {
p_221950_.setBlock(p_221951_, p_221949_.setValue(LIT, true), 3);
}
}
@Override
protected void neighborChanged(BlockState p_55699_, Level p_55700_, BlockPos p_55701_, Block p_55702_, @Nullable Orientation p_368542_, boolean p_55704_) {
if (p_55699_.getValue(LIT) == this.hasNeighborSignal(p_55700_, p_55701_, p_55699_) && !p_55700_.getBlockTicks().willTickThisTick(p_55701_, this)) {
p_55700_.scheduleTick(p_55701_, this, 2);
}
}
@Override
protected int getDirectSignal(BlockState p_55719_, BlockGetter p_55720_, BlockPos p_55721_, Direction p_55722_) {
return p_55722_ == Direction.DOWN ? p_55719_.getSignal(p_55720_, p_55721_, p_55722_) : 0;
}
@Override
protected boolean isSignalSource(BlockState p_55730_) {
return true;
}
@Override
public void animateTick(BlockState p_221954_, Level p_221955_, BlockPos p_221956_, RandomSource p_221957_) {
if (p_221954_.getValue(LIT)) {
double d0 = p_221956_.getX() + 0.5 + (p_221957_.nextDouble() - 0.5) * 0.2;
double d1 = p_221956_.getY() + 0.7 + (p_221957_.nextDouble() - 0.5) * 0.2;
double d2 = p_221956_.getZ() + 0.5 + (p_221957_.nextDouble() - 0.5) * 0.2;
p_221955_.addParticle(DustParticleOptions.REDSTONE, d0, d1, d2, 0.0, 0.0, 0.0);
}
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_55717_) {
p_55717_.add(LIT);
}
private static boolean isToggledTooFrequently(Level p_55685_, BlockPos p_55686_, boolean p_55687_) {
List<RedstoneTorchBlock.Toggle> list = RECENT_TOGGLES.computeIfAbsent(p_55685_, p_55680_ -> Lists.newArrayList());
if (p_55687_) {
list.add(new RedstoneTorchBlock.Toggle(p_55686_.immutable(), p_55685_.getGameTime()));
}
int i = 0;
for (RedstoneTorchBlock.Toggle redstonetorchblock$toggle : list) {
if (redstonetorchblock$toggle.pos.equals(p_55686_)) {
if (++i >= 8) {
return true;
}
}
}
return false;
}
@Nullable
protected Orientation randomOrientation(Level p_362843_, BlockState p_364833_) {
return ExperimentalRedstoneUtils.initialOrientation(p_362843_, null, Direction.UP);
}
public static class Toggle {
final BlockPos pos;
final long when;
public Toggle(BlockPos p_55734_, long p_55735_) {
this.pos = p_55734_;
this.when = p_55735_;
}
}
}