Sequenced Gearshift

- Added Sequenced Gearshifts
- Fixed custom swords breaking blocks when held in creative mode
- Fixed belts cancelling flight when touched
- Fixed Entities being blocked by contraption boundaries when moved on belts
- Fixed Flexpeater going funky when edited while active
- Fixed Links not firing when placed into a powered location
This commit is contained in:
simibubi 2020-03-11 21:40:55 +01:00
parent 8c793b8d28
commit 14e053fafd
39 changed files with 1155 additions and 29 deletions

View file

@ -41,6 +41,7 @@ import com.simibubi.create.modules.contraptions.processing.BasinBlock;
import com.simibubi.create.modules.contraptions.redstone.AnalogLeverBlock; import com.simibubi.create.modules.contraptions.redstone.AnalogLeverBlock;
import com.simibubi.create.modules.contraptions.redstone.ContactBlock; import com.simibubi.create.modules.contraptions.redstone.ContactBlock;
import com.simibubi.create.modules.contraptions.relays.advanced.SpeedControllerBlock; import com.simibubi.create.modules.contraptions.relays.advanced.SpeedControllerBlock;
import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.SequencedGearshiftBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTunnelBlock; import com.simibubi.create.modules.contraptions.relays.belt.BeltTunnelBlock;
import com.simibubi.create.modules.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.modules.contraptions.relays.elementary.CogWheelBlock;
@ -164,6 +165,7 @@ public enum AllBlocks {
BRASS_CASING(new CasingBlock("crafter_top")), BRASS_CASING(new CasingBlock("crafter_top")),
MECHANICAL_CRAFTER(new MechanicalCrafterBlock()), MECHANICAL_CRAFTER(new MechanicalCrafterBlock()),
SEQUENCED_GEARSHIFT(new SequencedGearshiftBlock()),
FLYWHEEL(new FlywheelBlock()), FLYWHEEL(new FlywheelBlock()),
FURNACE_ENGINE(new FurnaceEngineBlock()), FURNACE_ENGINE(new FurnaceEngineBlock()),
ROTATION_SPEED_CONTROLLER(new SpeedControllerBlock()), ROTATION_SPEED_CONTROLLER(new SpeedControllerBlock()),

View file

@ -12,6 +12,7 @@ import com.simibubi.create.foundation.packet.NbtPacket;
import com.simibubi.create.foundation.packet.SimplePacketBase; import com.simibubi.create.foundation.packet.SimplePacketBase;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket; import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionStallPacket;
import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket;
import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket; import com.simibubi.create.modules.curiosities.symmetry.SymmetryEffectPacket;
import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket; import com.simibubi.create.modules.curiosities.zapper.ZapperBeamPacket;
import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket; import com.simibubi.create.modules.logistics.item.filter.FilterScreenPacket;
@ -34,6 +35,7 @@ public enum AllPackets {
CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new), CONFIGURE_SCHEMATICANNON(ConfigureSchematicannonPacket.class, ConfigureSchematicannonPacket::new),
CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new), CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new),
CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new), CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new),
CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new),
PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new), PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new),
UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new), UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new),
CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new), CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new),

View file

