Do some reliability improvements

This commit is contained in:
grimmauld 2021-04-20 01:15:38 +02:00
parent 2b3fb358ad
commit 19129c321f
5 changed files with 100 additions and 86 deletions

View file

@ -2,7 +2,6 @@ package com.simibubi.create.content.optics;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -12,19 +11,19 @@ import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.item.DyeColor; import net.minecraft.item.DyeColor;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3d;
public class Beam extends ArrayList<BeamSegment> { public class Beam extends ArrayList<BeamSegment> {
private final Set<ILightHandler<?>> lightEventListeners; private final Set<ILightHandler<?>> lightEventListeners;
private final Vector3d direction;
@Nullable @Nullable
private final Beam parent; private final Beam parent;
private boolean removed = false;
public Beam(@Nullable Beam parent, Vector3d direction) { public Beam(@Nullable Beam parent) {
super(); super();
this.parent = parent; this.parent = parent;
this.direction = direction;
lightEventListeners = new HashSet<>(); lightEventListeners = new HashSet<>();
} }
@ -43,8 +42,22 @@ public class Beam extends ArrayList<BeamSegment> {
lightEventListeners.add(tile); lightEventListeners.add(tile);
} }
@Nullable
public Vector3d getDirection() { 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 @Override
@ -53,15 +66,14 @@ public class Beam extends ArrayList<BeamSegment> {
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false; if (!super.equals(o)) return false;
Beam that = (Beam) o; Beam that = (Beam) o;
return lightEventListeners.equals(that.lightEventListeners) && Objects.equals(direction, that.direction); return lightEventListeners.equals(that.lightEventListeners);
} }
public boolean isRemoved() { public boolean isRemoved() {
return isEmpty() || get(0).getHandler() // || !get(0).getHandler().getOutBeams().contains(this)
.getTile() TileEntity handler = getHandler();
.isRemoved() || !get(0).getHandler() removed = removed || isEmpty() || handler == null || handler.isRemoved() || (parent != null && parent.isRemoved());
.getOutBeams() return removed;
.contains(this) || (parent != null && parent.isRemoved());
} }
public float[] getColorAt(BlockPos testBlockPos) { public float[] getColorAt(BlockPos testBlockPos) {

View file

@ -1,7 +1,6 @@
package com.simibubi.create.content.optics; package com.simibubi.create.content.optics;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -22,20 +21,19 @@ import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> { public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
@Nullable
default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection) { default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection) {
return constructOutBeam(parent, beamDirection, getTile().getPos()); return constructOutBeam(parent, beamDirection, getTile().getPos());
} }
@Nullable
default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection, BlockPos testBlockPos) { default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection, BlockPos testBlockPos) {
Beam beam = new Beam(parent);
float[] segmentColor = parent == null ? DyeColor.WHITE.getColorComponentValues() : parent.getColorAt(testBlockPos);
World world = getTile().getWorld(); World world = getTile().getWorld();
if (world == null) if (world == null)
return null; return beam;
float[] segmentColor = parent == null ? DyeColor.WHITE.getColorComponentValues() : parent.getColorAt(testBlockPos);
Vector3d direction = VecHelper.step(beamDirection); Vector3d direction = VecHelper.step(beamDirection);
Beam beam = new Beam(parent, direction);
Vector3d testPos = VecHelper.getCenterOf(testBlockPos); Vector3d testPos = VecHelper.getCenterOf(testBlockPos);
BeamSegment segment = new BeamSegment(this, segmentColor, testPos, direction); BeamSegment segment = new BeamSegment(this, segmentColor, testPos, direction);
@ -54,9 +52,6 @@ public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
if (newColor == null) { if (newColor == null) {
if (testState.getOpacity(world, testBlockPos) >= 15 && testState.getBlock() != Blocks.BEDROCK || (lightHandler != null && !lightHandler.canLightPass())) { if (testState.getOpacity(world, testBlockPos) >= 15 && testState.getBlock() != Blocks.BEDROCK || (lightHandler != null && !lightHandler.canLightPass())) {
if (lightHandler != null) {
lightHandler.setColor(segmentColor);
}
break; break;
} }
} else if (!Arrays.equals(segmentColor, newColor)) { } else if (!Arrays.equals(segmentColor, newColor)) {
@ -72,9 +67,6 @@ public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
T getTile(); T getTile();
default void setColor(float[] segmentColor) {
}
@Nullable @Nullable
default Direction getBeamRotationAround() { default Direction getBeamRotationAround() {
return null; return null;
@ -92,7 +84,5 @@ public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
return false; return false;
} }
default Collection<Beam> getOutBeams() { default void updateBeams(){}
return Collections.emptySet();
}
} }

View file

@ -1,10 +1,11 @@
package com.simibubi.create.content.optics.mirror; package com.simibubi.create.content.optics.mirror;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream; import java.util.stream.Stream;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@ -112,24 +113,28 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
if (beacon != null) { if (beacon != null) {
beaconBeam = constructOutBeam(null, VecHelper.UP, beacon.getPos()); beaconBeam = constructOutBeam(null, VecHelper.UP, beacon.getPos());
if (beaconBeam != null) { if (beaconBeam != null && !beaconBeam.isEmpty()) {
beaconBeam.addListener(this); beaconBeam.addListener(this);
beaconBeam.onCreated(); beaconBeam.onCreated();
} }
} }
} }
private void updateBeams() { @Override
public void updateBeams() {
Map<Beam, Beam> newBeams = new HashMap<>(); Map<Beam, Beam> newBeams = new HashMap<>();
for (Map.Entry<Beam, Beam> entry : beams.entrySet()) { for (Map.Entry<Beam, Beam> entry : beams.entrySet()) {
entry.getValue()
.onRemoved();
if (entry.getKey() if (entry.getKey()
.isRemoved()) .isRemoved())
continue; continue;
Beam reflected = reflectBeam(entry.getKey()); Beam reflected = reflectBeam(entry.getKey());
if (reflected != null) { if (reflected != null && !reflected.isEmpty()) {
newBeams.put(entry.getKey(), reflected); newBeams.put(entry.getKey(), reflected);
reflected.onCreated(); reflected.onCreated();
entry.getKey()
.addListener(this);
} }
} }
beams = newBeams; beams = newBeams;
@ -138,7 +143,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
private Vector3d getReflectionAngle(Vector3d inputAngle) { private Vector3d getReflectionAngle(Vector3d inputAngle) {
inputAngle = inputAngle.normalize(); inputAngle = inputAngle.normalize();
Vector3d normal = new Matrix3d().asIdentity() Vector3d normal = new Matrix3d().asIdentity()
.asAxisRotation(getAxis(), AngleHelper.rad(angle)) .asAxisRotation(getBlockState().get(BlockStateProperties.AXIS), AngleHelper.rad(angle))
.transform(VecHelper.UP); .transform(VecHelper.UP);
return inputAngle.subtract(normal.scale(2 * inputAngle.dotProduct(normal))); return inputAngle.subtract(normal.scale(2 * inputAngle.dotProduct(normal)));
} }
@ -160,26 +165,10 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
return this; return this;
} }
@Override
public void setColor(float[] initialColor) {
}
@Nonnull @Nonnull
@Override @Override
public Direction getBeamRotationAround() { public Direction getBeamRotationAround() {
return Direction.getFacingFromAxisDirection(getAxis(), Direction.AxisDirection.POSITIVE); return Direction.getFacingFromAxisDirection(getBlockState().get(BlockStateProperties.AXIS), Direction.AxisDirection.POSITIVE);
}
public float getAngle() {
return angle;
}
public void setAngle(float forcedAngle) {
angle = forcedAngle;
}
private Direction.Axis getAxis() {
return getBlockState().get(BlockStateProperties.AXIS);
} }
@Override @Override
@ -206,13 +195,13 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
public Stream<Beam> constructSubBeams(Beam beam) { public Stream<Beam> constructSubBeams(Beam beam) {
if (beams.keySet() if (beams.keySet()
.stream() .stream()
.filter(((Predicate<Beam>) Beam::isRemoved).negate())
.map(Beam::getDirection) .map(Beam::getDirection)
.map(Vector3d::normalize) .filter(Objects::nonNull)
.anyMatch(beam.getDirection() .anyMatch(b -> b.equals(beam.getDirection())))
.normalize()::equals))
return Stream.empty(); return Stream.empty();
Beam reflected = reflectBeam(beam); Beam reflected = reflectBeam(beam);
if (reflected != null) { if (reflected != null && !reflected.isEmpty()) {
beams.put(beam, reflected); beams.put(beam, reflected);
beam.addListener(this); beam.addListener(this);
return Stream.of(reflected); return Stream.of(reflected);
@ -220,23 +209,17 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
return Stream.empty(); return Stream.empty();
} }
@Nullable
private Beam reflectBeam(Beam beam) { private Beam reflectBeam(Beam beam) {
Vector3d inDir = beam.getDirection() Vector3d inDir = beam.getDirection();
.normalize(); if (inDir == null)
return null;
Vector3d outDir = getReflectionAngle(inDir).normalize(); Vector3d outDir = getReflectionAngle(inDir).normalize();
if (inDir.subtract(outDir) if (inDir.subtract(outDir)
.normalize() == Vector3d.ZERO) .normalize() == Vector3d.ZERO)
return null; return null;
// TE already has input beam at that direction
return constructOutBeam(beam, outDir); return constructOutBeam(beam, outDir);
} }
@Override
public Collection<Beam> getOutBeams() {
return beams.keySet();
}
} }

View file

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

View file

@ -5,19 +5,22 @@
"compatibilityLevel": "JAVA_8", "compatibilityLevel": "JAVA_8",
"refmap": "create.refmap.json", "refmap": "create.refmap.json",
"client": [ "client": [
"TileWorldHookMixin",
"CancelTileEntityRenderMixin", "CancelTileEntityRenderMixin",
"EntityContraptionInteractionMixin",
"FogColorTrackerMixin", "FogColorTrackerMixin",
"LightUpdateMixin", "LightUpdateMixin",
"NetworkLightUpdateMixin", "NetworkLightUpdateMixin",
"RenderHooksMixin", "RenderHooksMixin",
"ShaderCloseMixin", "ShaderCloseMixin",
"StoreProjectionMatrixMixin",
"TileRemoveMixin", "TileRemoveMixin",
"EntityContraptionInteractionMixin", "TileWorldHookMixin"
"StoreProjectionMatrixMixin"
], ],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
}, },
"minVersion": "0.8" "minVersion": "0.8",
"mixins": [
"LightHandlersAreSolidToBeaconsMixin"
]
} }