Will ponders ever cease?

- New ponder scenes for Smart Observer, Threshold Switch, Elevator Pulley, Contraption Controls and Mechanical Rollers
- Added #contraption_controlled as a tag for items accepted by the contraption controls slot
This commit is contained in:
simibubi 2023-05-06 02:58:47 +02:00
parent 9f2c511647
commit 0abbeaebad
55 changed files with 2006 additions and 360 deletions

View file

@ -579,7 +579,7 @@ bf2b0310500213ff853c748c236eb5d01f61658e assets/create/blockstates/yellow_toolbo
7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json
b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json
b04b22fd6e7941c2b2559fbb4e28f31cf54657af assets/create/lang/en_ud.json
a4e2558314ebba2f5ff3b121672ed3f8f57b0278 assets/create/lang/en_us.json
9489a13cafb96d2c968ea47185d12f959ccb4c02 assets/create/lang/en_us.json
487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json
b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json
3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json
@ -5317,6 +5317,7 @@ a8bdc387cfa6296ebcc4af14323e2ddb632234dc data/create/tags/fluids/bottomless/allo
74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/items/blaze_burner_fuel/regular.json
97061ef67cac1fafd869493d06115b968bcb99bf data/create/tags/items/blaze_burner_fuel/special.json
d99d5c67bdffff60789a19bd51a5c5267c75e0a4 data/create/tags/items/casing.json
f450961313b78ba24b2cc8cc83e2c5a2886a9695 data/create/tags/items/contraption_controlled.json
c98ffdc2780c2a7690c590f46f014aeee7b0b504 data/create/tags/items/create_ingots.json
4480f211f4a37bfee193eba945bc9f5a8d2c6e34 data/create/tags/items/crushed_ores.json
49847bfbea11808b5101c972023a7f5833fe5a14 data/create/tags/items/deployable_drink.json

View file

@ -1660,8 +1660,8 @@
"create.train_assembly.bogeys_too_close": "Bogeys %1$s and %2$s are too close to each other",
"create.train_assembly.single_bogey_carriage": "This Bogey type cannot support a carriage on its own",
"create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "A mounted controls block is facing sideways",
"create.train_assembly.no_controls": "Attach at least one forward-facing Train Controls block (Are you missing Super Glue?)",
"create.train_assembly.sideways_controls": "Train Controls cannot face sideways",
"create.train_assembly.bogey_created": "Bogey created. Click again to cycle type",
"create.train_assembly.requires_casing": "Use Railway Casing to create bogeys on tracks",
@ -2379,6 +2379,14 @@
"create.ponder.cogwheel_casing.text_2": "Components added after encasing will not connect to the shaft outputs",
"create.ponder.cogwheel_casing.text_3": "The Wrench can be used to toggle connections",
"create.ponder.contraption_controls.header": "Using Contraption Controls",
"create.ponder.contraption_controls.text_1": "Actors on moving contraptions are always active by default",
"create.ponder.contraption_controls.text_2": "Contraption Controls can be used to toggle them on the fly",
"create.ponder.contraption_controls.text_3": "They can be attached anywhere on the contraption",
"create.ponder.contraption_controls.text_4": "While disassembled, the filter can be changed to target specific types of actors",
"create.ponder.contraption_controls.text_5": "If it is redstone-activated during assembly...",
"create.ponder.contraption_controls.text_6": "...targeted actors will be turned off from the start",
"create.ponder.creative_fluid_tank.header": "Creative Fluid Tanks",
"create.ponder.creative_fluid_tank.text_1": "Creative Fluid Tanks can be used to provide a bottomless supply of fluid",
"create.ponder.creative_fluid_tank.text_2": "Right-Click with a fluid containing item to configure it",
@ -2463,6 +2471,31 @@
"create.ponder.display_link_redstone.text_2": "Once unpowered, the Timer is reset and new info is sent immediately",
"create.ponder.display_link_redstone.text_3": "Signals emitted from the source do not affect the Link",
"create.ponder.elevator_pulley.header": "Using the Elevator Pulley",
"create.ponder.elevator_pulley.text_1": "Elevator Pulleys can move structures vertically between marked locations",
"create.ponder.elevator_pulley.text_10": "Any redstone contact sharing this column will be converted",
"create.ponder.elevator_pulley.text_11": "Supply a redstone pulse to call the elevator to the contact",
"create.ponder.elevator_pulley.text_12": "The movement speed depends on the rotation input on the pulley",
"create.ponder.elevator_pulley.text_13": "Scroll and click on the controls block to choose a floor while on-board",
"create.ponder.elevator_pulley.text_14": "Right-Clicking the assembled pulley will turn the cabin back into blocks",
"create.ponder.elevator_pulley.text_15": "Sliding doors attached to the cabin will open and close automatically",
"create.ponder.elevator_pulley.text_16": "Elevator Contacts emit a signal while the cabin is on their floor",
"create.ponder.elevator_pulley.text_17": "This can be useful to trigger doors or special effects upon arrival",
"create.ponder.elevator_pulley.text_18": "Display Links on any of the contacts can show the current floor of the elevator",
"create.ponder.elevator_pulley.text_2": "Start by constructing a cabin",
"create.ponder.elevator_pulley.text_3": "Place a pair of Redstone Contacts facing each other...",
"create.ponder.elevator_pulley.text_4": "...and glue one of them to your moving structure",
"create.ponder.elevator_pulley.text_5": "Contraption Controls can be attached to make floor selection easier",
"create.ponder.elevator_pulley.text_6": "Ensure that the pulley is supplied with Rotational Power",
"create.ponder.elevator_pulley.text_7": "Right-Clicking the pulley assembles the elevator",
"create.ponder.elevator_pulley.text_8": "The stationary contact now turns into an Elevator Contact",
"create.ponder.elevator_pulley.text_9": "Elevator Contacts represent a 'floor' and can be configured",
"create.ponder.elevator_pulley_multi_rope.header": "Synchronised Pulley Movement",
"create.ponder.elevator_pulley_multi_rope.text_1": "Whenever a pulley assembles a contraption...",
"create.ponder.elevator_pulley_multi_rope.text_2": "...other pulleys on the same layer will connect to the structure",
"create.ponder.elevator_pulley_multi_rope.text_3": "They do not require to be powered, the effect is purely cosmetic",
"create.ponder.empty_blaze_burner.header": "Using Empty Blaze Burners",
"create.ponder.empty_blaze_burner.text_1": "Right-click a Blaze with the empty burner to capture it",
"create.ponder.empty_blaze_burner.text_2": "Alternatively, Blazes can be collected from their Spawners directly",
@ -2764,6 +2797,22 @@
"create.ponder.mechanical_pump_speed.text_4": "Pumps can combine their throughputs within shared pipe networks",
"create.ponder.mechanical_pump_speed.text_5": "Ensure that all of them are facing in the same direction",
"create.ponder.mechanical_roller_fill.header": "Filling terrain with the Roller",
"create.ponder.mechanical_roller_fill.text_1": "While disassembled, rollers can be set to other modes",
"create.ponder.mechanical_roller_fill.text_2": "The 'fill' modes can help to bridge gaps between pavement and terrain",
"create.ponder.mechanical_roller_fill.text_3": "On 'straight fill', they will place simple columns down to the surface",
"create.ponder.mechanical_roller_fill.text_4": "On 'sloped fill', layers placed further down will increase in size",
"create.ponder.mechanical_roller_fill.text_5": "As opposed to 'clear & pave', neither of these modes will cause the rollers to break existing blocks",
"create.ponder.mechanical_roller_pave.header": "Clearing and Paving with the Roller",
"create.ponder.mechanical_roller_pave.text_1": "Mechanical rollers help to clean up long tracks or paths conveniently",
"create.ponder.mechanical_roller_pave.text_2": "In its default mode, without a material set, it will simply clear blocks like a Drill",
"create.ponder.mechanical_roller_pave.text_3": "While disassembled, a suitable paving material can be specified",
"create.ponder.mechanical_roller_pave.text_4": "Materials can be supplied via chests or barrels attached to the structure",
"create.ponder.mechanical_roller_pave.text_5": "In addition to breaking blocks, it will now replace the layer beneath them",
"create.ponder.mechanical_roller_pave.text_6": "Note that any block destroyed by a roller has a chance not to yield drops",
"create.ponder.mechanical_roller_pave.text_7": "Rollers are especially useful on Trains, but can also be used on most other types of moving contraptions",
"create.ponder.mechanical_saw_breaker.header": "Cutting Trees with the Mechanical Saw",
"create.ponder.mechanical_saw_breaker.text_1": "When given Rotational Force, a Mechanical Saw will cut trees directly in front of it",
"create.ponder.mechanical_saw_breaker.text_2": "In order to cut the tree fully, the Saw has to break the last block connecting it to the ground",
@ -2878,6 +2927,11 @@
"create.ponder.rope_pulley_modes.text_1": "Whenever Pulleys stop moving, the moved structure reverts to blocks",
"create.ponder.rope_pulley_modes.text_2": "It can be configured never to revert to solid blocks, or only at the location it started at",
"create.ponder.rope_pulley_multi_rope.header": "Synchronised Pulley Movement",
"create.ponder.rope_pulley_multi_rope.text_1": "Whenever a pulley assembles a contraption...",
"create.ponder.rope_pulley_multi_rope.text_2": "...other pulleys on the same layer will connect to the structure",
"create.ponder.rope_pulley_multi_rope.text_3": "They do not require to be powered, the effect is purely cosmetic",
"create.ponder.rose_quartz_lamp.header": "Rose Quartz Lamps",
"create.ponder.rose_quartz_lamp.text_1": "Rose Quartz Lamps activate on a Redstone signal",
"create.ponder.rose_quartz_lamp.text_2": "They will continue to emit redstone power afterwards",
@ -2919,6 +2973,14 @@
"create.ponder.smart_chute.text_3": "Use the value panel to specify the extracted stack size",
"create.ponder.smart_chute.text_4": "Redstone power will prevent Smart Chutes from acting.",
"create.ponder.smart_observer.header": "Advanced detection with Smart Observers",
"create.ponder.smart_observer.text_1": "Smart Observers can be used detect a variety of events",
"create.ponder.smart_observer.text_2": "It can detect items or fluids inside of generic containers",
"create.ponder.smart_observer.text_3": "The filter slot can be used to look for specific contents only",
"create.ponder.smart_observer.text_4": "It also activates when the block itself matches the filter",
"create.ponder.smart_observer.text_5": "Additionally, smart observers can monitor belts, chutes and pipes",
"create.ponder.smart_observer.text_6": "...and will emit a pulse, if an item enters or exits a funnel",
"create.ponder.smart_pipe.header": "Controlling Fluid flow using Smart Pipes",
"create.ponder.smart_pipe.text_1": "Smart pipes can help control flows by fluid type",
"create.ponder.smart_pipe.text_2": "When placed directly at the source, they can specify the type of fluid to extract",
@ -2986,6 +3048,17 @@
"create.ponder.super_glue.text_5": "Overlapping glue volumes will move together",
"create.ponder.super_glue.text_6": "Blocks hanging on others usually do not require glue",
"create.ponder.threshold_switch.header": "Monitoring with the Threshold Switch",
"create.ponder.threshold_switch.text_1": "Threshold Switches monitor the fill level of containers",
"create.ponder.threshold_switch.text_2": "When the inventory content exceeds the upper threshold...",
"create.ponder.threshold_switch.text_3": "...the switch will change its redstone output",
"create.ponder.threshold_switch.text_4": "The signal stays until the lower threshold is reached",
"create.ponder.threshold_switch.text_5": "The redstone output can now be used to control item supply, keeping the buffer filled",
"create.ponder.threshold_switch.text_6": "The specific thresholds can be changed in the UI",
"create.ponder.threshold_switch.text_7": "A filter can help to only count specific contents toward the total",
"create.ponder.threshold_switch.text_8": "Fluid buffers can be monitored in a similar fashion",
"create.ponder.threshold_switch.text_9": "...as well as, curiously, the length of an extended rope pulley",
"create.ponder.track_chunks.header": "Traversing unloaded Chunks",
"create.ponder.track_chunks.text_1": "Tracks stay functional outside of loaded chunks",
"create.ponder.track_chunks.text_2": "Trains will travel through inactive sections of the world without issue",

View file

@ -0,0 +1,25 @@
{
"replace": false,
"values": [
"create:portable_fluid_interface",
"create:mechanical_drill",
"create:mechanical_saw",
"create:deployer",
"create:portable_storage_interface",
"create:redstone_contact",
"create:mechanical_harvester",
"create:mechanical_plough",
"create:mechanical_roller",
"create:train_door",
"create:framed_glass_door",
"create:andesite_funnel",
"create:brass_funnel",
"create:peculiar_bell",
"create:haunted_bell",
"minecraft:bell",
"minecraft:campfire",
"minecraft:soul_campfire",
"minecraft:dispenser",
"minecraft:dropper"
]
}

View file

