Pondering about sticky stuff

- Scenes for chassis, super glue, stickers and redstone contact
- Added a warning when players try to use experimental rendering while shaders are active
This commit is contained in:
simibubi 2021-03-13 18:24:10 +01:00
parent d735d237ec
commit a40d0f58c2
16 changed files with 832 additions and 29 deletions

View file

@ -7,7 +7,6 @@ import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.MatrixStacker;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -30,9 +29,9 @@ public class StickerRenderer extends SafeTileEntityRenderer<StickerTileEntity> {
BlockState state = te.getBlockState(); BlockState state = te.getBlockState();
SuperByteBuffer head = AllBlockPartials.STICKER_HEAD.renderOn(state); SuperByteBuffer head = AllBlockPartials.STICKER_HEAD.renderOn(state);
float offset = te.piston.getValue(AnimationTickHolder.getPartialTicks()); float offset = te.piston.getValue(AnimationTickHolder.getPartialTicks(te.getWorld()));
if (te.getWorld() != Minecraft.getInstance().world) if (te.getWorld() != Minecraft.getInstance().world && !te.isVirtual())
offset = state.get(StickerBlock.EXTENDED) ? 1 : 0; offset = state.get(StickerBlock.EXTENDED) ? 1 : 0;
Direction facing = state.get(StickerBlock.FACING); Direction facing = state.get(StickerBlock.FACING);

View file

@ -1,5 +1,9 @@
package com.simibubi.create.content.contraptions.components.structureMovement.glue; package com.simibubi.create.content.contraptions.components.structureMovement.glue;
import javax.annotation.Nullable;
import org.apache.commons.lang3.Validate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllEntityTypes;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
@ -14,13 +18,19 @@ import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.BlockFace;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.DirectionalBlock; import net.minecraft.block.DirectionalBlock;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld; import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.*; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntitySize;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.Pose;
import net.minecraft.entity.effect.LightningBoltEntity; import net.minecraft.entity.effect.LightningBoltEntity;
import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.item.ItemEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -29,10 +39,21 @@ import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket; import net.minecraft.network.IPacket;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.state.BooleanProperty; import net.minecraft.state.BooleanProperty;
import net.minecraft.util.*; import net.minecraft.util.ActionResultType;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.*; import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@ -40,9 +61,6 @@ import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
import org.apache.commons.lang3.Validate;
import javax.annotation.Nullable;
public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement { public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement {
@ -149,6 +167,9 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
public boolean isVisible() { public boolean isVisible() {
if (!isAlive()) if (!isAlive())
return false; return false;
if (world instanceof WrappedWorld)
return true;
BlockPos pos = hangingPosition; BlockPos pos = hangingPosition;
BlockPos pos2 = pos.offset(getFacingDirection().getOpposite()); BlockPos pos2 = pos.offset(getFacingDirection().getOpposite());
return isValidFace(world, pos2, getFacingDirection()) != isValidFace(world, pos, return isValidFace(world, pos2, getFacingDirection()) != isValidFace(world, pos,

View file

@ -1,5 +1,10 @@
package com.simibubi.create.foundation.command; package com.simibubi.create.foundation.command;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.apache.logging.log4j.LogManager;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen; import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
@ -9,6 +14,8 @@ import com.simibubi.create.foundation.ponder.PonderRegistry;
import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.PonderUI;
import com.simibubi.create.foundation.ponder.content.PonderIndexScreen; import com.simibubi.create.foundation.ponder.content.PonderIndexScreen;
import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher;
import com.simibubi.create.foundation.render.backend.OptifineHandler;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
@ -21,10 +28,6 @@ import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.ForgeConfig; import net.minecraftforge.common.ForgeConfig;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
import org.apache.logging.log4j.LogManager;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class ConfigureConfigPacket extends SimplePacketBase { public class ConfigureConfigPacket extends SimplePacketBase {
@ -112,10 +115,17 @@ public class ConfigureConfigPacket extends SimplePacketBase {
return; return;
} }
AllConfigs.CLIENT.experimentalRendering.set(Boolean.parseBoolean(value)); boolean parsedBoolean = Boolean.parseBoolean(value);
ITextComponent text = boolToText(AllConfigs.CLIENT.experimentalRendering.get()).appendSibling(new StringTextComponent(" Experimental Rendering").applyTextStyle(TextFormatting.WHITE)); boolean cannotUseER = OptifineHandler.usingShaders() && parsedBoolean;
player.sendStatusMessage(text, false);
AllConfigs.CLIENT.experimentalRendering.set(parsedBoolean);
ITextComponent text = boolToText(AllConfigs.CLIENT.experimentalRendering.get())
.appendSibling(new StringTextComponent(" Experimental Rendering").applyTextStyle(TextFormatting.WHITE));
ITextComponent error = new StringTextComponent("Experimental Rendering does not support Optifine Shaders")
.applyTextStyle(TextFormatting.RED);
player.sendStatusMessage(cannotUseER ? error : text, false);
FastRenderDispatcher.refresh(); FastRenderDispatcher.refresh();
} }

View file

@ -1,14 +1,37 @@
package com.simibubi.create.foundation.ponder; package com.simibubi.create.foundation.ponder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.lwjgl.opengl.GL11;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.foundation.gui.*; import com.simibubi.create.foundation.gui.AbstractSimiScreen;
import com.simibubi.create.foundation.gui.AllGuiTextures;
import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.gui.GuiGameElement;
import com.simibubi.create.foundation.gui.ScreenOpener;
import com.simibubi.create.foundation.gui.UIRenderHelper;
import com.simibubi.create.foundation.ponder.PonderScene.SceneTransform; import com.simibubi.create.foundation.ponder.PonderScene.SceneTransform;
import com.simibubi.create.foundation.ponder.content.*; import com.simibubi.create.foundation.ponder.content.DebugScenes;
import com.simibubi.create.foundation.ponder.content.PonderChapter;
import com.simibubi.create.foundation.ponder.content.PonderIndex;
import com.simibubi.create.foundation.ponder.content.PonderTag;
import com.simibubi.create.foundation.ponder.content.PonderTagScreen;
import com.simibubi.create.foundation.ponder.ui.PonderButton; import com.simibubi.create.foundation.ponder.ui.PonderButton;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.utility.*; import com.simibubi.create.foundation.utility.ColorHelper;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.LerpedFloat;
import com.simibubi.create.foundation.utility.LerpedFloat.Chaser; import com.simibubi.create.foundation.utility.LerpedFloat.Chaser;
import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.Pointing;
import net.minecraft.client.ClipboardHelper; import net.minecraft.client.ClipboardHelper;
import net.minecraft.client.GameSettings; import net.minecraft.client.GameSettings;
import net.minecraft.client.MainWindow; import net.minecraft.client.MainWindow;
@ -29,13 +52,6 @@ import net.minecraft.world.gen.feature.template.PlacementSettings;
import net.minecraft.world.gen.feature.template.Template; import net.minecraft.world.gen.feature.template.Template;
import net.minecraftforge.fml.client.gui.GuiUtils; import net.minecraftforge.fml.client.gui.GuiUtils;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import org.apache.commons.lang3.mutable.MutableBoolean;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;
public class PonderUI extends AbstractSimiScreen { public class PonderUI extends AbstractSimiScreen {

View file

@ -10,6 +10,7 @@ import java.util.function.UnaryOperator;
import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel;
import com.simibubi.create.content.contraptions.base.KineticBlock; import com.simibubi.create.content.contraptions.base.KineticBlock;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem;
import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
@ -533,6 +534,11 @@ public class SceneBuilder {
}); });
} }
public ElementLink<EntityElement> createGlueEntity(BlockPos pos, Direction face) {
effects.superGlue(pos, face, false);
return createEntity(world -> new SuperGlueEntity(world, pos, face.getOpposite()));
}
public void createItemOnBeltLike(BlockPos location, Direction insertionSide, ItemStack stack) { public void createItemOnBeltLike(BlockPos location, Direction insertionSide, ItemStack stack) {
addInstruction(scene -> { addInstruction(scene -> {
PonderWorld world = scene.getWorld(); PonderWorld world = scene.getWorld();

View file

@ -105,8 +105,8 @@ public class SceneBuildingUtil {
} }
public Selection layers(int y, int height) { public Selection layers(int y, int height) {
return cuboid(new BlockPos(0, y, 0), new Vec3i(sceneBounds.getXSize(), return cuboid(new BlockPos(0, y, 0), new Vec3i(sceneBounds.getXSize() - 1,
Math.min(sceneBounds.getYSize() - y, height) - 1, sceneBounds.getZSize())); Math.min(sceneBounds.getYSize() - y, height) - 1, sceneBounds.getZSize() - 1));
} }
public Selection cuboid(BlockPos origin, Vec3i size) { public Selection cuboid(BlockPos origin, Vec3i size) {

View file

@ -0,0 +1,570 @@
package com.simibubi.create.foundation.ponder.content;
import org.apache.commons.lang3.mutable.MutableObject;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.RadialChassisBlock;
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.EntityElement;
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.entity.Entity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class ChassisScenes {
public static void linearGroup(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("linear_chassis_group", "Moving Linear Chassis in groups");
scene.configureBasePlate(0, 0, 5);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
scene.world.showSection(util.select.layer(1), Direction.DOWN);
scene.idle(10);
BlockPos centralChassis = util.grid.at(2, 2, 2);
ElementLink<WorldSectionElement> chassis =
scene.world.showIndependentSection(util.select.position(centralChassis), Direction.DOWN);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.position(centralChassis.west()), Direction.EAST, chassis);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(centralChassis.east()), Direction.WEST, chassis);
scene.idle(4);
scene.world.showSectionAndMerge(util.select.position(centralChassis.east()
.north()), Direction.SOUTH, chassis);
scene.idle(3);
scene.world.showSectionAndMerge(util.select.position(centralChassis.up()), Direction.DOWN, chassis);
scene.idle(2);
scene.world.showSectionAndMerge(util.select.position(centralChassis.up()
.east()), Direction.DOWN, chassis);
scene.idle(10);
scene.overlay.showText(80)
.attachKeyFrame()
.placeNearTarget()
.text("Linear Chassis connect to identical Chassis blocks next to them")
.pointAt(util.vector.topOf(util.grid.at(2, 3, 2)));
scene.idle(90);
BlockPos bearingPos = util.grid.at(2, 1, 2);
scene.world.moveSection(chassis, util.vector.of(0, -1 / 1024f, 0), 0);
scene.world.configureCenterOfRotation(chassis, util.vector.centerOf(bearingPos));
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(chassis, 0, 360, 0, 80);
scene.idle(20);
scene.overlay.showText(80)
.placeNearTarget()
.text("When one is moved by a Contraption, the others are dragged with it")
.pointAt(util.vector.topOf(util.grid.at(2, 3, 2)));
scene.idle(90);
Selection wrong1 = util.select.position(2, 4, 2);
Selection wrong2 = util.select.position(0, 2, 2);
scene.addKeyframe();
scene.world.showSection(wrong2, Direction.EAST);
scene.idle(10);
scene.world.showSection(wrong1, Direction.DOWN);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.RED, wrong2, wrong2, 80);
scene.overlay.showSelectionWithText(wrong1, 80)
.colored(PonderPalette.RED)
.placeNearTarget()
.text("Chassis of a different type or facing another direction will not attach");
scene.idle(40);
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(chassis, 0, 360, 0, 80);
}
public static void linearAttachement(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("linear_chassis_attachment", "Attaching blocks using Linear Chassis");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
BlockPos chassisPos = util.grid.at(2, 2, 2);
Selection chassis = util.select.position(chassisPos);
scene.world.showSection(util.select.layer(1), Direction.DOWN);
scene.world.showSection(chassis, Direction.DOWN);
scene.idle(10);
InputWindowElement input =
new InputWindowElement(util.vector.blockSurface(chassisPos, Direction.WEST), Pointing.LEFT).rightClick()
.withItem(new ItemStack(Items.SLIME_BALL));
scene.overlay.showControls(input, 30);
scene.idle(7);
scene.world.modifyBlock(chassisPos, s -> s.with(LinearChassisBlock.STICKY_BOTTOM, true), false);
scene.effects.superGlue(chassisPos, Direction.WEST, false);
scene.idle(30);
scene.overlay.showText(60)
.text("The open faces of a Linear Chassis can be made Sticky")
.placeNearTarget()
.pointAt(util.vector.blockSurface(chassisPos, Direction.WEST));
scene.idle(70);
scene.overlay.showControls(input, 15);
scene.idle(7);
scene.world.modifyBlock(chassisPos, s -> s.with(LinearChassisBlock.STICKY_TOP, true), false);
scene.effects.superGlue(chassisPos, Direction.EAST, false);
scene.idle(15);
scene.overlay.showText(60)
.text("Click again to make the opposite side sticky")
.placeNearTarget()
.pointAt(util.vector.topOf(chassisPos));
scene.idle(10);
scene.rotateCameraY(60);
scene.idle(35);
scene.rotateCameraY(-60);
scene.idle(25);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(chassisPos, Direction.WEST), Pointing.LEFT).rightClick()
.whileSneaking(),
30);
scene.idle(7);
scene.world.modifyBlock(chassisPos, s -> s.with(LinearChassisBlock.STICKY_BOTTOM, false), false);
scene.effects.superGlue(chassisPos, Direction.WEST, false);
scene.idle(30);
scene.overlay.showText(60)
.text("Sneak and Right-Click with an empty hand to remove the slime")
.placeNearTarget()
.pointAt(util.vector.blockSurface(chassisPos, Direction.WEST));
scene.idle(70);
scene.world.hideSection(chassis, Direction.UP);
scene.idle(20);
ElementLink<WorldSectionElement> glassSection =
scene.world.showIndependentSection(util.select.position(chassisPos.up()), Direction.DOWN);
scene.world.moveSection(glassSection, util.vector.of(0, -1, 0), 0);
scene.idle(25);
scene.addKeyframe();
scene.world.showSectionAndMerge(util.select.fromTo(2, 4, 2, 2, 5, 2), Direction.DOWN, glassSection);
ElementLink<WorldSectionElement> topGlassSection =
scene.world.showIndependentSection(util.select.position(2, 6, 2), Direction.DOWN);
scene.world.moveSection(topGlassSection, util.vector.of(0, -1, 0), 0);
scene.idle(30);
Selection column1 = util.select.fromTo(2, 3, 2, 2, 3, 2);
Selection column2 = util.select.fromTo(2, 3, 2, 2, 4, 2);
Selection column3 = util.select.fromTo(2, 3, 2, 2, 5, 2);
scene.overlay.showSelectionWithText(column3, 80)
.colored(PonderPalette.GREEN)
.text("Stickied faces of the Linear Chassis will attach a line of blocks in front of it")
.placeNearTarget();
scene.idle(90);
BlockPos bearingPos = util.grid.at(2, 1, 2);
scene.world.configureCenterOfRotation(glassSection, util.vector.centerOf(bearingPos));
scene.world.rotateBearing(bearingPos, 180, 40);
scene.world.rotateSection(glassSection, 0, 180, 0, 40);
scene.world.rotateSection(topGlassSection, 0, 180, 0, 40);
scene.idle(50);
Vec3d blockSurface = util.vector.blockSurface(chassisPos, Direction.NORTH);
scene.overlay.showCenteredScrollInput(chassisPos, Direction.NORTH, 50);
scene.overlay.showControls(new InputWindowElement(blockSurface, Pointing.UP).scroll()
.withWrench(), 50);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column3, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column2, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column1, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column2, 15);
scene.idle(10);
scene.overlay.showText(60)
.pointAt(blockSurface)
.text("Using a Wrench, a precise Range can be specified for this chassis")
.placeNearTarget();
scene.idle(70);
scene.world.rotateBearing(bearingPos, 180, 40);
scene.world.rotateSection(glassSection, 0, 180, 0, 40);
scene.idle(50);
scene.world.rotateSection(topGlassSection, 0, 180, 0, 0);
scene.world.showSectionAndMerge(util.select.position(1, 3, 2), Direction.UP, glassSection);
scene.world.showSectionAndMerge(util.select.position(3, 3, 2), Direction.UP, glassSection);
scene.world.showSectionAndMerge(util.select.fromTo(1, 4, 2, 1, 6, 2), Direction.DOWN, glassSection);
scene.world.showSectionAndMerge(util.select.fromTo(3, 4, 2, 3, 6, 2), Direction.DOWN, glassSection);
scene.addKeyframe();
scene.idle(20);
scene.overlay.showCenteredScrollInput(chassisPos, Direction.NORTH, 50);
scene.overlay.showControls(new InputWindowElement(blockSurface, Pointing.UP).whileCTRL()
.scroll()
.withWrench(), 50);
column1 = util.select.fromTo(1, 3, 2, 3, 3, 2);
column2 = util.select.fromTo(1, 3, 2, 3, 4, 2);
column3 = util.select.fromTo(1, 3, 2, 3, 5, 2);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column2, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column1, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column2, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, column3, 15);
scene.idle(10);
scene.overlay.showText(80)
.pointAt(blockSurface)
.text("Holding CTRL and scrolling adjusts the range of all attached Chassis Blocks")
.placeNearTarget();
scene.idle(90);
scene.world.rotateBearing(bearingPos, 180, 40);
scene.world.rotateSection(glassSection, 0, 180, 0, 40);
scene.world.rotateSection(topGlassSection, 0, 180, 0, 40);
scene.idle(50);
Vec3d glueSurface = util.vector.blockSurface(chassisPos.west(), Direction.NORTH);
scene.overlay.showText(80)
.attachKeyFrame()
.pointAt(glueSurface)
.text("Attaching blocks to any other side requires the use of Super Glue")
.placeNearTarget();
scene.idle(90);
scene.overlay.showControls(new InputWindowElement(glueSurface, Pointing.DOWN).rightClick()
.withItem(AllItems.SUPER_GLUE.asStack()), 30);
scene.idle(7);
ElementLink<EntityElement> glueEntity = scene.world.createGlueEntity(chassisPos.west(), Direction.NORTH);
scene.idle(20);
ElementLink<WorldSectionElement> gluedPlank =
scene.world.showIndependentSection(util.select.position(3, 3, 1), Direction.SOUTH);
scene.world.moveSection(gluedPlank, util.vector.of(-2, -1, 0), 0);
scene.idle(15);
scene.effects.superGlue(chassisPos.west(), Direction.NORTH, true);
scene.idle(20);
scene.world.modifyEntity(glueEntity, Entity::remove);
scene.world.hideIndependentSection(glassSection, Direction.UP);
scene.world.hideIndependentSection(gluedPlank, Direction.UP);
scene.world.hideIndependentSection(topGlassSection, Direction.UP);
scene.idle(15);
scene.addKeyframe();
ElementLink<WorldSectionElement> chain =
scene.world.showIndependentSection(util.select.position(2, 7, 2), Direction.DOWN);
scene.world.configureCenterOfRotation(chain, util.vector.centerOf(bearingPos));
scene.world.moveSection(chain, util.vector.of(0, -5, 0), 0);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(2, 8, 2, 3, 9, 2), Direction.DOWN, chain);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(3, 9, 1, 3, 9, 0), Direction.SOUTH, chain);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(2, 9, 0, 1, 9, 0), Direction.EAST, chain);
scene.idle(20);
scene.overlay.showText(80)
.pointAt(util.vector.topOf(chassisPos.up(2)))
.text("Using these mechanics, structures of any shape can move as a Contraption")
.placeNearTarget();
scene.idle(30);
scene.world.rotateBearing(bearingPos, 720, 160);
scene.world.rotateSection(chain, 0, 720, 0, 160);
}
public static void radial(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("radial_chassis", "Attaching blocks using Radial Chassis");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
util.select.position(2, 4, 2);
BlockPos chassisPos = util.grid.at(2, 2, 2);
Selection chassis = util.select.position(chassisPos);
scene.world.showSection(util.select.layer(1), Direction.DOWN);
scene.idle(10);
ElementLink<WorldSectionElement> contraption = scene.world.showIndependentSection(chassis, Direction.DOWN);
scene.idle(5);
ElementLink<WorldSectionElement> top =
scene.world.showIndependentSection(util.select.position(chassisPos.up()), Direction.DOWN);
scene.idle(10);
scene.overlay.showText(50)
.attachKeyFrame()
.placeNearTarget()
.text("Radial Chassis connect to identical Chassis blocks in a row")
.pointAt(util.vector.topOf(chassisPos.up()));
scene.idle(60);
BlockPos bearingPos = util.grid.at(2, 1, 2);
scene.world.moveSection(contraption, util.vector.of(0, -1 / 1024f, 0), 0);
scene.world.configureCenterOfRotation(contraption, util.vector.centerOf(bearingPos));
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(contraption, 0, 360, 0, 80);
scene.world.rotateSection(top, 0, 360, 0, 80);
scene.idle(20);
scene.overlay.showText(70)
.placeNearTarget()
.text("When one is moved by a Contraption, the others are dragged with it")
.pointAt(util.vector.topOf(util.grid.at(2, 3, 2)));
scene.idle(80);
scene.world.hideIndependentSection(top, Direction.UP);
scene.idle(15);
scene.addKeyframe();
InputWindowElement input =
new InputWindowElement(util.vector.blockSurface(chassisPos, Direction.WEST), Pointing.LEFT).rightClick()
.withItem(new ItemStack(Items.SLIME_BALL));
scene.overlay.showControls(input, 30);
scene.idle(7);
scene.world.modifyBlock(chassisPos, s -> s.with(RadialChassisBlock.STICKY_WEST, true), false);
scene.effects.superGlue(chassisPos, Direction.WEST, false);
scene.idle(30);
scene.overlay.showText(60)
.text("The side faces of a Radial Chassis can be made Sticky")
.placeNearTarget()
.pointAt(util.vector.blockSurface(chassisPos, Direction.WEST));
scene.idle(70);
scene.overlay.showControls(input, 15);
scene.idle(7);
scene.world.modifyBlock(chassisPos, s -> s.with(RadialChassisBlock.STICKY_EAST, true)
.with(RadialChassisBlock.STICKY_NORTH, true)
.with(RadialChassisBlock.STICKY_SOUTH, true), false);
scene.effects.superGlue(chassisPos, Direction.EAST, false);
scene.effects.superGlue(chassisPos, Direction.SOUTH, false);
scene.effects.superGlue(chassisPos, Direction.NORTH, false);
scene.idle(15);
scene.overlay.showText(60)
.text("Click again to make all other sides sticky")
.placeNearTarget()
.pointAt(util.vector.topOf(chassisPos));
scene.idle(10);
scene.rotateCameraY(60);
scene.idle(35);
scene.rotateCameraY(-60);
scene.idle(25);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(chassisPos, Direction.WEST), Pointing.LEFT).rightClick()
.whileSneaking(),
30);
scene.idle(7);
scene.world.modifyBlock(chassisPos, s -> s.with(RadialChassisBlock.STICKY_WEST, false), false);
scene.effects.superGlue(chassisPos, Direction.WEST, false);
scene.idle(30);
scene.overlay.showText(60)
.text("Sneak and Right-Click with an empty hand to remove the slime")
.placeNearTarget()
.pointAt(util.vector.blockSurface(chassisPos, Direction.WEST));
scene.idle(70);
Selection s = util.select.position(chassisPos.north());
Selection growing = s.copy();
Selection r1 = util.select.fromTo(1, 2, 1, 3, 2, 3)
.substract(chassis);
Selection r2 = r1.copy()
.add(util.select.fromTo(0, 2, 1, 0, 2, 3))
.add(util.select.fromTo(1, 2, 0, 3, 2, 0))
.add(util.select.fromTo(1, 2, 4, 3, 2, 4))
.add(util.select.fromTo(4, 2, 1, 4, 2, 3));
Selection r3 = util.select.layer(2)
.add(util.select.fromTo(-1, 2, 1, 5, 2, 3))
.add(util.select.fromTo(1, 2, -1, 3, 2, 5))
.substract(chassis);
scene.addKeyframe();
scene.world.showSectionAndMerge(r1, Direction.DOWN, contraption);
ElementLink<WorldSectionElement> outer = scene.world.showIndependentSection(util.select.layer(2)
.substract(chassis)
.substract(r1), Direction.DOWN);
scene.world.showSection(util.select.fromTo(0, 3, 3, 1, 3, 4), Direction.DOWN);
scene.idle(10);
Vec3d blockSurface = util.vector.blockSurface(chassisPos, Direction.NORTH);
AxisAlignedBB bb = new AxisAlignedBB(blockSurface, blockSurface).grow(.501, .501, 0);
scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, bb, bb, 60);
scene.overlay.showOutline(PonderPalette.WHITE, s, s, 80);
scene.overlay.showText(40)
.text("Whenever a Block is next to a sticky face...")
.placeNearTarget()
.pointAt(blockSurface.add(0, .5, 0));
scene.idle(60);
MutableObject<Selection> obj = new MutableObject<>(growing);
r2.forEach(pos -> {
scene.idle(1);
Selection add = obj.getValue()
.copy()
.add(util.select.position(pos));
scene.overlay.showOutline(PonderPalette.WHITE, s, add, 3);
obj.setValue(add);
});
scene.overlay.showSelectionWithText(obj.getValue(), 60)
.colored(PonderPalette.GREEN)
.text("...it will attach all reachable blocks within a radius on that layer");
scene.idle(70);
scene.world.configureCenterOfRotation(outer, util.vector.centerOf(bearingPos));
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(contraption, 0, 360, 0, 80);
scene.world.rotateSection(outer, 0, 360, 0, 80);
scene.idle(90);
scene.addKeyframe();
blockSurface = util.vector.topOf(chassisPos);
scene.overlay.showCenteredScrollInput(chassisPos, Direction.UP, 50);
scene.overlay.showControls(new InputWindowElement(blockSurface, Pointing.DOWN).scroll()
.withWrench(), 50);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, r2, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, r3, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, r2, 20);
scene.idle(10);
scene.overlay.showOutline(PonderPalette.WHITE, chassis, r1, 15);
scene.idle(10);
scene.overlay.showText(60)
.pointAt(blockSurface)
.text("Using a Wrench, a precise Radius can be specified for this chassis")
.placeNearTarget();
scene.idle(70);
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(contraption, 0, 360, 0, 80);
scene.idle(90);
scene.world.destroyBlock(util.grid.at(1, 2, 0));
scene.idle(1);
scene.world.destroyBlock(util.grid.at(1, 2, 1));
scene.idle(1);
scene.world.destroyBlock(util.grid.at(1, 2, 3));
scene.idle(1);
scene.world.destroyBlock(util.grid.at(1, 2, 4));
scene.idle(10);
Selection ignored = util.select.fromTo(0, 2, 1, 0, 2, 3)
.add(util.select.position(1, 2, 2));
scene.overlay.showOutline(PonderPalette.GREEN, r2, r2.copy()
.substract(util.select.fromTo(0, 2, 0, 1, 2, 4)), 80);
scene.markAsFinished();
scene.overlay.showSelectionWithText(ignored, 80)
.colored(PonderPalette.RED)
.text("Blocks not reachable by any sticky face will not attach");
}
public static void superGlue(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("super_glue", "Attaching blocks using Super Glue");
scene.configureBasePlate(0, 0, 5);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
scene.world.showSection(util.select.layer(1), Direction.DOWN);
scene.idle(10);
BlockPos central = util.grid.at(2, 2, 2);
ElementLink<WorldSectionElement> plank =
scene.world.showIndependentSection(util.select.position(central), Direction.DOWN);
scene.idle(15);
Vec3d blockSurface = util.vector.blockSurface(central, Direction.NORTH);
scene.overlay.showControls(new InputWindowElement(blockSurface, Pointing.DOWN).rightClick()
.withItem(AllItems.SUPER_GLUE.asStack()), 40);
scene.idle(7);
ElementLink<EntityElement> glueEntity = scene.world.createGlueEntity(central, Direction.NORTH);
scene.idle(10);
scene.overlay.showText(60)
.pointAt(blockSurface)
.placeNearTarget()
.text("Super Glue can be used between any two blocks")
.colored(PonderPalette.GREEN);
scene.idle(50);
scene.world.glueBlockOnto(central.north(), Direction.SOUTH, plank);
scene.idle(20);
scene.world.modifyEntity(glueEntity, Entity::remove);
BlockPos bearingPos = util.grid.at(2, 1, 2);
scene.world.configureCenterOfRotation(plank, util.vector.centerOf(bearingPos));
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(plank, 0, 360, 0, 80);
scene.idle(30);
scene.overlay.showText(80)
.attachKeyFrame()
.pointAt(util.vector.topOf(central))
.placeNearTarget()
.text("The attached blocks will move together when assembled into a Contraption");
scene.idle(90);
scene.overlay.showText(50)
.attachKeyFrame()
.pointAt(util.vector.topOf(central))
.placeNearTarget()
.text("Whenever Super Glue is held in the off-hand...");
scene.idle(60);
scene.world.glueBlockOnto(central.south(), Direction.NORTH, plank);
scene.idle(5);
scene.world.glueBlockOnto(central.north()
.east(), Direction.WEST, plank);
scene.idle(5);
scene.world.glueBlockOnto(central.up(), Direction.DOWN, plank);
scene.idle(5);
scene.world.glueBlockOnto(central.south()
.west(), Direction.EAST, plank);
scene.idle(10);
scene.overlay.showText(80)
.pointAt(util.vector.topOf(central)
.subtract(.5, 0, 0))
.placeNearTarget()
.text("...added blocks will be glued to the face they were placed on automatically");
scene.idle(90);
scene.world.rotateBearing(bearingPos, 360, 80);
scene.world.rotateSection(plank, 0, 360, 0, 80);
scene.idle(90);
glueEntity = scene.world.createGlueEntity(central, Direction.UP);
scene.world.destroyBlock(central.up());
scene.idle(20);
scene.addKeyframe();
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(central), Pointing.DOWN).leftClick(), 40);
scene.idle(7);
scene.world.modifyEntity(glueEntity, Entity::remove);
scene.effects.superGlue(central, Direction.UP, false);
scene.idle(10);
scene.overlay.showText(60)
.pointAt(util.vector.topOf(central))
.placeNearTarget()
.text("Super Glue can be removed with Left-Click");
}
}