@ -50,6 +50,7 @@ import com.simibubi.create.modules.contraptions.redstone.AnalogLeverTileEntity;
import com.simibubi.create.modules.contraptions.redstone.AnalogLeverTileEntityRenderer; import com.simibubi.create.modules.contraptions.redstone.AnalogLeverTileEntityRenderer;
import com.simibubi.create.modules.contraptions.relays.advanced.SpeedControllerRenderer; import com.simibubi.create.modules.contraptions.relays.advanced.SpeedControllerRenderer;
import com.simibubi.create.modules.contraptions.relays.advanced.SpeedControllerTileEntity; import com.simibubi.create.modules.contraptions.relays.advanced.SpeedControllerTileEntity;
import com.simibubi.create.modules.contraptions.relays.advanced.sequencer.SequencedGearshiftTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntityRenderer; import com.simibubi.create.modules.contraptions.relays.belt.BeltTileEntityRenderer;
import com.simibubi.create.modules.contraptions.relays.belt.BeltTunnelTileEntity; import com.simibubi.create.modules.contraptions.relays.belt.BeltTunnelTileEntity;
@ -121,10 +122,7 @@ public enum AllTileEntities {
MECHANICAL_BEARING(MechanicalBearingTileEntity::new, AllBlocks.MECHANICAL_BEARING), MECHANICAL_BEARING(MechanicalBearingTileEntity::new, AllBlocks.MECHANICAL_BEARING),
CLOCKWORK_BEARING(ClockworkBearingTileEntity::new, AllBlocks.CLOCKWORK_BEARING), CLOCKWORK_BEARING(ClockworkBearingTileEntity::new, AllBlocks.CLOCKWORK_BEARING),
ROPE_PULLEY(PulleyTileEntity::new, AllBlocks.ROPE_PULLEY), ROPE_PULLEY(PulleyTileEntity::new, AllBlocks.ROPE_PULLEY),
CHASSIS( CHASSIS(ChassisTileEntity::new, AllBlocks.ROTATION_CHASSIS, AllBlocks.TRANSLATION_CHASSIS,
ChassisTileEntity::new,
AllBlocks.ROTATION_CHASSIS,
AllBlocks.TRANSLATION_CHASSIS,
AllBlocks.TRANSLATION_CHASSIS_SECONDARY), AllBlocks.TRANSLATION_CHASSIS_SECONDARY),
DRILL(DrillTileEntity::new, AllBlocks.DRILL), DRILL(DrillTileEntity::new, AllBlocks.DRILL),
SAW(SawTileEntity::new, AllBlocks.SAW), SAW(SawTileEntity::new, AllBlocks.SAW),
@ -139,6 +137,7 @@ public enum AllTileEntities {
DEPLOYER(DeployerTileEntity::new, AllBlocks.DEPLOYER), DEPLOYER(DeployerTileEntity::new, AllBlocks.DEPLOYER),
BASIN(BasinTileEntity::new, AllBlocks.BASIN), BASIN(BasinTileEntity::new, AllBlocks.BASIN),
MECHANICAL_CRAFTER(MechanicalCrafterTileEntity::new, AllBlocks.MECHANICAL_CRAFTER), MECHANICAL_CRAFTER(MechanicalCrafterTileEntity::new, AllBlocks.MECHANICAL_CRAFTER),
SEQUENCED_GEARSHIFT(SequencedGearshiftTileEntity::new, AllBlocks.SEQUENCED_GEARSHIFT),
ROTATION_SPEED_CONTROLLER(SpeedControllerTileEntity::new, AllBlocks.ROTATION_SPEED_CONTROLLER), ROTATION_SPEED_CONTROLLER(SpeedControllerTileEntity::new, AllBlocks.ROTATION_SPEED_CONTROLLER),
SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE), SPEED_GAUGE(SpeedGaugeTileEntity::new, AllBlocks.SPEED_GAUGE),
STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE), STRESS_GAUGE(StressGaugeTileEntity::new, AllBlocks.STRESS_GAUGE),
@ -151,9 +150,7 @@ public enum AllTileEntities {
EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR, AllBlocks.VERTICAL_EXTRACTOR), EXTRACTOR(ExtractorTileEntity::new, AllBlocks.EXTRACTOR, AllBlocks.VERTICAL_EXTRACTOR),
LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR, AllBlocks.VERTICAL_LINKED_EXTRACTOR), LINKED_EXTRACTOR(LinkedExtractorTileEntity::new, AllBlocks.LINKED_EXTRACTOR, AllBlocks.VERTICAL_LINKED_EXTRACTOR),
TRANSPOSER(TransposerTileEntity::new, AllBlocks.TRANSPOSER, AllBlocks.VERTICAL_TRANSPOSER), TRANSPOSER(TransposerTileEntity::new, AllBlocks.TRANSPOSER, AllBlocks.VERTICAL_TRANSPOSER),
LINKED_TRANSPOSER( LINKED_TRANSPOSER(LinkedTransposerTileEntity::new, AllBlocks.LINKED_TRANSPOSER,
LinkedTransposerTileEntity::new,
AllBlocks.LINKED_TRANSPOSER,
AllBlocks.VERTICAL_LINKED_TRANSPOSER), AllBlocks.VERTICAL_LINKED_TRANSPOSER),
BELT_FUNNEL(FunnelTileEntity::new, AllBlocks.BELT_FUNNEL, AllBlocks.VERTICAL_FUNNEL), BELT_FUNNEL(FunnelTileEntity::new, AllBlocks.BELT_FUNNEL, AllBlocks.VERTICAL_FUNNEL),
ENTITY_DETECTOR(BeltObserverTileEntity::new, AllBlocks.ENTITY_DETECTOR), ENTITY_DETECTOR(BeltObserverTileEntity::new, AllBlocks.ENTITY_DETECTOR),
@ -206,6 +203,7 @@ public enum AllTileEntities {
bind(GearboxTileEntity.class, new GearboxTileEntityRenderer()); bind(GearboxTileEntity.class, new GearboxTileEntityRenderer());
bind(GearshiftTileEntity.class, new SplitShaftTileEntityRenderer()); bind(GearshiftTileEntity.class, new SplitShaftTileEntityRenderer());
bind(ClutchTileEntity.class, new SplitShaftTileEntityRenderer()); bind(ClutchTileEntity.class, new SplitShaftTileEntityRenderer());
bind(SequencedGearshiftTileEntity.class, new SplitShaftTileEntityRenderer());
bind(BeltTileEntity.class, new BeltTileEntityRenderer()); bind(BeltTileEntity.class, new BeltTileEntityRenderer());
bind(WaterWheelTileEntity.class, new KineticTileEntityRenderer()); bind(WaterWheelTileEntity.class, new KineticTileEntityRenderer());
bind(HandCrankTileEntity.class, new HandCrankTileEntityRenderer()); bind(HandCrankTileEntity.class, new HandCrankTileEntityRenderer());

View file

@ -41,6 +41,12 @@ public enum ScreenResources {
FILTER("filter.png", 200, 100), FILTER("filter.png", 200, 100),
ATTRIBUTE_FILTER("filter.png", 0, 100, 200, 86), ATTRIBUTE_FILTER("filter.png", 0, 100, 200, 86),
SEQUENCER("sequencer.png", 156, 128),
SEQUENCER_INSTRUCTION("sequencer.png", 14, 47, 131, 18),
SEQUENCER_WAIT("sequencer.png", 14, 65, 131, 18),
SEQUENCER_END("sequencer.png", 14, 83, 131, 18),
SEQUENCER_EMPTY("sequencer.png", 14, 101, 131, 18),
// Logistical Index // Logistical Index
INDEX_TOP("index.png", 41, 0, 174, 22), INDEX_TOP("index.png", 41, 0, 174, 22),

View file

@ -1,8 +1,10 @@
package com.simibubi.create.foundation.gui.widgets; package com.simibubi.create.foundation.gui.widgets;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function;
import com.simibubi.create.AllKeys; import com.simibubi.create.AllKeys;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour.StepContext;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.TextFormatting;
@ -18,6 +20,7 @@ public class ScrollInput extends AbstractSimiWidget {
protected int min, max; protected int min, max;
protected int shiftStep; protected int shiftStep;
Function<StepContext, Integer> step;
public ScrollInput(int xIn, int yIn, int widthIn, int heightIn) { public ScrollInput(int xIn, int yIn, int widthIn, int heightIn) {
super(xIn, yIn, widthIn, heightIn); super(xIn, yIn, widthIn, heightIn);
@ -25,8 +28,13 @@ public class ScrollInput extends AbstractSimiWidget {
min = 0; min = 0;
max = 1; max = 1;
shiftStep = 5; shiftStep = 5;
step = standardStep();
} }
public Function<StepContext, Integer> standardStep() {
return c -> c.shift ? shiftStep : 1;
}
public ScrollInput withRange(int min, int max) { public ScrollInput withRange(int min, int max) {
this.min = min; this.min = min;
this.max = max; this.max = max;
@ -44,6 +52,11 @@ public class ScrollInput extends AbstractSimiWidget {
return this; return this;
} }
public ScrollInput withStepFunction(Function<StepContext, Integer> step) {
this.step = step;
return this;
}
public ScrollInput writingTo(Label label) { public ScrollInput writingTo(Label label) {
this.displayLabel = label; this.displayLabel = label;
writeToLabel(); writeToLabel();
@ -62,7 +75,7 @@ public class ScrollInput extends AbstractSimiWidget {
writeToLabel(); writeToLabel();
return this; return this;
} }
public ScrollInput withShiftStep(int step) { public ScrollInput withShiftStep(int step) {
shiftStep = step; shiftStep = step;
return this; return this;
@ -73,18 +86,25 @@ public class ScrollInput extends AbstractSimiWidget {
if (!isHovered) if (!isHovered)
return false; return false;
StepContext context = new StepContext();
context.control = AllKeys.ctrlDown();
context.shift = AllKeys.shiftDown();
context.currentValue = state;
context.forward = delta > 0;
int priorState = state; int priorState = state;
boolean shifted = AllKeys.shiftDown(); boolean shifted = AllKeys.shiftDown();
int step = (int) Math.signum(delta) * (shifted ? shiftStep : 1); int step = (int) Math.signum(delta) * this.step.apply(context);
state += step; state += step;
if (shifted) if (shifted)
state -= state % shiftStep; state -= state % shiftStep;
clampState(); clampState();
if (priorState != state) if (priorState != state)
onChanged(); onChanged();
return priorState != state; return priorState != state;
} }
@ -94,7 +114,7 @@ public class ScrollInput extends AbstractSimiWidget {
if (state < min) if (state < min)
state = min; state = min;
} }
public void onChanged() { public void onChanged() {
if (displayLabel != null) if (displayLabel != null)
writeToLabel(); writeToLabel();
@ -102,7 +122,7 @@ public class ScrollInput extends AbstractSimiWidget {
onScroll.accept(state); onScroll.accept(state);
updateTooltip(); updateTooltip();
} }
protected void writeToLabel() { protected void writeToLabel() {
displayLabel.text = "" + state; displayLabel.text = "" + state;
} }

View file

@ -112,7 +112,7 @@ public abstract class AbstractToolItem extends ToolItem {
@Override @Override
public boolean canPlayerBreakBlockWhileHolding(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) { public boolean canPlayerBreakBlockWhileHolding(BlockState state, World worldIn, BlockPos pos, PlayerEntity player) {
return !(hasType(SWORD) && !player.isCreative()); return !hasType(SWORD) || !player.isCreative();
} }
@Override @Override
@ -126,7 +126,8 @@ public abstract class AbstractToolItem extends ToolItem {
return false; return false;
} }
public void modifyDrops(final Collection<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool, BlockState state) { public void modifyDrops(final Collection<ItemStack> drops, IWorld world, BlockPos pos, ItemStack tool,
BlockState state) {
} }
public void spawnParticles(IWorld world, BlockPos pos, ItemStack tool, BlockState state) { public void spawnParticles(IWorld world, BlockPos pos, ItemStack tool, BlockState state) {

View file

@ -67,7 +67,10 @@ public class RotationPropagator {
// Axis <-> Axis // Axis <-> Axis
if (connectedByAxis) { if (connectedByAxis) {
return getAxisModifier(from, direction) * getAxisModifier(to, direction.getOpposite()); float axisModifier = getAxisModifier(to, direction.getOpposite());
if (axisModifier != 0)
axisModifier = 1 / axisModifier;
return getAxisModifier(from, direction) * axisModifier;
} }
// Attached Encased Belts // Attached Encased Belts

View file

@ -39,7 +39,7 @@ public abstract class HorizontalAxisKineticBlock extends KineticBlock {
return this.getDefaultState().with(HORIZONTAL_AXIS, context.getPlacementHorizontalFacing().rotateY().getAxis()); return this.getDefaultState().with(HORIZONTAL_AXIS, context.getPlacementHorizontalFacing().rotateY().getAxis());
} }
public Axis getPreferredHorizontalAxis(BlockItemUseContext context) { public static Axis getPreferredHorizontalAxis(BlockItemUseContext context) {
Direction prefferedSide = null; Direction prefferedSide = null;
for (Direction side : Direction.values()) { for (Direction side : Direction.values()) {
if (side.getAxis().isVertical()) if (side.getAxis().isVertical())

View file

@ -40,7 +40,7 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock {
} }
} }
public Axis getPreferredAxis(BlockItemUseContext context) { public static Axis getPreferredAxis(BlockItemUseContext context) {
Axis prefferedAxis = null; Axis prefferedAxis = null;
for (Direction side : Direction.values()) { for (Direction side : Direction.values()) {
BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(side)); BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(side));

View file

@ -0,0 +1,45 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import java.util.Vector;
import com.simibubi.create.foundation.packet.TileEntityConfigurationPacket;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.common.util.Constants.NBT;
public class ConfigureSequencedGearshiftPacket extends TileEntityConfigurationPacket<SequencedGearshiftTileEntity> {
private ListNBT instructions;
public ConfigureSequencedGearshiftPacket(BlockPos pos, Vector<Instruction> instructions) {
super(pos);
this.instructions = Instruction.serializeAll(instructions);
}
public ConfigureSequencedGearshiftPacket(PacketBuffer buffer) {
super(buffer);
}
@Override
protected void readSettings(PacketBuffer buffer) {
instructions = buffer.readCompoundTag().getList("data", NBT.TAG_COMPOUND);
}
@Override
protected void writeSettings(PacketBuffer buffer) {
CompoundNBT tag = new CompoundNBT();
tag.put("data", instructions);
buffer.writeCompoundTag(tag);
}
@Override
protected void applySettings(SequencedGearshiftTileEntity te) {
te.run(-1);
te.instructions = Instruction.deserializeAll(instructions);
te.sendData();
}
}

View file

@ -0,0 +1,105 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import java.util.Vector;
import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
public class Instruction {
SequencerInstructions instruction;
InstructionSpeedModifiers speedModifier;
int value;
public Instruction(SequencerInstructions instruction) {
this(instruction, 1);
}
public Instruction(SequencerInstructions instruction, int value) {
this.instruction = instruction;
speedModifier = InstructionSpeedModifiers.FORWARD;
this.value = value;
}
int getDuration(float initialProgress, float speed) {
int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2;
speed *= speedModifier.value;
speed = Math.abs(speed);
double degreesPerTick = (speed * 360) / 60 / 20;
double metersPerTick = speed / 512;
switch (instruction) {
case TURN_ANGLE:
return (int) ((1 - initialProgress) * value / degreesPerTick + 1);
case TURN_DISTANCE:
return (int) ((1 - initialProgress) * value / metersPerTick + offset);
case WAIT:
return (int) ((1 - initialProgress) * value + 1);
case END:
default:
break;
}
return 0;
}
int getSpeedModifier() {
switch (instruction) {
case TURN_ANGLE:
case TURN_DISTANCE:
return speedModifier.value;
case END:
case WAIT:
default:
break;
}
return 0;
}
public static ListNBT serializeAll(Vector<Instruction> instructions) {
ListNBT list = new ListNBT();
instructions.forEach(i -> list.add(i.serialize()));
return list;
}
public static Vector<Instruction> deserializeAll(ListNBT list) {
if (list.isEmpty())
return createDefault();
Vector<Instruction> instructions = new Vector<>(5);
list.forEach(inbt -> instructions.add(deserialize((CompoundNBT) inbt)));
return instructions;
}
public static Vector<Instruction> createDefault() {
Vector<Instruction> instructions = new Vector<>(5);
instructions.add(new Instruction(SequencerInstructions.TURN_ANGLE, 90));
instructions.add(new Instruction(SequencerInstructions.END));
return instructions;
}
CompoundNBT serialize() {
CompoundNBT tag = new CompoundNBT();
tag.putString("Type", NBTHelper.writeEnum(instruction));
tag.putString("Modifier", NBTHelper.writeEnum(speedModifier));
tag.putInt("Value", value);
return tag;
}
static Instruction deserialize(CompoundNBT tag) {
Instruction instruction =
new Instruction(NBTHelper.readEnum(tag.getString("Type"), SequencerInstructions.class));
instruction.speedModifier = NBTHelper.readEnum(tag.getString("Modifier"), InstructionSpeedModifiers.class);
instruction.value = tag.getInt("Value");
return instruction;
}
}

View file

@ -0,0 +1,31 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.foundation.utility.Lang;
public enum InstructionSpeedModifiers {
FORWARD_FAST(2, ">>"), FORWARD(1, "->"), BACK(-1, "<-"), BACK_FAST(-2, "<<"),
;
String translationKey;
int value;
String label;
private InstructionSpeedModifiers(int modifier, String label) {
this.label = label;
translationKey = "gui.sequenced_gearshift.speed." + Lang.asId(name());
value = modifier;
}
static List<String> getOptions() {
List<String> options = new ArrayList<>();
for (InstructionSpeedModifiers entry : values())
options.add(Lang.translate(entry.translationKey));
return options;
}
}

View file

@ -0,0 +1,139 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.modules.contraptions.base.HorizontalAxisKineticBlock;
import com.simibubi.create.modules.contraptions.base.KineticBlock;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.RotatedPillarKineticBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorldReader;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock
implements IWithTileEntity<SequencedGearshiftTileEntity> {
public static final BooleanProperty VERTICAL = BooleanProperty.create("vertical");
public static final IntegerProperty STATE = IntegerProperty.create("state", 0, 5);
public SequencedGearshiftBlock() {
super(Properties.from(Blocks.ANDESITE));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(STATE, VERTICAL));
}
@Override
public TileEntity createTileEntity(BlockState state, IBlockReader world) {
return new SequencedGearshiftTileEntity();
}
@Override
public boolean shouldCheckWeakPower(BlockState state, IWorldReader world, BlockPos pos, Direction side) {
return false;
}
@Override
public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos fromPos,
boolean isMoving) {
if (worldIn.isRemote)
return;
boolean previouslyPowered = state.get(STATE) != 0;
if (previouslyPowered != worldIn.isBlockPowered(pos))
withTileEntityDo(worldIn, pos, SequencedGearshiftTileEntity::onRedstoneUpdate);
}
@Override
public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) {
if (state.get(VERTICAL))
return face.getAxis().isVertical();
return super.hasShaftTowards(world, pos, state, face);
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
ItemStack held = player.getHeldItemMainhand();
if (AllItems.WRENCH.typeOf(held))
return false;
if (held.getItem() instanceof BlockItem) {
BlockItem blockItem = (BlockItem) held.getItem();
if (blockItem.getBlock() instanceof KineticBlock && hasShaftTowards(worldIn, pos, state, hit.getFace()))
return false;
}
DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
displayScreen((SequencedGearshiftTileEntity) worldIn.getTileEntity(pos));
});
return true;
}
@OnlyIn(value = Dist.CLIENT)
protected void displayScreen(SequencedGearshiftTileEntity te) {
ScreenOpener.open(new SequencedGearshiftScreen(te));
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
Axis preferredAxis = RotatedPillarKineticBlock.getPreferredAxis(context);
if (preferredAxis != null && !context.isPlacerSneaking())
return withAxis(preferredAxis, context);
return withAxis(context.getNearestLookingDirection().getAxis(), context);
}
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
Direction facing = context.getFace();
if (facing.getAxis().isVertical() && !state.get(VERTICAL)) {
KineticTileEntity.switchToBlockState(context.getWorld(), context.getPos(), state.cycle(VERTICAL));
return ActionResultType.SUCCESS;
}
return super.onWrenched(state, context);
}
private BlockState withAxis(Axis axis, BlockItemUseContext context) {
BlockState state = getDefaultState().with(VERTICAL, axis.isVertical());
if (axis.isVertical())
return state.with(HORIZONTAL_AXIS, context.getPlacementHorizontalFacing().getAxis());
return state.with(HORIZONTAL_AXIS, axis);
}
@Override
public Axis getRotationAxis(BlockState state) {
if (state.get(VERTICAL))
return Axis.Y;
return super.getRotationAxis(state);
}
@Override
protected boolean hasStaticPart() {
return true;
}
}

View file

@ -0,0 +1,195 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import java.util.Vector;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllPackets;
import com.simibubi.create.ScreenResources;
import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.ScreenElementRenderer;
import com.simibubi.create.foundation.gui.widgets.ScrollInput;
import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
public class SequencedGearshiftScreen extends AbstractSimiScreen {
private static final ItemStack renderedItem = new ItemStack(AllBlocks.SEQUENCED_GEARSHIFT.get());
private static final ScreenResources background = ScreenResources.SEQUENCER;
private final String title = Lang.translate("gui.sequenced_gearshift.title");
private int lastModification;
private Vector<Instruction> instructions;
private BlockPos pos;
private Vector<Vector<ScrollInput>> inputs;
public SequencedGearshiftScreen(SequencedGearshiftTileEntity te) {
this.instructions = te.instructions;
this.pos = te.getPos();
lastModification = -1;
}
@Override
protected void init() {
setWindowSize(background.width + 50, background.height);
super.init();
widgets.clear();
inputs = new Vector<>(5);
for (int row = 0; row < inputs.capacity(); row++)
inputs.add(new Vector<>(3));
for (int row = 0; row < instructions.size(); row++)
initInputsOfRow(row);
}
public void initInputsOfRow(int row) {
int x = guiLeft + 28;
int y = guiTop + 29;
int rowHeight = 18;
Vector<ScrollInput> rowInputs = inputs.get(row);
rowInputs.forEach(widgets::remove);
rowInputs.clear();
int index = row;
Instruction instruction = instructions.get(row);
ScrollInput type =
new SelectionScrollInput(x, y + rowHeight * row, 50, 14).forOptions(SequencerInstructions.getOptions())
.calling(state -> instructionUpdated(index, state)).setState(instruction.instruction.ordinal())
.titled(Lang.translate("gui.sequenced_gearshift.instruction"));
ScrollInput value =
new ScrollInput(x + 54, y + rowHeight * row, 30, 14).calling(state -> instruction.value = state);
ScrollInput direction = new SelectionScrollInput(x + 88, y + rowHeight * row, 18, 14)
.forOptions(InstructionSpeedModifiers.getOptions())
.calling(state -> instruction.speedModifier = InstructionSpeedModifiers.values()[state])
.titled(Lang.translate("gui.sequenced_gearshift.speed"));
rowInputs.add(type);
rowInputs.add(value);
rowInputs.add(direction);
widgets.addAll(rowInputs);
updateParamsOfRow(row);
}
public void updateParamsOfRow(int row) {
Instruction instruction = instructions.get(row);
Vector<ScrollInput> rowInputs = inputs.get(row);
SequencerInstructions def = instruction.instruction;
boolean hasValue = def.hasValueParameter;
boolean hasModifier = def.hasSpeedParameter;
ScrollInput value = rowInputs.get(1);
value.active = value.visible = hasValue;
if (hasValue)
value.withRange(1, def.maxValue + 1).titled(Lang.translate(def.parameterKey)).withShiftStep(def.shiftStep)
.setState(instruction.value).onChanged();
if (def == SequencerInstructions.WAIT) {
value.withStepFunction(context -> {
int v = context.currentValue;
if (!context.forward)
v--;
if (v < 20)
return context.shift ? 20 : 1;
return context.shift ? 100 : 20;
});
} else
value.withStepFunction(value.standardStep());
ScrollInput modifier = rowInputs.get(2);
modifier.active = modifier.visible = hasModifier;
if (hasModifier)
modifier.setState(instruction.speedModifier.ordinal());
}
@Override
protected void renderWindow(int mouseX, int mouseY, float partialTicks) {
int hFontColor = 0xD3CBBE;
background.draw(this, guiLeft, guiTop);
for (int row = 0; row < instructions.capacity(); row++) {
ScreenResources toDraw = ScreenResources.SEQUENCER_EMPTY;
int yOffset = toDraw.height * row;
if (row < instructions.size()) {
Instruction instruction = instructions.get(row);
SequencerInstructions def = instruction.instruction;
def.background.draw(guiLeft + 14, guiTop + 29 + yOffset);
label(32, 6 + yOffset, Lang.translate(def.translationKey));
if (def.hasValueParameter) {
String text = def.formatValue(instruction.value);
int stringWidth = font.getStringWidth(text);
label(85 + (12 - stringWidth / 2), 6 + yOffset, text);
}
if (def.hasSpeedParameter)
label(120, 6 + yOffset, instruction.speedModifier.label);
continue;
}
toDraw.draw(guiLeft + 14, guiTop + 29 + yOffset);
}
font.drawStringWithShadow(title, guiLeft - 3 + (background.width - font.getStringWidth(title)) / 2, guiTop + 10,
hFontColor);
ScreenElementRenderer.render3DItem(this::getRenderedBlock);
}
private void label(int x, int y, String text) {
font.drawStringWithShadow(text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE);
}
@Override
public void tick() {
super.tick();
if (lastModification >= 0)
lastModification++;
if (lastModification >= 20) {
lastModification = -1;
sendPacket();
}
}
public void sendPacket() {
AllPackets.channel.sendToServer(new ConfigureSequencedGearshiftPacket(pos, instructions));
}
@Override
public void removed() {
sendPacket();
}
public ItemStack getRenderedBlock() {
GlStateManager.translated(guiLeft + background.width + 20, guiTop + 50, 0);
GlStateManager.scaled(5, 5, 5);
return renderedItem;
}
private void instructionUpdated(int index, int state) {
SequencerInstructions newValue = SequencerInstructions.values()[state];
instructions.get(index).instruction = newValue;
updateParamsOfRow(index);
if (newValue == SequencerInstructions.END) {
for (int i = instructions.size() - 1; i > index; i--) {
instructions.remove(i);
Vector<ScrollInput> rowInputs = inputs.get(i);
rowInputs.forEach(widgets::remove);
rowInputs.clear();
}
} else {
if (index + 1 < instructions.capacity() && index + 1 == instructions.size()) {
instructions.add(new Instruction(SequencerInstructions.END));
initInputsOfRow(index + 1);
}
}
}
}

View file

@ -0,0 +1,128 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import java.util.Vector;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.modules.contraptions.relays.encased.SplitShaftTileEntity;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraftforge.common.util.Constants.NBT;
public class SequencedGearshiftTileEntity extends SplitShaftTileEntity {
Vector<Instruction> instructions;
int currentInstruction;
int currentInstructionDuration;
int timer;
public SequencedGearshiftTileEntity() {
super(AllTileEntities.SEQUENCED_GEARSHIFT.type);
instructions = Instruction.createDefault();
currentInstruction = -1;
currentInstructionDuration = -1;
timer = 0;
}
@Override
public void tick() {
super.tick();
if (isIdle())
return;
if (world.isRemote)
return;
if (timer < currentInstructionDuration) {
timer++;
return;
}
run(currentInstruction + 1);
}
@Override
public void onSpeedChanged(float previousSpeed) {
super.onSpeedChanged(previousSpeed);
if (isIdle())
return;
float currentSpeed = Math.abs(speed);
if (Math.abs(previousSpeed) == currentSpeed)
return;
Instruction instruction = getInstruction(currentInstruction);
if (instruction == null)
return;
// Update instruction time with regards to new speed
float initialProgress = timer / (float) currentInstructionDuration;
currentInstructionDuration = instruction.getDuration(initialProgress, getTheoreticalSpeed());
timer = 0;
}
public boolean isIdle() {
return currentInstruction == -1;
}
public void onRedstoneUpdate() {
if (!isIdle())
return;
if (!world.isBlockPowered(pos)) {
world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, 0), 3);
return;
}
run(0);
}
protected void run(int instructionIndex) {
Instruction instruction = getInstruction(instructionIndex);
if (instruction == null || instruction.instruction == SequencerInstructions.END) {
if (getModifier() != 0)
detachKinetics();
currentInstruction = -1;
currentInstructionDuration = -1;
timer = 0;
if (!world.isBlockPowered(pos))
world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, 0), 3);
else
sendData();
return;
}
detachKinetics();
currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed());
currentInstruction = instructionIndex;
timer = 0;
world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3);
}
public Instruction getInstruction(int instructionIndex) {
return instructionIndex >= 0 && instructionIndex < instructions.size() ? instructions.get(instructionIndex)
: null;
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.putInt("InstructionIndex", currentInstruction);
compound.putInt("InstructionDuration", currentInstructionDuration);
compound.putInt("Timer", timer);
compound.put("Instructions", Instruction.serializeAll(instructions));
return super.write(compound);
}
@Override
public void read(CompoundNBT compound) {
currentInstruction = compound.getInt("InstructionIndex");
currentInstructionDuration = compound.getInt("InstructionDuration");
timer = compound.getInt("Timer");
instructions = Instruction.deserializeAll(compound.getList("Instructions", NBT.TAG_COMPOUND));
super.read(compound);
}
@Override
public float getRotationSpeedModifier(Direction face) {
return (!hasSource() || face == getSourceFacing()) ? 1 : getModifier();
}
public int getModifier() {
return isIdle() ? 0 : instructions.get(currentInstruction).getSpeedModifier();
}
}

