diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java index 49cba252a..197637276 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java @@ -28,7 +28,8 @@ import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions { +public class ClockworkBearingTileEntity extends KineticTileEntity + implements IBearingTileEntity, IDisplayAssemblyExceptions { protected ControlledContraptionEntity hourHand; protected ControlledContraptionEntity minuteHand; @@ -40,9 +41,10 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe protected boolean running; protected boolean assembleNextTick; protected AssemblyException lastException; - protected ScrollOptionBehaviour operationMode; + private float prevForcedAngle; + public ClockworkBearingTileEntity(TileEntityType type) { super(type); setLazyTickRate(3); @@ -67,6 +69,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe super.tick(); if (world.isRemote) { + prevForcedAngle = hourAngle; clientMinuteAngleDiff /= 2; clientHourAngleDiff /= 2; } @@ -341,6 +344,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe @Override public float getInterpolatedAngle(float partialTicks) { + if (isVirtual()) + return MathHelper.lerp(partialTicks, prevForcedAngle, hourAngle); if (hourHand == null || hourHand.isStalled()) partialTicks = 0; return MathHelper.lerp(partialTicks, hourAngle, hourAngle + getHourArmSpeed()); @@ -414,4 +419,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe public boolean shouldRenderAsTE() { return true; } + + public void setAngle(float forcedAngle) { + hourAngle = forcedAngle; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java index f2f9a475d..e729feae4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/IBearingTileEntity.java @@ -20,5 +20,7 @@ public interface IBearingTileEntity extends IControlContraption { return bearingAxis != axis; }); } + + void setAngle(float forcedAngle); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java index 182e063bb..00d708294 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java @@ -41,9 +41,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected float getOffset(KineticTileEntity te, float partialTicks) { PulleyTileEntity pulley = (PulleyTileEntity) te; - boolean running = pulley.running; - boolean moving = running && (pulley.movedContraption == null || !pulley.movedContraption.isStalled()); - float offset = pulley.getInterpolatedOffset(moving ? partialTicks : 0.5f); + float offset = pulley.getInterpolatedOffset(partialTicks); if (pulley.movedContraption != null) { AbstractContraptionEntity e = pulley.movedContraption; @@ -57,7 +55,7 @@ public class PulleyRenderer extends AbstractPulleyRenderer { @Override protected boolean isRunning(KineticTileEntity te) { - return ((PulleyTileEntity) te).running; + return ((PulleyTileEntity) te).running || te.isVirtual(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java index 5fde955e9..f6dbbb33c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java @@ -27,6 +27,7 @@ import net.minecraft.util.math.Vec3d; public class PulleyTileEntity extends LinearActuatorTileEntity { protected int initialOffset; + private float prevAnimatedOffset; public PulleyTileEntity(TileEntityType type) { super(type); @@ -41,6 +42,13 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { public double getMaxRenderDistanceSquared() { return super.getMaxRenderDistanceSquared() + offset * offset; } + + @Override + public void tick() { + super.tick(); + if (isVirtual()) + prevAnimatedOffset = offset; + } @Override protected void assemble() throws AssemblyException { @@ -219,4 +227,16 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { return new CenteredSideValueBoxTransform((state, d) -> d == Direction.UP); } + @Override + public float getInterpolatedOffset(float partialTicks) { + if (isVirtual()) + return MathHelper.lerp(partialTicks, prevAnimatedOffset, offset); + boolean moving = running && (movedContraption == null || !movedContraption.isStalled()); + return super.getInterpolatedOffset(moving ? partialTicks : 0.5f); + } + + public void animateOffset(float forcedOffset) { + offset = forcedOffset; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java index 1eee89b34..a622c8b8d 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -80,6 +80,7 @@ public class PonderScene { int offsetZ; int size; + boolean stoppedCounting; int totalTime; int currentTime; @@ -189,6 +190,7 @@ public class PonderScene { elements.add(baseWorldSection); totalTime = 0; + stoppedCounting = false; activeSchedule.addAll(schedule); activeSchedule.forEach(i -> i.onScheduled(this)); } @@ -269,7 +271,12 @@ public class PonderScene { } public void addToSceneTime(int time) { - totalTime += time; + if (!stoppedCounting) + totalTime += time; + } + + public void stopCounting() { + stoppedCounting = true; } public void addElement(PonderElement e) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java index 9ba29fd57..a1526380d 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java @@ -327,9 +327,10 @@ public class BearingScenes { scene.overlay.showText(60) .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) .placeNearTarget() - .text("This behaviour can be modified using a Wrench"); + .sharedText("behaviour_modify_wrench"); scene.idle(70); + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); scene.world.toggleRedstonePower(cogAndClutch); scene.effects.indicateRedstone(leverPos); scene.world.rotateSection(contraption, 0, -55, 0, 23); @@ -343,7 +344,6 @@ public class BearingScenes { scene.overlay.showText(120) .colored(PonderPalette.GREEN) .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 3), Direction.UP)) - .placeNearTarget() .text("It can be configured never to revert to solid blocks, or only near the angle it started at"); } @@ -410,11 +410,143 @@ public class BearingScenes { scene.world.rotateSection(contraption, 0, 0, 360 * 2, 74 * 2); scene.world.rotateBearing(bearingPos, -360 * 2, 74 * 2); scene.world.rotateSection(subContraption, 0, 0, 360 * 2, 74 * 2); - + scene.markAsFinished(); scene.idle(74 * 2); scene.world.setKineticSpeed(largeCog, 0); scene.world.setKineticSpeed(beltAndBearing, 0); } + public static void clockwork(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("clockwork_bearing", "Animating Structures using Clockwork Bearings"); + + Selection kinetics = util.select.fromTo(3, 3, 4, 3, 1, 6); + Selection largeCog = util.select.position(2, 0, 6); + BlockPos bearingPos = util.grid.at(3, 3, 3); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(kinetics, Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(bearingPos), Direction.DOWN); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos.north()), 60) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .text("Clockwork Bearings attach to blocks in front of them"); + scene.idle(50); + + ElementLink plank = + scene.world.showIndependentSection(util.select.position(2, 3, 2), Direction.SOUTH); + scene.world.moveSection(plank, util.vector.of(1, 0, 0), 0); + scene.idle(20); + + scene.world.rotateSection(plank, 0, 0, 60, 25); + scene.world.rotateBearing(bearingPos, 60, 25); + scene.world.setKineticSpeed(kinetics, 8); + scene.world.setKineticSpeed(largeCog, -4); + + scene.idle(25); + scene.overlay.showText(80) + .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) + .placeNearTarget() + .text("Upon receiving Rotational Force, the structure will be rotated according to the hour of the day"); + scene.idle(90); + + scene.overlay.showText(30) + .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) + .placeNearTarget() + .text("3:00"); + scene.world.rotateSection(plank, 0, 0, 30, 12); + scene.world.rotateBearing(bearingPos, 30, 12); + scene.idle(42); + scene.overlay.showText(30) + .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) + .placeNearTarget() + .text("4:00"); + scene.world.rotateSection(plank, 0, 0, 30, 12); + scene.world.rotateBearing(bearingPos, 30, 12); + scene.idle(42); + + InputWindowElement clickTheBearing = new InputWindowElement(util.vector.topOf(bearingPos), Pointing.DOWN); + InputWindowElement clickTheBearingSide = + new InputWindowElement(util.vector.blockSurface(bearingPos, Direction.WEST), Pointing.LEFT); + + scene.overlay.showControls(clickTheBearing.rightClick(), 60); + scene.idle(7); + scene.world.rotateSection(plank, 0, 0, -120, 0); + scene.world.rotateBearing(bearingPos, -120, 0); + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) + .placeNearTarget() + .text("Right-Click the bearing to start or stop animating the structure"); + scene.idle(70); + + scene.world.hideIndependentSection(plank, Direction.NORTH); + scene.idle(15); + + ElementLink hourHand = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 1, 3, 5, 2), Direction.SOUTH); + scene.world.configureCenterOfRotation(hourHand, util.vector.centerOf(bearingPos)); + scene.idle(15); + scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80) + .placeNearTarget() + .sharedText("movement_anchors"); + scene.idle(90); + + scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); + scene.idle(7); + scene.world.rotateSection(hourHand, 0, 0, 120, 50); + scene.world.rotateBearing(bearingPos, 120, 50); + scene.idle(60); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos.north(3)), 80) + .placeNearTarget() + .colored(PonderPalette.BLUE) + .text("In front of the Hour Hand, a second structure can be added"); + scene.idle(90); + scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); + scene.idle(7); + scene.world.rotateSection(hourHand, 0, 0, -120, 0); + scene.world.rotateBearing(bearingPos, -120, 0); + scene.idle(10); + + ElementLink minuteHand = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 0, 3, 6, 0), Direction.SOUTH); + scene.world.configureCenterOfRotation(minuteHand, util.vector.centerOf(bearingPos)); + scene.idle(30); + + scene.overlay.showOutline(PonderPalette.BLUE, minuteHand, util.select.fromTo(3, 3, 0, 3, 6, 0), 85); + scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80) + .placeNearTarget() + .colored(PonderPalette.GREEN) + .text("Ensure the two Structures are not attached to each other through super glue or similar"); + scene.idle(90); + + scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); + scene.idle(7); + + scene.world.rotateSection(hourHand, 0, 0, 120, 50); + scene.world.rotateSection(minuteHand, 0, 0, 180, 75); + scene.world.rotateBearing(bearingPos, 120, 50); + scene.idle(90); + scene.world.rotateSection(minuteHand, 0, 0, 6, 3); + + scene.overlay.showText(80) + .placeNearTarget() + .pointAt(util.vector.blockSurface(bearingPos.north(3), Direction.NORTH)) + .colored(PonderPalette.GREEN) + .text("The Second Structure will now rotate as the Minute Hand"); + scene.markAsFinished(); + + for (int i = 0; i < 40; i++) { + scene.idle(23); + scene.world.rotateSection(minuteHand, 0, 0, 6, 3); + if (i == 29) + scene.world.rotateSection(hourHand, 0, 0, 30, 20); + } + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java new file mode 100644 index 000000000..28706d1fa --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java @@ -0,0 +1,279 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonHeadBlock; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.ParrotElement; +import com.simibubi.create.foundation.ponder.elements.ParrotElement.FaceCursorPose; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.block.DoublePlantBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.state.properties.DoubleBlockHalf; +import net.minecraft.state.properties.PistonType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class PistonScenes { + + public static void movement(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_piston", "Moving Structures using Mechanical Pistons"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0) + .add(util.select.position(0, 1, 2)), Direction.UP); + + Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2); + BlockPos piston = util.grid.at(3, 1, 2); + BlockPos leverPos = util.grid.at(3, 2, 4); + BlockPos shaft = util.grid.at(3, 1, 3); + + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(piston), Direction.DOWN); + ElementLink contraption = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN); + scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0); + scene.idle(20); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east(2)), Direction.DOWN, contraption); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west()), Direction.DOWN, contraption); + scene.idle(15); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.overlay.showText(55) + .pointAt(util.vector.topOf(piston)) + .placeNearTarget() + .text("Mechanical Pistons can move blocks in front of them"); + scene.idle(65); + + scene.overlay.showText(45) + .pointAt(util.vector.blockSurface(shaft, Direction.SOUTH)) + .placeNearTarget() + .text("Speed and direction of movement depend on the Rotational Input"); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.OAK_PLANKS.getDefaultState(), false); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); + scene.idle(60); + + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(piston, Direction.WEST), Pointing.DOWN).rightClick() + .withItem(new ItemStack(Items.SLIME_BALL)), + 30); + scene.idle(7); + scene.world.modifyBlock(piston.north(), s -> s.with(MechanicalPistonHeadBlock.TYPE, PistonType.STICKY), false); + scene.effects.superGlue(piston, Direction.WEST, true); + + scene.idle(33); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + + scene.idle(25); + scene.overlay.showText(60) + .pointAt(util.vector.topOf(piston)) + .placeNearTarget() + .text("Sticky Mechanical Pistons can pull the attached blocks back"); + scene.idle(20); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.OAK_PLANKS.getDefaultState(), false); + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.AIR.getDefaultState(), false); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); + + scene.idle(50); + scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.AIR.getDefaultState(), false); + ElementLink chassis = + scene.world.showIndependentSection(util.select.fromTo(2, 2, 0, 2, 3, 2), Direction.DOWN); + scene.world.moveSection(chassis, util.vector.of(0, -1, 1), 0); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(1, 2, 0), Direction.EAST, chassis); + scene.idle(15); + scene.effects.superGlue(piston.west() + .north(), Direction.WEST, true); + scene.overlay.showText(80) + .pointAt(util.vector.topOf(piston.west())) + .placeNearTarget() + .sharedText("movement_anchors"); + + scene.idle(90); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.world.moveSection(chassis, util.vector.of(-2, 0, 0), 40); + } + + public static void poles(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("piston_pole", "Piston Extension Poles"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> -f); + + Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2); + BlockPos piston = util.grid.at(3, 1, 2); + + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(piston), Direction.DOWN); + ElementLink contraption = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN); + scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0); + scene.idle(20); + + BlockPos leverPos = util.grid.at(3, 2, 4); + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.setKineticSpeed(kinetics, 16); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.position(piston), 50) + .colored(PonderPalette.RED) + .placeNearTarget() + .text("Without attached Poles, a Mechanical Piston cannot move"); + scene.idle(60); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.setKineticSpeed(kinetics, 0); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east(2)), Direction.DOWN, contraption); + scene.idle(10); + + scene.overlay.showOutline(PonderPalette.RED, new Object(), util.select.fromTo(piston.east(), piston.east(2)), + 100); + scene.overlay.showSelectionWithText(util.select.fromTo(piston.west(), piston.west(2)), 100) + .text("The Length of pole added at its back determines the Extension Range") + .placeNearTarget() + .colored(PonderPalette.GREEN); + scene.idle(110); + + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west()), Direction.EAST, contraption); + scene.idle(10); + ElementLink birb = + scene.special.createBirb(util.vector.topOf(piston.west()), FaceCursorPose::new); + scene.idle(15); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.setKineticSpeed(kinetics, 16); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.special.moveParrot(birb, util.vector.of(-2, 0, 0), 40); + + } + + public static void movementModes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_piston_modes", "Movement Modes of the Mechanical Piston"); + scene.configureBasePlate(0, 0, 5); + Selection rose = util.select.fromTo(0, 2, 2, 0, 1, 2); + scene.world.showSection(util.select.layer(0) + .add(rose), Direction.UP); + + Selection kinetics = util.select.fromTo(3, 1, 3, 3, 1, 2); + BlockPos piston = util.grid.at(3, 1, 2); + BlockPos leverPos = util.grid.at(3, 2, 4); + BlockPos shaft = util.grid.at(3, 1, 3); + + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 3, 3, 2, 5), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(piston), Direction.DOWN); + ElementLink contraption = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.DOWN); + scene.world.moveSection(contraption, util.vector.of(0, 0, 1), 0); + scene.idle(20); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .east(2)), Direction.DOWN, contraption); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west()), Direction.DOWN, contraption); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(piston.north() + .west() + .up()), Direction.DOWN, contraption); + scene.idle(15); + scene.effects.superGlue(piston.west(), Direction.UP, true); + scene.idle(10); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.idle(40); + + scene.world.destroyBlock(util.grid.at(0, 1, 2)); + scene.world.destroyBlock(util.grid.at(0, 2, 2)); + scene.idle(10); + scene.overlay.showSelectionWithText(rose, 70) + .text("Whenever Pistons stop moving, the moved structure reverts to blocks") + .colored(PonderPalette.RED); + scene.idle(80); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(2, 0, 0), 40); + scene.world.hideSection(rose, Direction.UP); + scene.idle(50); + + scene.world.setBlock(util.grid.at(0, 1, 2), Blocks.ROSE_BUSH.getDefaultState(), false); + scene.world.setBlock(util.grid.at(0, 2, 2), Blocks.ROSE_BUSH.getDefaultState() + .with(DoublePlantBlock.HALF, DoubleBlockHalf.UPPER), false); + scene.world.showIndependentSection(rose, Direction.DOWN); + scene.overlay.showCenteredScrollInput(piston, Direction.UP, 60); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(piston), Pointing.DOWN).scroll() + .withWrench(), 60); + scene.overlay.showText(70) + .pointAt(util.vector.topOf(piston)) + .placeNearTarget() + .sharedText("behaviour_modify_wrench"); + scene.idle(80); + + scene.effects.indicateRedstone(leverPos); + scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); + scene.world.modifyKineticSpeed(kinetics, f -> -f); + scene.effects.rotationDirectionIndicator(shaft); + scene.world.moveSection(contraption, util.vector.of(-2, 0, 0), 40); + scene.idle(50); + scene.overlay.showText(120) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(util.grid.at(0, 1, 2), Direction.WEST)) + .placeNearTarget() + .text("It can be configured never to revert to solid blocks, or only at the location it started at"); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java index 2bbdb6088..67b6c5e68 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java @@ -77,6 +77,24 @@ public class PonderIndex { .addStoryBoard("funnels/transposer", FunnelScenes::transposer); PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass); + // Mechanical Piston + PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + .addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES, + PonderTag.MOVEMENT_ANCHOR); + PonderRegistry + .forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON, + AllBlocks.PISTON_EXTENSION_POLE) + .addStoryBoard("mechanical_piston/piston_pole", PistonScenes::poles); + PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) + .addStoryBoard("mechanical_piston/modes", PistonScenes::movementModes); + + // Windmill Bearing + PonderRegistry.forComponents(AllBlocks.ROPE_PULLEY) + .addStoryBoard("rope_pulley/anchor", PulleyScenes::movement, PonderTag.KINETIC_APPLIANCES, + PonderTag.MOVEMENT_ANCHOR) + .addStoryBoard("rope_pulley/modes", PulleyScenes::movementModes) + .addStoryBoard("rope_pulley/attachment", PulleyScenes::attachment); + // Windmill Bearing PonderRegistry.forComponents(AllBlocks.WINDMILL_BEARING) .addStoryBoard("windmill_bearing/source", BearingScenes::windmillsAsSource, PonderTag.KINETIC_SOURCES) @@ -91,6 +109,10 @@ public class PonderIndex { .addStoryBoard("mechanical_bearing/stabilized", BearingScenes::stabilizedBearings, PonderTag.CONTRAPTION_ACTOR); + // Clockwork Bearing + PonderRegistry.addStoryBoard(AllBlocks.CLOCKWORK_BEARING, "clockwork_bearing", BearingScenes::clockwork, + PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); + // Gantries PonderRegistry.addStoryBoard(AllBlocks.GANTRY_SHAFT, "gantry/intro", GantryScenes::introForShaft, PonderTag.KINETIC_APPLIANCES, PonderTag.MOVEMENT_ANCHOR); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java new file mode 100644 index 000000000..b4712e67c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java @@ -0,0 +1,221 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class PulleyScenes { + + public static void movement(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("rope_pulley", "Moving Structures using Rope Pulleys"); + scene.configureBasePlate(0, 0, 8); + + Selection reversable = util.select.fromTo(2, 3, 4, 2, 4, 2); + BlockPos leverPos = util.grid.at(1, 2, 4); + BlockPos pulleyPos = util.grid.at(2, 4, 2); + Selection redstoneStuff = util.select.fromTo(leverPos, leverPos.east()); + + scene.world.showSection(util.select.layer(0), Direction.UP); + ElementLink plank = + scene.world.showIndependentSection(util.select.position(2, 1, 2), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 2, 1, 4), Direction.DOWN); + scene.idle(10); + + scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH); + scene.idle(20); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + + scene.idle(45); + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST)) + .text("Rope Pulleys can move blocks vertically when given Rotational Force") + .placeNearTarget(); + scene.idle(70); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, -2, 40); + scene.world.moveSection(plank, util.vector.of(0, 2, 0), 40); + scene.idle(60); + + scene.overlay.showText(60) + .pointAt(util.vector.blockSurface(pulleyPos, Direction.SOUTH)) + .text("Direction and Speed of movement depend on the Rotational Input") + .placeNearTarget(); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(plank, util.vector.of(0, -2, 0), 40); + scene.idle(50); + + scene.world.hideIndependentSection(plank, Direction.NORTH); + scene.idle(15); + ElementLink chassis = + scene.world.showIndependentSection(util.select.fromTo(2, 1, 1, 0, 2, 1), Direction.SOUTH); + scene.world.moveSection(chassis, util.vector.of(1, 0, 1), 0); + scene.idle(5); + scene.world.showSectionAndMerge(util.select.position(2, 1, 0), Direction.SOUTH, chassis); + scene.idle(15); + scene.effects.superGlue(util.grid.at(3, 1, 1), Direction.SOUTH, true); + scene.overlay.showText(80) + .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.NORTH)) + .placeNearTarget() + .sharedText("movement_anchors"); + scene.idle(90); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, -2, 40); + scene.world.moveSection(chassis, util.vector.of(0, 2, 0), 40); + scene.idle(50); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(chassis, util.vector.of(0, -2, 0), 40); + scene.idle(50); + } + + public static void movementModes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("rope_pulley_modes", "Movement Modes of the Rope Pulley"); + scene.configureBasePlate(0, 0, 8); + + Selection reversable = util.select.fromTo(2, 3, 4, 2, 4, 2); + BlockPos leverPos = util.grid.at(1, 2, 4); + BlockPos pulleyPos = util.grid.at(2, 4, 2); + Selection redstoneStuff = util.select.fromTo(leverPos, leverPos.east()); + BlockPos flowerPos = util.grid.at(2, 1, 2); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.world.showSection(util.select.position(flowerPos), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 2, 1, 4), Direction.DOWN); + scene.idle(10); + + scene.world.showSection(util.select.position(pulleyPos), Direction.SOUTH); + ElementLink glass = + scene.world.showIndependentSection(util.select.position(pulleyPos.down()), Direction.UP); + scene.idle(20); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(glass, util.vector.of(0, -2, 0), 40); + scene.idle(40); + + scene.world.destroyBlock(flowerPos); + scene.idle(10); + scene.overlay.showSelectionWithText(util.select.position(flowerPos), 70) + .text("Whenever Pulleys stop moving, the moved structure reverts to blocks") + .placeNearTarget() + .colored(PonderPalette.RED); + scene.idle(80); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, -2, 40); + scene.world.moveSection(glass, util.vector.of(0, 2, 0), 40); + scene.world.hideSection(util.select.position(flowerPos), Direction.DOWN); + scene.idle(40); + + scene.world.setBlock(flowerPos, Blocks.BLUE_ORCHID.getDefaultState(), false); + scene.world.showSection(util.select.position(flowerPos), Direction.DOWN); + scene.overlay.showCenteredScrollInput(pulleyPos, Direction.UP, 60); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(pulleyPos), Pointing.DOWN).scroll() + .withWrench(), 60); + scene.overlay.showText(70) + .pointAt(util.vector.topOf(pulleyPos)) + .placeNearTarget() + .sharedText("behaviour_modify_wrench"); + scene.idle(80); + + scene.world.toggleRedstonePower(redstoneStuff); + scene.effects.indicateRedstone(leverPos); + scene.world.modifyKineticSpeed(reversable, f -> -f); + scene.effects.rotationDirectionIndicator(pulleyPos.south()); + scene.world.movePulley(pulleyPos, 2, 40); + scene.world.moveSection(glass, util.vector.of(0, -2, 0), 40); + scene.idle(50); + scene.overlay.showText(120) + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(flowerPos, Direction.WEST)) + .placeNearTarget() + .text("It can be configured never to revert to solid blocks, or only at the location it started at"); + } + + public static void attachment(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("rope_pulley_attachment", "Moving Pulleys as part of a Contraption"); + scene.configureBasePlate(0, 0, 8); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + Selection kinetics = util.select.fromTo(4, 3, 2, 4, 1, 5); + Selection largeCog = util.select.position(3, 0, 5); + + scene.world.showSection(kinetics, Direction.DOWN); + ElementLink poles = + scene.world.showIndependentSection(util.select.fromTo(4, 4, 2, 6, 4, 2), Direction.DOWN); + scene.world.moveSection(poles, util.vector.of(0, -1, 0), 0); + scene.idle(10); + + BlockPos pulleyPos = util.grid.at(3, 3, 2); + ElementLink pulley = + scene.world.showIndependentSection(util.select.position(pulleyPos), Direction.EAST); + scene.idle(10); + scene.world.showSectionAndMerge(util.select.fromTo(3, 1, 1, 3, 1, 2) + .add(util.select.position(3, 2, 1)), Direction.SOUTH, pulley); + + scene.idle(10); + scene.overlay.showText(50) + .pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST)) + .placeNearTarget() + .text("Whenever Pulleys are themselves being moved by a Contraption..."); + scene.idle(60); + + scene.world.setKineticSpeed(largeCog, -16); + scene.world.setKineticSpeed(kinetics, 32); + scene.effects.rotationDirectionIndicator(util.grid.at(4, 1, 5)); + scene.world.moveSection(poles, util.vector.of(-2, 0, 0), 40); + scene.world.moveSection(pulley, util.vector.of(-2, 0, 0), 40); + scene.idle(40); + + scene.overlay.showSelectionWithText(util.select.fromTo(1, 1, 1, 1, 1, 2), 50) + .colored(PonderPalette.GREEN) + .placeNearTarget() + .text("...its attached structure will be dragged with it"); + scene.idle(60); + scene.overlay.showText(80) + .colored(PonderPalette.RED) + .pointAt(util.vector.topOf(pulleyPos.west(2))) + .placeNearTarget() + .text("Mind that pulleys are only movable while stopped"); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java b/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java index c7e2ed679..73d233ba2 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/SharedText.java @@ -16,6 +16,7 @@ public class SharedText { add("rpm32", "32 RPM"); add("movement_anchors", "With the help of Chassis or Super Glue, larger structures can be moved."); + add("behaviour_modify_wrench", "This behaviour can be modified using a Wrench"); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java index 99e1e8f2b..fd788e53d 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/AnimateTileEntityInstruction.java @@ -4,7 +4,7 @@ import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Function; -import com.simibubi.create.content.contraptions.components.structureMovement.bearing.MechanicalBearingTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.bearing.IBearingTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderWorld; @@ -24,14 +24,14 @@ public class AnimateTileEntityInstruction extends TickingInstruction { public static AnimateTileEntityInstruction bearing(BlockPos location, float totalDelta, int ticks) { return new AnimateTileEntityInstruction(location, totalDelta, ticks, - (w, f) -> castIfPresent(w, location, MechanicalBearingTileEntity.class).ifPresent(bte -> bte.setAngle(f)), - (w) -> castIfPresent(w, location, MechanicalBearingTileEntity.class).map(bte -> bte.getInterpolatedAngle(0)) + (w, f) -> castIfPresent(w, location, IBearingTileEntity.class).ifPresent(bte -> bte.setAngle(f)), + (w) -> castIfPresent(w, location, IBearingTileEntity.class).map(bte -> bte.getInterpolatedAngle(0)) .orElse(0f)); } public static AnimateTileEntityInstruction pulley(BlockPos location, float totalDelta, int ticks) { return new AnimateTileEntityInstruction(location, totalDelta, ticks, - (w, f) -> castIfPresent(w, location, PulleyTileEntity.class).ifPresent(pulley -> pulley.offset = f), + (w, f) -> castIfPresent(w, location, PulleyTileEntity.class).ifPresent(pulley -> pulley.animateOffset(f)), (w) -> castIfPresent(w, location, PulleyTileEntity.class).map(pulley -> pulley.offset) .orElse(0f)); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java index b0c50333c..d9f5c70fc 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/DisplayWorldSectionInstruction.java @@ -35,6 +35,8 @@ public class DisplayWorldSectionInstruction extends FadeIntoSceneInstruction element.setAnimatedOffset(wse.get() + .getAnimatedOffset(), true)); element.set(initialSelection); element.setVisible(true); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java index a7f2e15b2..ef15e46dd 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/MarkAsFinishedInstruction.java @@ -14,5 +14,10 @@ public class MarkAsFinishedInstruction extends PonderInstruction { public void tick(PonderScene scene) { scene.setFinished(true); } + + @Override + public void onScheduled(PonderScene scene) { + scene.stopCounting(); + } } diff --git a/src/main/resources/ponder/clockwork_bearing.nbt b/src/main/resources/ponder/clockwork_bearing.nbt new file mode 100644 index 000000000..43b4c4f93 Binary files /dev/null and b/src/main/resources/ponder/clockwork_bearing.nbt differ diff --git a/src/main/resources/ponder/mechanical_piston/anchor.nbt b/src/main/resources/ponder/mechanical_piston/anchor.nbt new file mode 100644 index 000000000..7bbee5cc9 Binary files /dev/null and b/src/main/resources/ponder/mechanical_piston/anchor.nbt differ diff --git a/src/main/resources/ponder/mechanical_piston/modes.nbt b/src/main/resources/ponder/mechanical_piston/modes.nbt new file mode 100644 index 000000000..f9755f1ed Binary files /dev/null and b/src/main/resources/ponder/mechanical_piston/modes.nbt differ diff --git a/src/main/resources/ponder/mechanical_piston/piston_pole.nbt b/src/main/resources/ponder/mechanical_piston/piston_pole.nbt new file mode 100644 index 000000000..710f5930a Binary files /dev/null and b/src/main/resources/ponder/mechanical_piston/piston_pole.nbt differ diff --git a/src/main/resources/ponder/rope_pulley/anchor.nbt b/src/main/resources/ponder/rope_pulley/anchor.nbt new file mode 100644 index 000000000..2aa175277 Binary files /dev/null and b/src/main/resources/ponder/rope_pulley/anchor.nbt differ diff --git a/src/main/resources/ponder/rope_pulley/attachment.nbt b/src/main/resources/ponder/rope_pulley/attachment.nbt new file mode 100644 index 000000000..e61952ab2 Binary files /dev/null and b/src/main/resources/ponder/rope_pulley/attachment.nbt differ diff --git a/src/main/resources/ponder/rope_pulley/modes.nbt b/src/main/resources/ponder/rope_pulley/modes.nbt new file mode 100644 index 000000000..6da97dd80 Binary files /dev/null and b/src/main/resources/ponder/rope_pulley/modes.nbt differ