Add rotation mode selector

This commit is contained in:
grimmauld 2021-04-20 13:23:40 +02:00
parent a2e2e2a313
commit 8e33eade50
4 changed files with 87 additions and 24 deletions

View file

@ -5,10 +5,10 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.optics.Beam;
import com.simibubi.create.content.optics.ILightHandler;
import com.simibubi.create.foundation.collision.Matrix3d;
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 com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.*;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
@ -30,6 +30,7 @@ import java.util.function.Predicate;
import java.util.stream.Stream;
public class MirrorTileEntity extends KineticTileEntity implements ILightHandler<MirrorTileEntity> {
protected ScrollOptionBehaviour<RotationMode> movementMode;
protected float angle;
protected float clientAngleDiff;
Map<Beam, Beam> beams;
@ -46,6 +47,15 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
setLazyTickRate(20);
}
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
super.addBehaviours(behaviours);
movementMode = new ScrollOptionBehaviour<>(RotationMode.class, Lang.translate("optics.mirror.movement_mode"),
this, new CenteredSideValueBoxTransform((state, d) -> getAxis() != d.getAxis()));
movementMode.requiresWrench();
behaviours.add(movementMode);
}
@Override
public void write(CompoundNBT compound, boolean clientPacket) {
compound.putFloat("Angle", angle);
@ -63,6 +73,8 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
public float getInterpolatedAngle(float partialTicks) {
if (isVirtual())
return MathHelper.lerp(partialTicks + .5f, prevAngle, angle);
if (movementMode.get() == RotationMode.ROTATE_LIMITED && Math.abs(angle) == 90)
return angle;
return MathHelper.lerp(partialTicks, angle, angle + getAngularSpeed());
}
@ -89,6 +101,12 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
float newAngle = angle + angularSpeed;
angle = newAngle % 360;
if (movementMode.get() == RotationMode.ROTATE_LIMITED)
angle = MathHelper.clamp(angle, -90, 90);
if (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();
}
@ -144,7 +162,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
private Vector3d getReflectionAngle(Vector3d inputAngle) {
inputAngle = inputAngle.normalize();
Direction.Axis axis = getBlockState().get(BlockStateProperties.AXIS);
Direction.Axis axis = getAxis();
Vector3d normal;
if (axis.isHorizontal())
normal = new Matrix3d().asIdentity()
@ -178,7 +196,7 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
@Nonnull
@Override
public Direction getBeamRotationAround() {
return Direction.getFacingFromAxisDirection(getBlockState().get(BlockStateProperties.AXIS), Direction.AxisDirection.POSITIVE);
return Direction.getFacingFromAxisDirection(getAxis(), Direction.AxisDirection.POSITIVE);
}
@Override
@ -225,11 +243,14 @@ public class MirrorTileEntity extends KineticTileEntity implements ILightHandler
if (inDir == null)
return null;
Vector3d outDir = getReflectionAngle(inDir).normalize();
return constructOutBeam(beam, getReflectionAngle(inDir).normalize());
}
if (inDir.subtract(outDir)
.normalize() == Vector3d.ZERO)
return null;
return constructOutBeam(beam, outDir);
private Direction.Axis getAxis() {
return getBlockState().get(BlockStateProperties.AXIS);
}
public float getAngle() {
return angle;
}
}

View file

@ -0,0 +1,33 @@
package com.simibubi.create.content.optics.mirror;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions;
import com.simibubi.create.foundation.utility.Lang;
public enum RotationMode implements INamedIconOptions {
// FIXME: Add proper icons
ROTATE_FREE(AllIcons.I_ROTATE_PLACE),
ROTATE_45(AllIcons.I_ROTATE_PLACE_RETURNED),
ROTATE_LIMITED(AllIcons.I_ROTATE_NEVER_PLACE);
private final String translationKey;
private final AllIcons icon;
RotationMode(AllIcons icon) {
this.icon = icon;
translationKey = "optics.mirror.movement_mode." + Lang.asId(name());
}
@Override
public AllIcons getIcon() {
return icon;
}
@Override
public String getTranslationKey() {
return translationKey;
}
}

View file

@ -1,26 +1,20 @@
package com.simibubi.create.foundation.mixin;
import com.simibubi.create.content.optics.ILightHandler;
import com.simibubi.create.foundation.block.ITE;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import com.simibubi.create.foundation.utility.BeaconHelper;
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);
return BeaconHelper.getCorrectedOpacity(state, world, pos);
}
}

View file

@ -4,6 +4,9 @@ import java.util.Optional;
import javax.annotation.Nullable;
import com.simibubi.create.content.optics.ILightHandler;
import com.simibubi.create.foundation.block.ITE;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@ -27,7 +30,7 @@ public class BeaconHelper {
while (testPos.getY() > 0) {
testPos = testPos.down();
BlockState state = world.getBlockState(testPos);
if (state.getOpacity(world, testPos) >= 15 && state.getBlock() != Blocks.BEDROCK)
if (getCorrectedOpacity(state, world, testPos) >= 15 && state.getBlock() != Blocks.BEDROCK)
break;
if (state.getBlock() == Blocks.BEACON) {
TileEntity te = world.getTileEntity(testPos);
@ -59,4 +62,16 @@ public class BeaconHelper {
return ((IBeaconBeamColorProvider) block).getColor()
.getColorComponentValues();
}
public static int getCorrectedOpacity(BlockState state, IBlockReader world, BlockPos pos) {
try {
if (state.getBlock() instanceof ITE) {
TileEntity te = ((ITE<?>) state.getBlock()).getTileEntity(world, pos);
if (te instanceof ILightHandler && !((ILightHandler<?>) te).canLightPass())
return 15;
}
} catch (ITE.TileEntityException ignored) {
}
return state.getOpacity(world, pos);
}
}