@ -1023,6 +1023,7 @@ public class AllBlocks {
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(movementBehaviour(new PortableStorageInterfaceMovement()))
.item()
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1310,6 +1311,7 @@ public class AllBlocks {
.transform(BlockStressDefaults.setImpact(4.0))
.onRegister(movementBehaviour(new DrillMovementBehaviour()))
.item()
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1323,6 +1325,7 @@ public class AllBlocks {
.onRegister(movementBehaviour(new SawMovementBehaviour()))
.addLayer(() -> RenderType::cutoutMipped)
.item()
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1335,6 +1338,7 @@ public class AllBlocks {
.onRegister(movementBehaviour(new DeployerMovementBehaviour()))
.onRegister(interactionBehaviour(new DeployerMovingInteraction()))
.item(AssemblyOperatorBlockItem::new)
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1346,6 +1350,7 @@ public class AllBlocks {
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.partialBaseModel(c, p)))
.onRegister(movementBehaviour(new PortableStorageInterfaceMovement()))
.item()
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1357,6 +1362,7 @@ public class AllBlocks {
.onRegister(movementBehaviour(new ContactMovementBehaviour()))
.blockstate((c, p) -> p.directionalBlock(c.get(), AssetLookup.forPowered(c, p)))
.item(RedstoneContactItem::new)
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel("_", "block"))
.register();
@ -1387,6 +1393,7 @@ public class AllBlocks {
.blockstate(BlockStateGen.horizontalBlockProvider(true))
.addLayer(() -> RenderType::cutoutMipped)
.item()
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1397,7 +1404,9 @@ public class AllBlocks {
.transform(axeOrPickaxe())
.onRegister(movementBehaviour(new PloughMovementBehaviour()))
.blockstate(BlockStateGen.horizontalBlockProvider(false))
.simpleItem()
.item()
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.build()
.register();
public static final BlockEntry<RollerBlock> MECHANICAL_ROLLER =
@ -1410,6 +1419,7 @@ public class AllBlocks {
.blockstate(BlockStateGen.horizontalBlockProvider(true))
.addLayer(() -> RenderType::cutoutMipped)
.item(RollerBlockItem::new)
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.transform(customItemModel())
.register();
@ -1759,6 +1769,7 @@ public class AllBlocks {
.onRegister(movementBehaviour(FunnelMovementBehaviour.andesite()))
.blockstate(new FunnelGenerator("andesite", false)::generate)
.item(FunnelItem::new)
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.model(FunnelGenerator.itemModel("andesite"))
.build()
.register();
@ -1784,6 +1795,7 @@ public class AllBlocks {
.onRegister(movementBehaviour(FunnelMovementBehaviour.brass()))
.blockstate(new FunnelGenerator("brass", true)::generate)
.item(FunnelItem::new)
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.model(FunnelGenerator.itemModel("brass"))
.build()
.register();

View file

@ -60,6 +60,7 @@ public class AllMovementBehaviours {
static void registerDefaults() {
registerBehaviour(Blocks.BELL, new BellMovementBehaviour());
registerBehaviour(Blocks.CAMPFIRE, new CampfireMovementBehaviour());
registerBehaviour(Blocks.SOUL_CAMPFIRE, new CampfireMovementBehaviour());
DispenserMovementBehaviour.gatherMovedDispenseItemBehaviours();
registerBehaviour(Blocks.DISPENSER, new DispenserMovementBehaviour());

View file

@ -158,6 +158,7 @@ public class AllTags {
VANILLA_STRIPPED_LOGS,
VANILLA_STRIPPED_WOOD,
DEPLOYABLE_DRINK,
CONTRAPTION_CONTROLLED,
STRIPPED_LOGS(FORGE),
STRIPPED_WOOD(FORGE),

View file

@ -21,7 +21,7 @@ public class BellMovementBehaviour implements MovementBehaviour {
@Override
public boolean isActive(MovementContext context) {
return !(context.contraption instanceof CarriageContraption);
return MovementBehaviour.super.isActive(context) && !(context.contraption instanceof CarriageContraption);
}
@Override

View file

@ -17,7 +17,7 @@ public class CampfireMovementBehaviour implements MovementBehaviour {
@Override
public void tick(MovementContext context) {
if (context.world == null || !context.world.isClientSide || context.position == null
|| !context.state.getValue(CampfireBlock.LIT))
|| !context.state.getValue(CampfireBlock.LIT) || context.disabled)
return;
// Mostly copied from CampfireBlock and CampfireBlockEntity

View file

@ -30,9 +30,9 @@ public class ContraptionControlsBlock extends ControlsBlock implements IBE<Contr
BlockHitResult pHit) {
return onBlockEntityUse(pLevel, pPos, cte -> {
cte.pressButton();
cte.disabled = !cte.disabled;
cte.notifyUpdate();
if (!pLevel.isClientSide()) {
cte.disabled = !cte.disabled;
cte.notifyUpdate();
ContraptionControlsBlockEntity.sendStatus(pPlayer, cte.filtering.getFilter(), !cte.disabled);
AllSoundEvents.CONTROLLER_CLICK.play(cte.getLevel(), null, cte.getBlockPos(), 1,
cte.disabled ? 0.8f : 1.5f);

View file

@ -4,6 +4,7 @@ import java.util.List;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.AllTags.AllItemTags;
import com.simibubi.create.content.contraptions.components.structureMovement.interaction.controls.ControlsBlock;
import com.simibubi.create.foundation.blockEntity.BlockEntityBehaviour;
import com.simibubi.create.foundation.blockEntity.SmartBlockEntity;
@ -50,6 +51,7 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity {
public void addBehaviours(List<BlockEntityBehaviour> behaviours) {
behaviours.add(filtering = new FilteringBehaviour(this, new ControlsSlot()));
filtering.setLabel(Lang.translateDirect("contraptions.contoller.target"));
filtering.withPredicate(AllItemTags.CONTRAPTION_CONTROLLED::matches);
}
public void pressButton() {
@ -140,7 +142,7 @@ public class ContraptionControlsBlockEntity extends SmartBlockEntity {
@Override
public float getScale() {
return .5f;
return .508f;
}
@Override

View file

@ -144,7 +144,7 @@ public class FilteringBehaviour extends BlockEntityBehaviour implements ValueSet
public boolean setFilter(ItemStack stack) {
ItemStack filter = stack.copy();
if (!predicate.test(filter))
if (!filter.isEmpty() && !predicate.test(filter))
return false;
this.filter = filter;
count = Math.min(count, stack.getMaxStackSize());

View file

@ -160,6 +160,7 @@ public class BuilderTransformers {
.loot((lr, block) -> lr.add(block, BlockLoot.createDoorTable(block)))
.item()
.tag(ItemTags.DOORS)
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.model((c, p) -> p.blockSprite(c, p.modLoc("item/" + type + "_door")))
.build();
}
@ -455,6 +456,7 @@ public class BuilderTransformers {
}))
.item()
.model((c, p) -> p.withExistingParent(c.getName(), p.modLoc("block/" + c.getName())))
.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.build();
}

View file

@ -152,6 +152,9 @@ public class TagGen {
.add(Items.GLASS_BOTTLE, Items.POTION, Items.SPLASH_POTION, Items.LINGERING_POTION,
Items.HONEY_BOTTLE, Items.CAKE);
prov.tag(AllItemTags.CONTRAPTION_CONTROLLED.tag)
.add(Items.BELL, Items.CAMPFIRE, Items.SOUL_CAMPFIRE, Items.DISPENSER, Items.DROPPER);
prov.tag(AllItemTags.VANILLA_STRIPPED_LOGS.tag)
.add(Items.STRIPPED_ACACIA_LOG, Items.STRIPPED_BIRCH_LOG, Items.STRIPPED_CRIMSON_STEM,
Items.STRIPPED_DARK_OAK_LOG, Items.STRIPPED_JUNGLE_LOG, Items.STRIPPED_OAK_LOG,

View file

@ -95,6 +95,7 @@ public class PonderScene {
int basePlateSize;
float scaleFactor;
float yOffset;
boolean hidePlatformShadow;
private boolean stoppedCounting;
private int totalTime;
@ -106,6 +107,7 @@ public class PonderScene {
pointOfInterest = Vec3.ZERO;
textIndex = 1;
hidePlatformShadow = false;
this.world = world;
this.namespace = namespace;
@ -183,7 +185,7 @@ public class PonderScene {
.getDirection();
Vec3 location = selectedHit.getSecond()
.getLocation();
ItemStack pickBlock = blockState.getCloneItemStack(new BlockHitResult(location, direction, selectedPos, true),
world, selectedPos, Minecraft.getInstance().player);
@ -235,6 +237,7 @@ public class PonderScene {
public void renderScene(SuperRenderTypeBuffer buffer, PoseStack ms, float pt) {
ForcedDiffuseState.pushCalculator(DiffuseLightCalculator.DEFAULT);
ms.pushPose();
Minecraft mc = Minecraft.getInstance();
Entity prevRVE = mc.cameraEntity;
@ -457,6 +460,10 @@ public class PonderScene {
public int getBasePlateOffsetZ() {
return basePlateOffsetZ;
}
public boolean shouldHidePlatformShadow() {
return hidePlatformShadow;
}
public int getBasePlateSize() {
return basePlateSize;
@ -527,8 +534,8 @@ public class PonderScene {
UIRenderHelper.flipForGuiRender(ms);
float f = 30 * scaleFactor;
ms.scale(f, f, f);
ms.translate((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset,
(basePlateSize + basePlateOffsetZ) / -2f);
ms.translate((basePlateSize) / -2f - basePlateOffsetX, -1f + yOffset,
(basePlateSize) / -2f - basePlateOffsetZ);
return ms;
}
@ -555,8 +562,8 @@ public class PonderScene {
float f = 1f / (30 * scaleFactor);
vec = vec.multiply(f, -f, f);
vec = vec.subtract((basePlateSize + basePlateOffsetX) / -2f, -1f + yOffset,
(basePlateSize + basePlateOffsetZ) / -2f);
vec = vec.subtract((basePlateSize) / -2f - basePlateOffsetX, -1f + yOffset,
(basePlateSize) / -2f - basePlateOffsetZ);
return vec;
}

View file

@ -180,6 +180,13 @@ public class SceneBuilder {
public void scaleSceneView(float factor) {
scene.scaleFactor = factor;
}
/**
* Use this to disable the base plates' shadow for this scene
*/
public void removeShadow() {
scene.hidePlatformShadow = true;
}
/**
* Use this in case you are not happy with the vertical alignment of the scene

View file

@ -0,0 +1,401 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.content.logistics.block.redstone.SmartObserverBlockEntity;
import com.simibubi.create.content.logistics.block.redstone.ThresholdSwitchBlock;
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.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.Vec3;
public class DetectorScenes {
public static void smartObserver(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("smart_observer", "Advanced detection with Smart Observers");
scene.configureBasePlate(0, 0, 5);
scene.showBasePlate();
scene.idle(5);
Selection chuteObserver = util.select.fromTo(0, 1, 4, 0, 2, 4);
Selection chute = util.select.fromTo(1, 1, 4, 1, 3, 4);
Selection pipe = util.select.fromTo(3, 1, 4, 3, 3, 4);
Selection pipeObserver = util.select.fromTo(4, 1, 4, 4, 2, 4);
Selection redstoneDust = util.select.fromTo(1, 1, 2, 0, 1, 2);
Selection belt = util.select.fromTo(1, 1, 1, 3, 1, 1);
Selection chest = util.select.position(2, 1, 0);
Selection amethyst = util.select.position(3, 1, 0);
Selection largeCog = util.select.position(5, 0, 2);
Selection smallCogs = util.select.fromTo(3, 1, 2, 4, 1, 2);
BlockPos observerPos = util.grid.at(2, 1, 2);
BlockPos funnelPos = util.grid.at(3, 2, 1);
Selection funnelChest = util.select.fromTo(4, 1, 1, 4, 2, 1);
scene.world.showSection(util.select.position(observerPos), Direction.DOWN);
scene.idle(10);
scene.overlay.showText(60)
.text("Smart Observers can be used detect a variety of events")
.pointAt(util.vector.blockSurface(observerPos, Direction.WEST))
.placeNearTarget();
scene.idle(50);
scene.world.showSection(redstoneDust, Direction.EAST);
scene.idle(5);
ElementLink<WorldSectionElement> chestLink = scene.world.showIndependentSection(chest, Direction.SOUTH);
scene.world.moveSection(chestLink, util.vector.of(0, 0, 1), 0);
scene.idle(15);
ItemStack copperIngot = new ItemStack(Items.COPPER_INGOT);
ItemStack amethystItem = new ItemStack(Blocks.AMETHYST_BLOCK);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(observerPos.north(), Direction.NORTH), Pointing.RIGHT)
.withItem(copperIngot),
40);
scene.idle(7);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.world.toggleRedstonePower(redstoneDust);
scene.effects.indicateRedstone(observerPos);
scene.idle(15);
scene.overlay.showText(60)
.text("It can detect items or fluids inside of generic containers")
.attachKeyFrame()
.pointAt(util.vector.blockSurface(observerPos, Direction.WEST))
.placeNearTarget();
scene.idle(65);
scene.overlay.showCenteredScrollInput(observerPos, Direction.UP, 10);
scene.idle(5);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(observerPos, Direction.UP), Pointing.DOWN).rightClick()
.withItem(amethystItem),
60);
scene.idle(7);
scene.world.setFilterData(util.select.position(observerPos), SmartObserverBlockEntity.class, amethystItem);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.world.toggleRedstonePower(redstoneDust);
scene.idle(25);
scene.overlay.showText(60)
.text("The filter slot can be used to look for specific contents only")
.attachKeyFrame()
.pointAt(util.vector.blockSurface(observerPos, Direction.UP))
.placeNearTarget();
scene.idle(50);
scene.world.hideIndependentSection(chestLink, Direction.EAST);
scene.idle(10);
ElementLink<WorldSectionElement> amethystLink = scene.world.showIndependentSection(amethyst, Direction.EAST);
scene.world.moveSection(amethystLink, util.vector.of(-1, 0, 1), 0);
scene.idle(15);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.world.toggleRedstonePower(redstoneDust);
scene.effects.indicateRedstone(observerPos);
scene.idle(15);
scene.overlay.showText(50)
.text("It also activates when the block itself matches the filter")
.attachKeyFrame()
.pointAt(util.vector.blockSurface(observerPos.north(), Direction.WEST))
.placeNearTarget();
scene.idle(45);
scene.world.hideIndependentSection(amethystLink, Direction.EAST);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.world.toggleRedstonePower(redstoneDust);
scene.idle(15);
scene.world.showSection(largeCog, Direction.UP);
scene.idle(5);
scene.world.showSection(smallCogs, Direction.DOWN);
scene.world.showSection(belt, Direction.SOUTH);
scene.idle(15);
scene.world.setFilterData(util.select.position(0, 2, 4), SmartObserverBlockEntity.class, copperIngot);
scene.world.showSection(chuteObserver, Direction.DOWN);
scene.idle(2);
scene.world.setFilterData(util.select.position(4, 2, 4), SmartObserverBlockEntity.class,
new ItemStack(Items.LAVA_BUCKET));
scene.world.showSection(pipeObserver, Direction.DOWN);
scene.idle(5);
scene.world.showSection(chute, Direction.WEST);
scene.idle(2);
scene.world.showSection(pipe, Direction.EAST);
scene.idle(10);
scene.overlay.showText(60)
.text("Additionally, smart observers can monitor belts, chutes and pipes")
.attachKeyFrame()
.pointAt(util.vector.blockSurface(observerPos, Direction.UP))
.placeNearTarget();
scene.idle(60);
scene.world.createItemOnBelt(util.grid.at(3, 1, 1), Direction.EAST, amethystItem);
scene.idle(15);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.world.toggleRedstonePower(redstoneDust);
scene.effects.indicateRedstone(observerPos);
scene.idle(13);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.world.toggleRedstonePower(redstoneDust);
scene.idle(25);
scene.world.showSection(funnelChest, Direction.WEST);
scene.idle(5);
scene.world.showSection(util.select.position(funnelPos), Direction.DOWN);
scene.idle(5);
ElementLink<WorldSectionElement> observerLink =
scene.world.makeSectionIndependent(util.select.position(observerPos));
scene.world.moveSection(observerLink, util.vector.of(1, 1, 0), 10);
scene.world.hideSection(redstoneDust, Direction.EAST);
scene.idle(20);
scene.overlay.showText(60)
.text("...and will emit a pulse, if an item enters or exits a funnel")
.attachKeyFrame()
.pointAt(util.vector.blockSurface(observerPos.above()
.east(), Direction.WEST))
.placeNearTarget();
scene.idle(60);
for (int i = 0; i < 3; i++) {
scene.world.createItemOnBelt(util.grid.at(3, 1, 1), Direction.EAST, amethystItem);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.effects.indicateRedstone(observerPos.above()
.east());
scene.idle(5);
scene.world.toggleRedstonePower(util.select.position(observerPos));
scene.idle(25);
}
}
public static void thresholdSwitch(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("threshold_switch", "Monitoring with the Threshold Switch");
scene.configureBasePlate(0, 1, 5);
Selection fluidTank = util.select.fromTo(1, 1, 5, 1, 3, 5);
Selection pulley = util.select.fromTo(3, 2, 3, 2, 2, 3);
BlockPos pulleyPos = util.grid.at(2, 2, 3);
BlockPos switchPos = util.grid.at(1, 1, 3);
Selection redstone = util.select.fromTo(1, 1, 2, 1, 1, 1);
Selection chest = util.select.fromTo(3, 1, 3, 2, 1, 3);
Selection belt = util.select.fromTo(3, 0, 0, 3, 0, 6);
Selection cogs = util.select.fromTo(4, 0, 6, 5, 0, 6)
.add(util.select.position(5, 0, 5));
Selection inFunnel = util.select.position(3, 1, 2);
Selection outFunnel = util.select.position(3, 1, 4);
Selection baseStrip = util.select.fromTo(1, 0, 1, 1, 0, 5);
Selection basePlate = util.select.fromTo(0, 0, 1, 2, 0, 5)
.add(util.select.fromTo(4, 0, 5, 4, 0, 1));
scene.world.showSection(basePlate, Direction.UP);
ElementLink<WorldSectionElement> stripLink = scene.world.showIndependentSection(baseStrip, Direction.UP);
scene.world.moveSection(stripLink, util.vector.of(2, 0, 0), 0);
scene.idle(5);
scene.world.showSection(util.select.position(switchPos), Direction.DOWN);
scene.idle(10);
scene.world.showSection(chest, Direction.WEST);
scene.idle(10);
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
scene.idle(5);
scene.overlay.showText(60)
.text("Threshold Switches monitor the fill level of containers")
.pointAt(util.vector.blockSurface(switchPos, Direction.NORTH))
.placeNearTarget();
scene.idle(60);
scene.world.hideIndependentSection(stripLink, Direction.DOWN);
scene.idle(15);
scene.world.showSection(cogs, Direction.WEST);
scene.world.showSection(belt, Direction.NORTH);
scene.idle(5);
scene.world.showSection(inFunnel, Direction.DOWN);
scene.idle(10);
scene.world.showSection(redstone, Direction.SOUTH);
ItemStack ironIngot = new ItemStack(Items.IRON_INGOT, 32);
for (int i = 0; i < 5; i++) {
scene.world.createItemOnBelt(util.grid.at(3, 0, 0), Direction.NORTH, ironIngot);
scene.idle(10);
scene.world.removeItemsFromBelt(util.grid.at(3, 0, 2));
scene.world.flapFunnel(util.grid.at(3, 1, 2), false);
if (i % 2 == 1)
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
}
scene.addLazyKeyframe();
scene.world.createItemOnBelt(util.grid.at(3, 0, 0), Direction.NORTH, ironIngot);
scene.world.removeItemsFromBelt(util.grid.at(3, 0, 2));
scene.world.multiplyKineticSpeed(util.select.everywhere(), 1 / 8f);
scene.idle(10);
Vec3 upper = util.vector.blockSurface(switchPos, Direction.NORTH)
.add(0, 3 / 16f, 0);
scene.overlay.showLine(PonderPalette.RED, upper.add(2 / 16f, 0, 0), upper.subtract(2 / 16f, 0, 0), 60);
scene.overlay.showText(70)
.text("When the inventory content exceeds the upper threshold...")
.colored(PonderPalette.RED)
.pointAt(upper.subtract(2 / 16f, 0, 0))
.placeNearTarget();
scene.idle(60);
scene.world.removeItemsFromBelt(util.grid.at(3, 0, 2));
scene.world.flapFunnel(util.grid.at(3, 1, 2), false);
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
scene.effects.indicateRedstone(switchPos);
scene.world.toggleRedstonePower(redstone);
scene.idle(20);
scene.overlay.showText(50)
.text("...the switch will change its redstone output")
.pointAt(util.vector.blockSurface(switchPos.north(), Direction.DOWN))
.placeNearTarget();
scene.idle(50);
scene.world.showSection(outFunnel, Direction.DOWN);
scene.world.toggleRedstonePower(outFunnel);
scene.idle(15);
scene.world.multiplyKineticSpeed(util.select.everywhere(), 8f);
for (int i = 0; i < 5; i++) {
scene.idle(10);
scene.world.createItemOnBelt(util.grid.at(3, 0, 4), Direction.NORTH, ironIngot);
if (i % 3 == 1)
scene.world.modifyBlock(switchPos,
s -> s.setValue(ThresholdSwitchBlock.LEVEL, s.getValue(ThresholdSwitchBlock.LEVEL) - 1), false);
}
scene.world.multiplyKineticSpeed(util.select.everywhere(), 1 / 8f);
Vec3 lower = util.vector.blockSurface(switchPos, Direction.NORTH)
.add(0, -3 / 16f, 0);
scene.overlay.showLine(PonderPalette.GREEN, lower.add(2 / 16f, 0, 0), lower.subtract(2 / 16f, 0, 0), 60);
scene.overlay.showText(70)
.text("The signal stays until the lower threshold is reached")
.attachKeyFrame()
.colored(PonderPalette.GREEN)
.pointAt(lower.subtract(2 / 16f, 0, 0))
.placeNearTarget();
scene.idle(30);
for (int i = 0; i < 3; i++) {
scene.idle(10);
scene.world.createItemOnBelt(util.grid.at(3, 0, 4), Direction.NORTH, ironIngot);
if (i % 3 == 2)
scene.world.modifyBlock(switchPos,
s -> s.setValue(ThresholdSwitchBlock.LEVEL, s.getValue(ThresholdSwitchBlock.LEVEL) - 1), false);
}
scene.world.toggleRedstonePower(redstone);
scene.idle(40);
scene.overlay.showText(90)
.text("The redstone output can now be used to control item supply, keeping the buffer filled")
.pointAt(util.vector.blockSurface(switchPos.north(), Direction.DOWN))
.attachKeyFrame()
.placeNearTarget();
scene.idle(100);
scene.addKeyframe();
scene.overlay.showLine(PonderPalette.GREEN, lower.add(2 / 16f, 0, 0), lower.subtract(2 / 16f, 0, 0), 105);
scene.idle(5);
scene.overlay.showLine(PonderPalette.RED, upper.add(2 / 16f, 0, 0), upper.subtract(2 / 16f, 0, 0), 100);
scene.idle(15);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(switchPos, Direction.UP), Pointing.DOWN).rightClick(), 60);
scene.idle(7);
scene.overlay.showText(70)
.text("The specific thresholds can be changed in the UI")
.pointAt(upper.subtract(2 / 16f, 0, 0))
.placeNearTarget();
scene.idle(80);
scene.overlay.showCenteredScrollInput(switchPos, Direction.UP, 70);
scene.overlay.showText(70)
.text("A filter can help to only count specific contents toward the total")
.pointAt(util.vector.blockSurface(switchPos, Direction.UP))
.attachKeyFrame()
.placeNearTarget();
scene.idle(80);
scene.world.hideSection(belt, Direction.SOUTH);
scene.world.hideSection(cogs, Direction.EAST);
scene.idle(2);
scene.world.hideSection(inFunnel, Direction.EAST);
scene.idle(2);
scene.world.hideSection(chest, Direction.EAST);
scene.idle(2);
scene.world.hideSection(outFunnel, Direction.EAST);
scene.idle(9);
stripLink = scene.world.showIndependentSection(baseStrip, Direction.UP);
scene.world.moveSection(stripLink, util.vector.of(2, 0, 0), 0);
scene.idle(5);
ElementLink<WorldSectionElement> tankLink = scene.world.showIndependentSection(fluidTank, Direction.DOWN);
scene.world.moveSection(tankLink, util.vector.of(1, 0, -2), 0);
scene.idle(10);
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
scene.idle(15);
scene.overlay.showText(70)
.text("Fluid buffers can be monitored in a similar fashion")
.pointAt(util.vector.blockSurface(switchPos, Direction.NORTH))
.attachKeyFrame()
.placeNearTarget();
scene.idle(80);
scene.world.hideIndependentSection(tankLink, Direction.SOUTH);
scene.world.hideSection(redstone, Direction.NORTH);
ElementLink<WorldSectionElement> switchLink =
scene.world.makeSectionIndependent(util.select.position(switchPos));
scene.idle(10);
scene.world.moveSection(switchLink, util.vector.of(0, 1, 0), 15);
scene.world.modifyBlock(switchPos, s -> s.setValue(ThresholdSwitchBlock.LEVEL, 0), false);
scene.idle(5);
scene.world.showSection(pulley, Direction.DOWN);
scene.idle(15);
ElementLink<WorldSectionElement> hole = scene.world.makeSectionIndependent(util.select.position(2, 0, 3));
scene.world.hideIndependentSection(hole, Direction.DOWN);
scene.overlay.showText(70)
.text("...as well as, curiously, the length of an extended rope pulley")
.pointAt(util.vector.blockSurface(switchPos.above(), Direction.NORTH))
.attachKeyFrame()
.placeNearTarget();
scene.idle(10);
scene.world.setKineticSpeed(pulley, 32);
scene.world.movePulley(pulleyPos, 15, 205);
for (int i = 0; i < 4; i++) {
scene.idle(5);
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
scene.idle(45);
if (i == 1)
scene.markAsFinished();
}
scene.idle(5);
scene.world.cycleBlockProperty(switchPos, ThresholdSwitchBlock.LEVEL);
scene.world.setKineticSpeed(pulley, 0);
}
}

View file

@ -0,0 +1,512 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.content.contraptions.components.structureMovement.elevator.ElevatorContactBlock;
import com.simibubi.create.content.curiosities.deco.SlidingDoorBlock;
import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlock;
import com.simibubi.create.content.logistics.block.redstone.NixieTubeBlockEntity;
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.Components;
import com.simibubi.create.foundation.utility.Pointing;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.AABB;
public class ElevatorScenes {
public static void elevator(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("elevator_pulley", "Using the Elevator Pulley");
scene.configureBasePlate(1, 0, 5);
scene.scaleSceneView(.85f);
scene.removeShadow();
scene.setSceneOffsetY(-1.5f);
Selection topFloor = util.select.fromTo(5, 12, 0, 1, 12, 4);
Selection midFloor = util.select.fromTo(5, 6, 0, 1, 6, 4);
Selection botFloor = util.select.fromTo(5, 0, 0, 1, 0, 4);
Selection topCutout = util.select.fromTo(4, 12, 3, 2, 12, 1);
Selection midCutout = util.select.fromTo(4, 6, 3, 2, 6, 1);
Selection botCutout = util.select.fromTo(4, 0, 3, 2, 0, 1);
BlockPos topContact = util.grid.at(1, 13, 2);
BlockPos midContact = util.grid.at(1, 7, 2);
BlockPos botContact = util.grid.at(1, 1, 2);
Selection outputRedstone = util.select.fromTo(0, 0, 2, 0, 1, 2);
Selection topInput = util.select.fromTo(1, 13, 0, 1, 13, 1);
Selection midInput = util.select.fromTo(1, 7, 0, 1, 7, 1);
Selection botInput = util.select.fromTo(1, 1, 0, 1, 1, 1);
Selection pole = util.select.fromTo(6, 0, 3, 6, 17, 3)
.add(util.select.position(5, 17, 3));
Selection cog = util.select.fromTo(5, 18, 2, 4, 18, 2);
BlockPos nixiePos = util.grid.at(4, 13, 0);
BlockPos linkPos = util.grid.at(1, 14, 2);
BlockPos doorPos = util.grid.at(3, 14, 1);
Selection controls = util.select.position(4, 14, 2);
BlockPos pulleyPos = util.grid.at(3, 18, 2);
ElementLink<WorldSectionElement> camLink = scene.world.showIndependentSection(topFloor, Direction.UP);
scene.world.moveSection(camLink, util.vector.of(0, -12, 0), 0);
scene.world.setKineticSpeed(util.select.position(pulleyPos), 0);
scene.idle(5);
ElementLink<WorldSectionElement> pulleyLink =
scene.world.showIndependentSection(util.select.position(pulleyPos), Direction.DOWN);
scene.world.moveSection(pulleyLink, util.vector.of(0, -16, 0), 0);
scene.idle(15);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(3, 2, 2), Direction.WEST))
.text("Elevator Pulleys can move structures vertically between marked locations");
scene.idle(60);
scene.world.moveSection(pulleyLink, util.vector.of(0, 4, 0), 20);
scene.world.setBlocks(topCutout, Blocks.AIR.defaultBlockState(), false);
scene.idle(5);
ElementLink<WorldSectionElement> elevatorLink =
scene.world.showIndependentSection(util.select.fromTo(4, 13, 3, 2, 13, 1), Direction.DOWN);
scene.world.moveSection(elevatorLink, util.vector.of(0, -13, 0), 0);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(4, 14, 1, 4, 16, 1), Direction.DOWN, elevatorLink);
scene.idle(2);
scene.world.showSectionAndMerge(util.select.fromTo(2, 14, 1, 2, 16, 1), Direction.DOWN, elevatorLink);
scene.idle(2);
scene.world.showSectionAndMerge(util.select.fromTo(4, 14, 3, 4, 16, 3), Direction.DOWN, elevatorLink);
scene.idle(2);
scene.world.showSectionAndMerge(util.select.fromTo(2, 14, 3, 2, 16, 3), Direction.DOWN, elevatorLink);
scene.idle(10);
scene.world.showSectionAndMerge(util.select.fromTo(4, 17, 1, 2, 17, 3), Direction.DOWN, elevatorLink);
scene.overlay.showText(40)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(2, 2, 1), Direction.UP))
.text("Start by constructing a cabin");
scene.idle(30);
scene.world.showSectionAndMerge(util.select.position(2, 14, 2), Direction.WEST, elevatorLink);
scene.idle(2);
scene.world.showSectionAndMerge(util.select.position(1, 13, 2), Direction.EAST, camLink);
scene.idle(15);
scene.world.toggleRedstonePower(util.select.fromTo(2, 14, 2, 1, 13, 2));
scene.idle(15);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(1, 2, 1), Direction.UP))
.text("Place a pair of Redstone Contacts facing each other...");
scene.idle(55);
AABB glue1 = new AABB(util.grid.at(3, 4, 2));
AABB glue2 = glue1.inflate(1, 0, 1)
.expandTowards(0, -4, 0);
scene.overlay.showControls(new InputWindowElement(util.vector.centerOf(4, 3, 1), Pointing.RIGHT)
.withItem(AllItems.SUPER_GLUE.asStack()), 60);
scene.idle(7);
scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, glue1, glue1, 5);
scene.idle(1);
scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, glue1, glue2, 90);
scene.idle(10);
scene.overlay.showSelectionWithText(util.select.position(2, 1, 2), 80)
.placeNearTarget()
.colored(PonderPalette.GREEN)
.pointAt(util.vector.blockSurface(util.grid.at(1, 2, 1), Direction.UP))
.text("...and glue one of them to your moving structure");
scene.idle(70);
scene.world.showSectionAndMerge(controls, Direction.DOWN, elevatorLink);
scene.idle(15);
scene.effects.superGlue(util.grid.at(4, 1, 2), Direction.DOWN, true);
scene.overlay.showText(80)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(4, 1, 2), Direction.UP))
.text("Contraption Controls can be attached to make floor selection easier");
scene.idle(70);
scene.world.showSectionAndMerge(cog, Direction.DOWN, camLink);
scene.world.showSectionAndMerge(pole, Direction.UP, camLink);
scene.idle(10);
scene.world.setKineticSpeed(util.select.position(pulleyPos), 64);
scene.idle(5);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(3, 6, 2), Direction.WEST))
.text("Ensure that the pulley is supplied with Rotational Power");
scene.idle(75);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(3, 6, 2), Direction.NORTH), Pointing.RIGHT)
.rightClick(),
60);
scene.idle(7);
scene.effects.indicateSuccess(util.grid.at(3, 6, 2));
scene.world.toggleRedstonePower(util.select.position(1, 13, 2));
scene.world.setBlock(topContact, AllBlocks.ELEVATOR_CONTACT.getDefaultState()
.setValue(ElevatorContactBlock.FACING, Direction.EAST)
.setValue(ElevatorContactBlock.POWERING, true), false);
scene.world.movePulley(pulleyPos, 1, 0);
scene.overlay.showText(50)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(3, 6, 2), Direction.WEST))
.text("Right-Clicking the pulley assembles the elevator");
scene.idle(60);
scene.overlay.showText(70)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
.text("The stationary contact now turns into an Elevator Contact");
scene.idle(80);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP), Pointing.DOWN)
.rightClick(),
60);
scene.idle(7);
scene.overlay.showSelectionWithText(util.select.position(1, 1, 2), 60)
.placeNearTarget()
.colored(PonderPalette.BLUE)
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.UP))
.text("Elevator Contacts represent a 'floor' and can be configured");
scene.idle(75);
scene.world.moveSection(elevatorLink, util.vector.of(0, 7, 0), 15);
scene.world.moveSection(camLink, util.vector.of(0, 7, 0), 15);
scene.world.moveSection(pulleyLink, util.vector.of(0, 7, 0), 15);
scene.addLazyKeyframe();
scene.world.setBlocks(midCutout, Blocks.AIR.defaultBlockState(), false);
scene.idle(15);
scene.world.showSectionAndMerge(midFloor, Direction.EAST, camLink);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(midContact), Direction.DOWN, camLink);
scene.idle(10);
scene.effects.indicateSuccess(util.grid.at(1, 2, 2));
scene.world.setBlock(midContact, AllBlocks.ELEVATOR_CONTACT.getDefaultState()
.setValue(ElevatorContactBlock.FACING, Direction.EAST), false);
scene.idle(15);
AABB bb = new AABB(util.grid.at(1, 8, 2));
scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, bb, bb, 5);
scene.idle(1);
scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, bb, bb.expandTowards(0, -6, 0), 90);
scene.idle(10);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.UP))
.text("Any redstone contact sharing this column will be converted");
scene.idle(50);
scene.world.showSectionAndMerge(midInput, Direction.SOUTH, camLink);
scene.idle(15);
scene.world.toggleRedstonePower(midInput);
scene.effects.indicateRedstone(util.grid.at(1, 2, 0));
scene.world.cycleBlockProperty(midContact, ElevatorContactBlock.CALLING);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.POWERING);
scene.world.moveSection(elevatorLink, util.vector.of(0, -6, 0), 60);
scene.world.movePulley(pulleyPos, 6, 60);
scene.idle(20);
scene.world.toggleRedstonePower(midInput);
scene.idle(10);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(1, 1, 0), Direction.UP))
.text("Supply a redstone pulse to call the elevator to the contact");
scene.idle(30);
scene.world.cycleBlockProperty(midContact, ElevatorContactBlock.CALLING);
scene.world.cycleBlockProperty(midContact, ElevatorContactBlock.POWERING);
scene.world.toggleRedstonePower(util.select.position(1, 7, 1));
scene.idle(40);
scene.overlay.showText(70)
.placeNearTarget()
.pointAt(util.vector.centerOf(util.grid.at(2, 3, 3)))
.text("The movement speed depends on the rotation input on the pulley");
scene.idle(80);
scene.addLazyKeyframe();
scene.idle(10);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(4, 2, 2), Direction.UP), Pointing.DOWN)
.scroll(),
60);
scene.idle(15);
scene.overlay.showText(90)
.placeNearTarget()
.pointAt(util.vector.blockSurface(util.grid.at(4, 2, 2), Direction.UP))
.text("Scroll and click on the controls block to choose a floor while on-board");
scene.idle(85);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(4, 2, 2), Direction.UP), Pointing.DOWN)
.rightClick(),
10);
scene.idle(7);
scene.world.cycleBlockProperty(midContact, ElevatorContactBlock.POWERING);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.CALLING);
scene.world.toggleRedstonePower(util.select.position(1, 7, 1));
scene.world.moveSection(camLink, util.vector.of(0, -7, 0), 60);
scene.world.moveSection(pulleyLink, util.vector.of(0, -7, 0), 60);
scene.world.moveSection(elevatorLink, util.vector.of(0, -1, 0), 60);
scene.world.movePulley(pulleyPos, -6, 60);
scene.idle(60);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.POWERING);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.CALLING);
scene.idle(15);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(3, 6, 2), Direction.NORTH), Pointing.RIGHT)
.rightClick(),
60);
scene.idle(7);
scene.effects.indicateSuccess(util.grid.at(3, 6, 2));
scene.world.movePulley(pulleyPos, -1, 0);
scene.overlay.showText(80)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(3, 6, 2), Direction.WEST))
.text("Right-Clicking the assembled pulley will turn the cabin back into blocks");
scene.idle(90);
scene.world.showSectionAndMerge(util.select.fromTo(doorPos, doorPos.above()), Direction.DOWN, elevatorLink);
scene.idle(20);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(3, 6, 2), Direction.NORTH), Pointing.RIGHT)
.rightClick(),
60);
scene.idle(7);
scene.effects.indicateSuccess(util.grid.at(3, 6, 2));
scene.world.movePulley(pulleyPos, 1, 0);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.OPEN);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.VISIBLE);
scene.world.cycleBlockProperty(doorPos.above(), SlidingDoorBlock.VISIBLE);
scene.overlay.showText(80)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(3, 1, 1), Direction.NORTH))
.text("Sliding doors attached to the cabin will open and close automatically");
scene.idle(90);
scene.world.moveSection(elevatorLink, util.vector.of(0, 13, 0), 15);
scene.world.moveSection(camLink, util.vector.of(0, 13, 0), 15);
scene.world.moveSection(pulleyLink, util.vector.of(0, 13, 0), 15);
scene.world.setBlocks(botCutout, Blocks.AIR.defaultBlockState(), false);
scene.idle(15);
scene.world.showSectionAndMerge(botFloor, Direction.EAST, camLink);
scene.idle(5);
scene.world.showSectionAndMerge(util.select.position(botContact), Direction.DOWN, camLink);
scene.idle(10);
scene.effects.indicateSuccess(util.grid.at(1, 2, 2));
scene.world.setBlock(botContact, AllBlocks.ELEVATOR_CONTACT.getDefaultState()
.setValue(ElevatorContactBlock.FACING, Direction.EAST), false);
scene.idle(5);
scene.world.showSectionAndMerge(botInput, Direction.SOUTH, camLink);
scene.idle(15);
scene.world.toggleRedstonePower(botInput);
scene.effects.indicateRedstone(util.grid.at(1, 2, 0));
scene.world.cycleBlockProperty(botContact, ElevatorContactBlock.CALLING);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.POWERING);
scene.world.moveSection(elevatorLink, util.vector.of(0, -12, 0), 50);
scene.world.movePulley(pulleyPos, 12, 50);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.OPEN);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.VISIBLE);
scene.world.cycleBlockProperty(doorPos.above(), SlidingDoorBlock.VISIBLE);
scene.idle(20);
scene.world.toggleRedstonePower(botInput);
scene.world.showSectionAndMerge(outputRedstone, Direction.EAST, camLink);
scene.idle(30);
scene.world.cycleBlockProperty(botContact, ElevatorContactBlock.CALLING);
scene.world.cycleBlockProperty(botContact, ElevatorContactBlock.POWERING);
scene.world.toggleRedstonePower(util.select.position(1, 1, 1));
scene.world.toggleRedstonePower(outputRedstone);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.OPEN);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.VISIBLE);
scene.world.cycleBlockProperty(doorPos.above(), SlidingDoorBlock.VISIBLE);
scene.idle(15);
scene.overlay.showText(80)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.topOf(0, 1, 2))
.text("Elevator Contacts emit a signal while the cabin is on their floor");
scene.idle(90);
scene.overlay.showText(80)
.placeNearTarget()
.pointAt(util.vector.topOf(0, 1, 2))
.text("This can be useful to trigger doors or special effects upon arrival");
scene.idle(90);
scene.world.setBlock(nixiePos, AllBlocks.NIXIE_TUBES.get(DyeColor.GREEN)
.getDefaultState()
.setValue(NixieTubeBlock.FACING, Direction.WEST), false);
scene.world.moveSection(camLink, util.vector.of(0, -13, 0), 20);
scene.world.moveSection(pulleyLink, util.vector.of(0, -13, 0), 20);
scene.world.moveSection(elevatorLink, util.vector.of(0, -13, 0), 20);
scene.idle(30);
scene.world.showSectionAndMerge(util.select.position(nixiePos), Direction.DOWN, camLink);
scene.idle(15);
scene.overlay.showControls(
new InputWindowElement(util.vector.blockSurface(util.grid.at(4, 1, 0), Direction.UP), Pointing.DOWN)
.rightClick()
.withItem(AllBlocks.DISPLAY_LINK.asStack()),
15);
scene.world.toggleRedstonePower(util.select.position(1, 14, 2));
scene.idle(15);
scene.world.showSectionAndMerge(util.select.position(linkPos), Direction.DOWN, camLink);
scene.world.flashDisplayLink(linkPos);
scene.world.modifyBlockEntityNBT(util.select.position(nixiePos), NixieTubeBlockEntity.class, nbt -> {
Component component = Components.literal("0F");
nbt.putString("RawCustomText", component.getString());
nbt.putString("CustomText", Component.Serializer.toJson(component));
});
scene.overlay.showText(90)
.placeNearTarget()
.attachKeyFrame()
.pointAt(util.vector.centerOf(1, 2, 2))
.text("Display Links on any of the contacts can show the current floor of the elevator");
scene.idle(90);
scene.world.showSectionAndMerge(topInput, Direction.SOUTH, camLink);
scene.idle(15);
scene.world.toggleRedstonePower(topInput);
scene.effects.indicateRedstone(util.grid.at(1, 2, 0));
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.CALLING);
scene.world.cycleBlockProperty(botContact, ElevatorContactBlock.POWERING);
scene.world.moveSection(elevatorLink, util.vector.of(0, 12, 0), 70);
scene.world.movePulley(pulleyPos, -12, 70);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.OPEN);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.VISIBLE);
scene.world.cycleBlockProperty(doorPos.above(), SlidingDoorBlock.VISIBLE);
scene.idle(20);
scene.world.toggleRedstonePower(topInput);
scene.idle(10);
scene.world.flashDisplayLink(linkPos);
scene.world.modifyBlockEntityNBT(util.select.position(nixiePos), NixieTubeBlockEntity.class, nbt -> {
Component component = Components.literal("1F");
nbt.putString("RawCustomText", component.getString());
nbt.putString("CustomText", Component.Serializer.toJson(component));
});
scene.idle(40);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.CALLING);
scene.world.cycleBlockProperty(topContact, ElevatorContactBlock.POWERING);
scene.world.toggleRedstonePower(util.select.position(1, 13, 1));
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.OPEN);
scene.world.cycleBlockProperty(doorPos, SlidingDoorBlock.VISIBLE);
scene.world.cycleBlockProperty(doorPos.above(), SlidingDoorBlock.VISIBLE);
scene.world.flashDisplayLink(linkPos);
scene.world.modifyBlockEntityNBT(util.select.position(nixiePos), NixieTubeBlockEntity.class, nbt -> {
Component component = Components.literal("2F");
nbt.putString("RawCustomText", component.getString());
nbt.putString("CustomText", Component.Serializer.toJson(component));
});
}
public static void multiRope(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("elevator_pulley_multi_rope", "Synchronised Pulley Movement");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.scaleSceneView(.95f);
scene.showBasePlate();
scene.idle(5);
Selection mainPulley = util.select.fromTo(5, 0, 1, 5, 4, 1)
.add(util.select.fromTo(4, 4, 1, 3, 4, 1));
BlockPos pulley1 = util.grid.at(3, 4, 1);
BlockPos pulley2 = util.grid.at(3, 4, 3);
BlockPos pulley3 = util.grid.at(1, 4, 3);
Selection contraption = util.select.fromTo(3, 1, 3, 1, 1, 1);
ElementLink<WorldSectionElement> planksLink = scene.world.showIndependentSection(contraption, Direction.DOWN);
scene.idle(10);
scene.world.showSection(mainPulley, Direction.WEST);
scene.idle(4);
scene.world.showSection(util.select.position(pulley2), Direction.DOWN);
scene.idle(4);
scene.world.showSection(util.select.position(pulley3), Direction.DOWN);
scene.idle(15);
scene.world.movePulley(pulley1, 2, 20);
scene.idle(20);
scene.overlay.showText(60)
.pointAt(util.vector.topOf(util.grid.at(3, 1, 1)))
.placeNearTarget()
.text("Whenever a pulley assembles a contraption...");
scene.idle(70);
scene.world.movePulley(pulley2, 2, 0);
scene.world.movePulley(pulley3, 2, 0);
scene.idle(1);
scene.world.movePulley(pulley1, -2, 20);
scene.world.movePulley(pulley2, -2, 20);
scene.world.movePulley(pulley3, -2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, 2, 0), 20);
scene.idle(20);
scene.overlay.showText(80)
.pointAt(util.vector.blockSurface(util.grid.at(1, 4, 3), Direction.WEST))
.placeNearTarget()
.text("...other pulleys on the same layer will connect to the structure");
scene.idle(60);
scene.world.movePulley(pulley1, 2, 20);
scene.world.movePulley(pulley2, 2, 20);
scene.world.movePulley(pulley3, 2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, -2, 0), 20);
scene.idle(20);
scene.idle(20);
scene.world.movePulley(pulley1, -2, 20);
scene.world.movePulley(pulley2, -2, 20);
scene.world.movePulley(pulley3, -2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, 2, 0), 20);
scene.idle(20);
scene.overlay.showText(80)
.pointAt(util.vector.blockSurface(util.grid.at(1, 4, 3), Direction.WEST))
.placeNearTarget()
.text("They do not require to be powered, the effect is purely cosmetic");
scene.idle(60);
scene.world.movePulley(pulley1, 2, 20);
scene.world.movePulley(pulley2, 2, 20);
scene.world.movePulley(pulley3, 2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, -2, 0), 20);
scene.idle(20);
}
}

View file

@ -1,8 +1,10 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.actors.HarvesterBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableItemInterfaceBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlockEntity;
import com.simibubi.create.content.contraptions.components.actors.controls.ContraptionControlsBlockEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.LinearChassisBlock;
import com.simibubi.create.foundation.ponder.ElementLink;
import com.simibubi.create.foundation.ponder.PonderPalette;
@ -475,10 +477,10 @@ public class MovementActorScenes {
scene.idle(15);
scene.world.showSectionAndMerge(util.select.fromTo(4, 3, 3, 4, 2, 3), Direction.DOWN, contraption);
scene.idle(15);
BlockPos bearingPos = util.grid.at(4, 3, 4);
scene.addKeyframe();
scene.world.setKineticSpeed(util.select.position(4, 0, 6), 8);
scene.world.setKineticSpeed(util.select.position(5, 1, 6), -16);
scene.world.setKineticSpeed(util.select.position(4, 3, 5), -16);
@ -511,4 +513,240 @@ public class MovementActorScenes {
scene.idle(30);
}
public static void contraptionControls(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("contraption_controls", "Using Contraption Controls");
scene.configureBasePlate(1, 0, 6);
scene.scaleSceneView(0.9f);
scene.showBasePlate();
BlockPos cobblePos = util.grid.at(3, 1, 2);
BlockPos wheatPos = util.grid.at(2, 1, 1);
BlockPos bearingPos = util.grid.at(5, 1, 4);
Selection contraption = util.select.fromTo(5, 2, 4, 3, 2, 5)
.add(util.select.fromTo(3, 1, 5, 1, 1, 4));
BlockPos controlsPos1 = util.grid.at(1, 2, 5);
BlockPos controlsPos2 = util.grid.at(2, 2, 5);
BlockPos drillPos = util.grid.at(2, 1, 4);
BlockPos harvesterPos = util.grid.at(1, 1, 4);
Selection leverCol = util.select.fromTo(0, 0, 5, 0, 2, 5);
BlockPos leverPos = util.grid.at(0, 2, 5);
scene.idle(5);
scene.world.showSection(util.select.position(wheatPos), Direction.UP);
scene.world.showSection(util.select.position(cobblePos), Direction.UP);
scene.idle(10);
scene.world.showSection(util.select.position(bearingPos), Direction.DOWN);
scene.idle(5);
ElementLink<WorldSectionElement> contraptionLink =
scene.world.showIndependentSection(contraption, Direction.DOWN);
scene.world.configureCenterOfRotation(contraptionLink, util.vector.centerOf(bearingPos));
scene.idle(10);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(-280));
scene.world.setKineticSpeed(util.select.position(drillPos), 64);
scene.world.rotateBearing(bearingPos, -30, 20);
scene.world.rotateSection(contraptionLink, 0, -30, 0, 20);
BlockState harvested = Blocks.WHEAT.defaultBlockState();
scene.idle(20);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.topOf(cobblePos))
.text("Actors on moving contraptions are always active by default");
for (int i = 0; i < 10; i++) {
scene.idle(3);
scene.world.incrementBlockBreakingProgress(cobblePos);
}
Vec3 m = util.vector.of(.1, 0, -.1);
ItemStack cobbleItem = new ItemStack(Items.COBBLESTONE);
ItemStack wheatItem = new ItemStack(Items.WHEAT);
ElementLink<EntityElement> item1 = scene.world.createItemEntity(util.vector.centerOf(cobblePos), m, cobbleItem);
scene.idle(5);
scene.world.rotateBearing(bearingPos, -60, 40);
scene.world.rotateSection(contraptionLink, 0, -60, 0, 40);
scene.idle(5);
scene.world.setBlock(wheatPos, harvested, true);
ElementLink<EntityElement> item2 = scene.world.createItemEntity(util.vector.centerOf(wheatPos), m, wheatItem);
scene.idle(35);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(0));
scene.world.setKineticSpeed(util.select.position(drillPos), 0);
scene.idle(5);
scene.world.modifyEntity(item1, Entity::discard);
scene.world.modifyEntity(item2, Entity::discard);
scene.world.hideIndependentSection(contraptionLink, Direction.UP);
scene.idle(15);
contraptionLink = scene.world.showIndependentSection(contraption, Direction.DOWN);
scene.world.configureCenterOfRotation(contraptionLink, util.vector.centerOf(bearingPos));
scene.world.moveSection(contraptionLink, util.vector.of(0, 1 / 512f, 0), 0);
scene.world.restoreBlocks(util.select.position(wheatPos));
scene.world.restoreBlocks(util.select.position(cobblePos));
scene.idle(10);
scene.world.showSectionAndMerge(util.select.position(controlsPos1), Direction.DOWN, contraptionLink);
scene.idle(15);
scene.effects.superGlue(controlsPos1, Direction.DOWN, true);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.topOf(controlsPos1)
.add(0, -4 / 16f, 0))
.attachKeyFrame()
.text("Contraption Controls can be used to toggle them on the fly");
scene.idle(55);
scene.world.rotateBearing(bearingPos, -15, 10);
scene.world.rotateSection(contraptionLink, 0, -15, 0, 10);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(-280));
scene.world.setKineticSpeed(util.select.position(drillPos), 64);
scene.idle(10);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(0));
scene.world.setKineticSpeed(util.select.position(drillPos), 0);
scene.overlay.showControls(new InputWindowElement(util.vector.of(1.5, 2.75, 4.5), Pointing.DOWN).rightClick(),
15);
scene.idle(7);
scene.world.modifyBlockEntity(controlsPos1, ContraptionControlsBlockEntity.class, ccte -> ccte.disabled = true);
scene.effects.indicateRedstone(util.grid.at(1, 2, 4));
scene.idle(10);
scene.world.rotateBearing(bearingPos, -60, 40);
scene.world.rotateSection(contraptionLink, 0, -60, 0, 40);
scene.idle(40);
scene.overlay.showControls(new InputWindowElement(util.vector.of(3.5, 2.75, 1), Pointing.DOWN).rightClick(),
15);
scene.idle(7);
scene.world.modifyBlockEntity(controlsPos1, ContraptionControlsBlockEntity.class,
ccte -> ccte.disabled = false);
scene.effects.indicateRedstone(util.grid.at(3, 2, 0));
scene.idle(10);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(-280));
scene.world.setKineticSpeed(util.select.position(drillPos), 64);
scene.world.rotateBearing(bearingPos, -15, 10);
scene.world.rotateSection(contraptionLink, 0, -15, 0, 10);
scene.idle(10);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(0));
scene.world.setKineticSpeed(util.select.position(drillPos), 0);
scene.idle(5);
scene.world.hideIndependentSection(contraptionLink, Direction.UP);
scene.idle(15);
contraptionLink = scene.world.showIndependentSection(contraption, Direction.DOWN);
scene.world.showSectionAndMerge(util.select.position(controlsPos1), Direction.DOWN, contraptionLink);
scene.world.configureCenterOfRotation(contraptionLink, util.vector.centerOf(bearingPos));
scene.world.moveSection(contraptionLink, util.vector.of(0, 1 / 512f, 0), 0);
scene.idle(15);
scene.world.showSectionAndMerge(util.select.position(controlsPos2), Direction.DOWN, contraptionLink);
scene.idle(15);
scene.effects.superGlue(controlsPos2, Direction.DOWN, true);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.topOf(controlsPos2)
.add(0, -4 / 16f, 0))
.attachKeyFrame()
.text("They can be attached anywhere on the contraption");
scene.idle(75);
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(controlsPos2), Pointing.DOWN).rightClick()
.withItem(AllBlocks.MECHANICAL_DRILL.asStack()), 30);
scene.idle(5);
scene.overlay.showControls(new InputWindowElement(util.vector.centerOf(controlsPos1), Pointing.UP).rightClick()
.withItem(AllBlocks.MECHANICAL_HARVESTER.asStack()), 25);
scene.idle(2);
scene.world.setFilterData(util.select.position(controlsPos2), ContraptionControlsBlockEntity.class,
AllBlocks.MECHANICAL_DRILL.asStack());
scene.idle(5);
scene.world.setFilterData(util.select.position(controlsPos1), ContraptionControlsBlockEntity.class,
AllBlocks.MECHANICAL_HARVESTER.asStack());
scene.idle(30);
scene.overlay.showText(90)
.placeNearTarget()
.independent(80)
.attachKeyFrame()
.text("While disassembled, the filter can be changed to target specific types of actors");
scene.idle(90);
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(controlsPos2), Pointing.RIGHT).rightClick(),
15);
scene.idle(7);
scene.world.modifyBlockEntity(controlsPos2, ContraptionControlsBlockEntity.class, ccte -> ccte.disabled = true);
scene.effects.indicateRedstone(controlsPos2);
scene.idle(10);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(-280));
scene.world.rotateBearing(bearingPos, -90, 60);
scene.world.rotateSection(contraptionLink, 0, -90, 0, 60);
scene.idle(25);
scene.world.setBlock(wheatPos, harvested, true);
ElementLink<EntityElement> item3 = scene.world.createItemEntity(util.vector.centerOf(wheatPos), m, wheatItem);
scene.idle(35);
scene.world.modifyBlockEntity(harvesterPos, HarvesterBlockEntity.class, hte -> hte.setAnimatedSpeed(0));
scene.idle(5);
scene.world.modifyEntity(item3, Entity::discard);
scene.world.hideIndependentSection(contraptionLink, Direction.UP);
scene.idle(15);
scene.world.modifyBlockEntity(controlsPos2, ContraptionControlsBlockEntity.class,
ccte -> ccte.disabled = false);
contraptionLink = scene.world.showIndependentSection(contraption, Direction.DOWN);
scene.world.showSectionAndMerge(util.select.position(controlsPos1), Direction.DOWN, contraptionLink);
scene.world.showSectionAndMerge(util.select.position(controlsPos2), Direction.DOWN, contraptionLink);
scene.world.configureCenterOfRotation(contraptionLink, util.vector.centerOf(bearingPos));
scene.world.moveSection(contraptionLink, util.vector.of(0, 1 / 512f, 0), 0);
scene.world.restoreBlocks(util.select.position(wheatPos));
scene.idle(30);
scene.world.showSection(leverCol, Direction.EAST);
scene.overlay.showText(50)
.placeNearTarget()
.independent(100)
.attachKeyFrame()
.text("If it is redstone-activated during assembly...");
scene.idle(30);
scene.world.toggleRedstonePower(leverCol);
scene.effects.indicateRedstone(leverPos);
scene.world.modifyBlockEntity(controlsPos1, ContraptionControlsBlockEntity.class, ccte -> ccte.disabled = true);
scene.idle(35);
scene.world.setKineticSpeed(util.select.position(drillPos), 64);
scene.world.rotateBearing(bearingPos, -30, 20);
scene.world.rotateSection(contraptionLink, 0, -30, 0, 20);
scene.idle(20);
scene.overlay.showText(60)
.placeNearTarget()
.pointAt(util.vector.centerOf(wheatPos))
.text("...targeted actors will be turned off from the start");
for (int i = 0; i < 10; i++) {
scene.idle(3);
scene.world.incrementBlockBreakingProgress(cobblePos);
}
ElementLink<EntityElement> item4 = scene.world.createItemEntity(util.vector.centerOf(cobblePos), m, cobbleItem);
scene.idle(5);
scene.world.rotateBearing(bearingPos, -60, 40);
scene.world.rotateSection(contraptionLink, 0, -60, 0, 40);
scene.idle(40);
scene.world.setKineticSpeed(util.select.position(drillPos), 0);
scene.idle(5);
scene.world.modifyEntity(item4, Entity::discard);
}
}

View file

@ -182,12 +182,16 @@ public class PonderIndex {
HELPER.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON)
.addStoryBoard("mechanical_piston/modes", PistonScenes::movementModes);
// Windmill Bearing
// Pulleys
HELPER.forComponents(AllBlocks.ROPE_PULLEY)
.addStoryBoard("rope_pulley/anchor", PulleyScenes::movement, PonderTag.KINETIC_APPLIANCES,
PonderTag.MOVEMENT_ANCHOR)
.addStoryBoard("rope_pulley/modes", PulleyScenes::movementModes)
.addStoryBoard("rope_pulley/multi_rope", PulleyScenes::multiRope)
.addStoryBoard("rope_pulley/attachment", PulleyScenes::attachment);
HELPER.forComponents(AllBlocks.ELEVATOR_PULLEY)
.addStoryBoard("elevator_pulley/elevator", ElevatorScenes::elevator)
.addStoryBoard("elevator_pulley/multi_rope", ElevatorScenes::multiRope);
// Windmill Bearing
HELPER.forComponents(AllBlocks.WINDMILL_BEARING)
@ -252,6 +256,11 @@ public class PonderIndex {
.addStoryBoard("harvester", MovementActorScenes::harvester);
HELPER.forComponents(AllBlocks.MECHANICAL_PLOUGH)
.addStoryBoard("plough", MovementActorScenes::plough);
HELPER.forComponents(AllBlocks.CONTRAPTION_CONTROLS)
.addStoryBoard("contraption_controls", MovementActorScenes::contraptionControls);
HELPER.forComponents(AllBlocks.MECHANICAL_ROLLER)
.addStoryBoard("mechanical_roller/clear_and_pave", RollerScenes::clearAndPave)
.addStoryBoard("mechanical_roller/fill", RollerScenes::fill);
// Fluids
HELPER.forComponents(AllBlocks.FLUID_PIPE)
@ -305,6 +314,11 @@ public class PonderIndex {
HELPER.forComponents(AllBlocks.ROSE_QUARTZ_LAMP)
.addStoryBoard("rose_quartz_lamp", RedstoneScenes2::roseQuartzLamp);
HELPER.forComponents(AllBlocks.SMART_OBSERVER)
.addStoryBoard("smart_observer", DetectorScenes::smartObserver);
HELPER.forComponents(AllBlocks.THRESHOLD_SWITCH)
.addStoryBoard("threshold_switch", DetectorScenes::thresholdSwitch);
// Trains
HELPER.forComponents(AllBlocks.TRACK)
.addStoryBoard("train_track/placement", TrackScenes::placement)
@ -402,6 +416,7 @@ public class PonderIndex {
.add(AllBlocks.MECHANICAL_ARM)
.add(AllBlocks.MECHANICAL_PISTON)
.add(AllBlocks.ROPE_PULLEY)
.add(AllBlocks.ELEVATOR_PULLEY)
.add(AllBlocks.MECHANICAL_BEARING)
.add(AllBlocks.GANTRY_SHAFT)
.add(AllBlocks.GANTRY_CARRIAGE)
@ -485,6 +500,8 @@ public class PonderIndex {
.add(Blocks.WHITE_WOOL);
PonderRegistry.TAGS.forTag(PonderTag.REDSTONE)
.add(AllBlocks.SMART_OBSERVER)
.add(AllBlocks.THRESHOLD_SWITCH)
.add(AllBlocks.ORANGE_NIXIE_TUBE)
.add(AllBlocks.REDSTONE_CONTACT)
.add(AllBlocks.ANALOG_LEVER)
@ -501,6 +518,7 @@ public class PonderIndex {
.add(AllBlocks.MECHANICAL_BEARING)
.add(AllBlocks.CLOCKWORK_BEARING)
.add(AllBlocks.ROPE_PULLEY)
.add(AllBlocks.ELEVATOR_PULLEY)
.add(AllBlocks.GANTRY_CARRIAGE)
.add(AllBlocks.CART_ASSEMBLER)
.add(AllBlocks.TRACK_STATION);
@ -527,6 +545,7 @@ public class PonderIndex {
.add(AllBlocks.BRASS_FUNNEL)
.add(AllBlocks.SEATS.get(DyeColor.WHITE))
.add(AllBlocks.TRAIN_CONTROLS)
.add(AllBlocks.CONTRAPTION_CONTROLS)
.add(AllBlocks.REDSTONE_CONTACT)
.add(Blocks.BELL)
.add(Blocks.DISPENSER)

View file

@ -165,7 +165,7 @@ public class PulleyScenes {
scene.world.showSection(util.select.position(flowerPos), Direction.DOWN);
scene.overlay.showCenteredScrollInput(pulleyPos, Direction.UP, 60);
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(pulleyPos), Pointing.DOWN).rightClick(),
60);
60);
scene.overlay.showText(70)
.pointAt(util.vector.topOf(pulleyPos))
.placeNearTarget()
@ -241,4 +241,90 @@ public class PulleyScenes {
scene.idle(50);
}
public static void multiRope(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("rope_pulley_multi_rope", "Synchronised Pulley Movement");
scene.configureBasePlate(0, 0, 5);
scene.setSceneOffsetY(-1);
scene.scaleSceneView(.95f);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
Selection contraption = util.select.fromTo(3, 1, 1, 1, 1, 3);
BlockPos crankPos = util.grid.at(3, 4, 0);
BlockPos pulley1 = util.grid.at(3, 4, 1);
BlockPos pulley2 = util.grid.at(3, 4, 3);
BlockPos pulley3 = util.grid.at(1, 4, 3);
Selection kinetics = util.select.fromTo(3, 4, 0, 3, 4, 1);
ElementLink<WorldSectionElement> planksLink = scene.world.showIndependentSection(contraption, Direction.DOWN);
scene.idle(10);
scene.world.showSection(util.select.position(pulley1), Direction.DOWN);
scene.idle(4);
scene.world.showSection(util.select.position(pulley2), Direction.DOWN);
scene.idle(4);
scene.world.showSection(util.select.position(pulley3), Direction.DOWN);
scene.idle(4);
scene.world.showSection(util.select.position(crankPos), Direction.SOUTH);
scene.idle(15);
scene.world.setKineticSpeed(kinetics, 32);
scene.world.movePulley(pulley1, 2, 20);
scene.idle(20);
scene.world.setKineticSpeed(kinetics, 0);
scene.overlay.showText(60)
.pointAt(util.vector.topOf(util.grid.at(3, 1, 1)))
.placeNearTarget()
.text("Whenever a pulley assembles a contraption...");
scene.idle(70);
scene.world.movePulley(pulley2, 2, 0);
scene.world.movePulley(pulley3, 2, 0);
scene.idle(1);
scene.world.setKineticSpeed(kinetics, -32);
scene.world.movePulley(pulley1, -2, 20);
scene.world.movePulley(pulley2, -2, 20);
scene.world.movePulley(pulley3, -2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, 2, 0), 20);
scene.idle(20);
scene.world.setKineticSpeed(kinetics, 0);
scene.overlay.showText(80)
.pointAt(util.vector.blockSurface(util.grid.at(1, 4, 3), Direction.WEST))
.placeNearTarget()
.text("...other pulleys on the same layer will connect to the structure");
scene.idle(60);
scene.world.setKineticSpeed(kinetics, 32);
scene.world.movePulley(pulley1, 2, 20);
scene.world.movePulley(pulley2, 2, 20);
scene.world.movePulley(pulley3, 2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, -2, 0), 20);
scene.idle(20);
scene.world.setKineticSpeed(kinetics, 0);
scene.idle(20);
scene.world.setKineticSpeed(kinetics, 32);
scene.world.movePulley(pulley1, -2, 20);
scene.world.movePulley(pulley2, -2, 20);
scene.world.movePulley(pulley3, -2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, 2, 0), 20);
scene.idle(20);
scene.world.setKineticSpeed(kinetics, 0);
scene.overlay.showText(80)
.pointAt(util.vector.blockSurface(util.grid.at(1, 4, 3), Direction.WEST))
.placeNearTarget()
.text("They do not require to be powered, the effect is purely cosmetic");
scene.idle(60);
scene.world.setKineticSpeed(kinetics, 32);
scene.world.movePulley(pulley1, 2, 20);
scene.world.movePulley(pulley2, 2, 20);
scene.world.movePulley(pulley3, 2, 20);
scene.world.moveSection(planksLink, util.vector.of(0, -2, 0), 20);
scene.idle(20);
scene.world.setKineticSpeed(kinetics, 0);
}
}

View file

@ -0,0 +1,539 @@
package com.simibubi.create.foundation.ponder.content;
import com.simibubi.create.content.contraptions.components.actors.RollerBlockEntity;
import com.simibubi.create.content.logistics.trains.management.edgePoint.station.StationBlock;
import com.simibubi.create.foundation.gui.AllIcons;
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.ParrotElement;
import com.simibubi.create.foundation.ponder.element.ParrotElement.FacePointOfInterestPose;
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.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.phys.Vec3;
public class RollerScenes {
public static void clearAndPave(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("mechanical_roller_pave", "Clearing and Paving with the Roller");
scene.configureBasePlate(0, 0, 9);
scene.scaleSceneView(.75f);
scene.setSceneOffsetY(-1);
scene.showBasePlate();
scene.idle(5);
BlockPos stationPos = util.grid.at(7, 1, 1);
Selection gantryPole = util.select.fromTo(9, 5, 4, 1, 5, 4);
Selection cogs = util.select.fromTo(9, 0, 4, 9, 4, 4);
Selection gantryCar = util.select.fromTo(7, 2, 8, 7, 4, 8);
BlockPos bogeyPos = util.grid.at(7, 2, 4);
Selection someRubble = util.select.fromTo(2, 1, 3, 3, 2, 5)
.substract(util.select.fromTo(3, 1, 4, 2, 1, 4));
Selection chest = util.select.fromTo(7, 2, 5, 8, 3, 5);
Selection rollers = util.select.fromTo(6, 2, 3, 6, 2, 5);
Selection train = util.select.fromTo(8, 3, 4, 7, 2, 4);
BlockPos controlsPos = util.grid.at(7, 3, 4);
for (int i = 8; i >= 0; i--) {
scene.world.showSection(util.select.position(i, 1, 4), Direction.DOWN);
scene.idle(1);
}
scene.special.movePointOfInterest(util.grid.at(0, 3, 4));
scene.idle(5);
scene.world.showSection(util.select.position(stationPos), Direction.DOWN);
scene.idle(5);
ElementLink<ParrotElement> birbLink =
scene.special.createBirb(util.vector.centerOf(8, 3, 4), FacePointOfInterestPose::new);
ElementLink<WorldSectionElement> trainLink = scene.world.showIndependentSection(train, Direction.DOWN);
scene.idle(5);
scene.world.showSectionAndMerge(rollers, Direction.EAST, trainLink);
scene.idle(15);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, true);
scene.overlay.showText(60)
.pointAt(util.vector.topOf(util.grid.at(6, 2, 4)))
.attachKeyFrame()
.text("Mechanical rollers help to clean up long tracks or paths conveniently")
.placeNearTarget();
scene.idle(70);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, false);
scene.world.showSection(someRubble, Direction.DOWN);
scene.world.toggleControls(controlsPos);
scene.world.moveSection(trainLink, util.vector.of(-1.5, 0, 0), 30);
scene.special.moveParrot(birbLink, util.vector.of(-1.5, 0, 0), 30);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.world.animateBogey(bogeyPos, 1.5f, 30);
scene.idle(30);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.overlay.showControls(new InputWindowElement(util.vector.topOf(util.grid.at(2, 2, 4)), Pointing.DOWN)
.showing(AllIcons.I_ROLLER_PAVE), 70);
scene.overlay.showText(80)
.pointAt(util.vector.topOf(util.grid.at(2, 2, 4)))
.attachKeyFrame()
.text("In its default mode, without a material set, it will simply clear blocks like a Drill")
.placeNearTarget();
for (int i = 0; i < 10; i++) {
scene.idle(3);
scene.world.incrementBlockBreakingProgress(util.grid.at(3, 1, 5));
scene.world.incrementBlockBreakingProgress(util.grid.at(3, 1, 3));
scene.world.incrementBlockBreakingProgress(util.grid.at(3, 2, 5));
}
scene.world.moveSection(trainLink, util.vector.of(-1, 0, 0), 20);
scene.special.moveParrot(birbLink, util.vector.of(-1, 0, 0), 20);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.world.animateBogey(bogeyPos, 1f, 20);
scene.idle(20);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
for (int i = 0; i < 10; i++) {
scene.idle(3);
scene.world.incrementBlockBreakingProgress(util.grid.at(2, 2, 4));
scene.world.incrementBlockBreakingProgress(util.grid.at(2, 1, 3));
}
scene.world.moveSection(trainLink, util.vector.of(-2, 0, 0), 40);
scene.special.moveParrot(birbLink, util.vector.of(-2, 0, 0), 40);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.world.animateBogey(bogeyPos, 2f, 40);
scene.idle(40);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.special.hideElement(birbLink, Direction.UP);
scene.world.hideIndependentSection(trainLink, Direction.UP);
scene.idle(15);
birbLink = scene.special.createBirb(util.vector.centerOf(8, 3, 4), FacePointOfInterestPose::new);
trainLink = scene.world.showIndependentSection(train, Direction.DOWN);
scene.world.toggleControls(controlsPos);
scene.idle(5);
scene.world.showSectionAndMerge(rollers, Direction.EAST, trainLink);
scene.idle(15);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, true);
scene.world.hideSection(someRubble, Direction.DOWN);
Vec3 filterSlot = util.vector.of(6.75 - 1 / 16f, 3, 3.25 + 1 / 16f);
scene.overlay.showFilterSlotInput(filterSlot, Direction.UP, 60);
scene.overlay.showText(60)
.pointAt(filterSlot.add(-.125, 0, 0))
.attachKeyFrame()
.text("While disassembled, a suitable paving material can be specified")
.placeNearTarget();
scene.idle(50);
Block paveMaterial = Blocks.TUFF;
ItemStack paveItem = new ItemStack(paveMaterial);
scene.overlay.showControls(new InputWindowElement(filterSlot, Pointing.DOWN).withItem(paveItem), 40);
scene.idle(7);
scene.world.setFilterData(rollers, RollerBlockEntity.class, paveItem);
scene.idle(20);
scene.world.showSectionAndMerge(chest, Direction.DOWN, trainLink);
scene.idle(15);
scene.overlay.showText(70)
.pointAt(util.vector.topOf(util.grid.at(7, 3, 5)))
.text("Materials can be supplied via chests or barrels attached to the structure")
.placeNearTarget();
scene.idle(60);
scene.world.restoreBlocks(someRubble);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, false);
scene.world.showSection(someRubble, Direction.DOWN);
scene.world.toggleControls(controlsPos);
scene.world.showSection(someRubble, Direction.DOWN);
scene.world.moveSection(trainLink, util.vector.of(-1.5, 0, 0), 30);
scene.special.moveParrot(birbLink, util.vector.of(-1.5, 0, 0), 30);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.world.animateBogey(bogeyPos, 1.5f, 30);
scene.world.replaceBlocks(util.select.fromTo(5, 0, 3, 5, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(20);
scene.world.replaceBlocks(util.select.fromTo(4, 0, 3, 4, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(10);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.overlay.showText(80)
.pointAt(util.vector.topOf(util.grid.at(5, 0, 3)))
.attachKeyFrame()
.text("In addition to breaking blocks, it will now replace the layer beneath them")
.placeNearTarget();
for (int i = 0; i < 10; i++) {
scene.idle(3);
scene.world.incrementBlockBreakingProgress(util.grid.at(3, 1, 5));
scene.world.incrementBlockBreakingProgress(util.grid.at(3, 1, 3));
scene.world.incrementBlockBreakingProgress(util.grid.at(3, 2, 5));
}
scene.world.moveSection(trainLink, util.vector.of(-1, 0, 0), 20);
scene.special.moveParrot(birbLink, util.vector.of(-1, 0, 0), 20);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.world.animateBogey(bogeyPos, 1f, 20);
scene.idle(10);
scene.world.replaceBlocks(util.select.fromTo(3, 0, 3, 3, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(10);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
for (int i = 0; i < 10; i++) {
scene.idle(3);
scene.world.incrementBlockBreakingProgress(util.grid.at(2, 2, 4));
scene.world.incrementBlockBreakingProgress(util.grid.at(2, 1, 3));
}
scene.world.moveSection(trainLink, util.vector.of(-3, 0, 0), 60);
scene.special.moveParrot(birbLink, util.vector.of(-3, 0, 0), 60);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.world.animateBogey(bogeyPos, 3f, 60);
scene.idle(10);
scene.world.replaceBlocks(util.select.fromTo(2, 0, 3, 2, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(20);
scene.world.replaceBlocks(util.select.fromTo(1, 0, 3, 1, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(20);
scene.world.replaceBlocks(util.select.fromTo(0, 0, 3, 0, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(10);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.special.hideElement(birbLink, Direction.UP);
scene.world.hideIndependentSection(trainLink, Direction.UP);
scene.idle(5);
scene.world.hideSection(util.select.fromTo(8, 1, 4, 0, 1, 4), Direction.SOUTH);
scene.world.hideSection(util.select.position(stationPos), Direction.UP);
scene.idle(10);
scene.overlay.showSelectionWithText(util.select.fromTo(5, 0, 3, 0, 0, 5), 90)
.pointAt(util.vector.topOf(util.grid.at(3, 0, 4)))
.attachKeyFrame()
.colored(PonderPalette.RED)
.text("Note that any block destroyed by a roller has a chance not to yield drops")
.placeNearTarget();
scene.idle(100);
scene.world.showSection(gantryPole, Direction.DOWN);
scene.world.showSection(cogs, Direction.WEST);
scene.idle(10);
ElementLink<WorldSectionElement> gantryLink = scene.world.showIndependentSection(gantryCar, Direction.UP);
scene.world.moveSection(gantryLink, util.vector.of(0, 0, -4), 0);
scene.idle(10);
ElementLink<WorldSectionElement> gantryLink2 = scene.world.showIndependentSection(rollers, Direction.EAST);
scene.idle(5);
ElementLink<WorldSectionElement> gantryLink3 = scene.world.showIndependentSection(chest, Direction.SOUTH);
scene.world.moveSection(gantryLink3, util.vector.of(0, 0, -2), 0);
scene.idle(15);
paveMaterial = Blocks.GRASS_BLOCK;
paveItem = new ItemStack(paveMaterial);
scene.overlay.showControls(new InputWindowElement(filterSlot, Pointing.DOWN).withItem(paveItem), 40);
scene.idle(7);
scene.world.setFilterData(rollers, RollerBlockEntity.class, paveItem);
scene.idle(20);
scene.overlay.showText(110)
.independent()
.attachKeyFrame()
.text(
"Rollers are especially useful on Trains, but can also be used on most other types of moving contraptions");
scene.idle(20);
scene.world.moveSection(gantryLink, util.vector.of(-5.5, 0, 0), 110);
scene.world.moveSection(gantryLink2, util.vector.of(-5.5, 0, 0), 110);
scene.world.moveSection(gantryLink3, util.vector.of(-5.5, 0, 0), 110);
scene.world.setKineticSpeed(gantryPole, 48);
for (int i = 0; i < 5; i++)
scene.world.setKineticSpeed(util.select.position(9, i, 4), i % 2 == 0 ? -48 : 48);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
for (int i = 0; i < 5; i++) {
scene.world.replaceBlocks(util.select.fromTo(5 - i, 0, 3, 5 - i, 0, 5), paveMaterial.defaultBlockState(),
true);
scene.idle(20);
}
scene.world.replaceBlocks(util.select.fromTo(0, 0, 3, 0, 0, 5), paveMaterial.defaultBlockState(), true);
scene.idle(10);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 2, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.world.setKineticSpeed(util.select.everywhere(), 0);
}
public static void fill(SceneBuilder scene, SceneBuildingUtil util) {
scene.title("mechanical_roller_fill", "Filling terrain with the Roller");
scene.configureBasePlate(0, 0, 9);
scene.scaleSceneView(.625f);
scene.setSceneOffsetY(-3);
scene.world.showSection(util.select.layer(0), Direction.UP);
scene.idle(5);
BlockPos stationPos = util.grid.at(7, 5, 1);
BlockPos controlsPos = util.grid.at(7, 7, 4);
BlockPos bogeyPos = util.grid.at(7, 6, 4);
Selection train = util.select.fromTo(8, 6, 4, 7, 7, 5);
Selection rollers = util.select.fromTo(6, 6, 3, 6, 6, 5);
scene.special.movePointOfInterest(util.grid.at(0, 7, 4));
for (int i = 8; i >= 0; i--) {
scene.world.showSection(util.select.fromTo(i, 4, 3, i, 5, 5), Direction.DOWN);
scene.idle(1);
}
// 1
scene.idle(5);
scene.world.showSection(util.select.fromTo(8, 1, 2, 6, 4, 2), Direction.DOWN);
scene.world.showSection(util.select.fromTo(8, 1, 6, 6, 4, 6), Direction.DOWN);
scene.idle(5);
scene.world.showSection(util.select.fromTo(7, 4, 1, 7, 5, 1), Direction.SOUTH);
scene.idle(5);
ElementLink<WorldSectionElement> trainLink = scene.world.showIndependentSection(train, Direction.DOWN);
ElementLink<ParrotElement> birbLink =
scene.special.createBirb(util.vector.centerOf(8, 7, 4), FacePointOfInterestPose::new);
scene.idle(5);
scene.world.showSectionAndMerge(rollers, Direction.EAST, trainLink);
scene.idle(15);
Vec3 filterSlot = util.vector.of(6.75 - 1 / 16f, 7, 3.75 - 1 / 16f);
scene.overlay.showFilterSlotInput(filterSlot, Direction.UP, 60);
scene.overlay.showText(60)
.pointAt(filterSlot.add(-.125, 0, 0))
.attachKeyFrame()
.text("While disassembled, rollers can be set to other modes")
.placeNearTarget();
scene.idle(70);
scene.overlay.showSelectionWithText(util.select.fromTo(5, 3, 3, 0, 1, 5), 90)
.attachKeyFrame()
.colored(PonderPalette.BLUE)
.text("The 'fill' modes can help to bridge gaps between pavement and terrain")
.placeNearTarget();
scene.idle(100);
scene.overlay.showControls(new InputWindowElement(filterSlot, Pointing.DOWN).showing(AllIcons.I_ROLLER_FILL),
50);
scene.idle(15);
Block paveMaterial = Blocks.COARSE_DIRT;
ItemStack paveItem = new ItemStack(paveMaterial);
scene.overlay
.showControls(new InputWindowElement(filterSlot.add(0, 0, -6 / 16f), Pointing.UP).withItem(paveItem), 35);
scene.idle(7);
scene.world.setFilterData(rollers, RollerBlockEntity.class, paveItem);
scene.idle(10);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, false);
scene.world.toggleControls(controlsPos);
scene.idle(20);
scene.world.moveSection(trainLink, util.vector.of(-5.5, 0, 0), 110);
scene.special.moveParrot(birbLink, util.vector.of(-5.5, 0, 0), 110);
scene.world.animateBogey(bogeyPos, 5.5f, 110);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 6, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
for (int j = 0; j < 5; j++) {
for (int i = 0; i < 3; i++) {
scene.world.showSection(util.select.fromTo(5 - j, 3 - i, 3, 5 - j, 3 - i, 5), null);
scene.idle(2);
}
if (j == 2)
scene.overlay.showText(90)
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(3, 2, 3), Direction.NORTH))
.text("On 'straight fill', they will place simple columns down to the surface")
.placeNearTarget();
scene.idle(14);
}
for (int i = 0; i < 3; i++) {
scene.world.showSection(util.select.fromTo(0, 3 - i, 3, 0, 3 - i, 5), null);
scene.idle(2);
}
scene.idle(4);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 6, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.idle(15);
scene.world.hideSection(util.select.fromTo(5, 1, 3, 0, 3, 5), Direction.SOUTH);
scene.world.hideIndependentSection(trainLink, Direction.UP);
scene.special.hideElement(birbLink, Direction.UP);
scene.idle(15);
scene.world.toggleControls(controlsPos);
scene.idle(15);
// 2
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, true);
birbLink = scene.special.createBirb(util.vector.centerOf(8, 7, 4), FacePointOfInterestPose::new);
trainLink = scene.world.showIndependentSection(train, Direction.DOWN);
scene.idle(5);
scene.world.showSectionAndMerge(rollers, Direction.EAST, trainLink);
scene.idle(25);
scene.overlay
.showControls(new InputWindowElement(filterSlot, Pointing.DOWN).showing(AllIcons.I_ROLLER_WIDE_FILL), 40);
scene.idle(45);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, false);
scene.world.toggleControls(controlsPos);
scene.idle(20);
scene.world.moveSection(trainLink, util.vector.of(-5.5, 0, 0), 110);
scene.special.moveParrot(birbLink, util.vector.of(-5.5, 0, 0), 110);
scene.world.animateBogey(bogeyPos, 5.5f, 110);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 6, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
for (int j = 0; j < 5; j++) {
for (int i = 0; i < 3; i++) {
scene.world.showSection(util.select.fromTo(5 - j, 3 - i, 1, 5 - j, 3 - i, 7), null);
scene.idle(2);
}
if (j == 2)
scene.overlay.showText(90)
.attachKeyFrame()
.pointAt(util.vector.blockSurface(util.grid.at(3, 2, 3), Direction.NORTH))
.text("On 'sloped fill', layers placed further down will increase in size")
.placeNearTarget();
scene.idle(14);
}
for (int i = 0; i < 3; i++) {
scene.world.showSection(util.select.fromTo(0, 3 - i, 1, 0, 3 - i, 7), null);
scene.idle(2);
}
scene.idle(4);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 6, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
scene.idle(15);
scene.world.hideSection(util.select.fromTo(5, 1, 1, 0, 3, 7), Direction.SOUTH);
scene.world.hideIndependentSection(trainLink, Direction.UP);
scene.special.hideElement(birbLink, Direction.UP);
scene.idle(15);
scene.world.toggleControls(controlsPos);
scene.world.replaceBlocks(util.select.fromTo(5, 1, 3, 0, 3, 5), Blocks.COBBLESTONE.defaultBlockState(), false);
scene.idle(15);
// 3
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, true);
scene.world.showSection(util.select.fromTo(5, 1, 3, 0, 3, 5), Direction.NORTH);
birbLink = scene.special.createBirb(util.vector.centerOf(8, 7, 4), FacePointOfInterestPose::new);
trainLink = scene.world.showIndependentSection(train, Direction.DOWN);
scene.idle(5);
scene.world.showSectionAndMerge(rollers, Direction.EAST, trainLink);
scene.idle(25);
scene.world.cycleBlockProperty(stationPos, StationBlock.ASSEMBLING);
scene.world.animateTrainStation(stationPos, false);
scene.world.toggleControls(controlsPos);
scene.idle(20);
scene.world.moveSection(trainLink, util.vector.of(-5.5, 0, 0), 110);
scene.special.moveParrot(birbLink, util.vector.of(-5.5, 0, 0), 110);
scene.world.animateBogey(bogeyPos, 5.5f, 110);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 6, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(-100));
scene.overlay.showText(110)
.attachKeyFrame()
.independent()
.text(
"As opposed to 'clear & pave', neither of these modes will cause the rollers to break existing blocks")
.placeNearTarget();
for (int j = 0; j < 5; j++) {
for (int i = 0; i < 3; i++) {
scene.world.showSection(util.select.fromTo(5 - j, 3 - i, 1, 5 - j, 3 - i, 7), null);
scene.idle(2);
}
scene.idle(14);
}
for (int i = 0; i < 3; i++) {
scene.world.showSection(util.select.fromTo(0, 3 - i, 1, 0, 3 - i, 7), null);
scene.idle(2);
}
scene.rotateCameraY(-30);
scene.idle(4);
for (int i = 0; i < 3; i++)
scene.world.modifyBlockEntity(util.grid.at(6, 6, 3 + i), RollerBlockEntity.class,
rte -> rte.setAnimatedSpeed(0));
}
}

View file

@ -433,7 +433,7 @@ public class PonderUI extends NavigatableSimiScreen {
protected void renderScene(PoseStack ms, int mouseX, int mouseY, int i, float partialTicks) {
SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance();
PonderScene story = scenes.get(i);
PonderScene scene = scenes.get(i);
double value = lazyIndex.getValue(minecraft.getFrameTime());
double diff = i - value;
double slide = Mth.lerp(diff * diff, 200, 600) * diff;
@ -449,24 +449,29 @@ public class PonderUI extends NavigatableSimiScreen {
ms.pushPose();
ms.translate(0, 0, -800);
story.getTransform()
scene.getTransform()
.updateScreenParams(width, height, slide);
story.getTransform()
scene.getTransform()
.apply(ms, partialTicks);
story.getTransform()
// ms.translate(-story.getBasePlateOffsetX() * .5, 0, -story.getBasePlateOffsetZ() * .5);
scene.getTransform()
.updateSceneRVE(partialTicks);
story.renderScene(buffer, ms, partialTicks);
scene.renderScene(buffer, ms, partialTicks);
buffer.draw();
BoundingBox bounds = story.getBounds();
BoundingBox bounds = scene.getBounds();
ms.pushPose();
// kool shadow fx
{
if (!scene.shouldHidePlatformShadow()) {
RenderSystem.enableCull();
RenderSystem.enableDepthTest();
ms.pushPose();
ms.translate(story.getBasePlateOffsetX(), 0, story.getBasePlateOffsetZ());
ms.translate(scene.getBasePlateOffsetX(), 0, scene.getBasePlateOffsetZ());
UIRenderHelper.flipForGuiRender(ms);
float flash = finishingFlash.getValue(partialTicks) * .9f;
@ -477,21 +482,21 @@ public class PonderUI extends NavigatableSimiScreen {
flash = 1 - flash;
for (int f = 0; f < 4; f++) {
ms.translate(story.getBasePlateSize(), 0, 0);
ms.translate(scene.getBasePlateSize(), 0, 0);
ms.pushPose();
ms.translate(0, 0, -1 / 1024f);
if (flash > 0) {
ms.pushPose();
ms.scale(1, .5f + flash * .75f, 1);
GuiUtils.drawGradientRect(ms.last()
.pose(), 0, 0, -1, -story.getBasePlateSize(), 0, 0x00_c6ffc9,
.pose(), 0, 0, -1, -scene.getBasePlateSize(), 0, 0x00_c6ffc9,
new Color(0xaa_c6ffc9).scaleAlpha(alpha)
.getRGB());
ms.popPose();
}
ms.translate(0, 0, 2 / 1024f);
GuiUtils.drawGradientRect(ms.last()
.pose(), 0, 0, 0, -story.getBasePlateSize(), 4, 0x66_000000, 0x00_000000);
.pose(), 0, 0, 0, -scene.getBasePlateSize(), 4, 0x66_000000, 0x00_000000);
ms.popPose();
ms.mulPose(Vector3f.YP.rotationDegrees(-90));
}

View file

@ -814,8 +814,8 @@
"create.train_assembly.bogeys_too_close": "Bogeys %1$s and %2$s are too close to each other",
"create.train_assembly.single_bogey_carriage": "This Bogey type cannot support a carriage on its own",
"create.train_assembly.nothing_attached": "No structure attached to Bogey %1$s",
"create.train_assembly.no_controls": "At least one forward-facing controls block needs to be mounted on the train",
"create.train_assembly.sideways_controls": "A mounted controls block is facing sideways",
"create.train_assembly.no_controls": "Attach at least one forward-facing Train Controls block (Are you missing Super Glue?)",
"create.train_assembly.sideways_controls": "Train Controls cannot face sideways",
"create.train_assembly.bogey_created": "Bogey created. Click again to cycle type",
"create.train_assembly.requires_casing": "Use Railway Casing to create bogeys on tracks",

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [1, 0.5, 7, 3.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [1, 4.5, 7, 7.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [1, 8.5, 7, 11.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [1, 12.5, 7, 15.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [9, 0.5, 15, 3.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [9, 4.5, 15, 7.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [9, 8.5, 15, 11.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

View file

@ -1,52 +1,16 @@
{
"credit": "Made with Blockbench",
"textures": {
"4": "create:block/contraption_controls_indicator",
"particle": "create:block/andesite_casing"
"4": "create:block/contraption_controls_indicator"
},
"elements": [
{
"from": [2, 9.05, 8],
"to": [14, 10.05, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10, 7]},
"from": [2, 9.125, 8],
"to": [14, 10.125, 14],
"rotation": {"angle": -22.5, "axis": "x", "origin": [8, 10.1, 7]},
"faces": {
"up": {"uv": [9, 12.5, 15, 15.5], "rotation": 180, "texture": "#4"}
}
}
],
"display": {
"thirdperson_righthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"thirdperson_lefthand": {
"rotation": [75, 45, 0],
"translation": [0, 2.5, 0],
"scale": [0.375, 0.375, 0.375]
},
"firstperson_righthand": {
"rotation": [0, 45, 0],
"scale": [0.4, 0.4, 0.4]
},
"firstperson_lefthand": {
"rotation": [0, 225, 0],
"scale": [0.4, 0.4, 0.4]
},
"ground": {
"translation": [0, 3, 0],
"scale": [0.25, 0.25, 0.25]
},
"gui": {
"rotation": [30, 225, 0],
"translation": [1.5, -0.25, 0],
"scale": [0.625, 0.625, 0.625]
},
"head": {
"translation": [0, 8.5, -2.25]
},
"fixed": {
"scale": [0.5, 0.5, 0.5]
}
}
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 B

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 B

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 B

After

Width:  |  Height:  |  Size: 311 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 B

After

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 B

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 323 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 B

After

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

After

Width:  |  Height:  |  Size: 324 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 312 B

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 311 B

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 B

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 B

After

Width:  |  Height:  |  Size: 337 B