mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-28 16:06:48 +01:00
A final thought
- Fixed non-splitting modes on brass tunnels - Ponder scenes for ejectors and tunnels
This commit is contained in:
parent
7de922f239
commit
bf2a506bb8
15 changed files with 973 additions and 10 deletions
|
@ -42,7 +42,7 @@ public class BeltTunnelInteractionHandler {
|
|||
}
|
||||
|
||||
World world = beltInventory.belt.getWorld();
|
||||
boolean onServer = !world.isRemote;
|
||||
boolean onServer = !world.isRemote || beltInventory.belt.isVirtual();
|
||||
boolean removed = false;
|
||||
BeltTunnelTileEntity nextTunnel = getTunnelOnSegement(beltInventory, upcomingSegment);
|
||||
|
||||
|
@ -128,7 +128,7 @@ public class BeltTunnelInteractionHandler {
|
|||
BeltTunnelTileEntity te = getTunnelOnSegement(beltInventory, offset);
|
||||
if (te == null)
|
||||
return;
|
||||
te.flap(side, inward ^ side.getAxis() == Axis.Z);
|
||||
te.flap(side, inward);
|
||||
}
|
||||
|
||||
protected static BeltTunnelTileEntity getTunnelOnSegement(BeltInventory beltInventory, int offset) {
|
||||
|
|
|
@ -147,7 +147,7 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe
|
|||
if (world.isRemote) {
|
||||
if (flaps.containsKey(side))
|
||||
flaps.get(side)
|
||||
.set(inward ? -1 : 1);
|
||||
.set(inward ^ side.getAxis() == Axis.Z ? -1 : 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
|
|||
return;
|
||||
if (stackToDistribute.isEmpty() && !syncedOutputActive)
|
||||
return;
|
||||
if (world.isRemote)
|
||||
if (world.isRemote && !isVirtual())
|
||||
return;
|
||||
|
||||
if (distributionProgress == -1) {
|
||||
|
@ -206,6 +206,7 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
|
|||
SelectionMode mode = selectionMode.get();
|
||||
boolean force = mode == SelectionMode.FORCED_ROUND_ROBIN || mode == SelectionMode.FORCED_SPLIT;
|
||||
boolean split = mode == SelectionMode.FORCED_SPLIT || mode == SelectionMode.SPLIT;
|
||||
boolean robin = mode == SelectionMode.FORCED_ROUND_ROBIN || mode == SelectionMode.ROUND_ROBIN;
|
||||
|
||||
if (mode == SelectionMode.RANDOMIZE)
|
||||
indexStart = rand.nextInt(amountTargets);
|
||||
|
@ -265,6 +266,8 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
|
|||
remainingOutputs--;
|
||||
if (!simulate)
|
||||
full.add(pair);
|
||||
if (robin)
|
||||
break;
|
||||
continue;
|
||||
} else if (!remainder.isEmpty() && !simulate) {
|
||||
full.add(pair);
|
||||
|
@ -336,7 +339,7 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
|
|||
return null;
|
||||
ItemStack result = sideOutput.handleInsertion(stack, side, simulate);
|
||||
if (result.isEmpty() && !simulate)
|
||||
tunnel.flap(side, true);
|
||||
tunnel.flap(side, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ public class DepotBehaviour extends TileEntityBehaviour {
|
|||
TransportedItemStack ts = iterator.next();
|
||||
if (!tick(ts))
|
||||
continue;
|
||||
if (world.isRemote)
|
||||
if (world.isRemote && !tileEntity.isVirtual())
|
||||
continue;
|
||||
if (heldItem == null) {
|
||||
heldItem = ts;
|
||||
|
|
|
@ -135,7 +135,8 @@ public class EjectorTileEntity extends KineticTileEntity {
|
|||
world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(pos).grow(-1 / 16f, 0, -1 / 16f));
|
||||
|
||||
// Launch Items
|
||||
if (!world.isRemote)
|
||||
boolean doLogic = !world.isRemote || isVirtual();
|
||||
if (doLogic)
|
||||
launchItems();
|
||||
|
||||
// Launch Entities
|
||||
|
@ -169,13 +170,15 @@ public class EjectorTileEntity extends KineticTileEntity {
|
|||
AllPackets.channel.sendToServer(new EjectorElytraPacket(pos));
|
||||
}
|
||||
|
||||
if (!world.isRemote) {
|
||||
if (doLogic) {
|
||||
lidProgress.chase(1, .8f, Chaser.EXP);
|
||||
state = State.LAUNCHING;
|
||||
if (!world.isRemote) {
|
||||
world.playSound(null, pos, SoundEvents.BLOCK_WOODEN_TRAPDOOR_CLOSE, SoundCategory.BLOCKS, .35f, 1f);
|
||||
world.playSound(null, pos, SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.BLOCKS, .1f, 1.4f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void deployElytra(PlayerEntity playerEntity) {
|
||||
EntityHack.setElytraFlying(playerEntity);
|
||||
|
@ -369,6 +372,8 @@ public class EjectorTileEntity extends KineticTileEntity {
|
|||
return;
|
||||
if (presentStackSize < maxStackSize.getValue())
|
||||
return;
|
||||
if (depotBehaviour.heldItem != null && depotBehaviour.heldItem.beltPosition < .49f)
|
||||
return;
|
||||
|
||||
Direction funnelFacing = getFacing().getOpposite();
|
||||
ItemStack held = depotBehaviour.getHeldItemStack();
|
||||
|
@ -502,6 +507,9 @@ public class EjectorTileEntity extends KineticTileEntity {
|
|||
NBTUtil.readBlockPos(compound.getCompound("EarlyTargetPos")));
|
||||
earlyTargetTime = compound.getFloat("EarlyTargetTime");
|
||||
}
|
||||
|
||||
if (compound.contains("ForceAngle"))
|
||||
lidProgress.startWithValue(compound.getFloat("ForceAngle"));
|
||||
}
|
||||
|
||||
public void updateSignal() {
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
package com.simibubi.create.foundation.ponder.content;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.logistics.block.depot.EjectorTileEntity;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
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.WorldSectionElement;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.Pointing;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraftforge.items.ItemHandlerHelper;
|
||||
|
||||
public class EjectorScenes {
|
||||
|
||||
public static void ejector(SceneBuilder scene, SceneBuildingUtil util) {
|
||||
scene.title("weighted_ejector", "Using Weighted Ejectors");
|
||||
scene.configureBasePlate(0, 0, 5);
|
||||
scene.showBasePlate();
|
||||
|
||||
BlockPos ejectorPos = util.grid.at(4, 1, 2);
|
||||
Selection ejectorS = util.select.position(ejectorPos);
|
||||
BlockPos targetPos = util.grid.at(0, 1, 2);
|
||||
Selection targetS = util.select.position(targetPos);
|
||||
|
||||
scene.world.setBlock(targetPos, AllBlocks.ANDESITE_CASING.getDefaultState(), false);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(targetS, Direction.DOWN);
|
||||
|
||||
scene.idle(10);
|
||||
ItemStack asStack = AllBlocks.WEIGHTED_EJECTOR.asStack();
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(targetPos), Pointing.DOWN).rightClick()
|
||||
.whileSneaking()
|
||||
.withItem(asStack), 50);
|
||||
scene.idle(7);
|
||||
Object slot = new Object();
|
||||
scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, slot, new AxisAlignedBB(targetPos), 160);
|
||||
|
||||
scene.overlay.showText(70)
|
||||
.attachKeyFrame()
|
||||
.colored(PonderPalette.OUTPUT)
|
||||
.text("Sneak and Right-Click holding an Ejector to select its target location")
|
||||
.pointAt(util.vector.blockSurface(targetPos, Direction.WEST))
|
||||
.placeNearTarget();
|
||||
scene.idle(80);
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(ejectorPos), Pointing.DOWN).rightClick()
|
||||
.withItem(asStack), 50);
|
||||
scene.idle(7);
|
||||
scene.world.setKineticSpeed(ejectorS, 0);
|
||||
scene.world.modifyTileNBT(ejectorS, EjectorTileEntity.class, nbt -> {
|
||||
NBTHelper.writeEnum(nbt, "State", EjectorTileEntity.State.RETRACTING);
|
||||
nbt.putFloat("ForceAngle", 1);
|
||||
});
|
||||
scene.world.showSection(ejectorS, Direction.DOWN);
|
||||
scene.idle(10);
|
||||
|
||||
scene.overlay.showText(60)
|
||||
.colored(PonderPalette.OUTPUT)
|
||||
.text("The placed ejector will now launch objects to the marked location")
|
||||
.pointAt(util.vector.blockSurface(ejectorPos, Direction.WEST))
|
||||
.placeNearTarget();
|
||||
scene.idle(70);
|
||||
|
||||
slot = new Object();
|
||||
AxisAlignedBB bb = new AxisAlignedBB(ejectorPos.west());
|
||||
scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, slot, bb, 20);
|
||||
scene.idle(10);
|
||||
scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, slot, bb.expand(-15, 15, 0), 100);
|
||||
scene.idle(10);
|
||||
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.colored(PonderPalette.GREEN)
|
||||
.text("A valid target can be at any height or distance within range")
|
||||
.pointAt(util.vector.blockSurface(targetPos, Direction.WEST))
|
||||
.placeNearTarget();
|
||||
scene.idle(70);
|
||||
scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, new Object(), bb.offset(-2, 0, -1), 60);
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(50)
|
||||
.colored(PonderPalette.RED)
|
||||
.text("They cannot however be off to a side")
|
||||
.pointAt(util.vector.blockSurface(targetPos.north()
|
||||
.east(), Direction.WEST))
|
||||
.placeNearTarget();
|
||||
scene.idle(70);
|
||||
scene.overlay.showSelectionWithText(util.select.position(ejectorPos.west()), 70)
|
||||
.colored(PonderPalette.OUTPUT)
|
||||
.text("If no valid Target was selected, it will simply target the block directly in front")
|
||||
.placeNearTarget();
|
||||
scene.idle(80);
|
||||
|
||||
scene.world.showSection(util.select.position(3, 0, 5), Direction.UP);
|
||||
scene.world.showSection(util.select.fromTo(4, 1, 5, 4, 1, 3), Direction.DOWN);
|
||||
scene.idle(12);
|
||||
scene.world.setKineticSpeed(ejectorS, 32);
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(50)
|
||||
.attachKeyFrame()
|
||||
.text("Supply Rotational Force in order to charge it up")
|
||||
.pointAt(util.vector.topOf(4, 1, 3))
|
||||
.placeNearTarget();
|
||||
scene.idle(60);
|
||||
|
||||
ItemStack copperBlock = AllBlocks.COPPER_BLOCK.asStack();
|
||||
ItemStack copperIngot = AllItems.COPPER_INGOT.asStack();
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(ejectorPos)
|
||||
.add(0.5, 0, 0), Pointing.RIGHT).withItem(copperBlock), 30);
|
||||
scene.idle(7);
|
||||
scene.world.createItemOnBeltLike(ejectorPos, Direction.NORTH, copperBlock);
|
||||
scene.idle(20);
|
||||
scene.overlay.showText(50)
|
||||
.text("Items placed on the ejector cause it to trigger")
|
||||
.pointAt(util.vector.topOf(ejectorPos))
|
||||
.placeNearTarget();
|
||||
scene.idle(60);
|
||||
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.hideSection(targetS, Direction.SOUTH);
|
||||
scene.idle(15);
|
||||
scene.world.restoreBlocks(targetS);
|
||||
scene.world.showSection(targetS, Direction.SOUTH);
|
||||
scene.idle(10);
|
||||
scene.world.createItemOnBeltLike(targetPos, Direction.SOUTH, copperIngot);
|
||||
scene.idle(20);
|
||||
scene.world.createItemOnBeltLike(ejectorPos, Direction.SOUTH, copperBlock);
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.text("If Inventories are targeted, the ejector will wait until there is space")
|
||||
.pointAt(util.vector.topOf(targetPos))
|
||||
.placeNearTarget();
|
||||
scene.idle(70);
|
||||
scene.effects.indicateSuccess(targetPos);
|
||||
scene.world.removeItemsFromBelt(targetPos);
|
||||
scene.idle(40);
|
||||
scene.world.hideSection(targetS, Direction.NORTH);
|
||||
scene.idle(15);
|
||||
scene.world.setBlock(targetPos, AllBlocks.ANDESITE_CASING.getDefaultState(), false);
|
||||
scene.world.showSection(targetS, Direction.NORTH);
|
||||
|
||||
Vec3d input = util.vector.of(4.8, 1 + 12 / 16f, 2.5);
|
||||
Vec3d topOfSlot = input.add(0, 2 / 16f, 0);
|
||||
scene.overlay.showControls(new InputWindowElement(topOfSlot, Pointing.DOWN).scroll()
|
||||
.withWrench(), 60);
|
||||
scene.overlay.showFilterSlotInput(input, 80);
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.text("Using the Wrench, a required Stack Size can be configured")
|
||||
.pointAt(topOfSlot)
|
||||
.placeNearTarget();
|
||||
scene.world.modifyTileNBT(ejectorS, EjectorTileEntity.class, nbt -> {
|
||||
nbt.putInt("ScrollValue", 10);
|
||||
});
|
||||
scene.idle(90);
|
||||
|
||||
scene.world.showSection(util.select.fromTo(5, 1, 0, 4, 1, 1), Direction.DOWN);
|
||||
scene.world.showSection(util.select.position(5, 0, 1), Direction.UP);
|
||||
scene.idle(15);
|
||||
|
||||
BlockPos beltPos = util.grid.at(4, 1, 0);
|
||||
scene.world.createItemOnBeltLike(beltPos, Direction.UP, copperBlock);
|
||||
scene.overlay.showText(100)
|
||||
.text("It is now limited to this stack size, and only activates when its held stack reaches this amount")
|
||||
.pointAt(util.vector.topOf(ejectorPos))
|
||||
.placeNearTarget();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
scene.idle(20);
|
||||
scene.world.createItemOnBeltLike(beltPos, Direction.UP, copperBlock);
|
||||
}
|
||||
scene.idle(20);
|
||||
scene.world.createItemOnBeltLike(beltPos, Direction.UP, ItemHandlerHelper.copyStackWithSize(copperBlock, 15));
|
||||
scene.idle(80);
|
||||
|
||||
scene.world.hideSection(util.select.fromTo(5, 1, 0, 4, 1, 1), Direction.UP);
|
||||
scene.world.hideSection(util.select.position(5, 0, 1), Direction.DOWN);
|
||||
scene.idle(30);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
|
||||
scene.addKeyframe();
|
||||
ElementLink<ParrotElement> birb = scene.special.createBirb(util.vector.topOf(ejectorPos)
|
||||
.add(0, -3 / 16f, 0), ParrotElement.FlappyPose::new);
|
||||
scene.idle(15);
|
||||
scene.world.modifyTileEntity(ejectorPos, EjectorTileEntity.class, ejector -> ejector.activateDeferred());
|
||||
scene.special.moveParrot(birb, util.vector.of(-2, 3, 0), 5);
|
||||
scene.special.rotateParrot(birb, 0, 360 * 2, 0, 21);
|
||||
scene.idle(5);
|
||||
scene.special.moveParrot(birb, util.vector.of(-1, 0, 0), 3);
|
||||
scene.idle(3);
|
||||
scene.special.moveParrot(birb, util.vector.of(-0.75, -1, 0), 6);
|
||||
scene.idle(6);
|
||||
scene.special.moveParrot(birb, util.vector.of(-0.25, -2 + 3 / 16f, 0), 12);
|
||||
scene.idle(15);
|
||||
scene.special.changeBirbPose(birb, ParrotElement.FaceCursorPose::new);
|
||||
scene.overlay.showText(80)
|
||||
.text("Other Entities will always trigger an Ejector when stepping on it")
|
||||
.pointAt(util.vector.topOf(targetPos))
|
||||
.placeNearTarget();
|
||||
|
||||
}
|
||||
|
||||
public static void splitY(SceneBuilder scene, SceneBuildingUtil util) {
|
||||
scene.title("weighted_ejector_tunnel", "Splitting item stacks using Weighted Ejectors");
|
||||
scene.configureBasePlate(0, 0, 5);
|
||||
scene.world.showSection(util.select.layer(0), Direction.UP);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(4, 1, 5, 0, 1, 3), Direction.DOWN);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.position(2, 2, 3), Direction.DOWN);
|
||||
scene.idle(10);
|
||||
scene.world.showSection(util.select.position(2, 1, 2), Direction.SOUTH);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(4, 1, 2, 3, 1, 1), Direction.SOUTH);
|
||||
scene.world.showSection(util.select.fromTo(2, 1, 1, 2, 1, 0), Direction.SOUTH);
|
||||
scene.idle(10);
|
||||
|
||||
BlockPos ejectorPos = util.grid.at(2, 1, 2);
|
||||
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.text("Combined with Brass Tunnels, Ejectors can split item stacks by specific amounts")
|
||||
.pointAt(util.vector.topOf(ejectorPos))
|
||||
.placeNearTarget();
|
||||
scene.idle(90);
|
||||
|
||||
BlockPos tunnel = util.grid.at(2, 2, 3);
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(tunnel), Pointing.DOWN).scroll()
|
||||
.withWrench(), 70);
|
||||
scene.idle(10);
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(util.vector.topOf(tunnel), Pointing.UP).showing(AllIcons.I_TUNNEL_PREFER_NEAREST),
|
||||
60);
|
||||
scene.overlay.showCenteredScrollInput(tunnel, Direction.UP, 100);
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(100)
|
||||
.attachKeyFrame()
|
||||
.colored(PonderPalette.BLUE)
|
||||
.text("First, configure the Brass Tunnel to 'Prefer Nearest', in order to prioritize its side output")
|
||||
.pointAt(util.vector.topOf(tunnel))
|
||||
.placeNearTarget();
|
||||
scene.idle(110);
|
||||
|
||||
Vec3d input = util.vector.of(2.5, 1 + 12 / 16f, 2.8);
|
||||
Vec3d topOfSlot = input.add(0, 2 / 16f, 0);
|
||||
scene.overlay.showControls(new InputWindowElement(topOfSlot, Pointing.DOWN).scroll()
|
||||
.withWrench(), 60);
|
||||
scene.overlay.showFilterSlotInput(input, 80);
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.text("The Stack Size set on the Ejector now determines the amount to be split off")
|
||||
.pointAt(topOfSlot)
|
||||
.placeNearTarget();
|
||||
scene.world.modifyTileNBT(util.select.position(2, 1, 2), EjectorTileEntity.class, nbt -> {
|
||||
nbt.putInt("ScrollValue", 10);
|
||||
});
|
||||
scene.idle(90);
|
||||
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(util.grid.at(4, 1, 3)), Pointing.DOWN)
|
||||
.withItem(AllItems.COPPER_INGOT.asStack()), 20);
|
||||
scene.idle(7);
|
||||
scene.world.createItemOnBelt(util.grid.at(4, 1, 3), Direction.UP, AllItems.COPPER_INGOT.asStack(64));
|
||||
scene.idle(40);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), 1 / 16f);
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.text("While a new stack of the configured size exits the side output...")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(2, 1, 1), Direction.WEST))
|
||||
.placeNearTarget();
|
||||
scene.idle(90);
|
||||
scene.overlay.showText(80)
|
||||
.text("...the remainder will continue on its path")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(0, 1, 3), Direction.UP))
|
||||
.placeNearTarget();
|
||||
scene.idle(90);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), 16f);
|
||||
}
|
||||
|
||||
public static void redstone(SceneBuilder scene, SceneBuildingUtil util) {
|
||||
scene.title("weighted_ejector_redstone", "Controlling Weighted Ejectors with Redstone");
|
||||
scene.configureBasePlate(0, 0, 5);
|
||||
scene.world.showSection(util.select.layer(0), Direction.UP);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(4, 1, 3, 4, 1, 5), Direction.DOWN);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(0, 1, 2, 0, 2, 2), Direction.DOWN);
|
||||
scene.idle(10);
|
||||
scene.world.showSection(util.select.position(4, 1, 2), Direction.SOUTH);
|
||||
scene.idle(5);
|
||||
Selection redstone = util.select.fromTo(3, 1, 2, 2, 1, 2);
|
||||
scene.world.showSection(redstone, Direction.EAST);
|
||||
|
||||
BlockPos ejectorPos = util.grid.at(4, 1, 2);
|
||||
Vec3d topOf = util.vector.topOf(ejectorPos.up(2));
|
||||
ItemStack copper = AllItems.COPPER_INGOT.asStack();
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.world.createItemEntity(topOf, util.vector.of(0, 0.1, 0), copper);
|
||||
scene.idle(12);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.createItemOnBeltLike(ejectorPos, Direction.UP, copper);
|
||||
scene.idle(20);
|
||||
if (i == 1) {
|
||||
scene.world.toggleRedstonePower(redstone);
|
||||
scene.effects.indicateRedstone(util.grid.at(2, 1, 2));
|
||||
scene.world.modifyTileNBT(util.select.position(4, 1, 2), EjectorTileEntity.class,
|
||||
nbt -> nbt.putBoolean("Powered", true));
|
||||
}
|
||||
}
|
||||
|
||||
scene.idle(10);
|
||||
scene.overlay.showText(60)
|
||||
.colored(PonderPalette.RED)
|
||||
.attachKeyFrame()
|
||||
.pointAt(util.vector.topOf(ejectorPos))
|
||||
.placeNearTarget()
|
||||
.text("When powered by Redstone, Ejectors will not activate");
|
||||
scene.idle(70);
|
||||
|
||||
scene.world.toggleRedstonePower(redstone);
|
||||
scene.idle(2);
|
||||
scene.world.modifyTileNBT(util.select.position(4, 1, 2), EjectorTileEntity.class,
|
||||
nbt -> nbt.putBoolean("Powered", false));
|
||||
scene.idle(5);
|
||||
scene.world.hideSection(redstone, Direction.WEST);
|
||||
scene.idle(10);
|
||||
ElementLink<WorldSectionElement> observer =
|
||||
scene.world.showIndependentSection(util.select.position(4, 1, 1), Direction.SOUTH);
|
||||
scene.world.moveSection(observer, util.vector.of(0.5, 1.5, -0.5), 0);
|
||||
scene.world.rotateSection(observer, 0, 30 - 180, 0, 0);
|
||||
scene.idle(20);
|
||||
scene.world.moveSection(observer, util.vector.of(-0.5, -1.5, 0.5), 10);
|
||||
scene.world.rotateSection(observer, 0, -30 + 180, 0, 10);
|
||||
scene.world.showSection(util.select.position(4, 1, 0), Direction.SOUTH);
|
||||
|
||||
Selection observerRedstone = util.select.fromTo(4, 1, 1, 4, 1, 0);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
scene.world.createItemEntity(topOf, util.vector.of(0, 0.1, 0), copper);
|
||||
scene.idle(12);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.createItemOnBeltLike(ejectorPos, Direction.UP, copper);
|
||||
scene.idle(1);
|
||||
scene.world.toggleRedstonePower(observerRedstone);
|
||||
scene.effects.indicateRedstone(util.grid.at(4, 1, 1));
|
||||
scene.idle(3);
|
||||
scene.world.toggleRedstonePower(observerRedstone);
|
||||
scene.idle(16);
|
||||
if (i == 3)
|
||||
scene.markAsFinished();
|
||||
if (i == 1) {
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(4, 1, 1), Direction.NORTH))
|
||||
.placeNearTarget()
|
||||
.text("Furthermore, Observers can detect when Ejectors activate");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -96,6 +96,10 @@ public class PonderIndex {
|
|||
ProcessingScenes::emptyBlazeBurner);
|
||||
PonderRegistry.addStoryBoard(AllBlocks.BLAZE_BURNER, "blaze_burner", ProcessingScenes::blazeBurner);
|
||||
PonderRegistry.addStoryBoard(AllBlocks.DEPOT, "depot", BeltScenes::depot);
|
||||
PonderRegistry.forComponents(AllBlocks.WEIGHTED_EJECTOR)
|
||||
.addStoryBoard("weighted_ejector/eject", EjectorScenes::ejector)
|
||||
.addStoryBoard("weighted_ejector/split", EjectorScenes::splitY)
|
||||
.addStoryBoard("weighted_ejector/redstone", EjectorScenes::redstone);
|
||||
|
||||
// Crafters
|
||||
PonderRegistry.forComponents(AllBlocks.MECHANICAL_CRAFTER)
|
||||
|
@ -121,6 +125,12 @@ public class PonderIndex {
|
|||
.addStoryBoard("funnels/transposer", FunnelScenes::transposer);
|
||||
PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_FUNNEL, "funnels/brass", FunnelScenes::brass);
|
||||
|
||||
// Tunnels
|
||||
PonderRegistry.addStoryBoard(AllBlocks.ANDESITE_TUNNEL, "tunnels/andesite", TunnelScenes::andesite);
|
||||
PonderRegistry.forComponents(AllBlocks.BRASS_TUNNEL)
|
||||
.addStoryBoard("tunnels/brass", TunnelScenes::brass)
|
||||
.addStoryBoard("tunnels/brass_modes", TunnelScenes::brassModes);
|
||||
|
||||
// Chassis & Super Glue
|
||||
PonderRegistry.forComponents(AllBlocks.LINEAR_CHASSIS, AllBlocks.SECONDARY_LINEAR_CHASSIS)
|
||||
.addStoryBoard("chassis/linear_group", ChassisScenes::linearGroup, PonderTag.CONTRAPTION_ASSEMBLY)
|
||||
|
|
|
@ -0,0 +1,564 @@
|
|||
package com.simibubi.create.foundation.ponder.content;
|
||||
|
||||
import java.util.Vector;
|
||||
|
||||
import com.simibubi.create.AllItems;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity;
|
||||
import com.simibubi.create.foundation.gui.AllIcons;
|
||||
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.elements.InputWindowElement;
|
||||
import com.simibubi.create.foundation.ponder.elements.WorldSectionElement;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.SidedFilteringBehaviour;
|
||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.NBTHelper;
|
||||
import com.simibubi.create.foundation.utility.Pointing;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.ItemEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class TunnelScenes {
|
||||
|
||||
public static void andesite(SceneBuilder scene, SceneBuildingUtil util) {
|
||||
scene.title("andesite_tunnel", "Using Andesite Tunnels");
|
||||
scene.configureBasePlate(0, 0, 5);
|
||||
|
||||
scene.world.cycleBlockProperty(util.grid.at(2, 1, 2), BeltBlock.CASING);
|
||||
|
||||
scene.world.showSection(util.select.layer(0), Direction.UP);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(4, 1, 5, 4, 1, 3), Direction.DOWN);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(4, 1, 2, 0, 1, 2), Direction.SOUTH);
|
||||
scene.idle(10);
|
||||
|
||||
Vector<ElementLink<WorldSectionElement>> tunnels = new Vector<>(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
tunnels.add(scene.world.showIndependentSection(util.select.position(1 + i, 2, 4), Direction.DOWN));
|
||||
scene.world.moveSection(tunnels.get(i), util.vector.of(0, 0, -2), 0);
|
||||
scene.idle(4);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.world.cycleBlockProperty(util.grid.at(1 + i, 1, 2), BeltBlock.CASING);
|
||||
scene.world.modifyTileNBT(util.select.position(1 + i, 1, 2), BeltTileEntity.class,
|
||||
nbt -> NBTHelper.writeEnum(nbt, "Casing", BeltTileEntity.CasingType.ANDESITE), true);
|
||||
scene.idle(4);
|
||||
}
|
||||
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(util.vector.topOf(util.grid.at(1, 2, 2)))
|
||||
.placeNearTarget()
|
||||
.text("Andesite Tunnels can be used to cover up your belts");
|
||||
scene.idle(70);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.world.cycleBlockProperty(util.grid.at(1 + i, 1, 2), BeltBlock.CASING);
|
||||
scene.world.hideIndependentSection(tunnels.get(i), Direction.UP);
|
||||
scene.idle(4);
|
||||
}
|
||||
scene.idle(10);
|
||||
scene.world.showSection(util.select.fromTo(2, 1, 0, 0, 1, 1), Direction.SOUTH);
|
||||
scene.idle(10);
|
||||
scene.world.showSection(util.select.position(2, 2, 2), Direction.DOWN);
|
||||
scene.idle(10);
|
||||
scene.world.cycleBlockProperty(util.grid.at(2, 1, 2), BeltBlock.CASING);
|
||||
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH))
|
||||
.placeNearTarget()
|
||||
.text("Whenever an Andesite Tunnel has connections to the sides...");
|
||||
scene.idle(70);
|
||||
|
||||
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(util.grid.at(4, 1, 2)), Pointing.DOWN)
|
||||
.withItem(AllItems.COPPER_INGOT.asStack()), 20);
|
||||
scene.idle(7);
|
||||
scene.world.createItemOnBelt(util.grid.at(4, 1, 2), Direction.UP, AllItems.COPPER_INGOT.asStack(64));
|
||||
scene.idle(40);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), 1 / 16f);
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.text("...they will split exactly one item off of any passing stacks")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(2, 1, 0), Direction.WEST))
|
||||
.placeNearTarget();
|
||||
scene.idle(90);
|
||||
scene.overlay.showText(80)
|
||||
.text("The remainder will continue on its path")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(0, 1, 2), Direction.UP))
|
||||
.placeNearTarget();
|
||||
scene.idle(90);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), 16f);
|
||||
}
|
||||
|
||||
public static void brass(SceneBuilder scene, SceneBuildingUtil util) {
|
||||
scene.title("brass_tunnel", "Using Brass Tunnels");
|
||||
scene.configureBasePlate(1, 0, 5);
|
||||
scene.world.cycleBlockProperty(util.grid.at(3, 1, 2), BeltBlock.CASING);
|
||||
|
||||
scene.world.showSection(util.select.layer(0), Direction.UP);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(5, 1, 5, 5, 1, 3), Direction.DOWN);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(5, 1, 2, 1, 1, 2), Direction.SOUTH);
|
||||
scene.idle(10);
|
||||
|
||||
Vector<ElementLink<WorldSectionElement>> tunnels = new Vector<>(3);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
tunnels.add(scene.world.showIndependentSection(util.select.position(2 + i, 2, 4), Direction.DOWN));
|
||||
scene.world.moveSection(tunnels.get(i), util.vector.of(0, 0, -2), 0);
|
||||
scene.idle(4);
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.world.cycleBlockProperty(util.grid.at(2 + i, 1, 2), BeltBlock.CASING);
|
||||
scene.world.modifyTileNBT(util.select.position(2 + i, 1, 2), BeltTileEntity.class,
|
||||
nbt -> NBTHelper.writeEnum(nbt, "Casing", BeltTileEntity.CasingType.BRASS), true);
|
||||
scene.idle(4);
|
||||
}
|
||||
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(util.vector.topOf(util.grid.at(2, 2, 2)))
|
||||
.placeNearTarget()
|
||||
.text("Brass Tunnels can be used to cover up your belts");
|
||||
scene.idle(70);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.world.cycleBlockProperty(util.grid.at(2 + i, 1, 2), BeltBlock.CASING);
|
||||
scene.world.hideIndependentSection(tunnels.get(i), Direction.UP);
|
||||
scene.idle(4);
|
||||
}
|
||||
scene.idle(10);
|
||||
scene.world.showSection(util.select.fromTo(3, 1, 0, 1, 1, 1), Direction.SOUTH);
|
||||
scene.idle(10);
|
||||
scene.world.showSection(util.select.position(3, 2, 2), Direction.DOWN);
|
||||
scene.idle(10);
|
||||
scene.world.cycleBlockProperty(util.grid.at(3, 1, 2), BeltBlock.CASING);
|
||||
scene.idle(10);
|
||||
|
||||
BlockPos tunnelPos = util.grid.at(3, 2, 2);
|
||||
for (Direction d : Iterate.horizontalDirections) {
|
||||
if (d == Direction.SOUTH)
|
||||
continue;
|
||||
Vec3d filter = getTunnelFilterVec(tunnelPos, d);
|
||||
scene.overlay.showFilterSlotInput(filter, 40);
|
||||
scene.idle(3);
|
||||
}
|
||||
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(getTunnelFilterVec(tunnelPos, Direction.WEST))
|
||||
.placeNearTarget()
|
||||
.text("Brass Tunnels have filter slots on each open side");
|
||||
scene.idle(70);
|
||||
|
||||
scene.rotateCameraY(70);
|
||||
|
||||
scene.idle(20);
|
||||
Vec3d tunnelFilterVec = getTunnelFilterVec(tunnelPos, Direction.EAST);
|
||||
scene.overlay.showFilterSlotInput(tunnelFilterVec, 40);
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(tunnelFilterVec)
|
||||
.placeNearTarget()
|
||||
.text("Filters on inbound connections simply block non-matching items");
|
||||
ItemStack copper = AllItems.COPPER_INGOT.asStack();
|
||||
Class<BrassTunnelTileEntity> tunnelClass = BrassTunnelTileEntity.class;
|
||||
scene.world.modifyTileEntity(tunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.EAST, copper));
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelFilterVec, Pointing.DOWN).withItem(copper), 30);
|
||||
ItemStack zinc = AllItems.ZINC_INGOT.asStack();
|
||||
scene.world.createItemOnBelt(util.grid.at(5, 1, 2), Direction.EAST, zinc);
|
||||
scene.idle(70);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), -2);
|
||||
scene.idle(20);
|
||||
scene.rotateCameraY(-70);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), -.5f);
|
||||
scene.idle(20);
|
||||
scene.world.modifyTileEntity(tunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.EAST, ItemStack.EMPTY));
|
||||
|
||||
tunnelFilterVec = getTunnelFilterVec(tunnelPos, Direction.NORTH);
|
||||
scene.overlay.showFilterSlotInput(tunnelFilterVec, 40);
|
||||
tunnelFilterVec = getTunnelFilterVec(tunnelPos, Direction.WEST);
|
||||
scene.overlay.showFilterSlotInput(tunnelFilterVec, 40);
|
||||
scene.overlay.showText(60)
|
||||
.attachKeyFrame()
|
||||
.pointAt(tunnelFilterVec)
|
||||
.placeNearTarget()
|
||||
.text("Filters on outbound connections can be used to sort items by type");
|
||||
scene.idle(70);
|
||||
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelFilterVec, Pointing.LEFT).withItem(copper), 30);
|
||||
scene.world.modifyTileEntity(tunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.WEST, copper));
|
||||
scene.idle(4);
|
||||
tunnelFilterVec = getTunnelFilterVec(tunnelPos, Direction.NORTH);
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelFilterVec, Pointing.RIGHT).withItem(zinc), 30);
|
||||
scene.world.modifyTileEntity(tunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.NORTH, zinc));
|
||||
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), 1.5f);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
scene.world.createItemOnBelt(util.grid.at(5, 1, 2), Direction.EAST, i % 2 == 0 ? zinc : copper);
|
||||
scene.idle(12);
|
||||
}
|
||||
|
||||
scene.idle(30);
|
||||
scene.world.modifyTileEntity(tunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.NORTH, ItemStack.EMPTY));
|
||||
scene.world.modifyTileEntity(tunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.WEST, ItemStack.EMPTY));
|
||||
scene.idle(10);
|
||||
|
||||
Vec3d tunnelTop = util.vector.topOf(tunnelPos);
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelTop, Pointing.DOWN).scroll()
|
||||
.withWrench(), 80);
|
||||
scene.idle(7);
|
||||
scene.overlay.showCenteredScrollInput(tunnelPos, Direction.UP, 120);
|
||||
scene.overlay.showText(120)
|
||||
.attachKeyFrame()
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget()
|
||||
.text(
|
||||
"Whenever a passing item has multiple valid exits, the distribution mode will decide how to handle it");
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.idle(40);
|
||||
scene.world.createItemOnBelt(util.grid.at(5, 1, 2), Direction.EAST, AllItems.BRASS_INGOT.asStack(63));
|
||||
}
|
||||
scene.idle(30);
|
||||
|
||||
scene.world.hideSection(util.select.position(3, 2, 2), Direction.UP);
|
||||
scene.idle(5);
|
||||
scene.world.hideSection(util.select.fromTo(5, 1, 2, 1, 1, 0), Direction.UP);
|
||||
scene.idle(15);
|
||||
|
||||
ElementLink<WorldSectionElement> newBelt =
|
||||
scene.world.showIndependentSection(util.select.fromTo(3, 3, 2, 0, 3, 4)
|
||||
.add(util.select.fromTo(5, 3, 3, 4, 3, 3)), Direction.DOWN);
|
||||
scene.world.moveSection(newBelt, util.vector.of(0, -2, -1), 0);
|
||||
scene.idle(15);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.idle(4);
|
||||
scene.world.showSectionAndMerge(util.select.position(3, 4, 2 + i), Direction.DOWN, newBelt);
|
||||
}
|
||||
|
||||
scene.overlay.showSelectionWithText(util.select.fromTo(3, 1, 1, 3, 2, 3), 80)
|
||||
.attachKeyFrame()
|
||||
.placeNearTarget()
|
||||
.text("Brass Tunnels on parallel belts will form a group");
|
||||
scene.idle(90);
|
||||
|
||||
ItemStack item1 = new ItemStack(Items.CARROT);
|
||||
ItemStack item2 = new ItemStack(Items.field_226638_pX_);
|
||||
ItemStack item3 = new ItemStack(Items.SWEET_BERRIES);
|
||||
|
||||
tunnelFilterVec = getTunnelFilterVec(tunnelPos, Direction.WEST);
|
||||
BlockPos newTunnelPos = tunnelPos.up(2)
|
||||
.south();
|
||||
scene.overlay
|
||||
.showControls(new InputWindowElement(tunnelFilterVec.add(0, 0, -1), Pointing.RIGHT).withItem(item1), 20);
|
||||
scene.world.modifyTileEntity(newTunnelPos.north(), tunnelClass,
|
||||
te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.WEST, item1));
|
||||
scene.idle(4);
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelFilterVec, Pointing.DOWN).withItem(item2), 20);
|
||||
scene.world.modifyTileEntity(newTunnelPos, tunnelClass, te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.WEST, item2));
|
||||
scene.idle(4);
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelFilterVec.add(0, 0, 1), Pointing.LEFT).withItem(item3),
|
||||
20);
|
||||
scene.world.modifyTileEntity(newTunnelPos.south(), tunnelClass,
|
||||
te -> te.getBehaviour(SidedFilteringBehaviour.TYPE)
|
||||
.setFilter(Direction.WEST, item3));
|
||||
scene.idle(30);
|
||||
|
||||
scene.overlay.showText(80)
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget()
|
||||
.text("Incoming Items will now be distributed across all connected exits");
|
||||
scene.idle(90);
|
||||
|
||||
BlockPos beltPos = util.grid.at(5, 3, 3);
|
||||
Vec3d m = util.vector.of(0, 0.1, 0);
|
||||
Vec3d spawn = util.vector.centerOf(util.grid.at(5, 3, 2));
|
||||
scene.world.createItemEntity(spawn, m, item1);
|
||||
scene.idle(12);
|
||||
scene.world.createItemOnBelt(beltPos, Direction.UP, item1);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.createItemEntity(spawn, m, item2);
|
||||
scene.idle(12);
|
||||
scene.world.createItemOnBelt(beltPos, Direction.UP, item2);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.createItemEntity(spawn, m, item3);
|
||||
scene.idle(12);
|
||||
scene.world.createItemOnBelt(beltPos, Direction.UP, item3);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.idle(50);
|
||||
|
||||
scene.world.showSectionAndMerge(util.select.position(3, 5, 2), Direction.DOWN, newBelt);
|
||||
|
||||
scene.overlay.showText(80)
|
||||
.pointAt(util.vector.blockSurface(tunnelPos.up()
|
||||
.north(), Direction.WEST))
|
||||
.placeNearTarget()
|
||||
.text("For this, items can also be inserted into the Tunnel block directly");
|
||||
scene.idle(20);
|
||||
|
||||
beltPos = util.grid.at(3, 3, 3);
|
||||
spawn = util.vector.centerOf(util.grid.at(3, 5, 1));
|
||||
scene.world.createItemEntity(spawn, m, item1);
|
||||
scene.idle(12);
|
||||
scene.world.createItemOnBelt(beltPos, Direction.EAST, item1);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.createItemEntity(spawn, m, item2);
|
||||
scene.idle(12);
|
||||
scene.world.createItemOnBelt(beltPos, Direction.EAST, item2);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.world.createItemEntity(spawn, m, item3);
|
||||
scene.idle(12);
|
||||
scene.world.createItemOnBelt(beltPos, Direction.EAST, item3);
|
||||
scene.world.modifyEntities(ItemEntity.class, Entity::remove);
|
||||
scene.idle(30);
|
||||
|
||||
}
|
||||
|
||||
protected static Vec3d getTunnelFilterVec(BlockPos pos, Direction d) {
|
||||
return VecHelper.getCenterOf(pos)
|
||||
.add(new Vec3d(d.getDirectionVec()).scale(.5))
|
||||
.add(0, 0.3, 0);
|
||||
}
|
||||
|
||||
public static void brassModes(SceneBuilder scene, SceneBuildingUtil util) {
|
||||
scene.title("brass_tunnel_modes", "Distribution Modes of the Brass Tunnel");
|
||||
scene.configureBasePlate(0, 1, 5);
|
||||
BlockState barrier = Blocks.BARRIER.getDefaultState();
|
||||
scene.world.setBlock(util.grid.at(1, 1, 0), barrier, false);
|
||||
scene.world.showSection(util.select.layer(0), Direction.UP);
|
||||
scene.idle(5);
|
||||
scene.world.showSection(util.select.fromTo(1, 1, 1, 5, 1, 5)
|
||||
.add(util.select.fromTo(3, 2, 5, 1, 2, 5)), Direction.DOWN);
|
||||
scene.idle(10);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
scene.world.showSection(util.select.position(3 - i, 2, 3), Direction.DOWN);
|
||||
scene.idle(4);
|
||||
}
|
||||
|
||||
Vec3d tunnelTop = util.vector.topOf(util.grid.at(2, 2, 3));
|
||||
scene.overlay.showControls(new InputWindowElement(tunnelTop, Pointing.DOWN).scroll()
|
||||
.withWrench(), 80);
|
||||
scene.idle(7);
|
||||
scene.overlay.showCenteredScrollInput(util.grid.at(2, 2, 3), Direction.UP, 120);
|
||||
scene.overlay.showText(120)
|
||||
.attachKeyFrame()
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget()
|
||||
.text("Using a Wrench, the distribution behaviour of Brass Tunnels can be configured");
|
||||
scene.idle(130);
|
||||
|
||||
Class<BrassTunnelTileEntity> tunnelClass = BrassTunnelTileEntity.class;
|
||||
ElementLink<WorldSectionElement> blockage =
|
||||
scene.world.showIndependentSection(util.select.position(4, 1, 0), Direction.UP);
|
||||
scene.world.moveSection(blockage, util.vector.of(-3, 0, 0), 0);
|
||||
|
||||
Vec3d modeVec = util.vector.of(4, 2.5, 3);
|
||||
scene.overlay.showControls(new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_SPLIT),
|
||||
140);
|
||||
|
||||
ElementLink<WorldSectionElement> blockage2 = null;
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (i < 30)
|
||||
scene.world.createItemOnBelt(util.grid.at(1, 1, 5), Direction.EAST, new ItemStack(Items.SNOWBALL, 12));
|
||||
scene.idle(i > 8 ? 30 : 40);
|
||||
|
||||
if (i == 0) {
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget()
|
||||
.text("'Split' will attempt to distribute the stack evenly between available outputs");
|
||||
}
|
||||
|
||||
if (i == 2) {
|
||||
scene.overlay.showText(60)
|
||||
.text("If an output is unable to take more items, it will be skipped")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
|
||||
.placeNearTarget()
|
||||
.colored(PonderPalette.GREEN);
|
||||
}
|
||||
|
||||
if (i == 4) {
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_FORCED_SPLIT), 140);
|
||||
scene.world.modifyTileEntity(util.grid.at(1, 2, 3), tunnelClass,
|
||||
te -> te.getBehaviour(ScrollOptionBehaviour.TYPE)
|
||||
.setValue(BrassTunnelTileEntity.SelectionMode.FORCED_SPLIT.ordinal()));
|
||||
}
|
||||
|
||||
if (i == 5) {
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.text("'Forced Split' will never skip outputs, and instead wait until they are free")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
|
||||
.placeNearTarget()
|
||||
.colored(PonderPalette.RED);
|
||||
scene.idle(60);
|
||||
scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 10);
|
||||
scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.getDefaultState(), false);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), 1.5f);
|
||||
}
|
||||
|
||||
if (i == 7) {
|
||||
scene.world.modifyTileEntity(util.grid.at(1, 2, 3), tunnelClass,
|
||||
te -> te.getBehaviour(ScrollOptionBehaviour.TYPE)
|
||||
.setValue(BrassTunnelTileEntity.SelectionMode.ROUND_ROBIN.ordinal()));
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_ROUND_ROBIN), 140);
|
||||
scene.overlay.showText(80)
|
||||
.attachKeyFrame()
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget()
|
||||
.text("'Round Robin' keeps stacks whole, and cycles through outputs iteratively");
|
||||
}
|
||||
|
||||
if (i == 7) {
|
||||
scene.world.moveSection(blockage, util.vector.of(1, 0, 0), 10);
|
||||
scene.world.setBlock(util.grid.at(1, 1, 0), barrier, false);
|
||||
}
|
||||
|
||||
if (i == 13) {
|
||||
scene.overlay.showText(60)
|
||||
.text("Once Again, if an output is unable to take more items, it will be skipped")
|
||||
.placeNearTarget()
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
|
||||
.colored(PonderPalette.GREEN);
|
||||
}
|
||||
|
||||
if (i == 15) {
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_FORCED_ROUND_ROBIN), 140);
|
||||
scene.world.modifyTileEntity(util.grid.at(1, 2, 3), tunnelClass,
|
||||
te -> te.getBehaviour(ScrollOptionBehaviour.TYPE)
|
||||
.setValue(BrassTunnelTileEntity.SelectionMode.FORCED_ROUND_ROBIN.ordinal()));
|
||||
}
|
||||
|
||||
if (i == 16) {
|
||||
scene.overlay.showText(50)
|
||||
.attachKeyFrame()
|
||||
.placeNearTarget()
|
||||
.text("'Forced Round Robin' never skips outputs")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
|
||||
.colored(PonderPalette.RED);
|
||||
scene.idle(30);
|
||||
scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 10);
|
||||
scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.getDefaultState(), false);
|
||||
}
|
||||
|
||||
if (i == 19) {
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_PREFER_NEAREST), 140);
|
||||
scene.world.modifyTileEntity(util.grid.at(1, 2, 3), tunnelClass,
|
||||
te -> te.getBehaviour(ScrollOptionBehaviour.TYPE)
|
||||
.setValue(BrassTunnelTileEntity.SelectionMode.PREFER_NEAREST.ordinal()));
|
||||
scene.world.moveSection(blockage, util.vector.of(1, 0, 0), 10);
|
||||
scene.world.setBlock(util.grid.at(1, 1, 0), barrier, false);
|
||||
scene.overlay.showText(70)
|
||||
.attachKeyFrame()
|
||||
.text("'Prefer Nearest' prioritizes the outputs closest to the items' input location")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
|
||||
.placeNearTarget()
|
||||
.colored(PonderPalette.GREEN);
|
||||
}
|
||||
|
||||
if (i == 21) {
|
||||
scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.BARRIER.getDefaultState(), false);
|
||||
blockage2 = scene.world.showIndependentSection(util.select.position(4, 1, 0), Direction.UP);
|
||||
scene.world.moveSection(blockage2, util.vector.of(-2, 0, 0), 0);
|
||||
}
|
||||
|
||||
if (i == 25) {
|
||||
scene.world.hideIndependentSection(blockage, Direction.DOWN);
|
||||
scene.world.setBlock(util.grid.at(1, 1, 0), Blocks.AIR.getDefaultState(), false);
|
||||
scene.world.hideIndependentSection(blockage2, Direction.DOWN);
|
||||
scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.AIR.getDefaultState(), false);
|
||||
}
|
||||
|
||||
if (i == 26) {
|
||||
scene.overlay.showControls(
|
||||
new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_RANDOMIZE), 140);
|
||||
scene.world.modifyTileEntity(util.grid.at(1, 2, 3), tunnelClass,
|
||||
te -> te.getBehaviour(ScrollOptionBehaviour.TYPE)
|
||||
.setValue(BrassTunnelTileEntity.SelectionMode.RANDOMIZE.ordinal()));
|
||||
}
|
||||
|
||||
if (i == 27) {
|
||||
scene.overlay.showText(70)
|
||||
.attachKeyFrame()
|
||||
.text("'Randomize' will distribute whole stacks to randomly picked outputs")
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget();
|
||||
}
|
||||
}
|
||||
|
||||
scene.world.hideSection(util.select.fromTo(3, 2, 5, 1, 2, 5), Direction.UP);
|
||||
scene.idle(10);
|
||||
scene.overlay
|
||||
.showControls(new InputWindowElement(modeVec, Pointing.RIGHT).showing(AllIcons.I_TUNNEL_SYNCHRONIZE), 140);
|
||||
scene.world.modifyTileEntity(util.grid.at(1, 2, 3), tunnelClass,
|
||||
te -> te.getBehaviour(ScrollOptionBehaviour.TYPE)
|
||||
.setValue(BrassTunnelTileEntity.SelectionMode.SYNCHRONIZE.ordinal()));
|
||||
scene.idle(30);
|
||||
scene.overlay.showText(70)
|
||||
.attachKeyFrame()
|
||||
.text("'Synchronize Inputs' is a unique setting for Brass Tunnels")
|
||||
.pointAt(tunnelTop)
|
||||
.placeNearTarget();
|
||||
|
||||
ItemStack item1 = new ItemStack(Items.CARROT);
|
||||
ItemStack item2 = new ItemStack(Items.field_226638_pX_);
|
||||
ItemStack item3 = AllItems.POLISHED_ROSE_QUARTZ.asStack();
|
||||
|
||||
scene.world.createItemOnBelt(util.grid.at(3, 1, 4), Direction.UP, item1);
|
||||
scene.world.createItemOnBelt(util.grid.at(2, 1, 4), Direction.UP, item2);
|
||||
scene.world.createItemOnBelt(util.grid.at(3, 1, 5), Direction.SOUTH, item1);
|
||||
scene.world.createItemOnBelt(util.grid.at(2, 1, 5), Direction.SOUTH, item2);
|
||||
|
||||
scene.idle(80);
|
||||
scene.world.createItemOnBelt(util.grid.at(2, 1, 5), Direction.SOUTH, item2);
|
||||
scene.rotateCameraY(-90);
|
||||
scene.idle(20);
|
||||
scene.world.multiplyKineticSpeed(util.select.everywhere(), .5f);
|
||||
|
||||
scene.overlay.showText(70)
|
||||
.text("Items are only allowed past if every tunnel in the group has one waiting")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(2, 1, 4), Direction.UP))
|
||||
.placeNearTarget()
|
||||
.colored(PonderPalette.OUTPUT);
|
||||
scene.idle(60);
|
||||
scene.world.createItemOnBelt(util.grid.at(1, 1, 5), Direction.SOUTH, item3);
|
||||
scene.idle(90);
|
||||
scene.rotateCameraY(90);
|
||||
|
||||
scene.overlay.showText(100)
|
||||
.text("This ensures that all affected belts supply items at the same rate")
|
||||
.pointAt(util.vector.blockSurface(util.grid.at(1, 2, 3), Direction.WEST))
|
||||
.placeNearTarget()
|
||||
.colored(PonderPalette.GREEN);
|
||||
}
|
||||
|
||||
}
|
|
@ -58,6 +58,11 @@ public class InputWindowElement extends AnimatedOverlayElement {
|
|||
return this;
|
||||
}
|
||||
|
||||
public InputWindowElement showing(AllIcons icon) {
|
||||
this.icon = icon;
|
||||
return this;
|
||||
}
|
||||
|
||||
public InputWindowElement leftClick() {
|
||||
icon = AllIcons.I_LMB;
|
||||
return this;
|
||||
|
|
BIN
src/main/resources/ponder/tunnels/andesite.nbt
Normal file
BIN
src/main/resources/ponder/tunnels/andesite.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/ponder/tunnels/brass.nbt
Normal file
BIN
src/main/resources/ponder/tunnels/brass.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/ponder/tunnels/brass_modes.nbt
Normal file
BIN
src/main/resources/ponder/tunnels/brass_modes.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/ponder/weighted_ejector/eject.nbt
Normal file
BIN
src/main/resources/ponder/weighted_ejector/eject.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/ponder/weighted_ejector/redstone.nbt
Normal file
BIN
src/main/resources/ponder/weighted_ejector/redstone.nbt
Normal file
Binary file not shown.
BIN
src/main/resources/ponder/weighted_ejector/split.nbt
Normal file
BIN
src/main/resources/ponder/weighted_ejector/split.nbt
Normal file
Binary file not shown.
Loading…
Reference in a new issue