minecraft-src/net/minecraft/world/level/block/entity/SculkSensorBlockEntity.java
2025-07-04 03:45:38 +03:00

141 lines
5 KiB
Java

package net.minecraft.world.level.block.entity;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.SculkSensorBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.BlockPositionSource;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.PositionSource;
import net.minecraft.world.level.gameevent.GameEvent.Context;
import net.minecraft.world.level.gameevent.GameEventListener.Provider;
import net.minecraft.world.level.gameevent.vibrations.VibrationSystem;
import org.jetbrains.annotations.Nullable;
public class SculkSensorBlockEntity extends BlockEntity implements Provider<VibrationSystem.Listener>, VibrationSystem {
private static final int DEFAULT_LAST_VIBRATION_FREQUENCY = 0;
private VibrationSystem.Data vibrationData;
private final VibrationSystem.Listener vibrationListener;
private final VibrationSystem.User vibrationUser;
private int lastVibrationFrequency = 0;
protected SculkSensorBlockEntity(BlockEntityType<?> blockEntityType, BlockPos blockPos, BlockState blockState) {
super(blockEntityType, blockPos, blockState);
this.vibrationUser = this.createVibrationUser();
this.vibrationData = new VibrationSystem.Data();
this.vibrationListener = new VibrationSystem.Listener(this);
}
public SculkSensorBlockEntity(BlockPos pos, BlockState blockState) {
this(BlockEntityType.SCULK_SENSOR, pos, blockState);
}
public VibrationSystem.User createVibrationUser() {
return new SculkSensorBlockEntity.VibrationUser(this.getBlockPos());
}
@Override
protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.loadAdditional(tag, registries);
this.lastVibrationFrequency = tag.getIntOr("last_vibration_frequency", 0);
RegistryOps<Tag> registryOps = registries.createSerializationContext(NbtOps.INSTANCE);
this.vibrationData = (VibrationSystem.Data)tag.read("listener", VibrationSystem.Data.CODEC, registryOps).orElseGet(VibrationSystem.Data::new);
}
@Override
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) {
super.saveAdditional(tag, registries);
tag.putInt("last_vibration_frequency", this.lastVibrationFrequency);
RegistryOps<Tag> registryOps = registries.createSerializationContext(NbtOps.INSTANCE);
tag.store("listener", VibrationSystem.Data.CODEC, registryOps, this.vibrationData);
}
@Override
public VibrationSystem.Data getVibrationData() {
return this.vibrationData;
}
@Override
public VibrationSystem.User getVibrationUser() {
return this.vibrationUser;
}
public int getLastVibrationFrequency() {
return this.lastVibrationFrequency;
}
public void setLastVibrationFrequency(int lastVibrationFrequency) {
this.lastVibrationFrequency = lastVibrationFrequency;
}
public VibrationSystem.Listener getListener() {
return this.vibrationListener;
}
protected class VibrationUser implements VibrationSystem.User {
public static final int LISTENER_RANGE = 8;
protected final BlockPos blockPos;
private final PositionSource positionSource;
public VibrationUser(final BlockPos pos) {
this.blockPos = pos;
this.positionSource = new BlockPositionSource(pos);
}
@Override
public int getListenerRadius() {
return 8;
}
@Override
public PositionSource getPositionSource() {
return this.positionSource;
}
@Override
public boolean canTriggerAvoidVibration() {
return true;
}
@Override
public boolean canReceiveVibration(ServerLevel level, BlockPos pos, Holder<GameEvent> gameEvent, @Nullable Context context) {
if (!pos.equals(this.blockPos) || !gameEvent.is(GameEvent.BLOCK_DESTROY) && !gameEvent.is(GameEvent.BLOCK_PLACE)) {
return VibrationSystem.getGameEventFrequency(gameEvent) == 0 ? false : SculkSensorBlock.canActivate(SculkSensorBlockEntity.this.getBlockState());
} else {
return false;
}
}
@Override
public void onReceiveVibration(
ServerLevel level, BlockPos pos, Holder<GameEvent> gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance
) {
BlockState blockState = SculkSensorBlockEntity.this.getBlockState();
if (SculkSensorBlock.canActivate(blockState)) {
int i = VibrationSystem.getGameEventFrequency(gameEvent);
SculkSensorBlockEntity.this.setLastVibrationFrequency(i);
int j = VibrationSystem.getRedstoneStrengthForDistance(distance, this.getListenerRadius());
if (blockState.getBlock() instanceof SculkSensorBlock sculkSensorBlock) {
sculkSensorBlock.activate(entity, level, this.blockPos, blockState, j, i);
}
}
}
@Override
public void onDataChanged() {
SculkSensorBlockEntity.this.setChanged();
}
@Override
public boolean requiresAdjacentChunksToBeTicking() {
return true;
}
}
}