Fix a bunch of stuff, mirroring colors now works correctly

This commit is contained in:
grimmauld 2021-04-19 18:27:53 +02:00
parent 5d54ed4682
commit 2b3fb358ad
4 changed files with 81 additions and 72 deletions

View file

@ -8,44 +8,33 @@ import java.util.Set;
import javax.annotation.Nullable;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.item.DyeColor;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
public class Beam extends ArrayList<BeamSegment> {
public final Set<Beam> subBeams;
private final Set<ILightHandler<?>> lightEventListeners;
private final Vector3d direction;
private boolean removed = false;
@Nullable
private final Beam parent;
public Beam(Vector3d direction) {
public Beam(@Nullable Beam parent, Vector3d direction) {
super();
this.parent = parent;
this.direction = direction;
lightEventListeners = new HashSet<>();
subBeams = new HashSet<>();
}
public void onRemoved() {
lightEventListeners.forEach(handler -> handler.onBeamRemoved(this));
subBeams.forEach(Beam::onRemoved);
subBeams.clear();
removed = true;
clear();
}
public void onCreated() {
lightEventListeners.stream()
.flatMap(handler -> handler.constructSubBeams(this))
.forEach(subBeams::add);
}
public void registerSubBeam(Beam beam) {
subBeams.add(beam);
.forEach(Beam::onCreated);
}
public void render(MatrixStack ms, IRenderTypeBuffer buffer, float partialTicks) {
if (removed)
throw new IllegalStateException("tried to render removed beam");
forEach(beamSegment -> beamSegment.renderSegment(ms, buffer, partialTicks));
}
@ -64,11 +53,28 @@ public class Beam extends ArrayList<BeamSegment> {
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
Beam that = (Beam) o;
return removed == that.removed && subBeams.equals(that.subBeams) && lightEventListeners.equals(that.lightEventListeners) && Objects.equals(direction, that.direction);
return lightEventListeners.equals(that.lightEventListeners) && Objects.equals(direction, that.direction);
}
public void removeSubBeam(Beam out) {
if (subBeams.remove(out))
out.onRemoved();
public boolean isRemoved() {
return isEmpty() || get(0).getHandler()
.getTile()
.isRemoved() || !get(0).getHandler()
.getOutBeams()
.contains(this) || (parent != null && parent.isRemoved());
}
public float[] getColorAt(BlockPos testBlockPos) {
float[] out = DyeColor.WHITE.getColorComponentValues();
for (BeamSegment segment : this) {
if (VecHelper.getCenterOf(testBlockPos)
.subtract(segment.getStart())
.dotProduct(segment.getNormalized()) > 0)
out = segment.getColors();
else
break;
}
return out;
}
}

View file

@ -120,16 +120,12 @@ public class BeamSegment {
beaconBeamModifier = Quaternion.IDENTITY;
} else {
Vector3f unitVec = axis.getUnitVector();
beaconBeamModifier = unitVec.getRadialQuaternion((float) (-Math.acos(dotProd) * Math.signum(new Vector3d(unitVec).dotProduct(getNormalized().crossProduct(UP)))));
beaconBeamModifier = unitVec.getRadialQuaternion((float) Math.acos(dotProd) * (new Vector3d(unitVec).dotProduct(getNormalized().crossProduct(UP)) > 0 ? -1 : 1));
}
}
return beaconBeamModifier;
}
public double getTotalSectionLength() {
return totalSectionLength.getValue();
}
public long getWorldTick() {
World world = getHandler()
.getTile()

View file

@ -1,6 +1,7 @@
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,19 +23,19 @@ import net.minecraft.world.World;
public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
@Nullable
default Beam constructOutBeam(Vector3d beamDirection) {
return constructOutBeam(beamDirection, getTile().getPos());
default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection) {
return constructOutBeam(parent, beamDirection, getTile().getPos());
}
@Nullable
default Beam constructOutBeam(Vector3d beamDirection, BlockPos testBlockPos) {
default Beam constructOutBeam(@Nullable Beam parent, Vector3d beamDirection, BlockPos testBlockPos) {
float[] segmentColor = getSegmentStartColor();
float[] segmentColor = parent == null ? DyeColor.WHITE.getColorComponentValues() : parent.getColorAt(testBlockPos);
World world = getTile().getWorld();
if (world == null)
return null;
Vector3d direction = VecHelper.step(beamDirection);
Beam beam = new Beam(direction);
Beam beam = new Beam(parent, direction);
Vector3d testPos = VecHelper.getCenterOf(testBlockPos);
BeamSegment segment = new BeamSegment(this, segmentColor, testPos, direction);
@ -74,18 +75,11 @@ public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
default void setColor(float[] segmentColor) {
}
default float[] getSegmentStartColor() {
return DyeColor.WHITE.getColorComponentValues();
}
@Nullable
default Direction getBeamRotationAround() {
return null;
}
default void onBeamRemoved(Beam beam) {
}
default Stream<Beam> constructSubBeams(Beam beam) {
return Stream.empty();
}
@ -97,4 +91,8 @@ public interface ILightHandler<T extends SmartTileEntity & ILightHandler<T>> {
default boolean canLightPass() {
return false;
}
default Collection<Beam> getOutBeams() {
return Collections.emptySet();
}
}

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.optics.mirror;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
@ -20,7 +21,6 @@ import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.BlockState;
import net.minecraft.item.DyeColor;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.BeaconTileEntity;
@ -40,7 +40,6 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
@Nullable
private BeaconTileEntity beacon;
private Beam beaconBeam = null;
private float[] initialColor = DyeColor.WHITE.getColorComponentValues();
public MirrorTileEntity(TileEntityType<?> typeIn) {
super(typeIn);
@ -93,7 +92,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
angle = newAngle % 360;
if (angle != prevAngle) {
updateReflections();
updateBeams();
}
if (beacon != null && beacon.isRemoved())
@ -105,17 +104,14 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
beacon = BeaconHelper.getBeaconTE(pos, world)
.orElse(null);
if (beaconBefore == beacon)
return;
if (beaconBefore != null) {
beaconBeam.onRemoved();
beaconBeam.clear();
beaconBeam = null;
updateReflections();
updateBeams();
}
if (beacon != null) {
beaconBeam = constructOutBeam(VecHelper.UP, beacon.getPos());
beaconBeam = constructOutBeam(null, VecHelper.UP, beacon.getPos());
if (beaconBeam != null) {
beaconBeam.addListener(this);
beaconBeam.onCreated();
@ -123,12 +119,18 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
}
}
private void updateReflections() {
new HashMap<>(beams).forEach(Beam::removeSubBeam);
private void updateBeams() {
Map<Beam, Beam> newBeams = new HashMap<>();
for (Beam beam : beams.keySet()) {
newBeams.put(beam, reflectBeam(beam));
for (Map.Entry<Beam, Beam> entry : beams.entrySet()) {
if (entry.getKey()
.isRemoved())
continue;
Beam reflected = reflectBeam(entry.getKey());
if (reflected != null) {
newBeams.put(entry.getKey(), reflected);
reflected.onCreated();
}
}
beams = newBeams;
}
@ -145,7 +147,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
public void lazyTick() {
super.lazyTick();
updateBeaconState();
updateReflections();
updateBeams();
}
@Override
@ -160,12 +162,6 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
@Override
public void setColor(float[] initialColor) {
this.initialColor = initialColor;
}
@Override
public float[] getSegmentStartColor() {
return initialColor;
}
@Nonnull
@ -205,17 +201,20 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
.iterator(), beaconIter);
}
@Override
public void onBeamRemoved(Beam beam) {
beams.remove(beam);
}
@Override
public Stream<Beam> constructSubBeams(Beam beam) {
if (beams.keySet()
.stream()
.map(Beam::getDirection)
.map(Vector3d::normalize)
.anyMatch(beam.getDirection()
.normalize()::equals))
return Stream.empty();
Beam reflected = reflectBeam(beam);
if (reflected != null) {
beams.put(beam, reflected);
beam.addListener(this);
return Stream.of(reflected);
}
return Stream.empty();
@ -223,11 +222,21 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
private Beam reflectBeam(Beam beam) {
Beam reflected = constructOutBeam(getReflectionAngle(beam.getDirection()));
if (reflected != null) {
beam.registerSubBeam(reflected);
reflected.onCreated();
}
return reflected;
Vector3d inDir = beam.getDirection()
.normalize();
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<Beam> getOutBeams() {
return beams.keySet();
}
}