View file

@ -0,0 +1,61 @@
package com.simibubi.create.modules.contraptions.relays.advanced.sequencer;
import java.util.ArrayList;
import java.util.List;
import com.simibubi.create.ScreenResources;
import com.simibubi.create.foundation.utility.Lang;
public enum SequencerInstructions {
TURN_ANGLE("angle", ScreenResources.SEQUENCER_INSTRUCTION, true, true, 360, 45),
TURN_DISTANCE("distance", ScreenResources.SEQUENCER_INSTRUCTION, true, true, 50, 5),
WAIT("duration", ScreenResources.SEQUENCER_WAIT, true, false, 600, 20),
END("", ScreenResources.SEQUENCER_END),
;
String translationKey;
String parameterKey;
boolean hasValueParameter;
boolean hasSpeedParameter;
ScreenResources background;
int maxValue;
int shiftStep;
private SequencerInstructions(String parameterName, ScreenResources background) {
this(parameterName, background, false, false, -1, -1);
}
private SequencerInstructions(String parameterName, ScreenResources background, boolean hasValueParameter,
boolean hasSpeedParameter, int maxValue, int shiftStep) {
this.hasValueParameter = hasValueParameter;
this.hasSpeedParameter = hasSpeedParameter;
this.background = background;
this.maxValue = maxValue;
this.shiftStep = shiftStep;
translationKey = "gui.sequenced_gearshift.instruction." + Lang.asId(name());
parameterKey = translationKey + "." + parameterName;
}
static List<String> getOptions() {
List<String> options = new ArrayList<>();
for (SequencerInstructions entry : values())
options.add(Lang.translate(entry.translationKey));
return options;
}
String formatValue(int value) {
if (this == TURN_ANGLE)
return value + "°";
if (this == TURN_DISTANCE)
return value + "m";
if (this == WAIT) {
if (value >= 20)
return (value / 20) + "s";
return value + "t";
}
return "" + value;
}
}

