Encased belt blocks

This commit is contained in:
reidbhuntley 2022-01-11 13:04:08 -05:00
parent 2768123b52
commit b1a9993b16
14 changed files with 174 additions and 173 deletions

View file

@ -75,7 +75,7 @@ public class KineticTileEntity extends SmartTileEntity
updateInitialConnections(state);
}
protected void updateInitialConnections(BlockState state) {
public void updateInitialConnections(BlockState state) {
if (state.getBlock() instanceof IRotate rotate) {
initialConnections = rotate.buildInitialConnections(ConnectionsBuilder.builder(), state).build();
if (getLevel() != null && !getLevel().isClientSide) {

View file

@ -130,15 +130,6 @@ public class GantryCarriageBlock extends DirectionalAxisKineticBlock implements
return Axis.Y;
}
public static Axis getValidGantryPinionAxis(BlockState state, Axis shaftAxis) {
Axis facingAxis = state.getValue(FACING)
.getAxis();
for (Axis axis : Iterate.axes)
if (axis != shaftAxis && axis != facingAxis)
return axis;
return Axis.Y;
}
@Override
public Class<GantryCarriageTileEntity> getTileEntityClass() {
return GantryCarriageTileEntity.class;

View file

@ -8,6 +8,7 @@ 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.solver.ConnectionsBuilder;
import com.simibubi.create.foundation.block.ITE;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -175,12 +176,17 @@ public class GantryShaftBlock extends DirectionalKineticBlock implements ITE<Gan
public void onPlace(BlockState state, Level worldIn, BlockPos pos, BlockState oldState, boolean isMoving) {
super.onPlace(state, worldIn, pos, oldState, isMoving);
if (!worldIn.isClientSide() && oldState.is(AllBlocks.GANTRY_SHAFT.get())) {
Part oldPart = oldState.getValue(PART), part = state.getValue(PART);
if ((oldPart != Part.MIDDLE && part == Part.MIDDLE) || (oldPart == Part.SINGLE && part != Part.SINGLE)) {
BlockEntity te = worldIn.getBlockEntity(pos);
if (te instanceof GantryShaftTileEntity)
((GantryShaftTileEntity) te).checkAttachedCarriageBlocks();
if (oldState.is(AllBlocks.GANTRY_SHAFT.get())) {
if (!worldIn.isClientSide()) {
Part oldPart = oldState.getValue(PART), part = state.getValue(PART);
if ((oldPart != Part.MIDDLE && part == Part.MIDDLE) || (oldPart == Part.SINGLE && part != Part.SINGLE)) {
withTileEntityDo(worldIn, pos, GantryShaftTileEntity::checkAttachedCarriageBlocks);
}
}
boolean oldPowered = oldState.getValue(POWERED), powered = state.getValue(POWERED);
if (oldPowered != powered) {
withTileEntityDo(worldIn, pos, kte -> kte.updateConnections(state));
}
}
}
@ -227,8 +233,9 @@ public class GantryShaftBlock extends DirectionalKineticBlock implements ITE<Gan
toUpdate.add(pos);
for (BlockPos blockPos : toUpdate) {
BlockState blockState = worldIn.getBlockState(blockPos);
if (blockState.getBlock() instanceof GantryShaftBlock)
if (blockState.getBlock() instanceof GantryShaftBlock gsb) {
worldIn.setBlock(blockPos, blockState.setValue(POWERED, shouldPower), 2);
}
}
}

View file

@ -22,17 +22,32 @@ public class GantryShaftTileEntity extends KineticTileEntity {
super(typeIn, pos, state);
}
@Override
public KineticConnections getConnections() {
BlockState state = getBlockState();
Direction facing = state.getValue(GantryShaftBlock.FACING);
private KineticConnections connections;
public void updateConnections(BlockState state) {
if (!AllBlocks.GANTRY_SHAFT.has(state)) {
connections = KineticConnections.empty();
return;
}
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();
if (state.getValue(GantryShaftBlock.POWERED))
builder = builder.withDirectional(AllConnections.Directional.GANTRY_RACK, facing);
return builder.withDirectional(AllConnections.Directional.GANTRY_RACK, facing).build();
connections = builder.build();
}
@Override
public KineticConnections getConnections() {
return connections;
}
@Override
public void initialize() {
updateConnections(getBlockState());
super.initialize();
}
public void checkAttachedCarriageBlocks() {

View file

@ -79,10 +79,10 @@ public class Instruction {
return 0;
}
Optional<InstructionSpeedModifiers> getSpeedModifier() {
float getSpeedModifier() {
return switch (instruction) {
case TURN_ANGLE, TURN_DISTANCE -> Optional.of(speedModifier);
default -> Optional.empty();
case TURN_ANGLE, TURN_DISTANCE -> speedModifier.value;
default -> 0;
};
}

View file

@ -162,23 +162,17 @@ public class SequencedGearshiftTileEntity extends KineticTileEntity {
ConnectionsBuilder builder = ConnectionsBuilder.builder();
if (isVirtual()) return builder.withFullShaft(facing.getAxis()).build();
builder = builder.withHalfShaft(facing.getOpposite());
builder = builder.withHalfShaft(facing.getOpposite(), 1);
Optional<InstructionSpeedModifiers> modifier = getModifier();
if (modifier.isEmpty() || isRemoved()) return builder.build();
float modifier = getModifier();
if (modifier == 0 || 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();
return builder.withHalfShaft(facing, modifier).build();
}
public Optional<InstructionSpeedModifiers> getModifier() {
public float getModifier() {
if (currentInstruction >= instructions.size() || isIdle())
return Optional.empty();
return 0;
return instructions.get(currentInstruction).getSpeedModifier();
}

View file

@ -2,6 +2,9 @@ package com.simibubi.create.content.contraptions.relays.encased;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.solver.ConnectionsBuilder;
import com.simibubi.create.content.contraptions.solver.KineticConnections;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.entity.BlockEntityType;
@ -11,10 +14,12 @@ public class AdjustablePulleyTileEntity extends KineticTileEntity {
int signal;
boolean signalChanged;
KineticConnections connections;
public AdjustablePulleyTileEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
signal = 0;
updateConnections(state);
setLazyTickRate(40);
}
@ -26,12 +31,14 @@ public class AdjustablePulleyTileEntity extends KineticTileEntity {
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
signal = compound.getInt("Signal");
analogSignalChanged(compound.getInt("Signal"));
super.read(compound, clientPacket);
}
public float getModifier() {
return getModifierForSignal(signal);
protected float getModifier() {
if (signal == 0)
return 1;
return 1 + ((signal + 1) / 16f);
}
public void neighbourChanged() {
@ -60,16 +67,16 @@ public class AdjustablePulleyTileEntity extends KineticTileEntity {
}
protected void analogSignalChanged(int newSignal) {
//detachKinetics();
//removeSource();
signal = newSignal;
//attachKinetics();
updateConnections(getBlockState());
}
protected float getModifierForSignal(int newPower) {
if (newPower == 0)
return 1;
return 1 + ((newPower + 1) / 16f);
private void updateConnections(BlockState state) {
connections = EncasedBeltBlock.encasedBeltConnections(state, getModifier()).build();
}
@Override
public KineticConnections getConnections() {
return connections;
}
}

View file

@ -4,6 +4,8 @@ import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
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.foundation.block.ITE;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
@ -121,8 +123,12 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock implements ITE<K
if ((part == Part.START) != positive)
part = Part.MIDDLE;
return stateIn.setValue(PART, part)
.setValue(CONNECTED_ALONG_FIRST_COORDINATE, connectionAlongFirst);
BlockState newState = stateIn.setValue(PART, part)
.setValue(CONNECTED_ALONG_FIRST_COORDINATE, connectionAlongFirst);
withTileEntityDo(worldIn, currentPos, kte -> kte.updateInitialConnections(newState));
return newState;
}
@Override
@ -164,39 +170,30 @@ public class EncasedBeltBlock extends RotatedPillarKineticBlock implements ITE<K
return state.getValue(AXIS);
}
public static boolean areBlocksConnected(BlockState state, BlockState other, Direction facing) {
public static ConnectionsBuilder encasedBeltConnections(BlockState state, float mod) {
Part part = state.getValue(PART);
Axis shaftAxis = state.getValue(AXIS);
Axis connectionAxis = getConnectionAxis(state);
Axis otherConnectionAxis = getConnectionAxis(other);
if (otherConnectionAxis != connectionAxis)
return false;
if (facing.getAxis() != connectionAxis)
return false;
if (facing.getAxisDirection() == AxisDirection.POSITIVE && (part == Part.MIDDLE || part == Part.START))
return true;
if (facing.getAxisDirection() == AxisDirection.NEGATIVE && (part == Part.MIDDLE || part == Part.END))
return true;
ConnectionsBuilder builder = ConnectionsBuilder.builder().withFullShaft(shaftAxis);
return false;
if (part == Part.START || part == Part.MIDDLE)
builder.withDirectional(AllConnections.Directional.ENCASED_BELT, AllConnections.pos(connectionAxis), mod);
if (part == Part.MIDDLE || part == Part.END)
builder.withDirectional(AllConnections.Directional.ENCASED_BELT, AllConnections.neg(connectionAxis), mod);
return builder;
}
@Override
public ConnectionsBuilder buildInitialConnections(ConnectionsBuilder builder, BlockState state) {
return encasedBeltConnections(state, 1);
}
protected static Axis getConnectionAxis(BlockState state) {
Axis axis = state.getValue(AXIS);
boolean connectionAlongFirst = state.getValue(CONNECTED_ALONG_FIRST_COORDINATE);
Axis connectionAxis =
connectionAlongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z);
return connectionAxis;
}
public static float getRotationSpeedModifier(KineticTileEntity from, KineticTileEntity to) {
float fromMod = 1;
float toMod = 1;
if (from instanceof AdjustablePulleyTileEntity)
fromMod = ((AdjustablePulleyTileEntity) from).getModifier();
if (to instanceof AdjustablePulleyTileEntity)
toMod = ((AdjustablePulleyTileEntity) to).getModifier();
return fromMod / toMod;
boolean alongFirst = state.getValue(CONNECTED_ALONG_FIRST_COORDINATE);
return alongFirst ? (axis == Axis.X ? Axis.Y : Axis.X) : (axis == Axis.Z ? Axis.Y : Axis.Z);
}
public enum Part implements StringRepresentable {

View file

@ -80,11 +80,11 @@ 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;
private static float getModifier(Direction from, Direction to) {
if (from == to) return 1;
Axis fromAxis = from.getAxis(), toAxis = to.getAxis();
if (fromAxis == toAxis) return true;
return AllConnections.perpendicularRatios(to.getNormal().subtract(from.getNormal()), fromAxis, toAxis) == -1;
if (fromAxis == toAxis) return -1;
return AllConnections.perpendicularRatios(to.getNormal().subtract(from.getNormal()), fromAxis, toAxis);
}
@Override
@ -92,10 +92,7 @@ public class GearboxBlock extends RotatedPillarKineticBlock implements ITE<Gearb
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);
builder = builder.withHalfShaft(cur, getModifier(start, cur));
}
return builder;
}

View file

@ -28,8 +28,8 @@ public class GearshiftTileEntity extends KineticTileEntity {
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())
.withHalfShaft(dir, -1)
.withHalfShaft(dir.getOpposite(), 1)
.build();
}

View file

@ -16,12 +16,10 @@ import java.util.Optional;
public class AllConnections {
public static void register() {
Shafts.registerTypes();
Directional.registerTypes();
Axial.registerTypes();
DirAxial.registerTypes();
Shafts.registerRatios();
Directional.registerRatios();
Axial.registerRatios();
DirAxial.registerRatios();
@ -29,48 +27,21 @@ public class AllConnections {
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 {
SHAFT("shaft") {
@Override
public List<Entry> genConnections(Direction dir) {
return List.of(new Entry(dir.getNormal(), SHAFT.type(dir.getOpposite()), 1));
}
},
ENCASED_BELT("encased_belt") {
@Override
public List<Entry> genConnections(Direction dir) {
return List.of(new Entry(dir.getNormal(), ENCASED_BELT.type(dir.getOpposite()), 1));
}
},
GANTRY_RACK("gantry_rack") {
@Override
public List<Entry> genConnections(Direction dir) { return List.of(); }

View file

@ -2,11 +2,13 @@ package com.simibubi.create.content.contraptions.solver;
import net.minecraft.core.Direction;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class ConnectionsBuilder {
private final Set<KineticConnection> connections = new HashSet<>();
private final Map<KineticConnection, Float> connections = new HashMap<>();
public static ConnectionsBuilder builder() {
return new ConnectionsBuilder();
@ -16,32 +18,31 @@ public class ConnectionsBuilder {
return new KineticConnections(connections);
}
public ConnectionsBuilder withHalfShaft(AllConnections.Shafts shaft, Direction dir) {
connections.add(KineticConnectionsRegistry.getConnectionType(shaft.type(dir)).get());
public ConnectionsBuilder withDirectional(AllConnections.Directional directional, Direction dir, float mod) {
connections.put(KineticConnectionsRegistry.getConnectionType(directional.type(dir)).get(), mod);
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 withDirectional(directional, dir, 1);
}
public ConnectionsBuilder withAxial(AllConnections.Axial axial, Direction.Axis axis, float mod) {
connections.put(KineticConnectionsRegistry.getConnectionType(axial.type(axis)).get(), mod);
return this;
}
public ConnectionsBuilder withAxial(AllConnections.Axial axial, Direction.Axis axis) {
connections.add(KineticConnectionsRegistry.getConnectionType(axial.type(axis)).get());
return withAxial(axial, axis, 1);
}
public ConnectionsBuilder withDirAxial(AllConnections.DirAxial dirAxial, Direction dir, boolean first, float mod) {
connections.put(KineticConnectionsRegistry.getConnectionType(dirAxial.type(dir, first)).get(), mod);
return this;
}
public ConnectionsBuilder withDirAxial(AllConnections.DirAxial dirAxial, Direction dir, boolean first) {
connections.add(KineticConnectionsRegistry.getConnectionType(dirAxial.type(dir, first)).get());
return this;
return withDirAxial(dirAxial, dir, first, 1);
}
public ConnectionsBuilder withLargeCog(Direction.Axis axis) {
@ -51,4 +52,16 @@ public class ConnectionsBuilder {
public ConnectionsBuilder withSmallCog(Direction.Axis axis) {
return withAxial(AllConnections.Axial.SMALL_COG, axis);
}
public ConnectionsBuilder withHalfShaft(Direction dir, float mod) {
return withDirectional(AllConnections.Directional.SHAFT, dir, mod);
}
public ConnectionsBuilder withHalfShaft(Direction dir) {
return withHalfShaft(dir, 1);
}
public ConnectionsBuilder withFullShaft(Direction.Axis axis) {
return this.withHalfShaft(AllConnections.pos(axis)).withHalfShaft(AllConnections.neg(axis));
}
}

View file

@ -1,51 +1,49 @@
package com.simibubi.create.content.contraptions.solver;
import com.simibubi.create.foundation.utility.Pair;
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 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.Stream;
public class KineticConnections {
private final Set<KineticConnection> connections;
private final Map<KineticConnection, Float> connections;
public KineticConnections(Set<KineticConnection> connections) {
public KineticConnections(Map<KineticConnection, Float> connections) {
this.connections = connections;
}
public static KineticConnections empty() {
return new KineticConnections(Set.of());
return new KineticConnections(Map.of());
}
public Stream<KineticConnection> stream() {
return connections.stream();
public Set<Map.Entry<KineticConnection, Float>> entries() {
return connections.entrySet();
}
public boolean hasStressOnlyConnections() {
return connections.stream()
.flatMap(c -> c.getRatios().values().stream()
return entries().stream()
.flatMap(c -> c.getKey().getRatios().values().stream()
.flatMap(m -> m.values().stream()))
.anyMatch(r -> r == 0);
}
public float getShaftSpeedModifier(Direction face) {
Vec3i offset = face.getNormal();
KineticConnection shaft = KineticConnectionsRegistry
.getConnectionType(AllConnections.Shafts.SHAFT.type(face.getOpposite())).get();
.getConnectionType(AllConnections.Directional.SHAFT.type(face)).get();
return stream()
.flatMap(c -> Optional.ofNullable(c.getRatios().get(offset))
.flatMap(r -> Optional.ofNullable(r.get(shaft)))
.stream())
.findFirst()
.orElse(0f);
return Optional.ofNullable(connections.get(shaft)).orElse(0f);
}
@Override
@ -63,18 +61,25 @@ public class KineticConnections {
public CompoundTag save(CompoundTag tag) {
ListTag connectionsTags = new ListTag();
for (KineticConnection connection : connections) {
connectionsTags.add(StringTag.valueOf(connection.name()));
for (Map.Entry<KineticConnection, Float> entry : connections.entrySet()) {
CompoundTag entryTag = new CompoundTag();
entryTag.putString("Name", entry.getKey().name());
if (entry.getValue() != 1) {
entryTag.putFloat("Mod", entry.getValue());
}
connectionsTags.add(entryTag);
}
tag.put("Connections", connectionsTags);
return tag;
}
public static KineticConnections load(CompoundTag tag) {
Set<KineticConnection> connections = new HashSet<>();
tag.getList("Connections", Tag.TAG_STRING).forEach(t -> {
KineticConnectionsRegistry.getConnectionType(t.getAsString())
.ifPresent(connections::add);
Map<KineticConnection, Float> connections = new HashMap<>();
tag.getList("Connections", Tag.TAG_COMPOUND).forEach(t -> {
CompoundTag ct = (CompoundTag) t;
String name = ct.getString("Name");
float mod = ct.contains("Mod") ? ct.getFloat("Mod") : 1;
KineticConnectionsRegistry.getConnectionType(name).ifPresent(c -> connections.put(c, mod));
});
return new KineticConnections(connections);
}

View file

@ -160,17 +160,21 @@ public class KineticNode {
* the connecting node and the second value is the speed ratio of the connection
*/
private Stream<Pair<KineticNode, Float>> getAllActiveConnections() {
return connections.stream()
.flatMap(from -> from.getRatios().entrySet().stream()
return connections.entries().stream()
.flatMap(from -> from.getKey().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));
for (Map.Entry<KineticConnection, Float> to : node.getConnections().entries()) {
Float ratio = ratios.get(to.getKey());
if (ratio != null) {
float fromMod = from.getValue();
float toMod = to.getValue();
return Optional.of(Pair.of(node, ratio * fromMod / toMod));
}
}
return Optional.empty();
});
})
)