607 lines
24 KiB
Java
607 lines
24 KiB
Java
package com.simibubi.create.infrastructure.ponder.scenes.fluid;
|
|
|
|
import com.simibubi.create.AllBlocks;
|
|
import com.simibubi.create.AllFluids;
|
|
import com.simibubi.create.content.fluids.drain.ItemDrainBlockEntity;
|
|
import com.simibubi.create.content.fluids.pipes.AxisPipeBlock;
|
|
import com.simibubi.create.content.fluids.pipes.FluidPipeBlock;
|
|
import com.simibubi.create.content.fluids.pipes.GlassFluidPipeBlock;
|
|
import com.simibubi.create.content.fluids.pipes.SmartFluidPipeBlockEntity;
|
|
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlock;
|
|
import com.simibubi.create.content.fluids.pipes.valve.FluidValveBlockEntity;
|
|
import com.simibubi.create.content.fluids.pump.PumpBlock;
|
|
import com.simibubi.create.content.fluids.tank.FluidTankBlockEntity;
|
|
import com.simibubi.create.content.processing.basin.BasinBlockEntity;
|
|
import com.simibubi.create.foundation.blockEntity.behaviour.fluid.SmartFluidTankBehaviour;
|
|
import com.simibubi.create.foundation.fluid.FluidHelper;
|
|
import com.simibubi.create.foundation.ponder.ElementLink;
|
|
import com.simibubi.create.foundation.ponder.PonderPalette;
|
|
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.element.InputWindowElement;
|
|
import com.simibubi.create.foundation.ponder.element.WorldSectionElement;
|
|
import com.simibubi.create.foundation.utility.Pointing;
|
|
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Direction.Axis;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.level.block.BeehiveBlock;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|
import net.minecraft.world.level.material.Fluids;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraftforge.common.ForgeMod;
|
|
import net.minecraftforge.fluids.FluidStack;
|
|
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
|
import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
|
|
|
|
public class PipeScenes {
|
|
|
|
public static void flow(SceneBuilder scene, SceneBuildingUtil util) {
|
|
scene.title("fluid_pipe_flow", "Moving Fluids using Copper Pipes");
|
|
scene.configureBasePlate(0, 0, 5);
|
|
scene.showBasePlate();
|
|
scene.idle(5);
|
|
|
|
BlockState pipeState = AllBlocks.FLUID_PIPE.getDefaultState()
|
|
.setValue(FluidPipeBlock.UP, false)
|
|
.setValue(FluidPipeBlock.DOWN, false);
|
|
|
|
scene.world.setBlock(util.grid.at(2, 1, 1), pipeState.setValue(FluidPipeBlock.NORTH, false)
|
|
.setValue(FluidPipeBlock.SOUTH, false), false);
|
|
scene.world.setBlock(util.grid.at(1, 1, 2), pipeState.setValue(FluidPipeBlock.WEST, false)
|
|
.setValue(FluidPipeBlock.EAST, false), false);
|
|
|
|
Selection largeCog = util.select.position(5, 0, 1);
|
|
Selection kinetics = util.select.fromTo(5, 1, 0, 3, 1, 0);
|
|
Selection tank = util.select.fromTo(4, 1, 2, 4, 2, 2);
|
|
Selection tank2 = util.select.fromTo(0, 1, 3, 0, 2, 3);
|
|
|
|
Selection strayPipes = util.select.fromTo(2, 1, 2, 2, 2, 2)
|
|
.add(util.select.fromTo(1, 2, 2, 1, 3, 2));
|
|
|
|
scene.world.showSection(tank, Direction.DOWN);
|
|
scene.idle(5);
|
|
scene.world.showSection(tank2, Direction.DOWN);
|
|
FluidStack content = new FluidStack(Fluids.LAVA, 10000);
|
|
scene.world.modifyBlockEntity(util.grid.at(4, 1, 2), FluidTankBlockEntity.class, be -> be.getTankInventory()
|
|
.fill(content, FluidAction.EXECUTE));
|
|
scene.idle(10);
|
|
|
|
for (int i = 4; i >= 1; i--) {
|
|
scene.world.showSection(util.select.position(i, 1, 1), i == 4 ? Direction.SOUTH : Direction.EAST);
|
|
scene.idle(3);
|
|
}
|
|
|
|
scene.overlay.showText(60)
|
|
.text("Fluid Pipes can connect two or more fluid sources and targets")
|
|
.attachKeyFrame()
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.topOf(1, 1, 1));
|
|
|
|
for (int i = 2; i <= 3; i++) {
|
|
scene.world.showSection(util.select.position(1, 1, i), Direction.NORTH);
|
|
scene.idle(3);
|
|
}
|
|
|
|
scene.idle(60);
|
|
|
|
scene.overlay.showControls(new InputWindowElement(util.vector.centerOf(2, 1, 1), Pointing.DOWN).rightClick()
|
|
.withWrench(), 40);
|
|
scene.idle(7);
|
|
scene.world.restoreBlocks(util.select.position(2, 1, 1));
|
|
scene.overlay.showText(70)
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.centerOf(2, 1, 1))
|
|
.placeNearTarget()
|
|
.text("Using a wrench, a straight pipe segment can be given a window");
|
|
scene.idle(40);
|
|
|
|
scene.overlay.showControls(new InputWindowElement(util.vector.centerOf(1, 1, 2), Pointing.DOWN).rightClick()
|
|
.withWrench(), 10);
|
|
scene.idle(7);
|
|
scene.world.restoreBlocks(util.select.position(1, 1, 2));
|
|
scene.idle(40);
|
|
|
|
Vec3 center = util.vector.centerOf(2, 1, 2);
|
|
AABB bb = new AABB(center, center).inflate(1 / 6f);
|
|
AABB bb1 = bb.move(-0.5, 0, 0);
|
|
AABB bb2 = bb.move(0, 0, -0.5);
|
|
|
|
scene.world.showSection(strayPipes, Direction.DOWN);
|
|
scene.idle(10);
|
|
scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb1, bb, 1);
|
|
scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb2, bb, 1);
|
|
scene.idle(1);
|
|
scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb1, bb1, 50);
|
|
scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb2, bb2, 50);
|
|
scene.idle(10);
|
|
scene.overlay.showText(55)
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.centerOf(2, 1, 2))
|
|
.placeNearTarget()
|
|
.colored(PonderPalette.RED)
|
|
.text("Windowed pipes will not connect to any other adjacent pipe segments");
|
|
scene.idle(60);
|
|
scene.world.hideSection(strayPipes, Direction.UP);
|
|
scene.idle(10);
|
|
|
|
BlockPos pumpPos = util.grid.at(3, 1, 1);
|
|
scene.world.setBlock(pumpPos, AllBlocks.MECHANICAL_PUMP.getDefaultState()
|
|
.setValue(PumpBlock.FACING, Direction.WEST), true);
|
|
scene.idle(10);
|
|
scene.world.showSection(largeCog, Direction.UP);
|
|
scene.world.showSection(kinetics, Direction.SOUTH);
|
|
scene.idle(10);
|
|
scene.world.multiplyKineticSpeed(util.select.everywhere(), 0.25f);
|
|
scene.world.setKineticSpeed(util.select.position(pumpPos), 8);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
|
|
scene.overlay.showText(70)
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.topOf(pumpPos))
|
|
.placeNearTarget()
|
|
.text("Powered by Mechanical Pumps, the Pipes can transport Fluids");
|
|
scene.idle(85);
|
|
scene.overlay.showSelectionWithText(tank, 40)
|
|
.colored(PonderPalette.RED)
|
|
.placeNearTarget()
|
|
.text("No fluid is being extracted at first");
|
|
scene.idle(70);
|
|
|
|
scene.overlay.showOutline(PonderPalette.GREEN, new Object(), tank, 100);
|
|
scene.idle(5);
|
|
scene.overlay.showOutline(PonderPalette.GREEN, new Object(), tank2, 100);
|
|
scene.idle(5);
|
|
scene.overlay.showText(100)
|
|
.attachKeyFrame()
|
|
.independent()
|
|
.text("Once the flow connects them, the endpoints gradually transfer their contents");
|
|
scene.overlay.showLine(PonderPalette.GREEN, util.vector.blockSurface(util.grid.at(4, 2, 2), Direction.WEST),
|
|
util.vector.blockSurface(util.grid.at(0, 2, 3), Direction.EAST), 80);
|
|
|
|
scene.world.multiplyKineticSpeed(util.select.everywhere(), 2);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.effects.rotationSpeedIndicator(pumpPos);
|
|
|
|
scene.idle(120);
|
|
|
|
scene.overlay.showText(60)
|
|
.text("Thus, the Pipe blocks themselves never 'physically' contain any fluid")
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.topOf(1, 1, 1));
|
|
scene.idle(50);
|
|
}
|
|
|
|
public static void interaction(SceneBuilder scene, SceneBuildingUtil util) {
|
|
scene.title("fluid_pipe_interaction", "Draining and Filling fluid containers");
|
|
scene.configureBasePlate(0, 1, 5);
|
|
scene.showBasePlate();
|
|
scene.idle(5);
|
|
|
|
BlockPos pumpPos = util.grid.at(2, 1, 4);
|
|
Selection largeCog = util.select.position(5, 0, 4);
|
|
Selection kinetics = util.select.fromTo(5, 1, 5, 2, 1, 5);
|
|
Selection pipes = util.select.fromTo(1, 1, 4, 3, 1, 3)
|
|
.add(util.select.position(3, 1, 2));
|
|
Selection tank = util.select.fromTo(4, 1, 3, 4, 2, 3);
|
|
Selection drain = util.select.position(1, 1, 2);
|
|
Selection basin = util.select.position(3, 1, 1);
|
|
|
|
Selection waterSourceS = util.select.position(1, 1, 1);
|
|
Selection waterTargetS = util.select.position(4, 1, 1);
|
|
Selection waterTarget2S = util.select.fromTo(4, 0, 0, 4, 1, 0);
|
|
|
|
scene.world.setKineticSpeed(util.select.position(pumpPos), 0);
|
|
|
|
scene.world.showSection(pipes, Direction.DOWN);
|
|
scene.idle(10);
|
|
scene.world.showSection(basin, Direction.SOUTH);
|
|
scene.idle(5);
|
|
scene.world.showSection(drain, Direction.SOUTH);
|
|
scene.idle(5);
|
|
scene.world.showSection(tank, Direction.WEST);
|
|
|
|
scene.overlay.showText(60)
|
|
.text("Endpoints of a pipe network can interact with a variety of blocks")
|
|
.attachKeyFrame()
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 3), Direction.NORTH));
|
|
scene.idle(60);
|
|
scene.world.showSection(largeCog, Direction.UP);
|
|
scene.idle(5);
|
|
scene.world.showSection(kinetics, Direction.NORTH);
|
|
scene.idle(10);
|
|
scene.world.multiplyKineticSpeed(util.select.everywhere(), 0.5f);
|
|
scene.world.setKineticSpeed(util.select.position(pumpPos), 32);
|
|
BlockPos drainPos = util.grid.at(1, 1, 2);
|
|
scene.world.modifyBlockEntity(drainPos, ItemDrainBlockEntity.class,
|
|
be -> be.getBehaviour(SmartFluidTankBehaviour.TYPE)
|
|
.allowInsertion()
|
|
.getPrimaryHandler()
|
|
.fill(new FluidStack(Fluids.WATER, 1500), FluidAction.EXECUTE));
|
|
|
|
scene.idle(50);
|
|
scene.overlay.showOutline(PonderPalette.MEDIUM, new Object(), drain, 40);
|
|
scene.idle(5);
|
|
scene.overlay.showOutline(PonderPalette.MEDIUM, new Object(), tank, 40);
|
|
scene.idle(5);
|
|
scene.overlay.showOutline(PonderPalette.MEDIUM, new Object(), basin, 40);
|
|
scene.idle(5);
|
|
|
|
scene.overlay.showText(60)
|
|
.text("Any block with fluid storage capabilities can be filled or drained")
|
|
.attachKeyFrame()
|
|
.colored(PonderPalette.MEDIUM)
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.blockSurface(drainPos, Direction.UP));
|
|
scene.idle(100);
|
|
|
|
scene.world.hideSection(drain, Direction.NORTH);
|
|
scene.idle(5);
|
|
scene.world.hideSection(tank, Direction.EAST);
|
|
scene.idle(5);
|
|
scene.world.setBlock(drainPos, Blocks.AIR.defaultBlockState(), false);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.world.hideSection(basin, Direction.NORTH);
|
|
scene.idle(5);
|
|
scene.world.setBlock(util.grid.at(3, 1, 1), Blocks.AIR.defaultBlockState(), false);
|
|
scene.idle(5);
|
|
scene.world.setBlock(util.grid.at(3, 1, 3), AllBlocks.GLASS_FLUID_PIPE.getDefaultState()
|
|
.setValue(AxisPipeBlock.AXIS, Axis.Z), false);
|
|
scene.idle(10);
|
|
// scene.world.multiplyKineticSpeed(util.select.everywhere(), 2);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
ElementLink<WorldSectionElement> water = scene.world.showIndependentSection(waterSourceS, Direction.DOWN);
|
|
scene.world.moveSection(water, util.vector.of(0, 0, 1), 0);
|
|
scene.idle(10);
|
|
scene.world.setBlock(drainPos, Blocks.WATER.defaultBlockState(), false);
|
|
scene.idle(20);
|
|
|
|
scene.overlay.showText(60)
|
|
.text("Source blocks right in front of an open end can be picked up...")
|
|
.attachKeyFrame()
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.blockSurface(drainPos, Direction.SOUTH));
|
|
|
|
scene.idle(40);
|
|
scene.world.setBlock(drainPos.north(), Blocks.AIR.defaultBlockState(), false);
|
|
scene.idle(40);
|
|
ElementLink<WorldSectionElement> target = scene.world.showIndependentSection(waterTargetS, Direction.UP);
|
|
scene.world.moveSection(target, util.vector.of(-1, 0, 0), 0);
|
|
scene.idle(5);
|
|
scene.world.showSectionAndMerge(waterTarget2S, Direction.UP, target);
|
|
|
|
scene.overlay.showText(60)
|
|
.text("...while spilling into empty spaces can create fluid sources")
|
|
.attachKeyFrame()
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.NORTH));
|
|
|
|
scene.idle(80);
|
|
scene.world.hideIndependentSection(target, Direction.DOWN);
|
|
scene.idle(5);
|
|
scene.world.setBlock(drainPos, Blocks.BEE_NEST.defaultBlockState()
|
|
.setValue(BeehiveBlock.HONEY_LEVEL, 5), false);
|
|
scene.world.showSection(drain, Direction.DOWN);
|
|
scene.world.setBlock(util.grid.at(3, 1, 2), AllBlocks.FLUID_TANK.getDefaultState(), false);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.idle(15);
|
|
|
|
scene.overlay.showText(60)
|
|
.text("Pipes can also extract fluids from a handful of other blocks directly")
|
|
.attachKeyFrame()
|
|
.placeNearTarget()
|
|
.pointAt(util.vector.topOf(drainPos));
|
|
|
|
scene.idle(60);
|
|
scene.world.setBlock(drainPos, Blocks.BEE_NEST.defaultBlockState()
|
|
.setValue(BeehiveBlock.HONEY_LEVEL, 0), false);
|
|
}
|
|
|
|
public static void encasing(SceneBuilder scene, SceneBuildingUtil util) {
|
|
scene.title("encased_fluid_pipe", "Encasing Fluid Pipes");
|
|
scene.configureBasePlate(0, 0, 5);
|
|
scene.showBasePlate();
|
|
scene.idle(5);
|
|
scene.world.showSection(util.select.position(2, 0, 5), Direction.UP);
|
|
scene.idle(5);
|
|
scene.world.showSection(util.select.layer(1), Direction.DOWN);
|
|
scene.idle(15);
|
|
|
|
BlockState copperEncased = AllBlocks.ENCASED_FLUID_PIPE.getDefaultState()
|
|
.setValue(FluidPipeBlock.SOUTH, true)
|
|
.setValue(FluidPipeBlock.WEST, true);
|
|
ItemStack casingItem = AllBlocks.COPPER_CASING.asStack();
|
|
|
|
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(3, 1, 1), Pointing.DOWN).rightClick()
|
|
.withItem(casingItem), 60);
|
|
scene.idle(7);
|
|
scene.world.setBlock(util.grid.at(3, 1, 1), copperEncased, true);
|
|
scene.idle(10);
|
|
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.text("Copper Casing can be used to decorate Fluid Pipes")
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.topOf(3, 1, 1));
|
|
|
|
scene.idle(70);
|
|
scene.world.destroyBlock(util.grid.at(2, 1, 1));
|
|
scene.world.modifyBlock(util.grid.at(1, 1, 1), s -> s.setValue(FluidPipeBlock.EAST, false)
|
|
.setValue(FluidPipeBlock.NORTH, true), false);
|
|
scene.idle(5);
|
|
|
|
scene.overlay.showLine(PonderPalette.RED, util.vector.of(1.5, 1.75, 1), util.vector.of(1.5, 1.75, 2), 80);
|
|
scene.idle(5);
|
|
scene.addKeyframe();
|
|
scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(3.5, 2, 1.5), util.vector.of(3.5, 2, 2), 80);
|
|
scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(3, 2, 1.5), util.vector.of(3.5, 2, 1.5), 80);
|
|
|
|
scene.idle(25);
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.text("Aside from being concealed, Encased Pipes are locked into their connectivity state")
|
|
.pointAt(util.vector.blockSurface(util.grid.at(3, 1, 1), Direction.WEST));
|
|
|
|
scene.idle(70);
|
|
BlockState defaultState = AllBlocks.FLUID_PIPE.getDefaultState();
|
|
for (BooleanProperty booleanProperty : FluidPipeBlock.PROPERTY_BY_DIRECTION.values())
|
|
defaultState = defaultState.setValue(booleanProperty, false);
|
|
|
|
scene.world.setBlock(util.grid.at(3, 2, 1), defaultState.setValue(FluidPipeBlock.EAST, true)
|
|
.setValue(FluidPipeBlock.WEST, true), false);
|
|
scene.world.setBlock(util.grid.at(1, 2, 1), defaultState.setValue(FluidPipeBlock.UP, true)
|
|
.setValue(FluidPipeBlock.DOWN, true), false);
|
|
scene.world.showSection(util.select.layer(2), Direction.DOWN);
|
|
scene.idle(10);
|
|
scene.world.modifyBlock(util.grid.at(1, 1, 1), s -> s.setValue(FluidPipeBlock.UP, true)
|
|
.setValue(FluidPipeBlock.NORTH, false), false);
|
|
scene.idle(20);
|
|
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.colored(PonderPalette.RED)
|
|
.text("It will no longer react to any neighbouring blocks being added or removed")
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.centerOf(3, 2, 1));
|
|
scene.idle(20);
|
|
}
|
|
|
|
public static void valve(SceneBuilder scene, SceneBuildingUtil util) {
|
|
scene.title("valve_pipe", "Controlling Fluid flow using Valves");
|
|
scene.configureBasePlate(0, 0, 5);
|
|
scene.showBasePlate();
|
|
|
|
Selection cogs = util.select.fromTo(5, 0, 2, 5, 1, 2);
|
|
Selection tank1 = util.select.fromTo(3, 1, 3, 3, 2, 3);
|
|
Selection tank2 = util.select.fromTo(1, 1, 3, 1, 2, 3);
|
|
BlockPos valvePos = util.grid.at(2, 1, 1);
|
|
BlockPos handlePos = util.grid.at(2, 2, 1);
|
|
BlockPos pumpPos = util.grid.at(4, 1, 2);
|
|
Selection pipes1 = util.select.fromTo(4, 1, 3, 4, 1, 1);
|
|
Selection pipes2 = util.select.fromTo(3, 1, 1, 1, 1, 1);
|
|
Selection pipes3 = util.select.fromTo(0, 1, 1, 0, 1, 3);
|
|
|
|
scene.world.setKineticSpeed(pipes1, 0);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.world.setBlock(valvePos, AllBlocks.FLUID_PIPE.get()
|
|
.getAxisState(Axis.X), false);
|
|
scene.world.setBlock(util.grid.at(3, 1, 1), Blocks.AIR.defaultBlockState(), false);
|
|
scene.world.setBlock(util.grid.at(3, 1, 1), AllBlocks.GLASS_FLUID_PIPE.getDefaultState()
|
|
.setValue(GlassFluidPipeBlock.AXIS, Axis.X), false);
|
|
|
|
scene.idle(5);
|
|
scene.world.showSection(tank1, Direction.NORTH);
|
|
scene.idle(5);
|
|
scene.world.showSection(tank2, Direction.NORTH);
|
|
scene.idle(10);
|
|
scene.world.showSection(pipes1, Direction.WEST);
|
|
scene.idle(5);
|
|
scene.world.showSection(pipes2, Direction.SOUTH);
|
|
scene.idle(5);
|
|
scene.world.showSection(pipes3, Direction.EAST);
|
|
scene.idle(15);
|
|
|
|
scene.world.destroyBlock(valvePos);
|
|
scene.world.restoreBlocks(util.select.position(valvePos));
|
|
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.text("Valve pipes help control fluids propagating through pipe networks")
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.blockSurface(valvePos, Direction.WEST));
|
|
scene.idle(75);
|
|
|
|
scene.world.showSection(cogs, Direction.WEST);
|
|
scene.idle(10);
|
|
scene.world.setKineticSpeed(util.select.position(pumpPos), 64);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.text("Their shaft input controls whether fluid is currently allowed through")
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.topOf(valvePos));
|
|
scene.idle(60);
|
|
ElementLink<WorldSectionElement> handleLink =
|
|
scene.world.showIndependentSection(util.select.position(handlePos), Direction.DOWN);
|
|
scene.idle(15);
|
|
|
|
Selection valveKinetics = util.select.fromTo(2, 1, 1, 2, 2, 1);
|
|
scene.world.setKineticSpeed(valveKinetics, 16);
|
|
scene.world.rotateSection(handleLink, 0, 90, 0, 22);
|
|
scene.effects.rotationSpeedIndicator(handlePos);
|
|
scene.world.modifyBlockEntity(valvePos, FluidValveBlockEntity.class, be -> be.onSpeedChanged(0));
|
|
scene.idle(22);
|
|
scene.world.modifyBlock(valvePos, s -> s.setValue(FluidValveBlock.ENABLED, true), false);
|
|
scene.effects.indicateSuccess(valvePos);
|
|
scene.idle(5);
|
|
scene.world.setKineticSpeed(valveKinetics, 0);
|
|
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.text("Given Rotational Force in the opening direction, the valve will open up")
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.blockSurface(valvePos, Direction.NORTH));
|
|
scene.idle(90);
|
|
|
|
scene.overlay.showText(50)
|
|
.placeNearTarget()
|
|
.text("It can be closed again by reversing the input rotation")
|
|
.attachKeyFrame()
|
|
.pointAt(util.vector.blockSurface(valvePos, Direction.NORTH));
|
|
scene.idle(40);
|
|
|
|
scene.world.setKineticSpeed(valveKinetics, -16);
|
|
scene.world.rotateSection(handleLink, 0, -90, 0, 22);
|
|
scene.effects.rotationSpeedIndicator(handlePos);
|
|
scene.world.modifyBlockEntity(valvePos, FluidValveBlockEntity.class, be -> be.onSpeedChanged(0));
|
|
scene.idle(22);
|
|
scene.world.modifyBlock(valvePos, s -> s.setValue(FluidValveBlock.ENABLED, false), false);
|
|
scene.effects.indicateRedstone(valvePos);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.idle(5);
|
|
scene.world.setKineticSpeed(valveKinetics, 0);
|
|
}
|
|
|
|
public static void smart(SceneBuilder scene, SceneBuildingUtil util) {
|
|
scene.title("smart_pipe", "Controlling Fluid flow using Smart Pipes");
|
|
scene.configureBasePlate(1, 0, 5);
|
|
scene.showBasePlate();
|
|
scene.idle(5);
|
|
|
|
Selection tank1 = util.select.fromTo(4, 1, 3, 4, 2, 3);
|
|
Selection tank2 = util.select.fromTo(4, 1, 4, 4, 2, 4);
|
|
Selection additionalPipes = util.select.fromTo(3, 1, 4, 1, 1, 4);
|
|
Selection mainPipes = util.select.fromTo(3, 1, 3, 1, 1, 1);
|
|
Selection kinetics1 = util.select.fromTo(0, 0, 2, 0, 0, 5);
|
|
Selection kinetics2 = util.select.position(1, 0, 5);
|
|
BlockPos basinPos = util.grid.at(4, 1, 1);
|
|
BlockPos pumpPos = util.grid.at(1, 1, 2);
|
|
Selection pump = util.select.position(1, 1, 2);
|
|
Selection basin = util.select.position(basinPos);
|
|
BlockPos smartPos = util.grid.at(3, 1, 1);
|
|
|
|
scene.world.modifyBlockEntity(basinPos, BasinBlockEntity.class,
|
|
be -> be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
|
|
.ifPresent(fh -> fh.fill(new FluidStack(ForgeMod.MILK.get(), 1000), FluidAction.EXECUTE)));
|
|
|
|
scene.world.setBlock(util.grid.at(3, 1, 3), AllBlocks.FLUID_PIPE.get()
|
|
.getAxisState(Axis.X), false);
|
|
scene.world.setBlock(smartPos, AllBlocks.FLUID_PIPE.get()
|
|
.getAxisState(Axis.X), false);
|
|
scene.world.setBlock(util.grid.at(2, 1, 3), AllBlocks.GLASS_FLUID_PIPE.getDefaultState()
|
|
.setValue(GlassFluidPipeBlock.AXIS, Axis.X), false);
|
|
scene.world.setBlock(util.grid.at(1, 1, 3), AllBlocks.FLUID_PIPE.get()
|
|
.getAxisState(Axis.X)
|
|
.setValue(FluidPipeBlock.NORTH, true)
|
|
.setValue(FluidPipeBlock.WEST, false), false);
|
|
|
|
scene.world.showSection(basin, Direction.DOWN);
|
|
scene.idle(5);
|
|
scene.world.showSection(tank1, Direction.DOWN);
|
|
scene.idle(5);
|
|
scene.world.showSection(mainPipes, Direction.EAST);
|
|
scene.idle(15);
|
|
|
|
scene.world.destroyBlock(smartPos);
|
|
scene.world.restoreBlocks(util.select.position(smartPos));
|
|
|
|
Vec3 filterVec = util.vector.topOf(smartPos)
|
|
.subtract(0.25, 0, 0);
|
|
scene.overlay.showText(50)
|
|
.placeNearTarget()
|
|
.text("Smart pipes can help control flows by fluid type")
|
|
.pointAt(filterVec);
|
|
scene.idle(60);
|
|
|
|
scene.overlay.showSelectionWithText(util.select.position(basinPos), 80)
|
|
.placeNearTarget()
|
|
.colored(PonderPalette.GREEN)
|
|
.text("When placed directly at the source, they can specify the type of fluid to extract")
|
|
.attachKeyFrame()
|
|
.pointAt(filterVec);
|
|
scene.idle(90);
|
|
|
|
FluidStack chocolate = new FluidStack(FluidHelper.convertToStill(AllFluids.CHOCOLATE.get()), 1000);
|
|
ItemStack bucket = AllFluids.CHOCOLATE.get()
|
|
.getAttributes()
|
|
.getBucket(chocolate);
|
|
ItemStack milkBucket = new ItemStack(Items.MILK_BUCKET);
|
|
scene.overlay.showControls(new InputWindowElement(filterVec, Pointing.DOWN).rightClick()
|
|
.withItem(bucket), 80);
|
|
scene.idle(7);
|
|
scene.world.setFilterData(util.select.position(3, 1, 1), SmartFluidPipeBlockEntity.class, bucket);
|
|
scene.idle(10);
|
|
scene.overlay.showText(60)
|
|
.placeNearTarget()
|
|
.attachKeyFrame()
|
|
.text("Simply Right-Click their filter slot with any item containing the desired fluid")
|
|
.pointAt(filterVec);
|
|
scene.idle(50);
|
|
|
|
scene.world.showSection(kinetics2, Direction.WEST);
|
|
scene.world.setKineticSpeed(kinetics2, 24);
|
|
scene.idle(5);
|
|
scene.world.showSection(kinetics1, Direction.EAST);
|
|
scene.world.setKineticSpeed(kinetics1, -24);
|
|
scene.idle(10);
|
|
scene.world.setKineticSpeed(pump, 48);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.idle(100);
|
|
scene.world.setKineticSpeed(util.select.everywhere(), 0);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.idle(15);
|
|
scene.world.showSection(tank2, Direction.DOWN);
|
|
scene.world.showSection(additionalPipes, Direction.NORTH);
|
|
scene.world.setBlock(util.grid.at(3, 1, 1), AllBlocks.FLUID_PIPE.get()
|
|
.getAxisState(Axis.X), true);
|
|
scene.idle(10);
|
|
for (int i = 0; i < 3; i++) {
|
|
BlockPos pos = util.grid.at(1 + i, 1, 3);
|
|
scene.world.destroyBlock(pos);
|
|
scene.world.restoreBlocks(util.select.position(pos));
|
|
scene.idle(2);
|
|
}
|
|
scene.idle(15);
|
|
scene.world.modifyBlockEntity(basinPos, BasinBlockEntity.class,
|
|
be -> be.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY)
|
|
.ifPresent(fh -> fh.fill(chocolate, FluidAction.EXECUTE)));
|
|
scene.idle(10);
|
|
|
|
scene.overlay.showText(80)
|
|
.placeNearTarget()
|
|
.colored(PonderPalette.GREEN)
|
|
.text("When placed further down a pipe network, smart pipes will only let matching fluids continue")
|
|
.attachKeyFrame()
|
|
.pointAt(filterVec.add(-1, 0, 2));
|
|
scene.idle(90);
|
|
|
|
scene.overlay.showControls(new InputWindowElement(filterVec.add(-1, 0, 3), Pointing.DOWN).rightClick()
|
|
.withItem(milkBucket), 30);
|
|
scene.idle(7);
|
|
scene.world.setFilterData(util.select.position(2, 1, 4), SmartFluidPipeBlockEntity.class, milkBucket);
|
|
scene.idle(30);
|
|
|
|
scene.overlay.showControls(new InputWindowElement(filterVec.add(-1, 0, 2), Pointing.DOWN).rightClick()
|
|
.withItem(bucket), 30);
|
|
scene.idle(7);
|
|
scene.world.setFilterData(util.select.position(2, 1, 3), SmartFluidPipeBlockEntity.class, bucket);
|
|
scene.idle(30);
|
|
|
|
scene.world.setKineticSpeed(kinetics2, 24);
|
|
scene.world.setKineticSpeed(kinetics1, -24);
|
|
scene.world.setKineticSpeed(pump, 48);
|
|
scene.world.propagatePipeChange(pumpPos);
|
|
scene.effects.rotationSpeedIndicator(pumpPos);
|
|
scene.idle(40);
|
|
}
|
|
|
|
}
|