View file

@ -153,8 +153,13 @@ public class BeltBlock extends HorizontalKineticBlock
if (state.get(SLOPE) == Slope.VERTICAL) if (state.get(SLOPE) == Slope.VERTICAL)
return; return;
if (entityIn instanceof PlayerEntity && entityIn.isSneaking()) if (entityIn instanceof PlayerEntity) {
return; PlayerEntity player = (PlayerEntity) entityIn;
if (player.isSneaking())
return;
if (player.abilities.isFlying)
return;
}
if (belt == null || belt.getSpeed() == 0) if (belt == null || belt.getSpeed() == 0)
return; return;
if (entityIn instanceof ItemEntity && entityIn.isAlive()) { if (entityIn instanceof ItemEntity && entityIn.isAlive()) {

View file

@ -7,6 +7,7 @@ import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
import java.util.List; import java.util.List;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionEntity;
import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState; import com.simibubi.create.modules.contraptions.relays.belt.AllBeltAttachments.BeltAttachmentState;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Part;
import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope; import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
@ -14,6 +15,7 @@ import com.simibubi.create.modules.contraptions.relays.belt.BeltBlock.Slope;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.item.HangingEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.potion.EffectInstance; import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects; import net.minecraft.potion.Effects;
@ -150,7 +152,7 @@ public class BeltMovementHandler {
checkBB = checkBB.offset(checkDistance).grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y), checkBB = checkBB.offset(checkDistance).grow(-Math.abs(checkDistance.x), -Math.abs(checkDistance.y),
-Math.abs(checkDistance.z)); -Math.abs(checkDistance.z));
List<Entity> list = world.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB); List<Entity> list = world.getEntitiesWithinAABBExcludingEntity(entityIn, checkBB);
list.removeIf(e -> entityIn.isRidingOrBeingRiddenBy(e)); list.removeIf(e -> shouldIgnoreBlocking(entityIn, e));
if (!list.isEmpty()) { if (!list.isEmpty()) {
entityIn.setMotion(0, 0, 0); entityIn.setMotion(0, 0, 0);
info.ticksSinceLastCollision--; info.ticksSinceLastCollision--;
@ -186,4 +188,12 @@ public class BeltMovementHandler {
} }
} }
public static boolean shouldIgnoreBlocking(Entity me, Entity other) {
if (other instanceof ContraptionEntity)
return true;
if (other instanceof HangingEntity)
return true;
return me.isRidingOrBeingRiddenBy(other);
}
} }