View file

@ -84,7 +84,6 @@ public class DebugScenes {
scene.overlay.showSelectionWithText(zAxis, 20) scene.overlay.showSelectionWithText(zAxis, 20)
.colored(PonderPalette.BLUE) .colored(PonderPalette.BLUE)
.text("Das Z axis"); .text("Das Z axis");
scene.idle(10);
} }
public static void blocksScene(SceneBuilder scene, SceneBuildingUtil util) { public static void blocksScene(SceneBuilder scene, SceneBuildingUtil util) {

View file

@ -77,6 +77,17 @@ public class PonderIndex {
.addStoryBoard("funnels/transposer", FunnelScenes::transposer); .addStoryBoard("funnels/transposer", FunnelScenes::transposer);
PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass); PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass);
// Chassis & Super Glue
PonderRegistry.forComponents(AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS)
.addStoryBoard("chassis/linear_group", ChassisScenes::linearGroup)
.addStoryBoard("chassis/linear_attachment", ChassisScenes::linearAttachement);
PonderRegistry.forComponents(AllBlocks.RADIAL_CHASSIS)
.addStoryBoard("chassis/radial", ChassisScenes::radial);
PonderRegistry.forComponents(AllItems.SUPER_GLUE)
.addStoryBoard("super_glue", ChassisScenes::superGlue);
PonderRegistry.forComponents(AllBlocks.STICKER)
.addStoryBoard("sticker", RedstoneScenes::sticker);
// Mechanical Piston // Mechanical Piston
PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON)
.addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES, .addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES,
@ -128,6 +139,8 @@ public class PonderIndex {
PonderRegistry.forComponents(AllBlocks.PORTABLE_STORAGE_INTERFACE) PonderRegistry.forComponents(AllBlocks.PORTABLE_STORAGE_INTERFACE)
.addStoryBoard("portable_interface/transfer", MovementActorScenes::psiTransfer, PonderTag.CONTRAPTION_ACTOR) .addStoryBoard("portable_interface/transfer", MovementActorScenes::psiTransfer, PonderTag.CONTRAPTION_ACTOR)
.addStoryBoard("portable_interface/redstone", MovementActorScenes::psiRedstone); .addStoryBoard("portable_interface/redstone", MovementActorScenes::psiRedstone);
PonderRegistry.forComponents(AllBlocks.REDSTONE_CONTACT)
.addStoryBoard("redstone_contact", RedstoneScenes::contact);
// Debug scenes, can be found in game via the Brass Hand // Debug scenes, can be found in game via the Brass Hand
if (EDITOR_MODE) if (EDITOR_MODE)

View file

@ -0,0 +1,169 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.StickerTileEntity;
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.WorldSectionElement;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
public class RedstoneScenes {
public static void sticker(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("sticker", "Attaching blocks using the Sticker");
scene.configureBasePlate(0, 0, 5);
scene.showBasePlate();
scene.idle(5);
Selection redstone = util.select.fromTo(0, 2, 2, 2, 2, 2);
BlockPos stickerPos = util.grid.at(2, 2, 2);
Selection stickerSelect = util.select.position(stickerPos);
BlockPos buttonPos = util.grid.at(0, 2, 2);
BlockPos bearingPos = util.grid.at(2, 1, 2);
scene.world.showSection(util.select.fromTo(2, 1, 2, 0, 2, 2)
.substract(stickerSelect), Direction.DOWN);
scene.idle(10);
ElementLink<WorldSectionElement> sticker = scene.world.showIndependentSection(stickerSelect, Direction.DOWN);
scene.idle(10);
ElementLink<WorldSectionElement> plank =
scene.world.showIndependentSection(util.select.position(2, 2, 1), Direction.SOUTH);
scene.world.configureCenterOfRotation(sticker, util.vector.centerOf(stickerPos));
scene.world.configureCenterOfRotation(plank, util.vector.centerOf(stickerPos));
scene.overlay.showText(60)
.text("Stickers are ideal for Redstone-controlled block attachment")
.attachKeyFrame()
.pointAt(util.vector.blockSurface(stickerPos, Direction.WEST))
.placeNearTarget();
scene.idle(70);
scene.world.toggleRedstonePower(redstone);
scene.world.modifyBlock(stickerPos, s -> s.with(StickerBlock.EXTENDED, true), false);
scene.effects.indicateRedstone(buttonPos);
scene.world.modifyTileNBT(stickerSelect, StickerTileEntity.class, nbt -> {
});
scene.idle(20);
scene.world.toggleRedstonePower(redstone);
scene.idle(20);
scene.overlay.showText(60)
.text("Upon receiving a signal, it will toggle its state")
.pointAt(util.vector.blockSurface(stickerPos, Direction.WEST))
.placeNearTarget();
scene.idle(70);
scene.world.rotateBearing(bearingPos, 180 * 3, 80);
scene.world.rotateSection(sticker, 0, 180 * 3, 0, 80);
scene.world.rotateSection(plank, 0, 180 * 3, 0, 80);
scene.overlay.showText(70)
.text("If it is now moved in a contraption, the block will move with it")
.pointAt(util.vector.topOf(stickerPos))
.placeNearTarget();
scene.idle(90);
scene.addKeyframe();
scene.world.toggleRedstonePower(redstone);
scene.world.modifyBlock(stickerPos, s -> s.with(StickerBlock.EXTENDED, false), false);
scene.effects.indicateRedstone(buttonPos);
scene.world.modifyTileNBT(stickerSelect, StickerTileEntity.class, nbt -> {
});
scene.idle(20);
scene.world.toggleRedstonePower(redstone);
scene.idle(20);
scene.overlay.showText(60)
.text("Toggled once again, the block is no longer attached")
.pointAt(util.vector.blockSurface(stickerPos, Direction.WEST))
.placeNearTarget();
scene.idle(70);
scene.world.rotateBearing(bearingPos, 180 * 3, 80);
scene.world.rotateSection(sticker, 0, 180 * 3, 0, 80);
}
public static void contact(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("redstone_contact", "Redstone Contacts");
scene.configureBasePlate(0, 0, 5);
scene.showBasePlate();
scene.idle(5);
Selection contactAndRedstone = util.select.fromTo(1, 1, 0, 1, 1, 2);
Selection topContact = util.select.position(1, 2, 2);
scene.world.toggleRedstonePower(contactAndRedstone);
scene.world.toggleRedstonePower(topContact);
scene.world.showSection(contactAndRedstone, Direction.DOWN);
BlockPos bearingPos = util.grid.at(3, 1, 2);
scene.idle(25);
ElementLink<WorldSectionElement> contact = scene.world.showIndependentSection(topContact, Direction.DOWN);
scene.idle(10);
scene.world.toggleRedstonePower(topContact);
scene.world.toggleRedstonePower(contactAndRedstone);
scene.effects.indicateRedstone(util.grid.at(1, 1, 2));
scene.idle(10);
scene.overlay.showText(60)
.attachKeyFrame()
.placeNearTarget()
.pointAt(util.vector.of(1, 2, 2.5))
.text("Redstone Contacts facing each other will emit a redstone signal");
scene.idle(70);
scene.world.showSection(util.select.position(bearingPos), Direction.DOWN);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(2, 2, 2, 4, 2, 2), Direction.DOWN, contact);
scene.idle(10);
scene.effects.superGlue(util.grid.at(1, 2, 2), Direction.EAST, true);
scene.world.configureCenterOfRotation(contact, util.vector.centerOf(bearingPos));
int speed = 2;
scene.idle(10);
scene.world.rotateBearing(bearingPos, 10, speed);
scene.world.rotateSection(contact, 0, 10, 0, speed);
scene.idle(speed);
scene.world.toggleRedstonePower(topContact);
scene.world.toggleRedstonePower(contactAndRedstone);
scene.effects.indicateRedstone(util.grid.at(1, 1, 2));
scene.world.rotateBearing(bearingPos, 340, 34 * speed);
scene.world.rotateSection(contact, 0, 340, 0, 34 * speed);
scene.addKeyframe();
scene.idle(34 * speed);
scene.overlay.showText(100)
.placeNearTarget()
.pointAt(util.vector.of(1, 1.5, 2.5))
.text("This still applies when one of them is part of a moving Contraption");
for (int i = 0; i < 5; i++) {
scene.world.toggleRedstonePower(topContact);
scene.world.toggleRedstonePower(contactAndRedstone);
scene.effects.indicateRedstone(util.grid.at(1, 1, 2));
scene.world.rotateBearing(bearingPos, 20, 2 * speed);
scene.world.rotateSection(contact, 0, 20, 0, 2 * speed);
scene.idle(2 * speed);
scene.world.toggleRedstonePower(topContact);
scene.world.toggleRedstonePower(contactAndRedstone);
scene.world.rotateBearing(bearingPos, 340, 34 * speed);
scene.world.rotateSection(contact, 0, 340, 0, 34 * speed);
scene.idle(34 * speed);
if (i == 0)
scene.markAsFinished();
}
scene.world.toggleRedstonePower(topContact);
scene.world.toggleRedstonePower(contactAndRedstone);
scene.world.rotateBearing(bearingPos, 10, speed);
scene.world.rotateSection(contact, 0, 10, 0, speed);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.