diff --git a/src/main/java/com/simibubi/create/content/optics/Beam.java b/src/main/java/com/simibubi/create/content/optics/Beam.java index 6d46f963d..3eba0e18d 100644 --- a/src/main/java/com/simibubi/create/content/optics/Beam.java +++ b/src/main/java/com/simibubi/create/content/optics/Beam.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.optics; import java.util.ArrayList; import java.util.HashSet; -import java.util.Objects; import java.util.Set; import javax.annotation.Nullable; @@ -12,19 +11,19 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.item.DyeColor; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; public class Beam extends ArrayList { private final Set> lightEventListeners; - private final Vector3d direction; @Nullable private final Beam parent; + private boolean removed = false; - public Beam(@Nullable Beam parent, Vector3d direction) { + public Beam(@Nullable Beam parent) { super(); this.parent = parent; - this.direction = direction; lightEventListeners = new HashSet<>(); } @@ -43,8 +42,22 @@ public class Beam extends ArrayList { lightEventListeners.add(tile); } + @Nullable public Vector3d getDirection() { - return direction; + return isEmpty() ? null : get(0).getNormalized(); + } + + public void onRemoved() { + removed = true; + lightEventListeners.stream() + .filter(handler -> handler != this.getHandler()) + .forEach(ILightHandler::updateBeams); + } + + @Nullable + public TileEntity getHandler() { + return size() == 0 ? null : get(0).getHandler() + .getTile(); } @Override @@ -53,15 +66,14 @@ public class Beam extends ArrayList { if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; Beam that = (Beam) o; - return lightEventListeners.equals(that.lightEventListeners) && Objects.equals(direction, that.direction); + return lightEventListeners.equals(that.lightEventListeners); } public boolean isRemoved() { - return isEmpty() || get(0).getHandler() - .getTile() - .isRemoved() || !get(0).getHandler() - .getOutBeams() - .contains(this) || (parent != null && parent.isRemoved()); + // || !get(0).getHandler().getOutBeams().contains(this) + TileEntity handler = getHandler(); + removed = removed || isEmpty() || handler == null || handler.isRemoved() || (parent != null && parent.isRemoved()); + return removed; } public float[] getColorAt(BlockPos testBlockPos) { diff --git a/src/main/java/com/simibubi/create/content/optics/ILightHandler.java b/src/main/java/com/simibubi/create/content/optics/ILightHandler.java index 8c3dbd910..33cfab433 100644 --- a/src/main/java/com/simibubi/create/content/optics/ILightHandler.java +++ b/src/main/java/com/simibubi/create/content/optics/ILightHandler.java @@ -1,7 +1,6 @@ package com.simibubi.create.content.optics; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.stream.Stream; @@ -22,20 +21,19 @@ import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; public interface ILightHandler> { - @Nullable default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection) { return constructOutBeam(parent, beamDirection, getTile().getPos()); } - @Nullable default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection, BlockPos testBlockPos) { - - float[] segmentColor = parent == null ? DyeColor.WHITE.getColorComponentValues() : parent.getColorAt(testBlockPos); + Beam beam = new Beam(parent); World world = getTile().getWorld(); if (world == null) - return null; + return beam; + + float[] segmentColor = parent == null ? DyeColor.WHITE.getColorComponentValues() : parent.getColorAt(testBlockPos); Vector3d direction = VecHelper.step(beamDirection); - Beam beam = new Beam(parent, direction); + Vector3d testPos = VecHelper.getCenterOf(testBlockPos); BeamSegment segment = new BeamSegment(this, segmentColor, testPos, direction); @@ -54,9 +52,6 @@ public interface ILightHandler> { if (newColor == null) { if (testState.getOpacity(world, testBlockPos) >= 15 && testState.getBlock() != Blocks.BEDROCK || (lightHandler != null && !lightHandler.canLightPass())) { - if (lightHandler != null) { - lightHandler.setColor(segmentColor); - } break; } } else if (!Arrays.equals(segmentColor, newColor)) { @@ -72,9 +67,6 @@ public interface ILightHandler> { T getTile(); - default void setColor(float[] segmentColor) { - } - @Nullable default Direction getBeamRotationAround() { return null; @@ -92,7 +84,5 @@ public interface ILightHandler> { return false; } - default Collection getOutBeams() { - return Collections.emptySet(); - } + default void updateBeams(){} } diff --git a/src/main/java/com/simibubi/create/content/optics/mirror/MirrorTileEntity.java b/src/main/java/com/simibubi/create/content/optics/mirror/MirrorTileEntity.java index a184d7ced..1353eb466 100644 --- a/src/main/java/com/simibubi/create/content/optics/mirror/MirrorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/optics/mirror/MirrorTileEntity.java @@ -1,10 +1,11 @@ package com.simibubi.create.content.optics.mirror; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Objects; +import java.util.function.Predicate; import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -112,24 +113,28 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler if (beacon != null) { beaconBeam = constructOutBeam(null, VecHelper.UP, beacon.getPos()); - if (beaconBeam != null) { + if (beaconBeam != null && !beaconBeam.isEmpty()) { beaconBeam.addListener(this); beaconBeam.onCreated(); } } } - private void updateBeams() { + @Override + public void updateBeams() { Map newBeams = new HashMap<>(); for (Map.Entry entry : beams.entrySet()) { + entry.getValue() + .onRemoved(); if (entry.getKey() .isRemoved()) continue; - Beam reflected = reflectBeam(entry.getKey()); - if (reflected != null) { + if (reflected != null && !reflected.isEmpty()) { newBeams.put(entry.getKey(), reflected); reflected.onCreated(); + entry.getKey() + .addListener(this); } } beams = newBeams; @@ -138,7 +143,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler private Vector3d getReflectionAngle(Vector3d inputAngle) { inputAngle = inputAngle.normalize(); Vector3d normal = new Matrix3d().asIdentity() - .asAxisRotation(getAxis(), AngleHelper.rad(angle)) + .asAxisRotation(getBlockState().get(BlockStateProperties.AXIS), AngleHelper.rad(angle)) .transform(VecHelper.UP); return inputAngle.subtract(normal.scale(2 * inputAngle.dotProduct(normal))); } @@ -160,26 +165,10 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler return this; } - @Override - public void setColor(float[] initialColor) { - } - @Nonnull @Override public Direction getBeamRotationAround() { - return Direction.getFacingFromAxisDirection(getAxis(), Direction.AxisDirection.POSITIVE); - } - - public float getAngle() { - return angle; - } - - public void setAngle(float forcedAngle) { - angle = forcedAngle; - } - - private Direction.Axis getAxis() { - return getBlockState().get(BlockStateProperties.AXIS); + return Direction.getFacingFromAxisDirection(getBlockState().get(BlockStateProperties.AXIS), Direction.AxisDirection.POSITIVE); } @Override @@ -206,13 +195,13 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler public Stream constructSubBeams(Beam beam) { if (beams.keySet() .stream() + .filter(((Predicate) Beam::isRemoved).negate()) .map(Beam::getDirection) - .map(Vector3d::normalize) - .anyMatch(beam.getDirection() - .normalize()::equals)) + .filter(Objects::nonNull) + .anyMatch(b -> b.equals(beam.getDirection()))) return Stream.empty(); Beam reflected = reflectBeam(beam); - if (reflected != null) { + if (reflected != null && !reflected.isEmpty()) { beams.put(beam, reflected); beam.addListener(this); return Stream.of(reflected); @@ -220,23 +209,17 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler return Stream.empty(); } - + @Nullable private Beam reflectBeam(Beam beam) { - Vector3d inDir = beam.getDirection() - .normalize(); + Vector3d inDir = beam.getDirection(); + if (inDir == null) + return null; + Vector3d outDir = getReflectionAngle(inDir).normalize(); if (inDir.subtract(outDir) .normalize() == Vector3d.ZERO) return null; - - // TE already has input beam at that direction - return constructOutBeam(beam, outDir); } - - @Override - public Collection getOutBeams() { - return beams.keySet(); - } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/LightHandlersAreSolidToBeaconsMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/LightHandlersAreSolidToBeaconsMixin.java new file mode 100644 index 000000000..0f22aa4af --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/LightHandlersAreSolidToBeaconsMixin.java @@ -0,0 +1,26 @@ +package com.simibubi.create.foundation.mixin; + +import com.simibubi.create.content.optics.ILightHandler; +import com.simibubi.create.foundation.block.ITE; + +import net.minecraft.block.BlockState; +import net.minecraft.tileentity.BeaconTileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockReader; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(BeaconTileEntity.class) +public abstract class LightHandlersAreSolidToBeaconsMixin { + @Redirect(at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getOpacity(Lnet/minecraft/world/IBlockReader;Lnet/minecraft/util/math/BlockPos;)I"), method = "tick()V") + private int getCorrectedOpacity(BlockState state, IBlockReader world, BlockPos pos) { + try { + if (state.getBlock() instanceof ITE && ((ITE) state.getBlock()).getTileEntity(world, pos) instanceof ILightHandler) + return 15; + } catch (ITE.TileEntityException ignored) { + } + return state.getOpacity(world, pos); + } +} diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 6e988aa5a..897d4b642 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -1,23 +1,26 @@ { - "required": true, - "priority": 1100, - "package": "com.simibubi.create.foundation.mixin", - "compatibilityLevel": "JAVA_8", - "refmap": "create.refmap.json", - "client": [ - "TileWorldHookMixin", - "CancelTileEntityRenderMixin", - "FogColorTrackerMixin", - "LightUpdateMixin", - "NetworkLightUpdateMixin", - "RenderHooksMixin", - "ShaderCloseMixin", - "TileRemoveMixin", - "EntityContraptionInteractionMixin", - "StoreProjectionMatrixMixin" - ], - "injectors": { - "defaultRequire": 1 - }, - "minVersion": "0.8" + "required": true, + "priority": 1100, + "package": "com.simibubi.create.foundation.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "create.refmap.json", + "client": [ + "CancelTileEntityRenderMixin", + "EntityContraptionInteractionMixin", + "FogColorTrackerMixin", + "LightUpdateMixin", + "NetworkLightUpdateMixin", + "RenderHooksMixin", + "ShaderCloseMixin", + "StoreProjectionMatrixMixin", + "TileRemoveMixin", + "TileWorldHookMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8", + "mixins": [ + "LightHandlersAreSolidToBeaconsMixin" + ] }