View file

@ -3,11 +3,12 @@ package com.simibubi.create.modules.contraptions.relays.encased;
import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlockPartials;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.modules.contraptions.base.IRotate;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity; import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import net.minecraft.block.Block;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -15,9 +16,10 @@ import net.minecraft.util.math.BlockPos;
public class SplitShaftTileEntityRenderer extends KineticTileEntityRenderer { public class SplitShaftTileEntityRenderer extends KineticTileEntityRenderer {
@Override @Override
public void renderFast(KineticTileEntity te, double x, double y, double z, float partialTicks, public void renderFast(KineticTileEntity te, double x, double y, double z, float partialTicks, int destroyStage,
int destroyStage, BufferBuilder buffer) { BufferBuilder buffer) {
final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); Block block = te.getBlockState().getBlock();
final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState());
final BlockPos pos = te.getPos(); final BlockPos pos = te.getPos();
float time = AnimationTickHolder.getRenderTick(); float time = AnimationTickHolder.getRenderTick();
@ -37,8 +39,8 @@ public class SplitShaftTileEntityRenderer extends KineticTileEntityRenderer {
angle += offset; angle += offset;
angle = angle / 180f * (float) Math.PI; angle = angle / 180f * (float) Math.PI;
SuperByteBuffer superByteBuffer = AllBlockPartials.SHAFT_HALF.renderOnDirectional(te.getBlockState(), SuperByteBuffer superByteBuffer =
direction); AllBlockPartials.SHAFT_HALF.renderOnDirectional(te.getBlockState(), direction);
kineticRotationTransform(superByteBuffer, te, axis, angle, getWorld()); kineticRotationTransform(superByteBuffer, te, axis, angle, getWorld());
superByteBuffer.translate(x, y, z).renderInto(buffer); superByteBuffer.translate(x, y, z).renderInto(buffer);

View file

@ -60,7 +60,8 @@ public class RedstoneLinkTileEntity extends SmartTileEntity {
public void transmit(boolean signal) { public void transmit(boolean signal) {
transmittedSignal = signal; transmittedSignal = signal;
link.notifySignalChange(); if (link != null)
link.notifySignalChange();
} }
@Override @Override

View file

@ -14,6 +14,7 @@ import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.MathHelper;
public class FlexpeaterTileEntity extends SmartTileEntity { public class FlexpeaterTileEntity extends SmartTileEntity {
@ -36,8 +37,15 @@ public class FlexpeaterTileEntity extends SmartTileEntity {
maxState.withStepFunction(this::step); maxState.withStepFunction(this::step);
maxState.withFormatter(this::format); maxState.withFormatter(this::format);
maxState.withUnit(this::getUnit); maxState.withUnit(this::getUnit);
maxState.withCallback(this::onMaxDelayChanged);
behaviours.add(maxState); behaviours.add(maxState);
} }
private void onMaxDelayChanged(int newMax) {
state = MathHelper.clamp(state, 0, newMax);
sendData();
}
@Override @Override
public void read(CompoundNBT compound) { public void read(CompoundNBT compound) {

View file

@ -0,0 +1,31 @@
{
"variants": {
"vertical=false,axis=x,state=0" : { "model": "create:block/sequenced_gearshift/idle", "y": 90 },
"vertical=false,axis=x,state=1" : { "model": "create:block/sequenced_gearshift/seq_1", "y": 90 },
"vertical=false,axis=x,state=2" : { "model": "create:block/sequenced_gearshift/seq_2", "y": 90 },
"vertical=false,axis=x,state=3" : { "model": "create:block/sequenced_gearshift/seq_3", "y": 90 },
"vertical=false,axis=x,state=4" : { "model": "create:block/sequenced_gearshift/seq_4", "y": 90 },
"vertical=false,axis=x,state=5" : { "model": "create:block/sequenced_gearshift/seq_5", "y": 90 },
"vertical=false,axis=z,state=0" : { "model": "create:block/sequenced_gearshift/idle" },
"vertical=false,axis=z,state=1" : { "model": "create:block/sequenced_gearshift/seq_1" },
"vertical=false,axis=z,state=2" : { "model": "create:block/sequenced_gearshift/seq_2" },
"vertical=false,axis=z,state=3" : { "model": "create:block/sequenced_gearshift/seq_3" },
"vertical=false,axis=z,state=4" : { "model": "create:block/sequenced_gearshift/seq_4" },
"vertical=false,axis=z,state=5" : { "model": "create:block/sequenced_gearshift/seq_5" },
"vertical=true,axis=x,state=0" : { "model": "create:block/sequenced_gearshift/idle", "x": 90, "y": 90 },
"vertical=true,axis=x,state=1" : { "model": "create:block/sequenced_gearshift/seq_1", "x": 90, "y": 90 },
"vertical=true,axis=x,state=2" : { "model": "create:block/sequenced_gearshift/seq_2", "x": 90, "y": 90 },
"vertical=true,axis=x,state=3" : { "model": "create:block/sequenced_gearshift/seq_3", "x": 90, "y": 90 },
"vertical=true,axis=x,state=4" : { "model": "create:block/sequenced_gearshift/seq_4", "x": 90, "y": 90 },
"vertical=true,axis=x,state=5" : { "model": "create:block/sequenced_gearshift/seq_5", "x": 90, "y": 90 },
"vertical=true,axis=z,state=0" : { "model": "create:block/sequenced_gearshift/idle", "x": 90 },
"vertical=true,axis=z,state=1" : { "model": "create:block/sequenced_gearshift/seq_1", "x": 90 },
"vertical=true,axis=z,state=2" : { "model": "create:block/sequenced_gearshift/seq_2", "x": 90 },
"vertical=true,axis=z,state=3" : { "model": "create:block/sequenced_gearshift/seq_3", "x": 90 },
"vertical=true,axis=z,state=4" : { "model": "create:block/sequenced_gearshift/seq_4", "x": 90 },
"vertical=true,axis=z,state=5" : { "model": "create:block/sequenced_gearshift/seq_5", "x": 90 }
}
}

View file

@ -151,6 +151,7 @@
"block.create.logisticians_table": "Logisticians Table", "block.create.logisticians_table": "Logisticians Table",
"block.create.package_funnel": "Package Funnel", "block.create.package_funnel": "Package Funnel",
"block.create.belt_tunnel": "Conveyor Tunnel", "block.create.belt_tunnel": "Conveyor Tunnel",
"block.create.sequenced_gearshift": "Sequenced Gearshift",
"block.create.tiled_glass": "Tiled Glass", "block.create.tiled_glass": "Tiled Glass",
"block.create.framed_glass": "Large Glass Window", "block.create.framed_glass": "Large Glass Window",
@ -421,6 +422,21 @@
"create.gui.stockswitch.startAbove": "Start Signal above", "create.gui.stockswitch.startAbove": "Start Signal above",
"create.gui.stockswitch.stopAt": "Stop Signal at", "create.gui.stockswitch.stopAt": "Stop Signal at",
"create.gui.stockswitch.stopBelow": "Stop Signal below", "create.gui.stockswitch.stopBelow": "Stop Signal below",
"create.gui.sequenced_gearshift.title": "Sequenced Gearshift",
"create.gui.sequenced_gearshift.instruction": "Instruction",
"create.gui.sequenced_gearshift.instruction.turn_angle": "Turn",
"create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angle",
"create.gui.sequenced_gearshift.instruction.turn_distance": "Piston",
"create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distance",
"create.gui.sequenced_gearshift.instruction.wait": "Wait",
"create.gui.sequenced_gearshift.instruction.wait.duration": "Duration",
"create.gui.sequenced_gearshift.instruction.end": "End",
"create.gui.sequenced_gearshift.speed": "Speed, Direction",
"create.gui.sequenced_gearshift.speed.forward": "Input speed, Forwards",
"create.gui.sequenced_gearshift.speed.forward_fast": "Double speed, Forwards",
"create.gui.sequenced_gearshift.speed.back": "Input speed, Reversed",
"create.gui.sequenced_gearshift.speed.back_fast": "Double speed, Reversed",
"create.schematicAndQuill.dimensions": "Schematic Size: %1$sx%2$sx%3$s", "create.schematicAndQuill.dimensions": "Schematic Size: %1$sx%2$sx%3$s",
"create.schematicAndQuill.firstPos": "First position set.", "create.schematicAndQuill.firstPos": "First position set.",

View file

@ -0,0 +1,110 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"0": "create:block/brass_casing",
"1": "create:block/brass_gearbox",
"4": "create:block/sequenced_gearshift",
"particle": "create:block/brass_gearbox"
},
"elements": [
{
"name": "Core",
"from": [1, 1, 1],
"to": [15, 15, 15],
"faces": {
"north": {"uv": [1, 1, 15, 15], "texture": "#1"},
"south": {"uv": [1, 1, 15, 15], "texture": "#1"},
"up": {"uv": [1, 1, 15, 15], "texture": "#4"},
"down": {"uv": [1, 1, 15, 15], "texture": "#4"}
}
},
{
"name": "Top",
"from": [0, 14, 0],
"to": [5, 16, 16],
"faces": {
"north": {"uv": [11, 0, 16, 2], "texture": "#0"},
"east": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#4"},
"south": {"uv": [0, 0, 5, 2], "texture": "#0"},
"west": {"uv": [0, 0, 2, 16], "rotation": 270, "texture": "#4"},
"up": {"uv": [0, 0, 5, 16], "texture": "#4"},
"down": {"uv": [0, 0, 16, 16], "texture": "#0"}
}
},
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [5, 2, 16],
"faces": {
"north": {"uv": [11, 14, 16, 16], "texture": "#0"},
"east": {"uv": [2, 0, 0, 16], "rotation": 90, "texture": "#4"},
"south": {"uv": [0, 14, 5, 16], "texture": "#0"},
"west": {"uv": [2, 0, 0, 16], "rotation": 90, "texture": "#4"},
"up": {"uv": [0, 16, 16, 0], "texture": "#0"},
"down": {"uv": [0, 16, 5, 0], "texture": "#4"}
}
},
{
"name": "Top",
"from": [11, 14, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [16, 0, 11, 2], "texture": "#0"},
"east": {"uv": [0, 16, 2, 0], "rotation": 90, "texture": "#4"},
"south": {"uv": [5, 0, 0, 2], "texture": "#0"},
"west": {"uv": [0, 16, 2, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [11, 0, 16, 16], "texture": "#4"},
"down": {"uv": [16, 0, 0, 16], "texture": "#0"}
}
},
{
"name": "Bottom",
"from": [11, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 14, 5, 16], "texture": "#0"},
"east": {"uv": [2, 16, 0, 0], "rotation": 90, "texture": "#4"},
"south": {"uv": [11, 14, 16, 16], "texture": "#0"},
"west": {"uv": [2, 16, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [16, 16, 0, 0], "texture": "#0"},
"down": {"uv": [11, 16, 16, 0], "texture": "#4"}
}
},
{
"name": "SideWest",
"from": [0, 2, 0],
"to": [2, 14, 16],
"faces": {
"north": {"uv": [14, 2, 16, 14], "texture": "#0"},
"east": {"uv": [0, 2, 16, 14], "texture": "#0"},
"south": {"uv": [0, 2, 2, 14], "texture": "#0"},
"west": {"uv": [0, 2, 16, 14], "texture": "#0"}
}
},
{
"name": "SideEast",
"from": [14, 2, 0],
"to": [16, 14, 16],
"faces": {
"north": {"uv": [0, 2, 2, 14], "texture": "#0"},
"east": {"uv": [0, 2, 16, 14], "texture": "#0"},
"south": {"uv": [14, 2, 16, 14], "texture": "#0"},
"west": {"uv": [0, 2, 16, 14], "texture": "#0"}
}
}
],
"groups": [
{
"name": "encased_shaft",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6,
{
"name": "shaft",
"origin": [8, 8, 8],
"children": []
}
]
}
]
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/sequenced_gearshift/idle",
"textures": {
"4": "create:block/sequenced_gearshift_1"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/sequenced_gearshift/idle",
"textures": {
"4": "create:block/sequenced_gearshift_2"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/sequenced_gearshift/idle",
"textures": {
"4": "create:block/sequenced_gearshift_3"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/sequenced_gearshift/idle",
"textures": {
"4": "create:block/sequenced_gearshift_4"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "create:block/sequenced_gearshift/idle",
"textures": {
"4": "create:block/sequenced_gearshift_5"
}
}

View file

@ -0,0 +1,125 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"0": "create:block/brass_casing",
"1": "create:block/brass_gearbox",
"4": "create:block/sequenced_gearshift",
"particle": "create:block/axis",
"1_0": "create:block/axis",
"1_1": "create:block/axis_top"
},
"elements": [
{
"name": "Core",
"from": [1, 1, 1],
"to": [15, 15, 15],
"faces": {
"north": {"uv": [1, 1, 15, 15], "texture": "#1"},
"south": {"uv": [1, 1, 15, 15], "texture": "#1"},
"up": {"uv": [1, 1, 15, 15], "texture": "#4"},
"down": {"uv": [1, 1, 15, 15], "texture": "#4"}
}
},
{
"name": "Top",
"from": [0, 14, 0],
"to": [5, 16, 16],
"faces": {
"north": {"uv": [11, 0, 16, 2], "texture": "#0"},
"east": {"uv": [0, 0, 2, 16], "rotation": 90, "texture": "#4"},
"south": {"uv": [0, 0, 5, 2], "texture": "#0"},
"west": {"uv": [0, 0, 2, 16], "rotation": 270, "texture": "#4"},
"up": {"uv": [0, 0, 5, 16], "texture": "#4"},
"down": {"uv": [0, 0, 16, 16], "texture": "#0"}
}
},
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [5, 2, 16],
"faces": {
"north": {"uv": [11, 14, 16, 16], "texture": "#0"},
"east": {"uv": [2, 0, 0, 16], "rotation": 90, "texture": "#4"},
"south": {"uv": [0, 14, 5, 16], "texture": "#0"},
"west": {"uv": [2, 0, 0, 16], "rotation": 90, "texture": "#4"},
"up": {"uv": [0, 16, 16, 0], "texture": "#0"},
"down": {"uv": [0, 16, 5, 0], "texture": "#4"}
}
},
{
"name": "Top",
"from": [11, 14, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [16, 0, 11, 2], "texture": "#0"},
"east": {"uv": [0, 16, 2, 0], "rotation": 90, "texture": "#4"},
"south": {"uv": [5, 0, 0, 2], "texture": "#0"},
"west": {"uv": [0, 16, 2, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [11, 0, 16, 16], "texture": "#4"},
"down": {"uv": [16, 0, 0, 16], "texture": "#0"}
}
},
{
"name": "Bottom",
"from": [11, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 14, 5, 16], "texture": "#0"},
"east": {"uv": [2, 16, 0, 0], "rotation": 90, "texture": "#4"},
"south": {"uv": [11, 14, 16, 16], "texture": "#0"},
"west": {"uv": [2, 16, 0, 0], "rotation": 90, "texture": "#4"},
"up": {"uv": [16, 16, 0, 0], "texture": "#0"},
"down": {"uv": [11, 16, 16, 0], "texture": "#4"}
}
},
{
"name": "SideWest",
"from": [0, 2, 0],
"to": [2, 14, 16],
"faces": {
"north": {"uv": [14, 2, 16, 14], "texture": "#0"},
"east": {"uv": [0, 2, 16, 14], "texture": "#0"},
"south": {"uv": [0, 2, 2, 14], "texture": "#0"},
"west": {"uv": [0, 2, 16, 14], "texture": "#0"}
}
},
{
"name": "SideEast",
"from": [14, 2, 0],
"to": [16, 14, 16],
"faces": {
"north": {"uv": [0, 2, 2, 14], "texture": "#0"},
"east": {"uv": [0, 2, 16, 14], "texture": "#0"},
"south": {"uv": [14, 2, 16, 14], "texture": "#0"},
"west": {"uv": [0, 2, 16, 14], "texture": "#0"}
}
},
{
"name": "Axis",
"from": [6, 6, 0],
"to": [10, 10, 16],
"faces": {
"north": {"uv": [6, 6, 10, 10], "rotation": 180, "texture": "#1_1"},
"east": {"uv": [6, 0, 10, 16], "rotation": 90, "texture": "#1_0"},
"south": {"uv": [6, 6, 10, 10], "texture": "#1_1"},
"west": {"uv": [6, 0, 10, 16], "rotation": 270, "texture": "#1_0"},
"up": {"uv": [6, 0, 10, 16], "texture": "#1_0"},
"down": {"uv": [6, 0, 10, 16], "rotation": 180, "texture": "#1_0"}
}
}
],
"groups": [
{
"name": "encased_shaft",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6,
{
"name": "shaft",
"origin": [8, 8, 8],
"children": [7]
}
]
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "create:sequenced_gearshift"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -0,0 +1,33 @@
{
"type": "crafting_shaped",
"type": "crafting_shaped",
"pattern": [
" B ",
"SCS",
" I "
],
"key": {
"S": {
"item": "create:cogwheel"
},
"B": {
"item": "create:electron_tube"
},
"C": {
"item": "create:brass_casing"
},
"I": {
"item": "minecraft:clock"
}
},
"result": {
"item": "create:sequenced_gearshift",
"count": 1
},
"conditions": [
{
"type": "create:module",
"module": "contraptions"
}
]
}