mirror of
https://github.com/Creators-of-Create/Create.git
synced 2025-02-05 01:45:00 +01:00
Declutter and distribute for easier new additions
This commit is contained in:
parent
4fa551b452
commit
838eeeee10
6 changed files with 232 additions and 188 deletions
|
@ -1,11 +1,5 @@
|
|||
package com.simibubi.create.content.optics;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
|
@ -14,6 +8,12 @@ import net.minecraft.item.DyeColor;
|
|||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class Beam extends ArrayList<BeamSegment> {
|
||||
private final Set<ILightHandler> lightEventListeners;
|
||||
@Nullable
|
||||
|
@ -68,10 +68,16 @@ public class Beam extends ArrayList<BeamSegment> {
|
|||
}
|
||||
|
||||
public boolean isRemoved() {
|
||||
// || !get(0).getHandler().getOutBeams().contains(this)
|
||||
ILightHandler handler = getHandler();
|
||||
removed = removed || isEmpty() || handler == null || handler.getTile()
|
||||
.isRemoved() || (parent != null && parent.isRemoved());
|
||||
.isRemoved() || (parent != null && parent.isRemovedSimple());
|
||||
return removed;
|
||||
}
|
||||
|
||||
private boolean isRemovedSimple() {
|
||||
ILightHandler handler = getHandler();
|
||||
removed = removed || isEmpty() || handler == null || handler.getTile()
|
||||
.isRemoved();
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
@ -88,4 +94,10 @@ public class Beam extends ArrayList<BeamSegment> {
|
|||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public Beam getParent() {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
package com.simibubi.create.content.optics;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.utility.BeaconHelper;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.tileentity.BeaconTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public abstract class LightHandlingBehaviour<T extends SmartTileEntity & ILightHandlerProvider> extends TileEntityBehaviour implements ILightHandler {
|
||||
protected final T handler;
|
||||
public Set<Beam> beams;
|
||||
private boolean isUpdating;
|
||||
@Nullable
|
||||
private BeaconTileEntity beacon;
|
||||
private Beam beaconBeam = null;
|
||||
|
||||
public LightHandlingBehaviour(T te) {
|
||||
super(te);
|
||||
handler = te;
|
||||
isUpdating = false;
|
||||
beams = new HashSet<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (beacon != null && beacon.isRemoved())
|
||||
updateBeaconState();
|
||||
}
|
||||
|
||||
protected void updateBeaconState() {
|
||||
BeaconTileEntity beaconBefore = beacon;
|
||||
beacon = BeaconHelper.getBeaconTE(getBlockPos(), getHandlerWorld())
|
||||
.orElse(null);
|
||||
|
||||
if (beaconBefore != null) {
|
||||
beaconBeam.clear();
|
||||
beaconBeam = null;
|
||||
updateBeams();
|
||||
}
|
||||
|
||||
if (beacon != null) {
|
||||
beaconBeam = constructOutBeam(null, VecHelper.UP, beacon.getPos());
|
||||
if (beaconBeam != null && !beaconBeam.isEmpty()) {
|
||||
beaconBeam.addListener(this);
|
||||
beaconBeam.onCreated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTile() {
|
||||
return tileEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lazyTick() {
|
||||
super.lazyTick();
|
||||
updateBeaconState();
|
||||
updateBeams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBeams() {
|
||||
if (isUpdating)
|
||||
return;
|
||||
isUpdating = true;
|
||||
|
||||
Set<Beam> newBeams = new HashSet<>();
|
||||
for (Beam child : new HashSet<>(beams)) {
|
||||
Beam parent = child.getParent();
|
||||
|
||||
child.onRemoved();
|
||||
if (parent == null || parent.isRemoved())
|
||||
continue;
|
||||
constructSubBeams(parent, newBeams).forEach(Beam::onCreated);
|
||||
}
|
||||
beams = newBeams;
|
||||
isUpdating = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Beam> constructSubBeams(Beam beam) {
|
||||
if (beams.stream()
|
||||
.map(Beam::getParent)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(((Predicate<Beam>) Beam::isRemoved).negate())
|
||||
.map(Beam::getDirection)
|
||||
.filter(Objects::nonNull)
|
||||
.anyMatch(b -> b.equals(beam.getDirection())))
|
||||
return Stream.empty();
|
||||
return constructSubBeams(beam, beams);
|
||||
}
|
||||
|
||||
public Stream<Beam> constructSubBeams(Beam beam, Set<Beam> beamListing) {
|
||||
return safeConstructSubBeamsFor(beam)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(((Predicate<Beam>) Beam::isEmpty).negate())
|
||||
.peek(beamListing::add);
|
||||
}
|
||||
|
||||
protected abstract Stream<Beam> safeConstructSubBeamsFor(Beam beam);
|
||||
|
||||
@Override
|
||||
public Iterator<Beam> getRenderBeams() {
|
||||
Iterator<Beam> beaconIter = beaconBeam == null ? Collections.emptyIterator() : Collections.singleton(beaconBeam)
|
||||
.iterator();
|
||||
return Iterators.concat(beams.iterator(), beaconIter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
package com.simibubi.create.content.optics;
|
||||
|
||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||
import com.simibubi.create.content.optics.mirror.RotationMode;
|
||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public abstract class RotatedLightHandlingBehaviour<T extends KineticTileEntity & ILightHandlerProvider & RotationMode.RotationModeProvider> extends LightHandlingBehaviour<T> {
|
||||
protected float angle;
|
||||
protected float clientAngleDiff;
|
||||
private float prevAngle;
|
||||
|
||||
public RotatedLightHandlingBehaviour(T te) {
|
||||
super(te);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundNBT nbt, boolean clientPacket) {
|
||||
nbt.putFloat("Angle", angle);
|
||||
super.write(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT nbt, boolean clientPacket) {
|
||||
angle = nbt.getFloat("Angle");
|
||||
super.read(nbt, clientPacket);
|
||||
}
|
||||
|
||||
public float getInterpolatedAngle(float partialTicks) {
|
||||
if (tileEntity.isVirtual())
|
||||
return MathHelper.lerp(partialTicks + .5f, prevAngle, angle);
|
||||
if (handler.getMode() == RotationMode.ROTATE_LIMITED && Math.abs(angle) == 90)
|
||||
return angle;
|
||||
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
|
||||
}
|
||||
|
||||
public float getAngularSpeed() {
|
||||
float speed = handler.getSpeed() * 3 / 10f;
|
||||
if (handler.getSpeed() == 0)
|
||||
speed = 0;
|
||||
if (getHandlerWorld() != null && getHandlerWorld().isRemote) {
|
||||
speed *= ServerSpeedProvider.get();
|
||||
speed += clientAngleDiff / 3f;
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
prevAngle = angle;
|
||||
if (getHandlerWorld() != null && getHandlerWorld().isRemote)
|
||||
clientAngleDiff /= 2;
|
||||
|
||||
float angularSpeed = getAngularSpeed();
|
||||
float newAngle = angle + angularSpeed;
|
||||
angle = newAngle % 360;
|
||||
|
||||
if (handler.getMode() == RotationMode.ROTATE_LIMITED)
|
||||
angle = MathHelper.clamp(angle, -90, 90);
|
||||
if (handler.getMode() == RotationMode.ROTATE_45 && angle == prevAngle) // don't snap while still rotating
|
||||
angle = 45F * Math.round(Math.round(angle) / 45F);
|
||||
|
||||
|
||||
if (angle != prevAngle) {
|
||||
updateBeams();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,160 +1,29 @@
|
|||
package com.simibubi.create.content.optics.mirror;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
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;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.simibubi.create.content.optics.Beam;
|
||||
import com.simibubi.create.content.optics.ILightHandler;
|
||||
import com.simibubi.create.content.optics.RotatedLightHandlingBehaviour;
|
||||
import com.simibubi.create.foundation.collision.Matrix3d;
|
||||
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType;
|
||||
import com.simibubi.create.foundation.utility.AngleHelper;
|
||||
import com.simibubi.create.foundation.utility.BeaconHelper;
|
||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.tileentity.BeaconTileEntity;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
|
||||
public class MirrorBehaviour extends TileEntityBehaviour implements ILightHandler {
|
||||
public static final BehaviourType<MirrorBehaviour> TYPE = new BehaviourType<>();
|
||||
private final MirrorTileEntity mirror;
|
||||
protected float angle;
|
||||
protected float clientAngleDiff;
|
||||
Map<Beam, Beam> beams;
|
||||
private float prevAngle;
|
||||
@Nullable
|
||||
private BeaconTileEntity beacon;
|
||||
private Beam beaconBeam = null;
|
||||
private boolean isUpdating = false;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class MirrorBehaviour extends RotatedLightHandlingBehaviour<MirrorTileEntity> {
|
||||
public static final BehaviourType<MirrorBehaviour> TYPE = new BehaviourType<>();
|
||||
|
||||
public MirrorBehaviour(MirrorTileEntity te) {
|
||||
super(te);
|
||||
mirror = te;
|
||||
beacon = null;
|
||||
beams = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(CompoundNBT nbt, boolean clientPacket) {
|
||||
nbt.putFloat("Angle", angle);
|
||||
super.write(nbt, clientPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(CompoundNBT nbt, boolean clientPacket) {
|
||||
angle = nbt.getFloat("Angle");
|
||||
super.read(nbt, clientPacket);
|
||||
}
|
||||
|
||||
public float getInterpolatedAngle(float partialTicks) {
|
||||
if (tileEntity.isVirtual())
|
||||
return MathHelper.lerp(partialTicks + .5f, prevAngle, angle);
|
||||
if (mirror.movementMode.get() == RotationMode.ROTATE_LIMITED && Math.abs(angle) == 90)
|
||||
return angle;
|
||||
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
|
||||
}
|
||||
|
||||
public float getAngularSpeed() {
|
||||
float speed = mirror.getSpeed() * 3 / 10f;
|
||||
if (mirror.getSpeed() == 0)
|
||||
speed = 0;
|
||||
if (getHandlerWorld() != null && getHandlerWorld().isRemote) {
|
||||
speed *= ServerSpeedProvider.get();
|
||||
speed += clientAngleDiff / 3f;
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
|
||||
prevAngle = angle;
|
||||
if (getHandlerWorld() != null && getHandlerWorld().isRemote)
|
||||
clientAngleDiff /= 2;
|
||||
|
||||
float angularSpeed = getAngularSpeed();
|
||||
float newAngle = angle + angularSpeed;
|
||||
angle = newAngle % 360;
|
||||
|
||||
if (mirror.movementMode.get() == RotationMode.ROTATE_LIMITED)
|
||||
angle = MathHelper.clamp(angle, -90, 90);
|
||||
if (mirror.movementMode.get() == RotationMode.ROTATE_45 && angle == prevAngle) // don't snap while still rotating
|
||||
angle = 45F * Math.round(Math.round(angle) / 45F);
|
||||
|
||||
|
||||
if (angle != prevAngle) {
|
||||
updateBeams();
|
||||
}
|
||||
|
||||
if (beacon != null && beacon.isRemoved())
|
||||
updateBeaconState();
|
||||
}
|
||||
|
||||
private void updateBeaconState() {
|
||||
BeaconTileEntity beaconBefore = beacon;
|
||||
beacon = BeaconHelper.getBeaconTE(getBlockPos(), getHandlerWorld())
|
||||
.orElse(null);
|
||||
|
||||
if (beaconBefore != null) {
|
||||
beaconBeam.clear();
|
||||
beaconBeam = null;
|
||||
updateBeams();
|
||||
}
|
||||
|
||||
if (beacon != null) {
|
||||
beaconBeam = constructOutBeam(null, VecHelper.UP, beacon.getPos());
|
||||
if (beaconBeam != null && !beaconBeam.isEmpty()) {
|
||||
beaconBeam.addListener(this);
|
||||
beaconBeam.onCreated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBeams() {
|
||||
if (isUpdating)
|
||||
return;
|
||||
isUpdating = true;
|
||||
|
||||
Map<Beam, Beam> newBeams = new HashMap<>();
|
||||
for (Map.Entry<Beam, Beam> entry : new HashSet<>(beams.entrySet())) {
|
||||
entry.getValue()
|
||||
.onRemoved();
|
||||
if (entry.getKey()
|
||||
.isRemoved())
|
||||
continue;
|
||||
Beam reflected = reflectBeam(entry.getKey());
|
||||
if (reflected != null && !reflected.isEmpty()) {
|
||||
newBeams.put(entry.getKey(), reflected);
|
||||
reflected.onCreated();
|
||||
entry.getKey()
|
||||
.addListener(this);
|
||||
}
|
||||
}
|
||||
beams = newBeams;
|
||||
isUpdating = false;
|
||||
}
|
||||
|
||||
private Vector3d getReflectionAngle(Vector3d inputAngle) {
|
||||
inputAngle = inputAngle.normalize();
|
||||
Direction.Axis axis = mirror.getAxis();
|
||||
Direction.Axis axis = handler.getAxis();
|
||||
Vector3d normal;
|
||||
if (axis.isHorizontal())
|
||||
normal = new Matrix3d().asIdentity()
|
||||
|
@ -168,22 +37,11 @@ public class MirrorBehaviour extends TileEntityBehaviour implements ILightHandle
|
|||
return inputAngle.subtract(normal.scale(2 * inputAngle.dotProduct(normal)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lazyTick() {
|
||||
super.lazyTick();
|
||||
updateBeaconState();
|
||||
updateBeams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getTile() {
|
||||
return tileEntity;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Direction getBeamRotationAround() {
|
||||
return Direction.getFacingFromAxisDirection(mirror.getAxis(), Direction.AxisDirection.POSITIVE);
|
||||
return Direction.getFacingFromAxisDirection(handler.getAxis(), Direction.AxisDirection.POSITIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -192,37 +50,11 @@ public class MirrorBehaviour extends TileEntityBehaviour implements ILightHandle
|
|||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Beam> getRenderBeams() {
|
||||
Iterator<Beam> beaconIter = beaconBeam == null ? Collections.emptyIterator() : Collections.singleton(beaconBeam)
|
||||
.iterator();
|
||||
return Iterators.concat(beams.values()
|
||||
.iterator(), beaconIter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Beam> constructSubBeams(Beam beam) {
|
||||
if (beams.keySet()
|
||||
.stream()
|
||||
.filter(((Predicate<Beam>) Beam::isRemoved).negate())
|
||||
.map(Beam::getDirection)
|
||||
.filter(Objects::nonNull)
|
||||
.anyMatch(b -> b.equals(beam.getDirection())))
|
||||
return Stream.empty();
|
||||
Beam reflected = reflectBeam(beam);
|
||||
if (reflected != null && !reflected.isEmpty()) {
|
||||
beams.put(beam, reflected);
|
||||
beam.addListener(this);
|
||||
return Stream.of(reflected);
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Beam reflectBeam(Beam beam) {
|
||||
protected Stream<Beam> safeConstructSubBeamsFor(Beam beam) {
|
||||
Vector3d inDir = beam.getDirection();
|
||||
if (inDir == null)
|
||||
return null;
|
||||
return Stream.empty();
|
||||
|
||||
return constructOutBeam(beam, getReflectionAngle(inDir).normalize());
|
||||
return Stream.of(constructOutBeam(beam, getReflectionAngle(inDir).normalize()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import net.minecraft.util.math.AxisAlignedBB;
|
|||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public class MirrorTileEntity extends KineticTileEntity implements ILightHandlerProvider {
|
||||
public class MirrorTileEntity extends KineticTileEntity implements ILightHandlerProvider, RotationMode.RotationModeProvider {
|
||||
protected ScrollOptionBehaviour<RotationMode> movementMode;
|
||||
protected MirrorBehaviour mirror;
|
||||
|
||||
|
@ -63,4 +63,9 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
|
|||
public ILightHandler getHandler() {
|
||||
return mirror;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RotationMode getMode() {
|
||||
return movementMode.get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,4 +30,8 @@ public enum RotationMode implements INamedIconOptions {
|
|||
return translationKey;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface RotationModeProvider {
|
||||
RotationMode getMode();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue