Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ public DistanceDetectorRenderer(BlockEntityRendererProvider.Context pContext) {

@Override
public void render(@NotNull DistanceDetectorEntity pBlockEntity, float pPartialTick, @NotNull PoseStack pPoseStack, MultiBufferSource pBufferSource, int pPackedLight, int pPackedOverlay) {
if (pBlockEntity.getLaserVisibility())
renderBeaconBeam(pBlockEntity, pPoseStack, pBufferSource, BeaconRenderer.BEAM_LOCATION, pPartialTick, 1, 0, pBlockEntity.getCurrentDistance() - 0.5f, EnumColor.RED.getRgb(), 0.05f, 0.09f);
if (pBlockEntity.getLaserVisibility()) {
float distance = pBlockEntity.getCurrentDistance();
if (distance == -1) {
distance = pBlockEntity.getMaxRange();
}
renderBeaconBeam(pBlockEntity, pPoseStack, pBufferSource, BeaconRenderer.BEAM_LOCATION, pPartialTick, 1, 0, distance + 0.5f, EnumColor.RED.getRgb(), 0.05f, 0.09f);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ public final boolean ignoresTransparency() {

@LuaFunction
public final void setDetectionMode(int mode) {
if (mode > 2) mode = 2;
if (mode < 0) mode = 0;
mode = Math.min(Math.max(mode, 0), 2);
getPeripheralOwner().tileEntity.setDetectionType(DetectionType.values()[mode]);
}

Expand All @@ -66,12 +65,12 @@ public final String getDetectionMode() {

@LuaFunction
public final double getDistance() {
return getPeripheralOwner().tileEntity.getCurrentDistance() - 1;
return getPeripheralOwner().tileEntity.getCurrentDistance();
}

@LuaFunction
public final double calculateDistance() {
return getPeripheralOwner().tileEntity.calculateDistance() - 1;
return getPeripheralOwner().tileEntity.calculateAndUpdateDistance();
}

@LuaFunction
Expand All @@ -86,12 +85,12 @@ public final void setCalculatePeriodically(boolean shouldRenderPeriodically) {

@LuaFunction
public final void setMaxRange(double maxDistance) {
getPeripheralOwner().tileEntity.setMaxRange(Math.max(0, Math.min(APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get(), maxDistance)));
getPeripheralOwner().tileEntity.setMaxRange((float) maxDistance);
}

@LuaFunction
public final double getMaxRange() {
return getPeripheralOwner().tileEntity.getMaxDistance();
return getPeripheralOwner().tileEntity.getMaxRange();
}

public enum DetectionType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,12 @@ public CompoundTag getPeripheralSettings() {

@Override
public void markSettingsChanged() {
setChanged();
this.setChanged();
}

protected void sendUpdate() {
this.setChanged();
this.getLevel().sendBlockUpdated(this.getBlockPos(), this.getBlockState(), this.getBlockState(), 11);
}

public ComputerSide getComputerSide(Direction direction) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,34 @@
import de.srendi.advancedperipherals.common.blocks.base.PeripheralBlockEntity;
import de.srendi.advancedperipherals.common.configuration.APConfig;
import de.srendi.advancedperipherals.common.network.APNetworking;
import de.srendi.advancedperipherals.common.network.toclient.DistanceDetectorSyncPacket;
import de.srendi.advancedperipherals.common.setup.APBlockEntityTypes;
import de.srendi.advancedperipherals.common.util.HitResultUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.phys.*;

import org.jetbrains.annotations.NotNull;

import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

public class DistanceDetectorEntity extends PeripheralBlockEntity<DistanceDetectorPeripheral> {

private double maxRange = APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get();
private float currentDistance = 0;
private boolean showLaser = true;
private boolean shouldCalculatePeriodically = false;
private boolean ignoreTransparent = true;
private DistanceDetectorPeripheral.DetectionType detectionType = DistanceDetectorPeripheral.DetectionType.BOTH;
private final AtomicInteger maxRange = new AtomicInteger(Float.floatToRawIntBits(APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get().floatValue()));
private final AtomicInteger currentDistance = new AtomicInteger(Float.floatToRawIntBits(-1));
private final AtomicBoolean showLaser = new AtomicBoolean(true);
private volatile boolean periodicallyCalculate = false;
private volatile boolean ignoreTransparent = true;
private volatile DistanceDetectorPeripheral.DetectionType detectionType = DistanceDetectorPeripheral.DetectionType.BOTH;

public DistanceDetectorEntity(BlockPos pos, BlockState state) {
super(APBlockEntityTypes.DISTANCE_DETECTOR.get(), pos, state);
Expand All @@ -38,127 +44,170 @@ protected DistanceDetectorPeripheral createPeripheral() {
return new DistanceDetectorPeripheral(this);
}

public void setShowLaser(boolean showLaser) {
if (this.showLaser != showLaser)
APNetworking.sendToAll(new DistanceDetectorSyncPacket(getBlockPos(), getLevel().dimension(), currentDistance, showLaser));
this.showLaser = showLaser;
public float getMaxRange() {
return Float.intBitsToFloat(this.maxRange.get());
}

public void setCurrentDistance(float currentDistance) {
if (this.currentDistance != currentDistance)
APNetworking.sendToAll(new DistanceDetectorSyncPacket(getBlockPos(), getLevel().dimension(), currentDistance, showLaser));
this.currentDistance = currentDistance;
protected void setMaxRangeNoUpdate(float maxRange) {
maxRange = Math.min(Math.max(maxRange, 0), APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get().floatValue());
int maxRangeBits = Float.floatToRawIntBits(maxRange);
this.maxRange.set(maxRangeBits);
}

public void setShouldCalculatePeriodically(boolean shouldCalculatePeriodically) {
this.shouldCalculatePeriodically = shouldCalculatePeriodically;
public void setMaxRange(float maxRange) {
maxRange = Math.min(Math.max(maxRange, 0), APConfig.PERIPHERALS_CONFIG.distanceDetectorRange.get().floatValue());
int maxRangeBits = Float.floatToRawIntBits(maxRange);
if (this.maxRange.getAndSet(maxRangeBits) != maxRange) {
this.sendUpdate();
}
}

public double getMaxDistance() {
return maxRange;
public float getCurrentDistance() {
return Float.intBitsToFloat(this.currentDistance.get());
}

public void setMaxRange(double maxRange) {
this.maxRange = maxRange;
protected void setCurrentDistanceNoUpdate(float currentDistance) {
int currentDistanceBits = Float.floatToRawIntBits(currentDistance);
this.currentDistance.set(currentDistanceBits);
}

public float getCurrentDistance() {
return currentDistance;
public void setCurrentDistance(float currentDistance) {
int currentDistanceBits = Float.floatToRawIntBits(currentDistance);
if (this.currentDistance.getAndSet(currentDistanceBits) != currentDistanceBits) {
this.sendUpdate();
}
}

public boolean getLaserVisibility() {
return showLaser;
return this.showLaser.get();
}

protected void setShowLaserNoUpdate(boolean showLaser) {
this.showLaser.set(showLaser);
}

public void setShowLaser(boolean showLaser) {
if (this.showLaser.getAndSet(showLaser) != showLaser) {
this.sendUpdate();
}
}

public boolean shouldCalculatePeriodically() {
return shouldCalculatePeriodically;
return this.periodicallyCalculate;
}

public void setShouldCalculatePeriodically(boolean periodicallyCalculate) {
this.periodicallyCalculate = periodicallyCalculate;
this.setChanged();
}

public boolean ignoreTransparent() {
return ignoreTransparent;
return this.ignoreTransparent;
}

public void setIgnoreTransparent(boolean ignoreTransparent) {
this.ignoreTransparent = ignoreTransparent;
this.setChanged();
}

public DistanceDetectorPeripheral.DetectionType getDetectionType() {
return detectionType;
return this.detectionType;
}

public void setDetectionType(DistanceDetectorPeripheral.DetectionType detectionType) {
this.detectionType = detectionType;
this.setChanged();
}

@Override
public <T extends BlockEntity> void handleTick(Level level, BlockState state, BlockEntityType<T> type) {
if (level.getGameTime() % APConfig.PERIPHERALS_CONFIG.distanceDetectorUpdateRate.get() == 0 && shouldCalculatePeriodically) {
if (level.getGameTime() % APConfig.PERIPHERALS_CONFIG.distanceDetectorUpdateRate.get() == 0 && this.shouldCalculatePeriodically()) {
// We calculate the distance every 2 ticks, so we do not have to run the getDistance function of the peripheral
// on the main thread which prevents the 1 tick yield time of the function.
// The calculateDistance function is not thread safe, so we have to run it on the main thread.
// It should be okay to run that function every 2 ticks, calculating it does not take too much time.
calculateDistance();
this.calculateAndUpdateDistance();
}
}

@Override
public AABB getRenderBoundingBox() {
float currentDistance = this.getCurrentDistance();
if (currentDistance == -1) {
currentDistance = this.getMaxRange();
}
Direction direction = getBlockState().getValue(BaseBlock.ORIENTATION).front();
return AABB.ofSize(Vec3.atCenterOf(getBlockPos()), direction.getStepX() * currentDistance + 1, direction.getStepY() * currentDistance + 1, direction.getStepZ() * currentDistance + 1)
.move(direction.getStepX() * currentDistance / 2, direction.getStepY() * currentDistance / 2, direction.getStepZ() * currentDistance / 2);
.move(direction.getStepX() * currentDistance / 2, direction.getStepY() * currentDistance / 2, direction.getStepZ() * currentDistance / 2);
}

public double calculateDistance() {
Direction direction = getBlockState().getValue(BaseBlock.ORIENTATION).front();
Vec3 center = Vec3.atCenterOf(getBlockPos());
Vec3 from = center.add(direction.getStepX() * 0.501, direction.getStepY() * 0.501, direction.getStepZ() * 0.501);
Vec3 to = from.add(direction.getStepX() * maxRange, direction.getStepY() * maxRange, direction.getStepZ() * maxRange);
HitResult result = getResult(to, from);
@Override
public void load(@NotNull CompoundTag compound) {
this.setMaxRangeNoUpdate(compound.getFloat("maxRange"));
this.setCurrentDistanceNoUpdate(compound.getFloat("currentDistance"));
this.setShowLaserNoUpdate(compound.getBoolean("showLaser"));
this.setShouldCalculatePeriodically(compound.getBoolean("calculatePeriodically"));
this.setIgnoreTransparent(compound.getBoolean("ignoreTransparent"));
this.setDetectionType(DistanceDetectorPeripheral.DetectionType.values()[compound.getByte("detectionType")]);
super.load(compound);
}

float distance = calculateDistance(result, center, direction);
setCurrentDistance(distance);
return distance;
@Override
public void saveAdditional(@NotNull CompoundTag compound) {
super.saveAdditional(compound);
compound.putFloat("maxRange", this.getMaxRange());
compound.putFloat("currentDistance", this.getCurrentDistance());
compound.putBoolean("showLaser", this.getLaserVisibility());
compound.putBoolean("calculatePeriodically", this.shouldCalculatePeriodically());
compound.putBoolean("ignoreTransparent", this.ignoreTransparent());
compound.putByte("detectionType", (byte) this.getDetectionType().ordinal());
}

private HitResult getResult(Vec3 to, Vec3 from) {
if (detectionType == DistanceDetectorPeripheral.DetectionType.ENTITIES)
return HitResultUtil.getEntityHitResult(to, from, getLevel());
if (detectionType == DistanceDetectorPeripheral.DetectionType.BLOCK)
return HitResultUtil.getBlockHitResult(to, from, getLevel(), ignoreTransparent);
return HitResultUtil.getHitResult(to, from, getLevel(), ignoreTransparent);
@Override
public CompoundTag getUpdateTag() {
CompoundTag compound = super.getUpdateTag();
compound.putFloat("maxRange", this.getMaxRange());
compound.putFloat("currentDistance", this.getCurrentDistance());
compound.putBoolean("showLaser", this.getLaserVisibility());
return compound;
}

private float calculateDistance(HitResult result, Vec3 center, Direction direction) {
float distance = 0;
if (result.getType() != HitResult.Type.MISS) {
if (result instanceof BlockHitResult blockHitResult) {
BlockState resultBlock = getLevel().getBlockState(blockHitResult.getBlockPos());
distance = distManhattan(Vec3.atCenterOf(blockHitResult.getBlockPos()), center);
@Override
public ClientboundBlockEntityDataPacket getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}

distance = amendDistance(resultBlock, direction, distance);
}
if (result instanceof EntityHitResult entityHitResult) {
distance = distManhattan(entityHitResult.getLocation(), center);
}
public double calculateDistance() {
final double maxRange = this.getMaxRange();
Direction direction = getBlockState().getValue(BaseBlock.ORIENTATION).front();
Vec3 center = Vec3.atCenterOf(getBlockPos());
Vec3 from = center;
Vec3 to = from.add(direction.getStepX() * maxRange, direction.getStepY() * maxRange, direction.getStepZ() * maxRange);

HitResult result = this.getHitResult(to, from);
if (result.getType() == HitResult.Type.MISS) {
return -1;
}
return distance;
return getDistanceOnDirection(direction, result.getLocation(), center) - 0.5f;
}

private float amendDistance(BlockState resultBlock, Direction direction, float distance) {
if (resultBlock.getBlock() instanceof SlabBlock && direction.getAxis() == Direction.Axis.Y) {
SlabType type = resultBlock.getValue(SlabBlock.TYPE);
if (type == SlabType.TOP && direction == Direction.UP)
return distance + 0.5f;
if (type == SlabType.BOTTOM && direction == Direction.DOWN)
return distance - 0.5f;
}
public double calculateAndUpdateDistance() {
double distance = this.calculateDistance();
this.setCurrentDistance((float) distance);
return distance;
}

private float distManhattan(Vec3 from, Vec3 to) {
float f = (float) Math.abs(from.x - to.x);
float f1 = (float) Math.abs(from.y - to.y);
float f2 = (float) Math.abs(from.z - to.z);
return f + f1 + f2;
private HitResult getHitResult(Vec3 to, Vec3 from) {
Level level = this.getLevel();
return switch (this.detectionType) {
case ENTITIES -> HitResultUtil.getEntityHitResult(to, from, level);
case BLOCK -> HitResultUtil.getBlockHitResult(to, from, level, this.ignoreTransparent);
default -> HitResultUtil.getHitResult(to, from, level, this.ignoreTransparent);
};
}

private static float getDistanceOnDirection(Direction direction, Vec3 from, Vec3 to) {
Direction.Axis axis = direction.getAxis();
return Math.abs((float)(axis.choose(from.x, from.y, from.z) - axis.choose(to.x, to.y, to.z)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import de.srendi.advancedperipherals.AdvancedPeripherals;
import de.srendi.advancedperipherals.common.network.base.IPacket;
import de.srendi.advancedperipherals.common.network.toclient.DistanceDetectorSyncPacket;
import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectBulkSyncPacket;
import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectClearPacket;
import de.srendi.advancedperipherals.common.network.toclient.RenderableObjectDeletePacket;
Expand Down Expand Up @@ -39,7 +38,6 @@ public class APNetworking {
private static int index = 0;

public static void init() {
registerServerToClient(DistanceDetectorSyncPacket.class, DistanceDetectorSyncPacket::decode);
registerServerToClient(SaddleTurtleInfoPacket.class, SaddleTurtleInfoPacket::decode);
registerServerToClient(ToastToClientPacket.class, ToastToClientPacket::decode);
registerServerToClient(RenderableObjectSyncPacket.class, RenderableObjectSyncPacket::decode);
Expand Down
Loading
Loading