Everything

This commit is contained in:
reidbhuntley 2022-01-11 01:21:17 -05:00
parent 3f7fbef9d6
commit 2768123b52
84 changed files with 1030 additions and 996 deletions

View file

@ -2,6 +2,8 @@ package com.simibubi.create;
import java.util.Random;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -83,6 +85,7 @@ public class Create {
ModLoadingContext modLoadingContext = ModLoadingContext.get();
AllSoundEvents.prepare();
AllConnections.register();
AllBlocks.register();
AllItems.register();
AllFluids.register();

View file

@ -38,16 +38,20 @@ public class KineticDebugger {
return;
Level world = Minecraft.getInstance().level;
BlockPos toOutline = te.hasSource() ? te.source : te.getBlockPos();
BlockPos toOutline = te.getSpeedSource().orElse(te.getBlockPos());
BlockState state = te.getBlockState();
VoxelShape shape = world.getBlockState(toOutline)
.getBlockSupportShape(world, toOutline);
if (te.getTheoreticalSpeed() != 0 && !shape.isEmpty())
if (te.getTheoreticalSpeed() != 0 && !shape.isEmpty()) {
int color = te.getSpeedSource().flatMap($ -> te.getNetworkID())
.map(id -> Color.generateFromLong(id).getRGB())
.orElse(0xffcc00);
CreateClient.OUTLINER.chaseAABB("kineticSource", shape.bounds()
.move(toOutline))
.lineWidth(1 / 16f)
.colored(te.hasSource() ? Color.generateFromLong(te.network).getRGB() : 0xffcc00);
.colored(color);
}
if (state.getBlock() instanceof IRotate) {
Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state);

View file

@ -95,23 +95,20 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc
BlockState blockState = reader.getBlockState(neighbourPos);
Block block = blockState.getBlock();
return block instanceof IRotate
&& ((IRotate) block).hasShaftTowards(reader, neighbourPos, blockState, facing.getOpposite());
&& ((IRotate) block).hasShaftTowards(blockState, facing.getOpposite(), reader, pos);
}
public static Axis getRotationAxis(Axis facing, boolean alongFirstCoordinate) {
return switch (facing) {
case X -> alongFirstCoordinate ? Axis.Y : Axis.Z;
case Y -> alongFirstCoordinate ? Axis.X : Axis.Z;
case Z -> alongFirstCoordinate ? Axis.X : Axis.Y;
};
}
@Override
public Axis getRotationAxis(BlockState state) {
Axis pistonAxis = state.getValue(FACING)
.getAxis();
boolean alongFirst = state.getValue(AXIS_ALONG_FIRST_COORDINATE);
if (pistonAxis == Axis.X)
return alongFirst ? Axis.Y : Axis.Z;
if (pistonAxis == Axis.Y)
return alongFirst ? Axis.X : Axis.Z;
if (pistonAxis == Axis.Z)
return alongFirst ? Axis.X : Axis.Y;
throw new IllegalStateException("Unknown axis??");
return getRotationAxis(state.getValue(FACING).getAxis(), state.getValue(AXIS_ALONG_FIRST_COORDINATE));
}
@Override
@ -122,7 +119,7 @@ public abstract class DirectionalAxisKineticBlock extends DirectionalKineticBloc
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == getRotationAxis(state);
}

View file

@ -26,24 +26,24 @@ public abstract class DirectionalKineticBlock extends KineticBlock {
super.createBlockStateDefinition(builder);
}
public Direction getPreferredFacing(BlockPlaceContext context) {
Direction prefferedSide = null;
public static Direction getPreferredFacing(BlockPlaceContext context) {
Direction preferredSide = null;
for (Direction side : Iterate.directions) {
BlockState blockState = context.getLevel()
.getBlockState(context.getClickedPos()
.relative(side));
if (blockState.getBlock() instanceof IRotate) {
if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos()
.relative(side), blockState, side.getOpposite()))
if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) {
prefferedSide = null;
if (((IRotate) blockState.getBlock()).hasShaftTowards(
blockState, side.getOpposite(), context.getLevel(), context.getClickedPos()))
if (preferredSide != null && preferredSide.getAxis() != side.getAxis()) {
preferredSide = null;
break;
} else {
prefferedSide = side;
preferredSide = side;
}
}
}
return prefferedSide;
return preferredSide;
}
@Override

View file

@ -1,89 +0,0 @@
package com.simibubi.create.content.contraptions.base;
import java.util.List;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
public abstract class GeneratingKineticTileEntity extends KineticTileEntity {
public boolean reActivateSource;
public GeneratingKineticTileEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state);
}
@Override
public void tick() {
super.tick();
if (reActivateSource) {
updateGeneratedRotation();
reActivateSource = false;
}
}
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
boolean added = super.addToGoggleTooltip(tooltip, isPlayerSneaking);
// float stressBase = calculateAddedStressCapacity();
// if (stressBase != 0 && IRotate.StressImpact.isEnabled()) {
// tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.goggles.generator_stats")));
// tooltip.add(componentSpacing.plainCopy().append(Lang.translate("tooltip.capacityProvided").withStyle(ChatFormatting.GRAY)));
//
// float speed = getTheoreticalSpeed();
// if (speed != getGeneratedSpeed() && speed != 0)
// stressBase *= getGeneratedSpeed() / speed;
//
// speed = Math.abs(speed);
// float stressTotal = stressBase * speed;
//
// tooltip.add(
// componentSpacing.plainCopy()
// .append(new TextComponent(" " + IHaveGoggleInformation.format(stressTotal))
// .append(Lang.translate("generic.unit.stress"))
// .withStyle(ChatFormatting.AQUA))
// .append(" ")
// .append(Lang.translate("gui.goggles.at_current_speed").withStyle(ChatFormatting.DARK_GRAY)));
//
// added = true;
// }
return added;
}
public void updateGeneratedRotation() {
// float speed = getGeneratedSpeed();
// float prevSpeed = this.speed;
//
// if (level.isClientSide)
// return;
//
// if (prevSpeed != speed) {
// if (!hasSource()) {
// SpeedLevel levelBefore = SpeedLevel.of(this.speed);
// SpeedLevel levelafter = SpeedLevel.of(speed);
// if (levelBefore != levelafter)
// effects.queueRotationIndicators();
// }
//
// applyNewSpeed(prevSpeed, speed);
// }
//
// if (hasNetwork() && speed != 0) {
// KineticNetwork network = getOrCreateNetwork();
// notifyStressCapacityChange(calculateAddedStressCapacity());
// getOrCreateNetwork().updateStressFor(this, calculateStressApplied());
// network.updateStress();
// }
//
// onSpeedChanged(prevSpeed);
// sendData();
}
public Long createNetworkId() {
return worldPosition.asLong();
}
}

View file

@ -1,15 +1,11 @@
package com.simibubi.create.content.contraptions.base;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
@ -41,21 +37,21 @@ public abstract class HorizontalAxisKineticBlock extends KineticBlock {
}
public static Axis getPreferredHorizontalAxis(BlockPlaceContext context) {
Direction prefferedSide = null;
Direction preferredSide = null;
for (Direction side : Iterate.horizontalDirections) {
BlockState blockState = context.getLevel().getBlockState(context.getClickedPos().relative(side));
if (blockState.getBlock() instanceof IRotate) {
if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos().relative(side),
blockState, side.getOpposite()))
if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) {
prefferedSide = null;
if (((IRotate) blockState.getBlock()).hasShaftTowards(
blockState, side.getOpposite(), context.getLevel(), context.getClickedPos()))
if (preferredSide != null && preferredSide.getAxis() != side.getAxis()) {
preferredSide = null;
break;
} else {
prefferedSide = side;
preferredSide = side;
}
}
}
return prefferedSide == null ? null : prefferedSide.getAxis();
return preferredSide == null ? null : preferredSide.getAxis();
}
@Override
@ -64,12 +60,7 @@ public abstract class HorizontalAxisKineticBlock extends KineticBlock {
}
@Override
public KineticConnections getInitialConnections(BlockState state) {
return AllConnections.FULL_SHAFT.apply(state.getValue(HORIZONTAL_AXIS));
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(HORIZONTAL_AXIS);
}

View file

@ -34,23 +34,23 @@ public abstract class HorizontalKineticBlock extends KineticBlock {
}
public Direction getPreferredHorizontalFacing(BlockPlaceContext context) {
Direction prefferedSide = null;
Direction preferredSide = null;
for (Direction side : Iterate.horizontalDirections) {
BlockState blockState = context.getLevel()
.getBlockState(context.getClickedPos()
.relative(side));
if (blockState.getBlock() instanceof IRotate) {
if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos()
.relative(side), blockState, side.getOpposite()))
if (prefferedSide != null && prefferedSide.getAxis() != side.getAxis()) {
prefferedSide = null;
if (((IRotate) blockState.getBlock()).hasShaftTowards(
blockState, side.getOpposite(), context.getLevel(), context.getClickedPos()))
if (preferredSide != null && preferredSide.getAxis() != side.getAxis()) {
preferredSide = null;
break;
} else {
prefferedSide = side;
preferredSide = side;
}
}
}
return prefferedSide;
return preferredSide;
}
@Override

View file

@ -1,11 +1,12 @@
package com.simibubi.create.content.contraptions.base;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.item.ItemDescription;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.ChatFormatting;
@ -15,6 +16,7 @@ import net.minecraft.core.Direction.Axis;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
@ -121,12 +123,26 @@ public interface IRotate extends IWrenchable {
}
}
boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face);
boolean hasShaftTowards(BlockState state, Direction face);
default boolean hasShaftTowards(BlockState state, Direction face, LevelReader level, BlockPos pos) {
return hasShaftTowards(state, face);
}
Axis getRotationAxis(BlockState state);
default KineticConnections getInitialConnections(BlockState state) {
return AllConnections.EMPTY;
default ConnectionsBuilder buildInitialConnections(ConnectionsBuilder builder, BlockState state) {
for (Direction face : Iterate.directions) {
if (hasShaftTowards(state, face))
builder = builder.withHalfShaft(face);
}
if (state.getBlock() instanceof ICogWheel cog) {
if (cog.isLargeCog())
builder = builder.withLargeCog(getRotationAxis(state));
if (cog.isSmallCog())
builder = builder.withSmallCog(getRotationAxis(state));
}
return builder;
}
default SpeedLevel getMinimumRequiredSpeedLevel() {

View file

@ -8,7 +8,6 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@ -22,7 +21,7 @@ public abstract class KineticBlock extends Block implements IRotate {
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return false;
}

View file

@ -17,7 +17,7 @@ import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation;
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.IKineticController;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.content.contraptions.solver.KineticSolver;
@ -35,7 +35,6 @@ import net.minecraft.client.resources.language.I18n;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.Component;
@ -53,37 +52,41 @@ import net.minecraftforge.fml.DistExecutor;
public class KineticTileEntity extends SmartTileEntity
implements IHaveGoggleInformation, IHaveHoveringInformation, FlywheelRendered, IKineticController {
public @Nullable Long network = null;
public @Nullable BlockPos source = null;
protected KineticEffectHandler effects;
protected float theoreticalSpeed;
protected KineticConnections clientConnections;
protected @Nullable BlockPos speedSource;
protected boolean overstressed;
protected float networkImpact;
protected float networkCapacity;
private float theoreticalSpeed;
private long networkID;
private @Nullable BlockPos speedSource;
private boolean overstressed;
private float networkImpact;
private float networkCapacity;
private boolean kineticsInit;
protected boolean wasMoved;
private int flickerTally;
private int validationCountdown;
private final KineticConnections connections;
private KineticConnections initialConnections;
private boolean initialConnectionsChanged;
public KineticTileEntity(BlockEntityType<?> typeIn, BlockPos pos, BlockState state) {
super(typeIn, pos, state);
effects = new KineticEffectHandler(this);
if (state.getBlock() instanceof IRotate rotate) {
connections = rotate.getInitialConnections(state);
} else {
connections = AllConnections.EMPTY;
}
clientConnections = connections;
updateInitialConnections(state);
}
@Override public KineticConnections getConnections() { return connections; }
protected void updateInitialConnections(BlockState state) {
if (state.getBlock() instanceof IRotate rotate) {
initialConnections = rotate.buildInitialConnections(ConnectionsBuilder.builder(), state).build();
if (getLevel() != null && !getLevel().isClientSide) {
initialConnectionsChanged = true;
}
} else {
initialConnections = KineticConnections.empty();
}
}
@Override public KineticConnections getConnections() { return initialConnections; }
@Override public float getStressImpact() { return getDefaultStressImpact(); }
@ -102,13 +105,8 @@ public class KineticTileEntity extends SmartTileEntity
return (float) BlockStressValues.getCapacity(getStressConfigKey());
}
public float getRotationSpeedModifier(Vec3i offset) {
return getClientConnections().checkConnection(offset).orElse(0f);
}
public float getRotationSpeedModifier(Direction face) {
return getRotationSpeedModifier(face.getNormal());
public float getShaftSpeed(Direction face) {
return getSpeed() * getConnections().getShaftSpeedModifier(face);
}
@ -127,7 +125,7 @@ public class KineticTileEntity extends SmartTileEntity
if (level.isClientSide) {
cachedBoundingBox = null; // cache the bounding box for every frame between ticks
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.tickAudio());
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::tickAudio);
return;
}
@ -165,6 +163,11 @@ public class KineticTileEntity extends SmartTileEntity
}
public void onSpeedChanged(float previousSpeed) {
if (!level.isClientSide && getSpeedSource().isEmpty()) {
if (SpeedLevel.of(previousSpeed) != SpeedLevel.of(getSpeed()))
effects.queueRotationIndicators();
}
boolean fromOrToZero = (previousSpeed == 0) != (getSpeed() == 0);
boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed());
if (fromOrToZero || directionSwap)
@ -179,13 +182,19 @@ public class KineticTileEntity extends SmartTileEntity
@Override
protected void write(CompoundTag compound, boolean clientPacket) {
if (clientPacket) {
compound.putFloat("Speed", theoreticalSpeed);
compound.put("Connections", clientConnections.save(new CompoundTag()));
compound.putBoolean("Overstressed", overstressed);
compound.putFloat("Impact", networkImpact);
compound.putFloat("Capacity", networkCapacity);
if (speedSource != null)
compound.put("Source", NbtUtils.writeBlockPos(speedSource));
if (initialConnectionsChanged) {
compound.putBoolean("UpdateConnections", true);
initialConnectionsChanged = false;
}
compound.putFloat("Speed", getTheoreticalSpeed());
getNetworkID().ifPresent(id -> compound.putLong("Network", id));
if (isOverstressed())
compound.putBoolean("Overstressed", isOverstressed());
if (getNetworkImpact() > 0)
compound.putFloat("Impact", getNetworkImpact());
if (getNetworkCapacity() > 0)
compound.putFloat("Capacity", getNetworkCapacity());
getSpeedSource().ifPresent(source -> compound.put("Source", NbtUtils.writeBlockPos(source)));
}
super.write(compound, clientPacket);
@ -194,9 +203,11 @@ public class KineticTileEntity extends SmartTileEntity
@Override
protected void read(CompoundTag tag, boolean clientPacket) {
if (clientPacket) {
if (tag.getBoolean("UpdateConnections"))
updateInitialConnections(getBlockState());
updateFromSolver(tag.getFloat("Speed"),
tag.contains("Source") ? NbtUtils.readBlockPos(tag.getCompound("Source")) : null,
KineticConnections.load(tag.getCompound("Connections")),
tag.getLong("Network"),
tag.getBoolean("Overstressed"),
tag.getFloat("Impact"),
tag.getFloat("Capacity"));
@ -221,8 +232,8 @@ public class KineticTileEntity extends SmartTileEntity
return Optional.ofNullable(speedSource);
}
public KineticConnections getClientConnections() {
return clientConnections;
public Optional<Long> getNetworkID() {
return networkID == 0 ? Optional.empty() : Optional.of(networkID);
}
public boolean isOverstressed() {
@ -237,52 +248,41 @@ public class KineticTileEntity extends SmartTileEntity
return networkCapacity;
}
public void updateFromSolver(float theoreticalSpeed, @Nullable BlockPos speedSource, KineticConnections connections,
public void updateFromSolver(float theoreticalSpeed, @Nullable BlockPos speedSource, long networkID,
boolean overstressed, float networkImpact, float networkCapacity) {
float prevSpeed = getSpeed();
BlockPos prevSpeedSource = getSpeedSource().orElse(null);
KineticConnections prevConnections = getClientConnections();
BlockPos prevSpeedSource = this.speedSource;
long prevNetworkID = this.networkID;
boolean prevOverstressed = isOverstressed();
float prevNetworkImpact = getNetworkImpact();
float prevNetworkCapacity = getNetworkCapacity();
this.theoreticalSpeed = theoreticalSpeed;
this.speedSource = speedSource;
this.clientConnections = connections;
this.networkID = networkID;
this.overstressed = overstressed;
this.networkImpact = networkImpact;
this.networkCapacity = networkCapacity;
boolean send = false;
boolean changed = initialConnectionsChanged;
if (prevOverstressed != overstressed || prevNetworkImpact != networkImpact || prevNetworkCapacity != networkCapacity) {
if (!kineticsInit || prevOverstressed != overstressed || prevNetworkImpact != networkImpact
|| prevNetworkCapacity != networkCapacity) {
onStressChanged(prevNetworkImpact, prevNetworkCapacity, prevOverstressed);
send = true;
changed = true;
}
if (getSpeed() != prevSpeed) {
if (!kineticsInit || getSpeed() != prevSpeed) {
onSpeedChanged(prevSpeed);
send = true;
changed = true;
}
kineticsInit = true;
if (level.isClientSide) return;
if (!connections.equals(prevConnections))
send = true;
if (!Objects.equal(speedSource, prevSpeedSource))
send = true;
if (send)
if (changed || networkID != prevNetworkID || !Objects.equal(speedSource, prevSpeedSource))
sendData();
}
public boolean hasSource() {
return source != null;
}
public boolean hasNetwork() {
return network != null;
}
public boolean isSpeedRequirementFulfilled() {
BlockState state = getBlockState();
if (!(getBlockState().getBlock() instanceof IRotate))
@ -299,8 +299,12 @@ public class KineticTileEntity extends SmartTileEntity
}
public static void switchToBlockState(Level world, BlockPos pos, BlockState state) {
if (!world.isClientSide)
world.setBlock(pos, state, 3);
if (!world.isClientSide) {
world.setBlockAndUpdate(pos, state);
if (world.getBlockEntity(pos) instanceof KineticTileEntity kte) {
kte.updateInitialConnections(state);
}
}
}
@Override
@ -341,16 +345,17 @@ public class KineticTileEntity extends SmartTileEntity
@Override
public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneaking) {
boolean added = false;
float stressAtBase = getStressImpact();
if (stressAtBase != 0 && StressImpact.isEnabled()) {
// stress impact info
float impact = getStressImpact();
if (impact != 0 && StressImpact.isEnabled()) {
tooltip.add(componentSpacing.plainCopy()
.append(Lang.translate("gui.goggles.kinetic_stats")));
tooltip.add(componentSpacing.plainCopy()
.append(Lang.translate("tooltip.stressImpact")
.withStyle(ChatFormatting.GRAY)));
float stressTotal = stressAtBase * Math.abs(getTheoreticalSpeed());
float stressTotal = impact * Math.abs(getTheoreticalSpeed());
tooltip.add(componentSpacing.plainCopy()
.append(new TextComponent(" " + IHaveGoggleInformation.format(stressTotal))
@ -363,8 +368,31 @@ public class KineticTileEntity extends SmartTileEntity
added = true;
}
return added;
// stress capacity info
float capacity = getStressCapacity();
if (capacity != 0 && IRotate.StressImpact.isEnabled()) {
tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.goggles.generator_stats")));
tooltip.add(componentSpacing.plainCopy().append(Lang.translate("tooltip.capacityProvided").withStyle(ChatFormatting.GRAY)));
float speed = getTheoreticalSpeed();
if (speed != getGeneratedSpeed() && speed != 0)
capacity *= getGeneratedSpeed() / speed;
speed = Math.abs(speed);
float stressTotal = capacity * speed;
tooltip.add(
componentSpacing.plainCopy()
.append(new TextComponent(" " + IHaveGoggleInformation.format(stressTotal))
.append(Lang.translate("generic.unit.stress"))
.withStyle(ChatFormatting.AQUA))
.append(" ")
.append(Lang.translate("gui.goggles.at_current_speed").withStyle(ChatFormatting.DARK_GRAY)));
added = true;
}
return added;
}
public void clearKineticInformation() {

View file

@ -98,7 +98,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
if (KineticDebugger.isActive()) {
rainbowMode = true;
buffer.color(te.hasNetwork() ? Color.generateFromLong(te.network) : Color.WHITE);
buffer.color(te.getNetworkID().map(Color::generateFromLong).orElse(Color.WHITE));
} else {
float overStressedEffect = te.effects.overStressedEffect;
if (overStressedEffect != 0)
@ -117,7 +117,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer<KineticTil
float offset = ICogWheel.isLargeCog(te.getBlockState()) ? 11.25f : 0;
double d = (((axis == Axis.X) ? 0 : pos.getX()) + ((axis == Axis.Y) ? 0 : pos.getY())
+ ((axis == Axis.Z) ? 0 : pos.getZ())) % 2;
if (d == 0)
if (d == 0)
offset = 22.5f;
return offset;
}

View file

@ -24,40 +24,34 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock {
@Override
public BlockState rotate(BlockState state, Rotation rot) {
switch (rot) {
case COUNTERCLOCKWISE_90:
case CLOCKWISE_90:
switch (state.getValue(AXIS)) {
case X:
return state.setValue(AXIS, Direction.Axis.Z);
case Z:
return state.setValue(AXIS, Direction.Axis.X);
default:
return state;
}
default:
return state;
}
return switch (rot) {
case COUNTERCLOCKWISE_90, CLOCKWISE_90 -> switch (state.getValue(AXIS)) {
case X -> state.setValue(AXIS, Axis.Z);
case Z -> state.setValue(AXIS, Axis.X);
default -> state;
};
default -> state;
};
}
public static Axis getPreferredAxis(BlockPlaceContext context) {
Axis prefferedAxis = null;
Axis preferredAxis = null;
for (Direction side : Iterate.directions) {
BlockState blockState = context.getLevel()
.getBlockState(context.getClickedPos()
.relative(side));
if (blockState.getBlock() instanceof IRotate) {
if (((IRotate) blockState.getBlock()).hasShaftTowards(context.getLevel(), context.getClickedPos()
.relative(side), blockState, side.getOpposite()))
if (prefferedAxis != null && prefferedAxis != side.getAxis()) {
prefferedAxis = null;
if (((IRotate) blockState.getBlock()).hasShaftTowards(
blockState, side.getOpposite(), context.getLevel(), context.getClickedPos()))
if (preferredAxis != null && preferredAxis != side.getAxis()) {
preferredAxis = null;
break;
} else {
prefferedAxis = side.getAxis();
preferredAxis = side.getAxis();
}
}
}
return prefferedAxis;
return preferredAxis;
}
@Override

View file

@ -39,11 +39,7 @@ public class KineticData extends BasicData {
}
public KineticData setColor(KineticTileEntity te) {
if (te.hasNetwork()) {
setColor(Color.generateFromLong(te.network));
}else {
setColor(0xFF, 0xFF, 0xFF);
}
setColor(te.getNetworkID().map(Color::generateFromLong).orElse(Color.WHITE));
return this;
}

View file

@ -17,7 +17,6 @@ import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@ -68,7 +67,7 @@ public class DrillBlock extends DirectionalKineticBlock implements ITE<DrillTile
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(FACING)
.getOpposite();
}

View file

@ -13,7 +13,6 @@ import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@ -28,16 +27,16 @@ public class CuckooClockBlock extends HorizontalKineticBlock implements ITE<Cuck
public static CuckooClockBlock regular(Properties properties) {
return new CuckooClockBlock(false, properties);
}
public static CuckooClockBlock mysterious(Properties properties) {
return new CuckooClockBlock(true, properties);
}
protected CuckooClockBlock(boolean mysterious, Properties properties) {
super(properties);
this.mysterious = mysterious;
}
@Override
public VoxelShape getShape(BlockState p_220053_1_, BlockGetter p_220053_2_, BlockPos p_220053_3_,
CollisionContext p_220053_4_) {
@ -49,7 +48,7 @@ public class CuckooClockBlock extends HorizontalKineticBlock implements ITE<Cuck
if (!mysterious)
super.fillItemCategory(group, items);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
Direction preferred = getPreferredHorizontalFacing(context);
@ -59,7 +58,7 @@ public class CuckooClockBlock extends HorizontalKineticBlock implements ITE<Cuck
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(HORIZONTAL_FACING).getOpposite();
}
@ -72,7 +71,7 @@ public class CuckooClockBlock extends HorizontalKineticBlock implements ITE<Cuck
public Axis getRotationAxis(BlockState state) {
return state.getValue(HORIZONTAL_FACING).getAxis();
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;

View file

@ -98,22 +98,20 @@ public class HandCrankBlock extends DirectionalKineticBlock implements ITE<HandC
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
return face == state.getValue(FACING)
.getOpposite();
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(FACING).getOpposite();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.getValue(FACING)
.getAxis();
return state.getValue(FACING).getAxis();
}
@Override
public Class<HandCrankTileEntity> getTileEntityClass() {
return HandCrankTileEntity.class;
}
@Override
public BlockEntityType<? extends HandCrankTileEntity> getTileEntityType() {
return AllTileEntities.HAND_CRANK.get();

View file

@ -2,7 +2,7 @@ package com.simibubi.create.content.contraptions.components.crank;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import net.minecraft.core.BlockPos;
@ -13,7 +13,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class HandCrankTileEntity extends GeneratingKineticTileEntity {
public class HandCrankTileEntity extends KineticTileEntity {
public int inUse;
public boolean backwards;
@ -25,23 +25,16 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity {
}
public void turn(boolean back) {
boolean update = false;
if (getGeneratedSpeed() == 0 || back != backwards)
update = true;
inUse = 10;
this.backwards = back;
if (update && !level.isClientSide)
updateGeneratedRotation();
backwards = back;
}
@Override
public float getGeneratedSpeed() {
if (isRemoved()) return 0;
Block block = getBlockState().getBlock();
if (!(block instanceof HandCrankBlock))
if (!(block instanceof HandCrankBlock crank))
return 0;
HandCrankBlock crank = (HandCrankBlock) block;
int speed = (inUse == 0 ? 0 : backwards ? -1 : 1) * crank.getRotationSpeed();
return convertToDirection(speed, getBlockState().getValue(HandCrankBlock.FACING));
}
@ -66,12 +59,8 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity {
chasingVelocity += ((actualSpeed * 10 / 3f) - chasingVelocity) * .25f;
independentAngle += chasingVelocity;
if (inUse > 0) {
if (inUse > 0)
inUse--;
if (inUse == 0 && !level.isClientSide)
updateGeneratedRotation();
}
}
@Override

View file

@ -171,7 +171,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(AXIS);
}
@ -189,7 +189,7 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE
public Class<CrushingWheelTileEntity> getTileEntityClass() {
return CrushingWheelTileEntity.class;
}
@Override
public BlockEntityType<? extends CrushingWheelTileEntity> getTileEntityType() {
return AllTileEntities.CRUSHING_WHEEL.get();

View file

@ -13,7 +13,6 @@ import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@ -96,7 +95,7 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(FACING)
.getOpposite();
}
@ -110,7 +109,7 @@ public class EncasedFanBlock extends DirectionalKineticBlock implements ITE<Enca
public Class<EncasedFanTileEntity> getTileEntityClass() {
return EncasedFanTileEntity.class;
}
@Override
public BlockEntityType<? extends EncasedFanTileEntity> getTileEntityType() {
return AllTileEntities.ENCASED_FAN.get();

View file

@ -4,7 +4,7 @@ import javax.annotation.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock;
import com.simibubi.create.content.logistics.block.chute.ChuteTileEntity;
import com.simibubi.create.foundation.config.AllConfigs;
@ -20,7 +20,7 @@ import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
@MethodsReturnNonnullByDefault
public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements IAirCurrentSource {
public class EncasedFanTileEntity extends KineticTileEntity implements IAirCurrentSource {
public AirCurrent airCurrent;
protected int airCurrentUpdateCooldown;
@ -52,21 +52,21 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
super.write(compound, clientPacket);
}
public float calculateAddedStressCapacity() {
//return lastCapacityProvided = (isGenerator ? super.calculateAddedStressCapacity() : 0);
return 0;
}
public float calculateStressApplied() {
//return isGenerator ? 0 : super.calculateStressApplied();
return 0;
}
@Override
public float getGeneratedSpeed() {
return isGenerator ? AllConfigs.SERVER.kinetics.generatingFanSpeed.get() : 0;
}
@Override
public float getStressCapacity() {
return isGenerator ? super.getStressCapacity() : 0;
}
@Override
public float getStressImpact() {
return isGenerator ? 0 : super.getStressImpact();
}
public void queueGeneratorUpdate() {
updateGenerator = true;
}
@ -88,7 +88,6 @@ public class EncasedFanTileEntity extends GeneratingKineticTileEntity implements
if (shouldGenerate == isGenerator)
return;
isGenerator = shouldGenerate;
updateGeneratedRotation();
}
public boolean blockBelowIsHot() {

View file

@ -16,7 +16,6 @@ import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@ -74,7 +73,7 @@ public class FlywheelBlock extends HorizontalKineticBlock implements ITE<Flywhee
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(HORIZONTAL_FACING).getOpposite();
}

View file

@ -1,6 +1,6 @@
package com.simibubi.create.content.contraptions.components.flywheel;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.animation.InterpolatedChasingValue;
import net.minecraft.core.BlockPos;
@ -9,7 +9,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
public class FlywheelTileEntity extends GeneratingKineticTileEntity {
public class FlywheelTileEntity extends KineticTileEntity {
private float generatedCapacity;
private float generatedSpeed;
@ -25,7 +25,6 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
public void setRotation(float speed, float capacity) {
if (generatedSpeed != speed || generatedCapacity != capacity) {
if (speed == 0) {
if (stoppingCooldown == 0)
stoppingCooldown = 40;
@ -35,20 +34,15 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
stoppingCooldown = 0;
generatedSpeed = speed;
generatedCapacity = capacity;
updateGeneratedRotation();
}
}
@Override
public float getGeneratedSpeed() {
if (isRemoved()) return 0;
return convertToDirection(generatedSpeed, getBlockState().getValue(FlywheelBlock.HORIZONTAL_FACING));
}
public float calculateAddedStressCapacity() {
//return lastCapacityProvided = generatedCapacity;
return 0;
}
@Override
public AABB makeRenderBoundingBox() {
return super.makeRenderBoundingBox().inflate(2);
@ -78,7 +72,7 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
super.tick();
if (level.isClientSide) {
float targetSpeed = isVirtual() ? theoreticalSpeed : getGeneratedSpeed();
float targetSpeed = isVirtual() ? getTheoreticalSpeed() : getGeneratedSpeed();
visualSpeed.target(targetSpeed);
visualSpeed.tick();
angle += visualSpeed.value * 3 / 10f;
@ -86,13 +80,6 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
return;
}
/*
* After getting moved by pistons the generatedSpeed attribute reads 16 but the
* actual speed stays at 0, if it happens update rotation
*/
if (getGeneratedSpeed() != 0 && getSpeed() == 0)
updateGeneratedRotation();
if (stoppingCooldown == 0)
return;
@ -100,7 +87,6 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity {
if (stoppingCooldown == 0) {
generatedCapacity = 0;
generatedSpeed = 0;
updateGeneratedRotation();
}
}
}

View file

@ -19,7 +19,6 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
@ -44,7 +43,7 @@ public class MillstoneBlock extends KineticBlock implements ITE<MillstoneTileEnt
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == Direction.DOWN;
}

View file

@ -46,7 +46,7 @@ public class MechanicalMixerBlock extends KineticBlock implements ITE<Mechanical
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return false;
}

View file

@ -3,9 +3,6 @@ package com.simibubi.create.content.contraptions.components.motor;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.content.contraptions.solver.KineticSolver;
import com.simibubi.create.foundation.block.ITE;
import net.minecraft.core.BlockPos;
@ -13,8 +10,6 @@ import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.pathfinder.PathComputationType;
@ -44,7 +39,7 @@ public class CreativeMotorBlock extends DirectionalKineticBlock implements ITE<C
// IRotate:
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(FACING);
}
@ -54,11 +49,6 @@ public class CreativeMotorBlock extends DirectionalKineticBlock implements ITE<C
.getAxis();
}
@Override
public KineticConnections getInitialConnections(BlockState state) {
return AllConnections.HALF_SHAFT.apply(state.getValue(FACING));
}
@Override
public boolean hideStressImpact() {
return true;

View file

@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.motor;
import java.util.List;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
@ -15,7 +15,7 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
public class CreativeMotorTileEntity extends GeneratingKineticTileEntity {
public class CreativeMotorTileEntity extends KineticTileEntity {
public static final int DEFAULT_SPEED = 16;
protected ScrollValueBehaviour generatedSpeed;
@ -63,7 +63,7 @@ public class CreativeMotorTileEntity extends GeneratingKineticTileEntity {
step *= 4;
}
return (int) (current + (context.forward ? step : -step) == 0 ? step + 1 : step);
return current + (context.forward ? step : -step) == 0 ? step + 1 : step;
}
}

View file

@ -55,7 +55,7 @@ public class MechanicalPressBlock extends HorizontalKineticBlock implements ITE<
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(HORIZONTAL_FACING)
.getAxis();
}

View file

@ -21,7 +21,6 @@ import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
@ -97,9 +96,9 @@ public class SawBlock extends DirectionalAxisKineticBlock implements ITE<SawTile
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return isHorizontal(state) ? face == state.getValue(FACING).getOpposite()
: super.hasShaftTowards(world, pos, state, face);
: super.hasShaftTowards(state, face);
}
@Override
@ -116,12 +115,12 @@ public class SawBlock extends DirectionalAxisKineticBlock implements ITE<SawTile
public Class<SawTileEntity> getTileEntityClass() {
return SawTileEntity.class;
}
@Override
public BlockEntityType<? extends SawTileEntity> getTileEntityType() {
return AllTileEntities.SAW.get();
}
@Override
public boolean isPathfindable(BlockState state, BlockGetter reader, BlockPos pos, PathComputationType type) {
return false;

View file

@ -2,12 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
@ -18,10 +16,10 @@ public abstract class BearingBlock extends DirectionalKineticBlock {
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == state.getValue(FACING).getOpposite();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.getValue(FACING).getAxis();

View file

@ -77,10 +77,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity
if (!level.isClientSide && assembleNextTick) {
assembleNextTick = false;
if (running) {
boolean canDisassemble = true;
if (theoreticalSpeed == 0 && (canDisassemble || hourHand == null || hourHand.getContraption()
.getBlocks()
.isEmpty())) {
if (getTheoreticalSpeed() == 0) {
if (hourHand != null)
hourHand.getContraption()
.stop(level);

View file

@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be
import java.util.List;
import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
@ -25,7 +25,7 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
public class MechanicalBearingTileEntity extends KineticTileEntity
implements IBearingTileEntity, IDisplayAssemblyExceptions {
protected ScrollOptionBehaviour<RotationMode> movementMode;
@ -178,7 +178,6 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
running = true;
angle = 0;
sendData();
updateGeneratedRotation();
}
public void disassemble() {
@ -194,7 +193,6 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
movedContraption = null;
running = false;
updateGeneratedRotation();
assembleNextTick = false;
sendData();
}
@ -212,9 +210,8 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
if (running) {
boolean canDisassemble = movementMode.get() == RotationMode.ROTATE_PLACE
|| (isNearInitialAngle() && movementMode.get() == RotationMode.ROTATE_PLACE_RETURNED);
if (theoreticalSpeed == 0 && (canDisassemble || movedContraption == null || movedContraption.getContraption()
.getBlocks()
.isEmpty())) {
if (getTheoreticalSpeed() == 0 && (canDisassemble || movedContraption == null
|| movedContraption.getContraption().getBlocks().isEmpty())) {
if (movedContraption != null)
movedContraption.getContraption()
.stop(level);
@ -222,7 +219,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity
return;
}
} else {
if (theoreticalSpeed == 0 && !isWindmill())
if (getTheoreticalSpeed() == 0 && !isWindmill())
return;
assemble();
}

View file

@ -18,16 +18,38 @@ import net.minecraft.world.level.block.state.BlockState;
public class WindmillBearingTileEntity extends MechanicalBearingTileEntity {
protected ScrollOptionBehaviour<RotationDirection> movementDirection;
protected float lastGeneratedSpeed;
protected float generated;
public WindmillBearingTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
}
@Override
public void updateGeneratedRotation() {
super.updateGeneratedRotation();
lastGeneratedSpeed = getGeneratedSpeed();
public void initialize() {
updateGeneratedSpeed();
super.initialize();
}
@Override
public void assemble() {
super.assemble();
updateGeneratedSpeed();
}
@Override
public void disassemble() {
super.disassemble();
updateGeneratedSpeed();
}
public void updateGeneratedSpeed() {
if (!running) {
generated = 0;
} else if (movedContraption != null) {
int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks()
/ AllConfigs.SERVER.kinetics.windmillSailsPerRPM.get();
generated = Mth.clamp(sails, 1, 16) * getAngleSpeedDirection();
}
}
@Override
@ -39,13 +61,7 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity {
@Override
public float getGeneratedSpeed() {
if (!running)
return 0;
if (movedContraption == null)
return lastGeneratedSpeed;
int sails = ((BearingContraption) movedContraption.getContraption()).getSailBlocks()
/ AllConfigs.SERVER.kinetics.windmillSailsPerRPM.get();
return Mth.clamp(sails, 1, 16) * getAngleSpeedDirection();
return generated;
}
@Override
@ -60,14 +76,14 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity {
@Override
public void write(CompoundTag compound, boolean clientPacket) {
compound.putFloat("LastGenerated", lastGeneratedSpeed);
compound.putFloat("LastGenerated", generated);
super.write(compound, clientPacket);
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
if (!wasMoved)
lastGeneratedSpeed = compound.getFloat("LastGenerated");
generated = compound.getFloat("LastGenerated");
super.read(compound, clientPacket);
}
@ -86,7 +102,7 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity {
if (!running)
return;
if (!level.isClientSide)
updateGeneratedRotation();
updateGeneratedSpeed();
}
@Override
@ -94,16 +110,14 @@ public class WindmillBearingTileEntity extends MechanicalBearingTileEntity {
return true;
}
static enum RotationDirection implements INamedIconOptions {
enum RotationDirection implements INamedIconOptions {
CLOCKWISE(AllIcons.I_REFRESH), COUNTER_CLOCKWISE(AllIcons.I_ROTATE_CCW),
CLOCKWISE(AllIcons.I_REFRESH), COUNTER_CLOCKWISE(AllIcons.I_ROTATE_CCW),;
;
private final String translationKey;
private final AllIcons icon;
private String translationKey;
private AllIcons icon;
private RotationDirection(AllIcons icon) {
RotationDirection(AllIcons icon) {
this.icon = icon;
translationKey = "generic." + Lang.asId(name());
}

View file

@ -5,6 +5,8 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.Iterate;
@ -29,6 +31,15 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements
super(properties);
}
@Override
public ConnectionsBuilder buildInitialConnections(ConnectionsBuilder builder, BlockState state) {
return super.buildInitialConnections(builder, state).withDirAxial(
AllConnections.DirAxial.GANTRY_PINION,
state.getValue(FACING),
state.getValue(AXIS_ALONG_FIRST_COORDINATE)
);
}
@Override
public boolean canSurvive(BlockState state, LevelReader world, BlockPos pos) {
Direction direction = state.getValue(FACING);
@ -59,7 +70,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements
return InteractionResult.PASS;
if (player.getItemInHand(handIn)
.isEmpty()) {
withTileEntityDo(worldIn, pos, te -> te.checkValidGantryShaft());
withTileEntityDo(worldIn, pos, GantryCarriageTileEntity::checkValidGantryShaft);
return InteractionResult.SUCCESS;
}
return InteractionResult.PASS;
@ -103,8 +114,7 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements
}
public static boolean isValidGantryShaftAxis(BlockState pinionState, BlockState gantryState) {
return getValidGantryShaftAxis(pinionState) == gantryState.getValue(GantryShaftBlock.FACING)
.getAxis();
return getValidGantryShaftAxis(pinionState) == gantryState.getValue(GantryShaftBlock.FACING).getAxis();
}
public static Axis getValidGantryShaftAxis(BlockState state) {
@ -138,5 +148,5 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements
public BlockEntityType<? extends GantryCarriageTileEntity> getTileEntityType() {
return AllTileEntities.GANTRY_PINION.get();
}
}

View file

@ -122,25 +122,6 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp
super.read(compound, clientPacket);
}
public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff,
boolean connectedViaAxes, boolean connectedViaCogs) {
//float defaultModifier =
//super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs);
float defaultModifier = 1;
if (connectedViaAxes)
return defaultModifier;
if (!AllBlocks.GANTRY_SHAFT.has(stateTo))
return defaultModifier;
if (!stateTo.getValue(GantryShaftBlock.POWERED))
return defaultModifier;
Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ());
if (stateFrom.getValue(GantryCarriageBlock.FACING) != direction.getOpposite())
return defaultModifier;
return getGantryPinionModifier(stateTo.getValue(GantryShaftBlock.FACING), stateFrom.getValue(GantryCarriageBlock.FACING));
}
public static float getGantryPinionModifier(Direction shaft, Direction pinionDirection) {
Axis shaftAxis = shaft.getAxis();
float directionModifier = shaft.getAxisDirection()

View file

@ -50,7 +50,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
if (!(level.getBlockState(worldPosition)
.getBlock() instanceof PulleyBlock))
return;
if (theoreticalSpeed == 0)
if (getTheoreticalSpeed() == 0)
return;
int maxLength = AllConfigs.SERVER.kinetics.maxRopeLength.get();
int i = 1;

View file

@ -4,8 +4,6 @@ import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.KineticBlock;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.VecHelper;
@ -18,7 +16,6 @@ import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
@ -91,7 +88,7 @@ public class TurntableBlock extends KineticBlock implements ITE<TurntableTileEnt
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == Direction.DOWN;
}
@ -100,11 +97,6 @@ public class TurntableBlock extends KineticBlock implements ITE<TurntableTileEnt
return Axis.Y;
}
@Override
public KineticConnections getInitialConnections(BlockState state) {
return AllConnections.HALF_SHAFT.apply(Direction.DOWN);
}
@Override
public Class<TurntableTileEntity> getTileEntityClass() {
return TurntableTileEntity.class;

View file

@ -146,7 +146,7 @@ public class WaterWheelBlock extends DirectionalKineticBlock implements ITE<Wate
}
private void updateWheelSpeed(LevelAccessor world, BlockPos pos) {
withTileEntityDo(world, pos, WaterWheelTileEntity::updateGeneratedRotation);
withTileEntityDo(world, pos, WaterWheelTileEntity::updateGeneratedSpeed);
}
@Override
@ -185,7 +185,7 @@ public class WaterWheelBlock extends DirectionalKineticBlock implements ITE<Wate
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return state.getValue(FACING)
.getAxis() == face.getAxis();
}

View file

@ -4,7 +4,7 @@ import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.Iterate;
@ -15,9 +15,10 @@ import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
public class WaterWheelTileEntity extends GeneratingKineticTileEntity {
public class WaterWheelTileEntity extends KineticTileEntity {
private Map<Direction, Float> flows;
private float generated;
public WaterWheelTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
@ -27,6 +28,12 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity {
setLazyTickRate(20);
}
@Override
public void initialize() {
updateGeneratedSpeed();
super.initialize();
}
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
super.read(compound, clientPacket);
@ -59,12 +66,15 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity {
@Override
public float getGeneratedSpeed() {
float speed = 0;
return generated;
}
public void updateGeneratedSpeed() {
generated = 0;
for (Float f : flows.values())
speed += f;
if (speed != 0)
speed += AllConfigs.SERVER.kinetics.waterWheelBaseSpeed.get() * Math.signum(speed);
return speed;
generated += f;
if (generated != 0)
generated += AllConfigs.SERVER.kinetics.waterWheelBaseSpeed.get() * Math.signum(generated);
}
@Override

View file

@ -100,8 +100,8 @@ public class PumpTileEntity extends KineticTileEntity {
if (previousSpeed == getSpeed())
return;
if (theoreticalSpeed != 0)
reversed = theoreticalSpeed < 0;
if (getTheoreticalSpeed() != 0)
reversed = getTheoreticalSpeed() < 0;
if (level.isClientSide && !isVirtual())
return;

View file

@ -44,7 +44,7 @@ public class HosePulleyBlock extends HorizontalKineticBlock implements ITE<HoseP
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return state.getValue(HORIZONTAL_FACING)
.getClockWise() == face;
}
@ -98,7 +98,7 @@ public class HosePulleyBlock extends HorizontalKineticBlock implements ITE<HoseP
public Class<HosePulleyTileEntity> getTileEntityClass() {
return HosePulleyTileEntity.class;
}
@Override
public BlockEntityType<? extends HosePulleyTileEntity> getTileEntityType() {
return AllTileEntities.HOSE_PULLEY.get();

View file

@ -8,7 +8,6 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -31,7 +30,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -229,9 +227,6 @@ public class GantryShaftBlock extends DirectionalKineticBlock implements ITE<Gan
toUpdate.add(pos);
for (BlockPos blockPos : toUpdate) {
BlockState blockState = worldIn.getBlockState(blockPos);
BlockEntity te = worldIn.getBlockEntity(blockPos);
// if (te instanceof KineticTileEntity)
// ((KineticTileEntity) te).detachKinetics();
if (blockState.getBlock() instanceof GantryShaftBlock)
worldIn.setBlock(blockPos, blockState.setValue(POWERED, shouldPower), 2);
}
@ -257,23 +252,15 @@ public class GantryShaftBlock extends DirectionalKineticBlock implements ITE<Gan
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
return face.getAxis() == state.getValue(FACING)
.getAxis();
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(FACING).getAxis();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.getValue(FACING)
.getAxis();
return state.getValue(FACING).getAxis();
}
// @Override
// protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) {
// return super.areStatesKineticallyEquivalent(oldState, newState)
// && oldState.getValue(POWERED) == newState.getValue(POWERED);
// }
@Override
public float getParticleTargetRadius() {
return .35f;

View file

@ -4,6 +4,9 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageTileEntity;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
@ -19,6 +22,19 @@ public class GantryShaftTileEntity extends KineticTileEntity {
super(typeIn, pos, state);
}
@Override
public KineticConnections getConnections() {
BlockState state = getBlockState();
Direction facing = state.getValue(GantryShaftBlock.FACING);
ConnectionsBuilder builder = ConnectionsBuilder.builder().withFullShaft(facing.getAxis());
if (!AllBlocks.GANTRY_SHAFT.has(state) || !state.getValue(GantryShaftBlock.POWERED))
return builder.build();
return builder.withDirectional(AllConnections.Directional.GANTRY_RACK, facing).build();
}
public void checkAttachedCarriageBlocks() {
if (!canAssembleOn())
return;
@ -44,35 +60,6 @@ public class GantryShaftTileEntity extends KineticTileEntity {
checkAttachedCarriageBlocks();
}
public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff,
boolean connectedViaAxes, boolean connectedViaCogs) {
// float defaultModifier =
// super.propagateRotationTo(target, stateFrom, stateTo, diff, connectedViaAxes, connectedViaCogs);
float defaultModifier = 1;
if (connectedViaAxes)
return defaultModifier;
if (!stateFrom.getValue(GantryShaftBlock.POWERED))
return defaultModifier;
if (!AllBlocks.GANTRY_CARRIAGE.has(stateTo))
return defaultModifier;
Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ());
if (stateTo.getValue(GantryCarriageBlock.FACING) != direction)
return defaultModifier;
return GantryCarriageTileEntity.getGantryPinionModifier(stateFrom.getValue(GantryShaftBlock.FACING),
stateTo.getValue(GantryCarriageBlock.FACING));
}
public boolean isCustomConnection(KineticTileEntity other, BlockState state, BlockState otherState) {
if (!AllBlocks.GANTRY_CARRIAGE.has(otherState))
return false;
final BlockPos diff = other.getBlockPos()
.subtract(worldPosition);
Direction direction = Direction.getNearest(diff.getX(), diff.getY(), diff.getZ());
return otherState.getValue(GantryCarriageBlock.FACING) == direction;
}
public boolean canAssembleOn() {
BlockState blockState = getBlockState();
if (!AllBlocks.GANTRY_SHAFT.has(blockState))
@ -81,17 +68,12 @@ public class GantryShaftTileEntity extends KineticTileEntity {
return false;
float speed = getPinionMovementSpeed();
switch (blockState.getValue(GantryShaftBlock.PART)) {
case END:
return speed < 0;
case MIDDLE:
return speed != 0;
case START:
return speed > 0;
case SINGLE:
default:
return false;
}
return switch (blockState.getValue(GantryShaftBlock.PART)) {
case END -> speed < 0;
case MIDDLE -> speed != 0;
case START -> speed > 0;
default -> false;
};
}
public float getPinionMovementSpeed() {

View file

@ -11,6 +11,7 @@ import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
@ -46,8 +47,9 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements
}
@Override
public KineticConnections getInitialConnections(BlockState state) {
return AllConnections.SPEED_CONTROLLER.apply(state.getValue(HORIZONTAL_AXIS));
public ConnectionsBuilder buildInitialConnections(ConnectionsBuilder builder, BlockState state) {
return super.buildInitialConnections(builder, state)
.withAxial(AllConnections.Axial.SPEED_CONTROLLER_TOP, state.getValue(HORIZONTAL_AXIS));
}
@Override

View file

@ -61,11 +61,13 @@ public class SpeedControllerTileEntity extends KineticTileEntity {
}
@Override
public void onUpdate(Level level, KineticSolver solver, KineticNode node) {
public void onKineticsTick(Level level, KineticSolver solver, KineticNode node) {
BlockPos pos = node.getPos(), above = pos.above();
if (solver.isStressOnlyConnected(pos, above)) {
solver.getNode(above).get().setController(node, KineticControllerSerial.SPEED_CONTROLLER_COG);
}
solver.getNode(above).ifPresent(to -> {
if (node.checkStressOnlyConnection(to)) {
to.setController(KineticControllerSerial.SPEED_CONTROLLER_COG);
}
});
}
public void updateBracket() {

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
import java.util.Optional;
import java.util.Vector;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
@ -78,21 +79,11 @@ public class Instruction {
return 0;
}
int getSpeedModifier() {
switch (instruction) {
case TURN_ANGLE:
case TURN_DISTANCE:
return speedModifier.value;
case END:
case DELAY:
case AWAIT:
default:
break;
}
return 0;
Optional<InstructionSpeedModifiers> getSpeedModifier() {
return switch (instruction) {
case TURN_ANGLE, TURN_DISTANCE -> Optional.of(speedModifier);
default -> Optional.empty();
};
}
OnIsPoweredResult onRedstonePulse() {

View file

@ -18,12 +18,7 @@ public enum InstructionSpeedModifiers {
int value;
Component label;
private InstructionSpeedModifiers(int modifier, Component label) {
this.label = label;
translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name());
value = modifier;
}
private InstructionSpeedModifiers(int modifier, String label) {
InstructionSpeedModifiers(int modifier, String label) {
this.label = new TextComponent(label);
translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name());
value = modifier;

View file

@ -5,8 +5,8 @@ import java.util.Random;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticBlock;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.gui.ScreenOpener;
@ -38,6 +38,7 @@ import net.minecraftforge.fml.DistExecutor;
public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implements ITE<SequencedGearshiftTileEntity> {
public static final BooleanProperty VERTICAL = BooleanProperty.create("vertical");
public static final BooleanProperty POSITIVE = BooleanProperty.create("positive");
public static final IntegerProperty STATE = IntegerProperty.create("state", 0, 5);
public SequencedGearshiftBlock(Properties properties) {
@ -46,7 +47,7 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen
@Override
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
super.createBlockStateDefinition(builder.add(STATE, VERTICAL));
super.createBlockStateDefinition(builder.add(STATE, VERTICAL, POSITIVE));
}
@Override
@ -59,8 +60,7 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen
boolean isMoving) {
if (worldIn.isClientSide)
return;
if (!worldIn.getBlockTicks()
.willTickThisTick(pos, this))
if (!worldIn.getBlockTicks().willTickThisTick(pos, this))
worldIn.scheduleTick(pos, this, 0);
}
@ -72,11 +72,10 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
if (state.getValue(VERTICAL))
return face.getAxis()
.isVertical();
return super.hasShaftTowards(world, pos, state, face);
return face.getAxis().isVertical();
return super.hasShaftTowards(state, face);
}
@Override
@ -85,9 +84,8 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen
ItemStack held = player.getMainHandItem();
if (AllItems.WRENCH.isIn(held))
return InteractionResult.PASS;
if (held.getItem() instanceof BlockItem) {
BlockItem blockItem = (BlockItem) held.getItem();
if (blockItem.getBlock() instanceof KineticBlock && hasShaftTowards(worldIn, pos, state, hit.getDirection()))
if (held.getItem() instanceof BlockItem blockItem) {
if (blockItem.getBlock() instanceof KineticBlock && hasShaftTowards(state, hit.getDirection(), worldIn, hit.getBlockPos()))
return InteractionResult.PASS;
}
@ -102,37 +100,56 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen
ScreenOpener.open(new SequencedGearshiftScreen(te));
}
private static boolean sideFacesShaft(BlockPlaceContext context, Direction side) {
BlockPos pos = context.getClickedPos().relative(side);
BlockState state = context.getLevel().getBlockState(pos);
return state.getBlock() instanceof IRotate ir
&& ir.hasShaftTowards(state, side.getOpposite(), context.getLevel(), pos);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
Axis preferredAxis = RotatedPillarKineticBlock.getPreferredAxis(context);
if (preferredAxis != null && (context.getPlayer() == null || !context.getPlayer()
.isShiftKeyDown()))
return withAxis(preferredAxis, context);
return withAxis(context.getNearestLookingDirection()
.getAxis(), context);
Direction preferredFacing = null;
for (Direction dir : context.getNearestLookingDirections()) {
if (sideFacesShaft(context, dir.getOpposite())) {
preferredFacing = dir;
break;
}
}
if (preferredFacing != null && (context.getPlayer() == null || !context.getPlayer().isShiftKeyDown()))
return withFacing(preferredFacing, context);
return withFacing(context.getNearestLookingDirection(), context);
}
private BlockState withFacing(Direction dir, BlockPlaceContext context) {
Axis axis = dir.getAxis();
BlockState state = defaultBlockState()
.setValue(VERTICAL, axis.isVertical())
.setValue(POSITIVE, dir.getAxisDirection() == Direction.AxisDirection.POSITIVE);
if (axis.isVertical())
return state.setValue(HORIZONTAL_AXIS, context.getHorizontalDirection().getAxis());
return state.setValue(HORIZONTAL_AXIS, axis);
}
public Direction getFacing(BlockState state) {
Direction.AxisDirection axisDir = state.getValue(POSITIVE)
? Direction.AxisDirection.POSITIVE
: Direction.AxisDirection.NEGATIVE;
return Direction.fromAxisAndDirection(getRotationAxis(state), axisDir);
}
@Override
public InteractionResult onWrenched(BlockState state, UseOnContext context) {
BlockState newState = state;
if (context.getClickedFace()
.getAxis() != Axis.Y)
if (newState.getValue(HORIZONTAL_AXIS) != context.getClickedFace()
.getAxis())
if (context.getClickedFace().getAxis() != Axis.Y)
if (newState.getValue(HORIZONTAL_AXIS) != context.getClickedFace().getAxis())
newState = newState.cycle(VERTICAL);
return super.onWrenched(newState, context);
}
private BlockState withAxis(Axis axis, BlockPlaceContext context) {
BlockState state = defaultBlockState().setValue(VERTICAL, axis.isVertical());
if (axis.isVertical())
return state.setValue(HORIZONTAL_AXIS, context.getHorizontalDirection()
.getAxis());
return state.setValue(HORIZONTAL_AXIS, axis);
}
@Override
public Axis getRotationAxis(BlockState state) {
if (state.getValue(VERTICAL))

View file

@ -1,20 +1,19 @@
package com.simibubi.create.content.contraptions.relays.advanced.sequencer;
import java.util.Optional;
import java.util.Vector;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.content.contraptions.solver.KineticConnections.Entry;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class SequencedGearshiftTileEntity extends KineticTileEntity {
@ -47,7 +46,7 @@ public class SequencedGearshiftTileEntity extends KineticTileEntity {
return;
if (timer < currentInstructionDuration) {
timer++;
currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(theoreticalSpeed);
currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(getTheoreticalSpeed());
return;
}
run(currentInstruction + 1);
@ -58,7 +57,7 @@ public class SequencedGearshiftTileEntity extends KineticTileEntity {
super.onSpeedChanged(previousSpeed);
if (isIdle())
return;
float currentSpeed = Math.abs(theoreticalSpeed);
float currentSpeed = Math.abs(getTheoreticalSpeed());
if (Math.abs(previousSpeed) == currentSpeed)
return;
Instruction instruction = getInstruction(currentInstruction);
@ -101,12 +100,8 @@ public class SequencedGearshiftTileEntity extends KineticTileEntity {
return;
poweredPreviously = true;
switch (instruction.onRedstonePulse()) {
case CONTINUE:
if (instruction.onRedstonePulse() == OnIsPoweredResult.CONTINUE) {
run(currentInstruction + 1);
break;
default:
break;
}
}
@ -160,31 +155,31 @@ public class SequencedGearshiftTileEntity extends KineticTileEntity {
@Override
public KineticConnections getConnections() {
Direction.Axis axis = getBlockState().getValue(BlockStateProperties.HORIZONTAL_AXIS);
BlockState state = getBlockState();
SequencedGearshiftBlock block = (SequencedGearshiftBlock) state.getBlock();
Direction facing = block.getFacing(state);
if (isVirtual()) return AllConnections.FULL_SHAFT.apply(axis);
ConnectionsBuilder builder = ConnectionsBuilder.builder();
if (isVirtual()) return builder.withFullShaft(facing.getAxis()).build();
return getSpeedSource()
.map(p -> {
Direction dir = Direction.fromNormal(p.subtract(getBlockPos()));
float modifier = getModifier();
if (modifier == 0 || isRemoved()) return AllConnections.HALF_SHAFT.apply(dir);
builder = builder.withHalfShaft(facing.getOpposite());
Direction opp = dir.getOpposite();
String from = AllConnections.type(AllConnections.TYPE_SHAFT, opp);
String to = AllConnections.type(AllConnections.TYPE_SHAFT, dir);
return new KineticConnections(new Entry(opp.getNormal(), from, to, modifier))
.merge(AllConnections.HALF_SHAFT.apply(dir));
})
.orElse(AllConnections.FULL_SHAFT.apply(axis));
Optional<InstructionSpeedModifiers> modifier = getModifier();
if (modifier.isEmpty() || isRemoved()) return builder.build();
AllConnections.Shafts shaft = switch(modifier.get()) {
case FORWARD_FAST -> AllConnections.Shafts.SHAFT_X2;
case FORWARD -> AllConnections.Shafts.SHAFT;
case BACK -> AllConnections.Shafts.SHAFT_REV;
case BACK_FAST -> AllConnections.Shafts.SHAFT_REV_X2;
};
return builder.withHalfShaft(shaft, facing).build();
}
public int getModifier() {
if (currentInstruction >= instructions.size())
return 0;
return isIdle() ? 0
: instructions.get(currentInstruction)
.getSpeedModifier();
public Optional<InstructionSpeedModifiers> getModifier() {
if (currentInstruction >= instructions.size() || isIdle())
return Optional.empty();
return instructions.get(currentInstruction).getSpeedModifier();
}
}

View file

@ -5,6 +5,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;
import net.minecraft.world.level.LevelReader;
import org.apache.commons.lang3.mutable.MutableBoolean;
import com.simibubi.create.AllBlocks;
@ -52,7 +54,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
@ -113,10 +114,11 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
// }
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face, LevelReader level, BlockPos pos) {
if (face.getAxis() != getRotationAxis(state))
return false;
return getTileEntityOptional(world, pos).map(BeltTileEntity::hasPulley)
return getTileEntityOptional(level, pos).map(BeltTileEntity::hasPulley)
.orElse(false);
}

View file

@ -18,7 +18,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
@ -60,7 +59,7 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock
// IRotate:
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(AXIS);
}
@ -84,7 +83,7 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState, LevelAccessor world,
BlockPos pos, BlockPos neighbourPos) {
if (state.getValue(BlockStateProperties.WATERLOGGED))
if (state.getValue(BlockStateProperties.WATERLOGGED))
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
return state;
}
@ -94,7 +93,7 @@ public abstract class AbstractShaftBlock extends RotatedPillarKineticBlock
FluidState ifluidstate = context.getLevel()
.getFluidState(context.getClickedPos());
return super.getStateForPlacement(context).setValue(BlockStateProperties.WATERLOGGED,
Boolean.valueOf(ifluidstate.getType() == Fluids.WATER));
ifluidstate.getType() == Fluids.WATER);
}
@Override

View file

@ -8,7 +8,7 @@ import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock;
import com.simibubi.create.content.contraptions.relays.encased.EncasedCogwheelBlock;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.utility.Iterate;
@ -62,12 +62,6 @@ public class CogWheelBlock extends AbstractShaftBlock implements ICogWheel {
return !isLarge;
}
@Override
public KineticConnections getInitialConnections(BlockState state) {
return (isLargeCog() ? AllConnections.LARGE_COG_FULL_SHAFT : AllConnections.SMALL_COG_FULL_SHAFT)
.apply(state.getValue(AXIS));
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.getValue(AXIS));
@ -104,10 +98,9 @@ public class CogWheelBlock extends AbstractShaftBlock implements ICogWheel {
for (Direction d : Iterate.directionsInAxis(state.getValue(AXIS))) {
BlockState adjacentState = world.getBlockState(pos.relative(d));
if (!(adjacentState.getBlock() instanceof IRotate))
if (!(adjacentState.getBlock() instanceof IRotate def))
continue;
IRotate def = (IRotate) adjacentState.getBlock();
if (!def.hasShaftTowards(world, pos.relative(d), adjacentState, d.getOpposite()))
if (!def.hasShaftTowards(adjacentState, d.getOpposite(), world, pos.relative(d)))
continue;
encasedState =
encasedState.cycle(d.getAxisDirection() == AxisDirection.POSITIVE ? EncasedCogwheelBlock.TOP_SHAFT

View file

@ -40,11 +40,6 @@ public class ShaftBlock extends AbstractShaftBlock {
return AllBlocks.SHAFT.has(state);
}
@Override
public KineticConnections getInitialConnections(BlockState state) {
return AllConnections.FULL_SHAFT.apply(state.getValue(AXIS));
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) {
return AllShapes.SIX_VOXEL_POLE.get(state.getValue(AXIS));

View file

@ -47,7 +47,7 @@ public abstract class AbstractEncasedShaftBlock extends RotatedPillarKineticBloc
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(AXIS);
}

View file

@ -41,12 +41,6 @@ public class AdjustablePulleyBlock extends EncasedBeltBlock {
.hasNeighborSignal(context.getClickedPos()));
}
// @Override
// protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) {
// return super.areStatesKineticallyEquivalent(oldState, newState)
// && oldState.getValue(POWERED) == newState.getValue(POWERED);
// }
@Override
public void neighborChanged(BlockState state, Level worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.relays.encased;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import net.minecraft.core.BlockPos;
@ -20,13 +21,12 @@ public class ClutchTileEntity extends KineticTileEntity {
@Override
public KineticConnections getConnections() {
BlockState state = getBlockState();
Direction.Axis axis = state.getValue(BlockStateProperties.AXIS);
Direction dir = AllConnections.pos(state.getValue(GearshiftBlock.AXIS));
if (!state.getValue(BlockStateProperties.POWERED)) return AllConnections.FULL_SHAFT.apply(axis);
return getSpeedSource()
.map(p -> AllConnections.HALF_SHAFT.apply(Direction.fromNormal(p.subtract(getBlockPos()))))
.orElse(AllConnections.FULL_SHAFT.apply(axis));
ConnectionsBuilder builder = ConnectionsBuilder.builder();
if (!state.getValue(BlockStateProperties.POWERED))
return builder.withFullShaft(dir.getAxis()).build();
return builder.withHalfShaft(dir.getOpposite()).build();
}
}

View file

@ -155,7 +155,7 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock implements ITE<K
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(AXIS);
}

View file

@ -48,15 +48,14 @@ public class EncasedCogInstance extends KineticTileInstance<KineticTileEntity> {
rotatingModel = setup(getCogModel().createInstance());
Block block = blockState.getBlock();
if (!(block instanceof IRotate))
if (!(block instanceof IRotate def))
return;
IRotate def = (IRotate) block;
rotatingTopShaft = Optional.empty();
rotatingBottomShaft = Optional.empty();
for (Direction d : Iterate.directionsInAxis(axis)) {
if (!def.hasShaftTowards(tile.getLevel(), tile.getBlockPos(), blockState, d))
if (!def.hasShaftTowards(blockState, d, tile.getLevel(), tile.getBlockPos()))
continue;
RotatingData data = setup(getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, d)
.createInstance());

View file

@ -45,12 +45,11 @@ public class EncasedCogRenderer extends KineticTileEntityRenderer {
BlockState blockState = te.getBlockState();
Block block = blockState.getBlock();
if (!(block instanceof IRotate))
if (!(block instanceof IRotate def))
return;
IRotate def = (IRotate) block;
for (Direction d : Iterate.directionsInAxis(getRotationAxisOf(te))) {
if (!def.hasShaftTowards(te.getLevel(), te.getBlockPos(), blockState, d))
if (!def.hasShaftTowards(blockState, d, te.getLevel(), te.getBlockPos()))
continue;
renderRotatingBuffer(te, CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), d),
ms, buffer.getBuffer(RenderType.solid()), light);

View file

@ -133,7 +133,7 @@ public class EncasedCogwheelBlock extends RotatedPillarKineticBlock
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(AXIS)
&& state.getValue(face.getAxisDirection() == AxisDirection.POSITIVE ? TOP_SHAFT : BOTTOM_SHAFT);
}

View file

@ -1,25 +1,26 @@
package com.simibubi.create.content.contraptions.relays.encased;
import java.util.Random;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.foundation.block.ITE;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.core.Direction;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition.Builder;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.ticks.TickPriority;
import net.minecraft.world.level.material.PushReaction;
public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<KineticTileEntity> {
import javax.annotation.Nullable;
public class GearshiftBlock extends RotatedPillarKineticBlock implements ITE<KineticTileEntity> {
public static final BooleanProperty POWERED = BlockStateProperties.POWERED;
@ -36,8 +37,8 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Kin
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return super.getStateForPlacement(context).setValue(POWERED,
context.getLevel().hasNeighborSignal(context.getClickedPos()));
return super.getStateForPlacement(context)
.setValue(POWERED, context.getLevel().hasNeighborSignal(context.getClickedPos()));
}
@Override
@ -62,5 +63,23 @@ public class GearshiftBlock extends AbstractEncasedShaftBlock implements ITE<Kin
return AllTileEntities.GEARSHIFT.get();
}
@Override
public boolean shouldCheckWeakPower(BlockState state, LevelReader world, BlockPos pos, Direction side) {
return false;
}
@Override
public PushReaction getPistonPushReaction(@Nullable BlockState state) {
return PushReaction.NORMAL;
}
@Override
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() == state.getValue(AXIS);
}
@Override
public Direction.Axis getRotationAxis(BlockState state) {
return state.getValue(AXIS);
}
}

View file

@ -11,6 +11,7 @@ import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileInstance;
import com.simibubi.create.content.contraptions.base.flwdata.RotatingData;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.Direction;
@ -25,15 +26,13 @@ public class SplitShaftInstance extends KineticTileInstance<KineticTileEntity> {
keys = new ArrayList<>(2);
float speed = tile.getSpeed();
Material<RotatingData> rotatingMaterial = getRotatingMaterial();
for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) {
for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) {
Instancer<RotatingData> half = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, dir);
float splitSpeed = speed * tile.getRotationSpeedModifier(dir);
float splitSpeed = tile.getShaftSpeed(dir);
keys.add(setup(half.createInstance(), splitSpeed));
}
@ -46,8 +45,8 @@ public class SplitShaftInstance extends KineticTileInstance<KineticTileEntity> {
Direction[] directions = Iterate.directionsInAxis(boxAxis);
for (int i : Iterate.zeroAndOne) {
updateRotation(keys.get(i), tile.getSpeed() * tile.getRotationSpeedModifier(directions[i]));
for (int i : Iterate.zeroAndOne) {
updateRotation(keys.get(i), tile.getShaftSpeed(directions[i]));
}
}

View file

@ -6,6 +6,7 @@ import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.render.CachedBufferer;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
@ -41,12 +42,8 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer {
continue;
float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = (time * te.getSpeed() * 3f / 10) % 360;
float modifier = 1;
float angle = (time * te.getShaftSpeed(direction) * 3f / 10) % 360;
modifier = te.getRotationSpeedModifier(direction);
angle *= modifier;
angle += offset;
angle = angle / 180f * (float) Math.PI;

View file

@ -69,7 +69,7 @@ public class GaugeBlock extends DirectionalAxisKineticBlock implements ITE<Gauge
BlockState placedOnState = world.getBlockState(placedOnPos);
Block block = placedOnState.getBlock();
if (block instanceof IRotate && ((IRotate) block).hasShaftTowards(world, placedOnPos, placedOnState, face)) {
if (block instanceof IRotate ir && ir.hasShaftTowards(placedOnState, face, world, placedOnPos)) {
BlockState toPlace = defaultBlockState();
Direction horizontalFacing = context.getHorizontalDirection();
Direction nearestLookingDirection = context.getNearestLookingDirection();

View file

@ -62,7 +62,7 @@ public class SpeedGaugeTileEntity extends GaugeTileEntity {
super.addToGoggleTooltip(tooltip, isPlayerSneaking);
tooltip.add(componentSpacing.plainCopy().append(Lang.translate("gui.speedometer.title").withStyle(ChatFormatting.GRAY)));
tooltip.add(componentSpacing.plainCopy().append(SpeedLevel.getFormattedSpeedText(theoreticalSpeed, isOverstressed())));
tooltip.add(componentSpacing.plainCopy().append(SpeedLevel.getFormattedSpeedText(getTheoreticalSpeed(), isOverstressed())));
return true;
}

View file

@ -6,8 +6,15 @@ import java.util.List;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.DirectionHelper;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
@ -17,7 +24,6 @@ import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
@ -48,7 +54,7 @@ public class GearboxBlock extends RotatedPillarKineticBlock implements ITE<Gearb
return super.getDrops(state, builder);
return Arrays.asList(new ItemStack(AllItems.VERTICAL_GEARBOX.get()));
}
@Override
public ItemStack getCloneItemStack(BlockState state, HitResult target, BlockGetter world, BlockPos pos,
Player player) {
@ -65,7 +71,7 @@ public class GearboxBlock extends RotatedPillarKineticBlock implements ITE<Gearb
// IRotate:
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face.getAxis() != state.getValue(AXIS);
}
@ -74,6 +80,26 @@ public class GearboxBlock extends RotatedPillarKineticBlock implements ITE<Gearb
return state.getValue(AXIS);
}
private static boolean isReversed(Direction from, Direction to) {
if (from == to) return false;
Axis fromAxis = from.getAxis(), toAxis = to.getAxis();
if (fromAxis == toAxis) return true;
return AllConnections.perpendicularRatios(to.getNormal().subtract(from.getNormal()), fromAxis, toAxis) == -1;
}
@Override
public ConnectionsBuilder buildInitialConnections(ConnectionsBuilder builder, BlockState state) {
Axis axis = state.getValue(AXIS);
Direction start = DirectionHelper.getPositivePerpendicular(axis);
for (Direction cur : Iterate.directionsPerpendicularTo(axis)) {
AllConnections.Shafts shaft = isReversed(start, cur)
? AllConnections.Shafts.SHAFT_REV
: AllConnections.Shafts.SHAFT;
builder = builder.withHalfShaft(shaft, cur);
}
return builder;
}
@Override
public Class<GearboxTileEntity> getTileEntityClass() {
return GearboxTileEntity.class;

View file

@ -12,7 +12,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileInstance;
import com.simibubi.create.content.contraptions.base.flwdata.RotatingData;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
@ -20,7 +19,6 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
protected final EnumMap<Direction, RotatingData> keys;
protected Direction sourceFacing;
public GearboxInstance(MaterialManager modelManager, GearboxTileEntity tile) {
super(modelManager, tile);
@ -31,7 +29,6 @@ public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
int blockLight = world.getBrightness(LightLayer.BLOCK, pos);
int skyLight = world.getBrightness(LightLayer.SKY, pos);
updateSourceFacing();
Material<RotatingData> rotatingMaterial = getRotatingMaterial();
@ -56,29 +53,11 @@ public class GearboxInstance extends KineticTileInstance<GearboxTileEntity> {
}
private float getSpeed(Direction direction) {
float speed = tile.getSpeed();
if (speed != 0 && sourceFacing != null) {
if (sourceFacing.getAxis() == direction.getAxis())
speed *= sourceFacing == direction ? 1 : -1;
else if (sourceFacing.getAxisDirection() == direction.getAxisDirection())
speed *= -1;
}
return speed;
}
protected void updateSourceFacing() {
if (tile.hasSource()) {
BlockPos source = tile.source.subtract(pos);
sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ());
} else {
sourceFacing = null;
}
return tile.getShaftSpeed(direction);
}
@Override
public void update() {
updateSourceFacing();
for (Map.Entry<Direction, RotatingData> key : keys.entrySet()) {
Direction direction = key.getKey();
Direction.Axis axis = direction.getAxis();

View file

@ -40,16 +40,7 @@ public class GearboxRenderer extends KineticTileEntityRenderer {
SuperByteBuffer shaft = CachedBufferer.partialFacing(AllBlockPartials.SHAFT_HALF, te.getBlockState(), direction);
float offset = getRotationOffsetForPosition(te, pos, axis);
float angle = (time * te.getSpeed() * 3f / 10) % 360;
if (te.getSpeed() != 0 && te.hasSource()) {
BlockPos source = te.source.subtract(te.getBlockPos());
Direction sourceFacing = Direction.getNearest(source.getX(), source.getY(), source.getZ());
if (sourceFacing.getAxis() == direction.getAxis())
angle *= sourceFacing == direction ? 1 : -1;
else if (sourceFacing.getAxisDirection() == direction.getAxisDirection())
angle *= -1;
}
float angle = (time * te.getShaftSpeed(direction) * 3f / 10) % 360;
angle += offset;
angle = angle / 180f * (float) Math.PI;

View file

@ -2,7 +2,9 @@ package com.simibubi.create.content.contraptions.relays.gearbox;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.relays.encased.GearshiftBlock;
import com.simibubi.create.content.contraptions.solver.AllConnections;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import net.minecraft.core.BlockPos;
@ -20,13 +22,15 @@ public class GearshiftTileEntity extends KineticTileEntity {
@Override
public KineticConnections getConnections() {
BlockState state = getBlockState();
Direction.Axis axis = state.getValue(BlockStateProperties.AXIS);
Direction dir = AllConnections.pos(state.getValue(GearshiftBlock.AXIS));
if (!state.getValue(BlockStateProperties.POWERED)) return AllConnections.FULL_SHAFT.apply(axis);
return getSpeedSource()
.map(p -> AllConnections.FULL_SHAFT_REVERSER.apply(Direction.fromNormal(p.subtract(getBlockPos()))))
.orElse(AllConnections.FULL_SHAFT.apply(axis));
ConnectionsBuilder builder = ConnectionsBuilder.builder();
if (!state.getValue(BlockStateProperties.POWERED))
return builder.withFullShaft(dir.getAxis()).build();
return builder
.withHalfShaft(AllConnections.Shafts.SHAFT_REV, dir)
.withHalfShaft(AllConnections.Shafts.SHAFT, dir.getOpposite())
.build();
}
}

View file

@ -4,6 +4,7 @@ import java.util.Map;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.BlockPos;
@ -29,7 +30,7 @@ public class VerticalGearboxItem extends BlockItem {
@Override
public void fillItemCategory(CreativeModeTab p_150895_1_, NonNullList<ItemStack> p_150895_2_) {
}
@Override
public String getDescriptionId() {
return "item.create.vertical_gearbox";
@ -41,25 +42,26 @@ public class VerticalGearboxItem extends BlockItem {
@Override
protected boolean updateCustomBlockEntityTag(BlockPos pos, Level world, Player player, ItemStack stack, BlockState state) {
Axis prefferedAxis = null;
Axis preferredAxis = null;
for (Direction side : Iterate.horizontalDirections) {
BlockState blockState = world.getBlockState(pos.relative(side));
if (blockState.getBlock() instanceof IRotate) {
if (((IRotate) blockState.getBlock()).hasShaftTowards(world, pos.relative(side), blockState,
side.getOpposite()))
if (prefferedAxis != null && prefferedAxis != side.getAxis()) {
prefferedAxis = null;
if (blockState.getBlock() instanceof IRotate ir) {
if (ir.hasShaftTowards(blockState, side.getOpposite(), world, pos.relative(side)))
if (preferredAxis != null && preferredAxis != side.getAxis()) {
preferredAxis = null;
break;
} else {
prefferedAxis = side.getAxis();
preferredAxis = side.getAxis();
}
}
}
Axis axis = prefferedAxis == null ? player.getDirection()
Axis axis = preferredAxis == null ? player.getDirection()
.getClockWise()
.getAxis() : prefferedAxis == Axis.X ? Axis.Z : Axis.X;
world.setBlockAndUpdate(pos, state.setValue(BlockStateProperties.AXIS, axis));
.getAxis() : preferredAxis == Axis.X ? Axis.Z : Axis.X;
BlockState newState = state.setValue(BlockStateProperties.AXIS, axis);
KineticTileEntity.switchToBlockState(world, pos, newState);
return super.updateCustomBlockEntityTag(pos, world, player, stack, state);
}

View file

@ -1,13 +1,13 @@
package com.simibubi.create.content.contraptions.solver;
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryCarriageTileEntity;
import com.simibubi.create.foundation.utility.DirectionHelper;
import com.simibubi.create.foundation.utility.LazyMap;
import com.simibubi.create.content.contraptions.solver.KineticConnections.Entry;
import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Vec3i;
import net.minecraft.util.StringRepresentable;
import java.util.LinkedList;
import java.util.List;
@ -15,34 +15,250 @@ import java.util.Optional;
public class AllConnections {
private static Direction pos(Axis axis) {
public static void register() {
Shafts.registerTypes();
Directional.registerTypes();
Axial.registerTypes();
DirAxial.registerTypes();
Shafts.registerRatios();
Directional.registerRatios();
Axial.registerRatios();
DirAxial.registerRatios();
}
private static record Entry(Vec3i offset, String to, float ratio) {}
public enum Shafts {
SHAFT("shaft", 1),
SHAFT_REV("shaft_rev", -1),
SHAFT_X2("shaft_x2", 2),
SHAFT_REV_X2("shaft_rev_x2", -2);
public final String prefix;
public final float ratio;
Shafts(String prefix, float ratio) {
this.prefix = prefix;
this.ratio = ratio;
}
public String type(Direction dir) {
return prefix + "." + dir;
}
public static void registerTypes() {
for (Shafts value : values()) {
for (Direction dir : Direction.values()) {
KineticConnectionsRegistry.registerConnectionType(value.type(dir));
}
}
}
public static void registerRatios() {
for (Shafts from : values()) {
for (Shafts to : values()) {
for (Direction dir : Direction.values()) {
KineticConnectionsRegistry.registerConnectionRatio(
KineticConnectionsRegistry.getConnectionType(from.type(dir)).get(),
KineticConnectionsRegistry.getConnectionType(to.type(dir.getOpposite())).get(),
dir.getNormal(),
from.ratio / to.ratio
);
}
}
}
}
}
public enum Directional {
GANTRY_RACK("gantry_rack") {
@Override
public List<Entry> genConnections(Direction dir) { return List.of(); }
};
public final String prefix;
Directional(String prefix) {
this.prefix = prefix;
}
public abstract List<Entry> genConnections(Direction dir);
public String type(Direction dir) {
return prefix + "." + dir;
}
public static void registerTypes() {
for (Directional value : values()) {
for (Direction dir : Direction.values()) {
KineticConnectionsRegistry.registerConnectionType(value.type(dir));
}
}
}
public static void registerRatios() {
for (Directional from : values()) {
for (Direction dir : Direction.values()) {
String fromType = from.type(dir);
from.genConnections(dir).forEach(entry -> KineticConnectionsRegistry.registerConnectionRatio(
KineticConnectionsRegistry.getConnectionType(fromType).get(),
KineticConnectionsRegistry.getConnectionType(entry.to).get(),
entry.offset,
entry.ratio
));
}
}
}
}
public enum Axial {
SMALL_COG("small_cog") {
@Override
public List<Entry> genConnections(Axis axis) {
List<Entry> out = new LinkedList<>();
for (Direction cur : Iterate.directionsPerpendicularTo(axis)) {
Direction next = rot(cur, axis);
out.add(new Entry(cur.getNormal(), SMALL_COG.type(axis), -1));
out.add(new Entry(cur.getNormal().relative(next), LARGE_COG.type(axis), -0.5f));
}
return out;
}
},
LARGE_COG("large_cog") {
@Override
public List<Entry> genConnections(Axis axis) {
List<Entry> out = new LinkedList<>();
for (Direction cur : Iterate.directionsPerpendicularTo(axis)) {
out.add(largeToLarge(cur.getNormal().relative(pos(axis)), axis, cur.getAxis()));
out.add(largeToLarge(cur.getNormal().relative(neg(axis)), axis, cur.getAxis()));
}
return out;
}
},
SPEED_CONTROLLER_TOP("speed_controller_top") {
@Override
public List<Entry> genConnections(Axis axis) {
return oppAxis(axis)
.map(opp -> List.of(new Entry(Direction.UP.getNormal(), LARGE_COG.type(opp), 0)))
.orElseGet(List::of);
}
};
public final String prefix;
Axial(String prefix) {
this.prefix = prefix;
}
public abstract List<Entry> genConnections(Axis axis);
public String type(Axis axis) {
return prefix + "." + axis;
}
public static void registerTypes() {
for (Axial value : values()) {
for (Axis axis : Axis.values()) {
KineticConnectionsRegistry.registerConnectionType(value.type(axis));
}
}
}
public static void registerRatios() {
for (Axial from : values()) {
for (Axis axis : Axis.values()) {
String fromType = from.type(axis);
from.genConnections(axis).forEach(entry -> KineticConnectionsRegistry.registerConnectionRatio(
KineticConnectionsRegistry.getConnectionType(fromType).get(),
KineticConnectionsRegistry.getConnectionType(entry.to).get(),
entry.offset,
entry.ratio
));
}
}
}
}
public enum DirAxial {
GANTRY_PINION("gantry_pinion") {
@Override
public List<Entry> genConnections(Direction dir, boolean first) {
Axis shaftAxis = switch (dir.getAxis()) {
case X -> first ? Axis.Z : Axis.Y;
case Y -> first ? Axis.Z : Axis.X;
case Z -> first ? Axis.Y : Axis.X;
};
List<Entry> out = new LinkedList<>();
for (Direction shaftDir : Iterate.directionsInAxis(shaftAxis)) {
float ratio = GantryCarriageTileEntity.getGantryPinionModifier(shaftDir, dir);
out.add(new Entry(dir.getOpposite().getNormal(), Directional.GANTRY_RACK.type(shaftDir), ratio));
}
return out;
}
};
public final String prefix;
DirAxial(String prefix) {
this.prefix = prefix;
}
public abstract List<Entry> genConnections(Direction dir, boolean first);
public String type(Direction dir, boolean first) {
return prefix + "." + dir + "_" + (first ? "0" : "1");
}
public static void registerTypes() {
for (DirAxial value : values()) {
for (Direction dir : Direction.values()) {
for (boolean first : Iterate.trueAndFalse) {
KineticConnectionsRegistry.registerConnectionType(value.type(dir, first));
}
}
}
}
public static void registerRatios() {
for (DirAxial from : values()) {
for (Direction dir : Direction.values()) {
for (boolean first : Iterate.trueAndFalse) {
String fromType = from.type(dir, first);
from.genConnections(dir, first).forEach(entry -> KineticConnectionsRegistry.registerConnectionRatio(
KineticConnectionsRegistry.getConnectionType(fromType).get(),
KineticConnectionsRegistry.getConnectionType(entry.to).get(),
entry.offset,
entry.ratio
));
}
}
}
}
}
public static Direction pos(Axis axis) {
return Direction.get(Direction.AxisDirection.POSITIVE, axis);
}
private static Direction neg(Axis axis) {
public static Direction neg(Axis axis) {
return Direction.get(Direction.AxisDirection.NEGATIVE, axis);
}
public static String type(String name, StringRepresentable ext) {
return name + "." + ext;
public static Direction rot(Direction dir, Axis axis) {
return DirectionHelper.rotateAround(dir, axis);
}
public static final String
TYPE_SHAFT = "shaft",
TYPE_LARGE_COG = "large_cog",
TYPE_SMALL_COG = "small_cog",
TYPE_SPEED_CONTROLLER_TOP = "speed_controller_top";
private static Vec3i rhr(Vec3i vec) {
if (vec.getX() == 0) return new Vec3i(vec.getY(), vec.getZ(), 0);
if (vec.getY() == 0) return new Vec3i(vec.getZ(), vec.getX(), 0);
return new Vec3i(vec.getX(), vec.getY(), 0);
public static float perpendicularRatios(Vec3i diff, Axis from, Axis to) {
int fromDiff = from.choose(diff.getX(), diff.getY(), diff.getZ());
int toDiff = to.choose(diff.getX(), diff.getY(), diff.getZ());
return fromDiff * toDiff;
}
private static Entry largeToLarge(Vec3i diff, Axis from, Axis to) {
Vec3i rhr = rhr(diff);
float ratio = rhr.getX() == rhr.getY() ? 1 : rhr.getX();
return new Entry(diff, type(TYPE_LARGE_COG, from), type(TYPE_LARGE_COG, to), ratio);
return new Entry(diff, Axial.LARGE_COG.type(to), perpendicularRatios(diff, from, to));
}
private static Optional<Axis> oppAxis(Axis axis) {
@ -53,69 +269,4 @@ public class AllConnections {
};
}
public static final KineticConnections EMPTY = new KineticConnections();
public static final LazyMap<Direction, KineticConnections>
HALF_SHAFT = new LazyMap<>(dir ->
new KineticConnections(
new Entry(dir.getNormal(), type(TYPE_SHAFT, dir), type(TYPE_SHAFT, dir.getOpposite())))),
HALF_SHAFT_REVERSER = new LazyMap<>(dir ->
new KineticConnections(
new Entry(dir.getNormal(), type(TYPE_SHAFT, dir), type(TYPE_SHAFT, dir.getOpposite()), -1))),
FULL_SHAFT_REVERSER = new LazyMap<>(dir ->
HALF_SHAFT.apply(dir).merge(HALF_SHAFT_REVERSER.apply(dir.getOpposite())));
public static final LazyMap<Axis, KineticConnections>
FULL_SHAFT = new LazyMap<>(axis -> HALF_SHAFT.apply(pos(axis)).merge(HALF_SHAFT.apply(neg(axis)))),
LARGE_COG = new LazyMap<>(axis -> {
String large = type(TYPE_LARGE_COG, axis);
String small = type(TYPE_SMALL_COG, axis);
List<Entry> out = new LinkedList<>();
Direction cur = DirectionHelper.getPositivePerpendicular(axis);
for (int i = 0; i < 4; i++) {
Direction next = DirectionHelper.rotateAround(cur, axis);
out.add(largeToLarge(cur.getNormal().relative(pos(axis)), axis, cur.getAxis()));
out.add(largeToLarge(cur.getNormal().relative(neg(axis)), axis, cur.getAxis()));
out.add(new Entry(cur.getNormal().relative(next), large, small, -2));
cur = next;
}
oppAxis(axis).ifPresent(opp -> {
String sc = type(TYPE_SPEED_CONTROLLER_TOP, opp);
out.add(new Entry(Direction.DOWN.getNormal(), large, sc).stressOnly());
});
return new KineticConnections(out);
}),
SMALL_COG = new LazyMap<>(axis -> {
String large = type(TYPE_LARGE_COG, axis);
String small = type(TYPE_SMALL_COG, axis);
List<Entry> out = new LinkedList<>();
Direction cur = DirectionHelper.getPositivePerpendicular(axis);
for (int i = 0; i < 4; i++) {
Direction next = DirectionHelper.rotateAround(cur, axis);
out.add(new Entry(cur.getNormal(), small, small, i < 2 ? -1 : 1));
out.add(new Entry(cur.getNormal().relative(next), small, large));
cur = next;
}
return new KineticConnections(out);
}),
LARGE_COG_FULL_SHAFT = new LazyMap<>(axis -> LARGE_COG.apply(axis).merge(FULL_SHAFT.apply(axis))),
SMALL_COG_FULL_SHAFT = new LazyMap<>(axis -> SMALL_COG.apply(axis).merge(FULL_SHAFT.apply(axis))),
SPEED_CONTROLLER = new LazyMap<>(axis -> {
String sc = type(TYPE_SPEED_CONTROLLER_TOP, axis);
String large = type(TYPE_LARGE_COG, oppAxis(axis).get());
Vec3i up = Direction.UP.getNormal();
return new KineticConnections(new Entry(up, sc, large).stressOnly()).merge(FULL_SHAFT.apply(axis));
});
}

View file

@ -0,0 +1,54 @@
package com.simibubi.create.content.contraptions.solver;
import net.minecraft.core.Direction;
import java.util.HashSet;
import java.util.Set;
public class ConnectionsBuilder {
private final Set<KineticConnection> connections = new HashSet<>();
public static ConnectionsBuilder builder() {
return new ConnectionsBuilder();
}
public KineticConnections build() {
return new KineticConnections(connections);
}
public ConnectionsBuilder withHalfShaft(AllConnections.Shafts shaft, Direction dir) {
connections.add(KineticConnectionsRegistry.getConnectionType(shaft.type(dir)).get());
return this;
}
public ConnectionsBuilder withHalfShaft(Direction dir) {
return withHalfShaft(AllConnections.Shafts.SHAFT, dir);
}
public ConnectionsBuilder withFullShaft(Direction.Axis axis) {
return this.withHalfShaft(AllConnections.pos(axis)).withHalfShaft(AllConnections.neg(axis));
}
public ConnectionsBuilder withDirectional(AllConnections.Directional directional, Direction dir) {
connections.add(KineticConnectionsRegistry.getConnectionType(directional.type(dir)).get());
return this;
}
public ConnectionsBuilder withAxial(AllConnections.Axial axial, Direction.Axis axis) {
connections.add(KineticConnectionsRegistry.getConnectionType(axial.type(axis)).get());
return this;
}
public ConnectionsBuilder withDirAxial(AllConnections.DirAxial dirAxial, Direction dir, boolean first) {
connections.add(KineticConnectionsRegistry.getConnectionType(dirAxial.type(dir, first)).get());
return this;
}
public ConnectionsBuilder withLargeCog(Direction.Axis axis) {
return withAxial(AllConnections.Axial.LARGE_COG, axis);
}
public ConnectionsBuilder withSmallCog(Direction.Axis axis) {
return withAxial(AllConnections.Axial.SMALL_COG, axis);
}
}

View file

@ -4,10 +4,10 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.Level;
public interface IKineticController {
default void onUpdate(Level level, KineticSolver solver, KineticNode node) { }
default void onKineticsTick(Level level, KineticSolver solver, KineticNode node) { }
default KineticConnections getConnections() {
return AllConnections.EMPTY;
return KineticConnections.empty();
}
default float getGeneratedSpeed() {

View file

@ -0,0 +1,11 @@
package com.simibubi.create.content.contraptions.solver;
import net.minecraft.core.Vec3i;
import java.util.Map;
public record KineticConnection(String name) {
public Map<Vec3i, Map<KineticConnection, Float>> getRatios() {
return KineticConnectionsRegistry.getConnections(this);
}
}

View file

@ -1,106 +1,51 @@
package com.simibubi.create.content.contraptions.solver;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag;
import net.minecraft.util.Mth;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class KineticConnections {
private final Set<KineticConnection> connections;
public static record Entry(Vec3i offset, Value value) {
public Entry(Vec3i offset, String from, String to, float ratio) {
this(offset, new Value(from, to, ratio));
}
public Entry(Vec3i offset, String from, String to) {
this(offset, from, to, 1);
}
public Entry(Vec3i offset, String from) {
this(offset, from, from);
}
public Entry stressOnly() {
return new Entry(offset, new Value(value.from, value.to, 0));
}
}
public static record Value(String from, String to, float ratio) {
public boolean isStressOnly() {
return ratio == 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Value value = (Value) o;
return Float.compare(value.ratio, ratio) == 0 && from.equals(value.from) && to.equals(value.to);
}
@Override
public int hashCode() {
return Objects.hash(from, to, ratio);
}
}
private final Map<Vec3i, Value> connections;
private KineticConnections(Map<Vec3i, Value> connections) {
public KineticConnections(Set<KineticConnection> connections) {
this.connections = connections;
}
public KineticConnections(Stream<Entry> entries) {
this(entries.collect(Collectors.toMap(Entry::offset, Entry::value)));
public static KineticConnections empty() {
return new KineticConnections(Set.of());
}
public KineticConnections(Collection<Entry> entries) {
this(entries.stream());
public Stream<KineticConnection> stream() {
return connections.stream();
}
public KineticConnections(Entry... entries) {
this(Arrays.stream(entries));
public boolean hasStressOnlyConnections() {
return connections.stream()
.flatMap(c -> c.getRatios().values().stream()
.flatMap(m -> m.values().stream()))
.anyMatch(r -> r == 0);
}
public Set<Vec3i> getDirections() {
return connections.keySet();
}
public float getShaftSpeedModifier(Direction face) {
Vec3i offset = face.getNormal();
public Optional<Float> checkConnection(Vec3i offset) {
Value value = connections.get(offset);
if (value == null) return Optional.empty();
return Optional.of(value.ratio);
}
KineticConnection shaft = KineticConnectionsRegistry
.getConnectionType(AllConnections.Shafts.SHAFT.type(face.getOpposite())).get();
private Optional<Float> checkConnection(KineticConnections to, Vec3i offset, boolean stressOnly) {
Value fromValue = connections.get(offset);
Value toValue = to.connections.get(offset.multiply(-1));
if (fromValue == null || toValue == null) return Optional.empty();
if (!fromValue.from.equals(toValue.to) || !fromValue.to.equals(toValue.from)) return Optional.empty();
if (fromValue.isStressOnly() ^ toValue.isStressOnly()) return Optional.empty();
if (fromValue.isStressOnly()) return stressOnly ? Optional.of(0f) : Optional.empty();
return Optional.of(fromValue.ratio / toValue.ratio);
}
public Optional<Float> checkConnection(KineticConnections to, Vec3i offset) {
return checkConnection(to, offset, false);
}
public boolean checkStressOnlyConnection(KineticConnections to, Vec3i offset) {
return checkConnection(to, offset, true).isPresent();
return stream()
.flatMap(c -> Optional.ofNullable(c.getRatios().get(offset))
.flatMap(r -> Optional.ofNullable(r.get(shaft)))
.stream())
.findFirst()
.orElse(0f);
}
@Override
@ -116,43 +61,20 @@ public class KineticConnections {
return Objects.hash(connections);
}
public KineticConnections merge(KineticConnections other) {
Map<Vec3i, Value> connectionsNew = new HashMap<>();
connectionsNew.putAll(other.connections);
connectionsNew.putAll(connections);
return new KineticConnections(connectionsNew);
}
public boolean hasStressOnlyConnections() {
return connections.values().stream().anyMatch(Value::isStressOnly);
}
public CompoundTag save(CompoundTag tag) {
ListTag connectionsTags = new ListTag();
for (Map.Entry<Vec3i, Value> entry : connections.entrySet()) {
CompoundTag entryTag = new CompoundTag();
Value v = entry.getValue();
entryTag.put("Off", NBTHelper.writeVec3i(entry.getKey()));
entryTag.putString("From", v.from());
if (!v.to().equals(v.from()))
entryTag.putString("To", v.to());
if (v.ratio() != 1)
entryTag.putFloat("Ratio", v.ratio());
connectionsTags.add(entryTag);
for (KineticConnection connection : connections) {
connectionsTags.add(StringTag.valueOf(connection.name()));
}
tag.put("Connections", connectionsTags);
return tag;
}
public static KineticConnections load(CompoundTag tag) {
Map<Vec3i, Value> connections = new HashMap<>();
tag.getList("Connections", Tag.TAG_COMPOUND).forEach(c -> {
CompoundTag comp = (CompoundTag) c;
Vec3i offset = NBTHelper.readVec3i(comp.getList("Off", Tag.TAG_INT));
String from = comp.getString("From");
String to = comp.contains("To") ? comp.getString("To") : from;
float ratio = comp.contains("Ratio") ? comp.getFloat("Ratio") : 1;
connections.put(offset, new Value(from, to, ratio));
Set<KineticConnection> connections = new HashSet<>();
tag.getList("Connections", Tag.TAG_STRING).forEach(t -> {
KineticConnectionsRegistry.getConnectionType(t.getAsString())
.ifPresent(connections::add);
});
return new KineticConnections(connections);
}

View file

@ -0,0 +1,46 @@
package com.simibubi.create.content.contraptions.solver;
import net.minecraft.core.Vec3i;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
public class KineticConnectionsRegistry {
private static final Map<String, KineticConnection> connectionTypes = new HashMap<>();
private static final Map<KineticConnection, Map<Vec3i, Map<KineticConnection, Float>>> connectionRatios
= new HashMap<>();
public static KineticConnection registerConnectionType(String name) {
if (connectionTypes.containsKey(name))
throw new IllegalStateException("connection type named \"" + name + "\" already exists");
KineticConnection connection = new KineticConnection(name);
connectionTypes.put(name, connection);
return connection;
}
public static Optional<KineticConnection> getConnectionType(String name) {
return Optional.ofNullable(connectionTypes.get(name));
}
public static void registerConnectionRatio(KineticConnection from, KineticConnection to, Vec3i offset, float ratio) {
Map<KineticConnection, Float> fromMap = connectionRatios
.computeIfAbsent(from, $ -> new HashMap<>())
.computeIfAbsent(offset, $ -> new HashMap<>());
if (fromMap.containsKey(to)) return;
Map<KineticConnection, Float> toMap = connectionRatios
.computeIfAbsent(to, $ -> new HashMap<>())
.computeIfAbsent(offset.multiply(-1), $ -> new HashMap<>());
fromMap.put(to, ratio);
toMap.put(from, ratio == 0 ? 0 : 1/ratio);
}
public static Map<Vec3i, Map<KineticConnection, Float>> getConnections(KineticConnection from) {
return Optional.ofNullable(connectionRatios.get(from))
.map(Collections::unmodifiableMap)
.orElseGet(Map::of);
}
}

View file

@ -27,10 +27,14 @@ public enum KineticControllerSerial {
}
@Override
public void onUpdate(Level level, KineticSolver solver, KineticNode node) {
public void onKineticsTick(Level level, KineticSolver solver, KineticNode node) {
BlockPos below = node.getPos().below();
if (level.getBlockEntity(below) instanceof SpeedControllerTileEntity se) {
targetSpeed = se.getTargetSpeed();
} else if (generatedSpeed != 0) {
generatedSpeed = 0;
} else {
node.removeController();
}
Optional<KineticNode> seNode = solver.getNode(below);

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.solver;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.utility.Pair;
@ -18,6 +19,9 @@ import java.util.stream.Collectors;
public class KineticNetwork {
private static long nextID = 1L;
public final long id;
private final Set<KineticNode> members = new HashSet<>();
private final Set<KineticNode> generators = new HashSet<>();
private final Set<Pair<KineticNode, KineticNode>> conflictingCycles = new HashSet<>();
@ -36,10 +40,14 @@ public class KineticNetwork {
private final ResetableLazy<Float> totalStressCapacity = ResetableLazy.of(() ->
(float) members.stream().mapToDouble(KineticNode::getStressCapacity).sum());
private float latestSupernetworkStressImpact;
private float latestSupernetworkStressCapacity;
private boolean ticked;
private final Set<KineticNode> stressConnectors = new HashSet<>();
protected KineticNetwork(KineticNode root) {
id = nextID++;
addMember(root);
}
@ -150,11 +158,11 @@ public class KineticNetwork {
}
public float getTotalStressImpact() {
return totalStressImpact.get();
return latestSupernetworkStressImpact;
}
public float getTotalStressCapacity() {
return totalStressCapacity.get();
return latestSupernetworkStressCapacity;
}
public float getRootTheoreticalSpeed() {
@ -191,11 +199,16 @@ public class KineticNetwork {
for (KineticNetwork cur : stressConnected) {
cur.ticked = true;
cur.checkForSpeedingNodes(popQueue::add);
stressImpact += cur.getTotalStressImpact();
stressCapacity += cur.getTotalStressCapacity();
stressImpact += cur.totalStressImpact.get();
stressCapacity += cur.totalStressCapacity.get();
}
boolean nowOverstressed = stressImpact > stressCapacity;
for (KineticNetwork cur : stressConnected) {
cur.latestSupernetworkStressImpact = stressImpact;
cur.latestSupernetworkStressCapacity = stressCapacity;
}
boolean nowOverstressed = stressImpact > stressCapacity && IRotate.StressImpact.isEnabled();
if (!nowOverstressed) {
// we should only pop speeding nodes if the network isn't actually overstressed now
popQueue.forEach(pop);

View file

@ -5,16 +5,18 @@ import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.util.Mth;
import net.minecraft.world.level.block.Block;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -28,7 +30,6 @@ public class KineticNode {
private @Nullable IKineticController controller;
private @Nullable KineticControllerSerial controllerType;
private @Nullable Set<BlockPos> controlling;
private @Nullable KineticNode parent;
private @Nullable BlockPos speedSource;
@ -83,12 +84,15 @@ public class KineticNode {
}
tag.put("Connections", connections.save(new CompoundTag()));
tag.putFloat("Generated", generatedSpeed);
tag.putFloat("Capacity", stressCapacity);
tag.putFloat("Impact", stressImpact);
if (constantStress) {
if (generatedSpeed != 0)
tag.putFloat("Generated", generatedSpeed);
if (stressCapacity != 0)
tag.putFloat("Capacity", stressCapacity);
if (stressImpact != 0)
tag.putFloat("Impact", stressImpact);
if (constantStress)
tag.putBoolean("ConstantStress", true);
}
return tag;
}
@ -127,13 +131,10 @@ public class KineticNode {
return Optional.empty();
}
public boolean setController(KineticNode source, KineticControllerSerial controller) {
public boolean setController(KineticControllerSerial controller) {
if (this.controller != null) return false;
this.controller = controller.init(this);
this.controllerType = controller;
if (source.controlling == null)
source.controlling = new HashSet<>();
source.controlling.add(pos);
return true;
}
@ -158,24 +159,38 @@ public class KineticNode {
* @return a Stream containing a pair for each compatible connection with this node, where the first value is
* the connecting node and the second value is the speed ratio of the connection
*/
public Stream<Pair<KineticNode, Float>> getActiveConnections() {
return connections.getDirections().stream()
.map(d -> solver.getNode(pos.offset(d))
.map(n -> connections.checkConnection(n.connections, d)
.map(r -> Pair.of(n, r))))
.flatMap(Optional::stream)
private Stream<Pair<KineticNode, Float>> getAllActiveConnections() {
return connections.stream()
.flatMap(from -> from.getRatios().entrySet().stream()
.map(e -> {
Vec3i offset = e.getKey();
return solver.getNode(pos.offset(offset)).flatMap(node -> {
Map<KineticConnection, Float> ratios = e.getValue();
return node.getConnections().stream()
.map(ratios::get)
.filter(Objects::nonNull)
.findFirst()
.map(r -> Pair.of(node, r));
});
})
)
.flatMap(Optional::stream);
}
public Iterable<Pair<KineticNode, Float>> getActiveConnectionsList() {
return getActiveConnections().collect(Collectors.toList());
public Stream<Pair<KineticNode, Float>> getActiveConnections() {
return getAllActiveConnections().filter(p -> p.getSecond() != 0);
}
public Stream<KineticNode> getActiveStressOnlyConnections() {
return connections.getDirections().stream()
.map(d -> solver.getNode(pos.offset(d))
.filter(n -> connections.checkStressOnlyConnection(n.connections, d)))
.flatMap(Optional::stream);
return getAllActiveConnections().filter(p -> p.getSecond() == 0).map(Pair::getFirst);
}
public Optional<Float> checkConnection(KineticNode to) {
return getActiveConnections().filter(p -> p.getFirst() == to).findAny().map(Pair::getSecond);
}
public boolean checkStressOnlyConnection(KineticNode to) {
return getActiveStressOnlyConnections().anyMatch(n -> n == to);
}
public float getGeneratedSpeed() {
@ -298,7 +313,7 @@ public class KineticNode {
while (!frontier.isEmpty()) {
KineticNode cur = frontier.remove(0);
for (Pair<KineticNode, Float> pair : cur.getActiveConnectionsList()) {
for (Pair<KineticNode, Float> pair : cur.getActiveConnections().collect(Collectors.toList())) {
KineticNode next = pair.getFirst();
float ratio = pair.getSecond();
@ -334,12 +349,6 @@ public class KineticNode {
.map(Pair::getFirst)
.filter(n -> n.parent == this)
.forEach(KineticNode::rerootHere);
if (controlling != null) {
controlling.stream()
.map(solver::getNode)
.flatMap(Optional::stream)
.forEach(KineticNode::removeController);
}
}
private void rerootHere() {
@ -361,7 +370,7 @@ public class KineticNode {
protected void flushChanges() {
if (entity != null) {
entity.updateFromSolver(getTheoreticalSpeed(), getSpeedSource(), getConnections(),
entity.updateFromSolver(getTheoreticalSpeed(), getSpeedSource(), network.id,
network.isOverstressed(), network.getTotalStressImpact(), network.getTotalStressCapacity());
}
}

View file

@ -7,25 +7,19 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.WorldAttached;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.nbt.Tag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.saveddata.SavedData;
import org.checkerframework.checker.units.qual.C;
import org.jetbrains.annotations.NotNull;
public class KineticSolver extends SavedData {
@ -162,7 +156,7 @@ public class KineticSolver extends SavedData {
Set<KineticNode> popQueue = new HashSet<>();
Set<KineticNode> regenQueue = new HashSet<>();
for (KineticNode node : nodes.values()) {
node.getController().ifPresent(c -> c.onUpdate(level, this, node));
node.getController().ifPresent(c -> c.onKineticsTick(level, this, node));
switch (node.onUpdated()) {
case NEEDS_POP -> popQueue.add(node);
case NEEDS_REGEN -> regenQueue.add(node);
@ -188,19 +182,4 @@ public class KineticSolver extends SavedData {
}
}
}
public Optional<Float> isConnected(BlockPos from, BlockPos to) {
return getNode(from).flatMap(fromNode ->
getNode(to).flatMap(toNode ->
fromNode.getConnections()
.checkConnection(toNode.getConnections(), to.subtract(from))));
}
public boolean isStressOnlyConnected(BlockPos from, BlockPos to) {
return getNode(from).flatMap(fromNode ->
getNode(to).map(toNode ->
fromNode.getConnections()
.checkStressOnlyConnection(toNode.getConnections(), to.subtract(from)))
).orElse(false);
}
}

View file

@ -4,7 +4,6 @@ import com.simibubi.create.AllSoundEvents;
import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
@ -34,12 +33,6 @@ public interface IWrenchable {
KineticTileEntity.switchToBlockState(world, context.getClickedPos(), updateAfterWrenched(rotated, context));
BlockEntity te = context.getLevel()
.getBlockEntity(context.getClickedPos());
if (te instanceof GeneratingKineticTileEntity) {
((GeneratingKineticTileEntity) te).reActivateSource = true;
}
if (world.getBlockState(context.getClickedPos()) != state)
playRotateSound(world, context.getClickedPos());

View file

@ -29,7 +29,6 @@ import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.entity.BlockEntityType;
@ -63,12 +62,12 @@ public class CopperBacktankBlock extends HorizontalKineticBlock
builder.add(BlockStateProperties.WATERLOGGED);
super.createBlockStateDefinition(builder);
}
@Override
public boolean hasAnalogOutputSignal(BlockState p_149740_1_) {
return true;
}
@Override
public int getAnalogOutputSignal(BlockState p_180641_1_, Level world, BlockPos pos) {
return getTileEntityOptional(world, pos).map(CopperBacktankTileEntity::getComparatorOutput)
@ -78,7 +77,7 @@ public class CopperBacktankBlock extends HorizontalKineticBlock
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighbourState,
LevelAccessor world, BlockPos pos, BlockPos neighbourPos) {
if (state.getValue(BlockStateProperties.WATERLOGGED))
if (state.getValue(BlockStateProperties.WATERLOGGED))
world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
return state;
}
@ -92,7 +91,7 @@ public class CopperBacktankBlock extends HorizontalKineticBlock
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return face == Direction.UP;
}
@ -177,7 +176,7 @@ public class CopperBacktankBlock extends HorizontalKineticBlock
public Class<CopperBacktankTileEntity> getTileEntityClass() {
return CopperBacktankTileEntity.class;
}
@Override
public BlockEntityType<? extends CopperBacktankTileEntity> getTileEntityType() {
return AllTileEntities.COPPER_BACKTANK.get();

View file

@ -139,7 +139,7 @@ public class EjectorBlock extends HorizontalKineticBlock implements ITE<EjectorT
}
@Override
public boolean hasShaftTowards(LevelReader world, BlockPos pos, BlockState state, Direction face) {
public boolean hasShaftTowards(BlockState state, Direction face) {
return getRotationAxis(state) == face.getAxis();
}

View file

@ -12,67 +12,53 @@ import net.minecraft.core.Direction.Axis;
/**
* A bunch of methods that got stripped out of Direction in 1.15
*
*
* @author Mojang
*/
public class DirectionHelper {
public static Direction rotateAround(Direction dir, Direction.Axis axis) {
switch (axis) {
case X:
if (dir != WEST && dir != EAST) {
return rotateX(dir);
case X -> {
if (dir != WEST && dir != EAST) {
return rotateX(dir);
}
return dir;
}
return dir;
case Y:
if (dir != UP && dir != DOWN) {
return dir.getClockWise();
case Y -> {
if (dir != UP && dir != DOWN) {
return dir.getClockWise();
}
return dir;
}
return dir;
case Z:
if (dir != NORTH && dir != SOUTH) {
return rotateZ(dir);
case Z -> {
if (dir != NORTH && dir != SOUTH) {
return rotateZ(dir);
}
return dir;
}
return dir;
default:
throw new IllegalStateException("Unable to get CW facing for axis " + axis);
default -> throw new IllegalStateException("Unable to get CW facing for axis " + axis);
}
}
public static Direction rotateX(Direction dir) {
switch (dir) {
case NORTH:
return DOWN;
case EAST:
case WEST:
default:
throw new IllegalStateException("Unable to get X-rotated facing of " + dir);
case SOUTH:
return UP;
case UP:
return NORTH;
case DOWN:
return SOUTH;
}
return switch (dir) {
case NORTH -> DOWN;
case SOUTH -> UP;
case UP -> NORTH;
case DOWN -> SOUTH;
default -> throw new IllegalStateException("Unable to get X-rotated facing of " + dir);
};
}
public static Direction rotateZ(Direction dir) {
switch (dir) {
case EAST:
return DOWN;
case SOUTH:
default:
throw new IllegalStateException("Unable to get Z-rotated facing of " + dir);
case WEST:
return UP;
case UP:
return EAST;
case DOWN:
return WEST;
}
return switch (dir) {
case EAST -> DOWN;
case WEST -> UP;
case UP -> EAST;
case DOWN -> WEST;
default -> throw new IllegalStateException("Unable to get Z-rotated facing of " + dir);
};
}
public static Direction getPositivePerpendicular(Axis horizontalAxis) {

View file

@ -27,15 +27,19 @@ public class Iterate {
}
public static Direction[] directionsInAxis(Axis axis) {
switch (axis) {
case X:
return new Direction[] { Direction.EAST, Direction.WEST };
case Y:
return new Direction[] { Direction.UP, Direction.DOWN };
default:
case Z:
return new Direction[] { Direction.SOUTH, Direction.NORTH };
}
return switch (axis) {
case X -> new Direction[]{Direction.EAST, Direction.WEST};
case Y -> new Direction[]{Direction.UP, Direction.DOWN};
case Z -> new Direction[]{Direction.SOUTH, Direction.NORTH};
};
}
public static Direction[] directionsPerpendicularTo(Axis axis) {
return switch (axis) {
case X -> new Direction[]{Direction.SOUTH, Direction.DOWN, Direction.NORTH, Direction.UP};
case Y -> new Direction[]{Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH};
case Z -> new Direction[]{Direction.EAST, Direction.UP, Direction.WEST, Direction.DOWN};
};
}
public static List<BlockPos> hereAndBelow(BlockPos pos) {