diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index a637eb415..2b3ccbc27 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -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 diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 79b43b999..f26e5a388 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -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", diff --git a/src/generated/resources/data/create/tags/items/contraption_controlled.json b/src/generated/resources/data/create/tags/items/contraption_controlled.json new file mode 100644 index 000000000..1d5d6242f --- /dev/null +++ b/src/generated/resources/data/create/tags/items/contraption_controlled.json @@ -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" + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 545277640..474fd14cc 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -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 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(); diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index b42d1a742..f04306853 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -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()); diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index 212140104..49bf64205 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -158,6 +158,7 @@ public class AllTags { VANILLA_STRIPPED_LOGS, VANILLA_STRIPPED_WOOD, DEPLOYABLE_DRINK, + CONTRAPTION_CONTROLLED, STRIPPED_LOGS(FORGE), STRIPPED_WOOD(FORGE), diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java index ca3eb6234..ef99b83ed 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java @@ -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 diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java index 5948a02f6..a66e9d915 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java @@ -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 diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlock.java index 1f5e5e15c..f28206e1c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlock.java @@ -30,9 +30,9 @@ public class ContraptionControlsBlock extends ControlsBlock implements IBE { 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); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlockEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlockEntity.java index e6ac8628d..33300530f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlockEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/controls/ContraptionControlsBlockEntity.java @@ -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 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 diff --git a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java index dd68ca090..d6e702da2 100644 --- a/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/blockEntity/behaviour/filtering/FilteringBehaviour.java @@ -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()); diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index 279c4c661..48678d564 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -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(); } diff --git a/src/main/java/com/simibubi/create/foundation/data/TagGen.java b/src/main/java/com/simibubi/create/foundation/data/TagGen.java index 537a44958..eb90bd682 100644 --- a/src/main/java/com/simibubi/create/foundation/data/TagGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/TagGen.java @@ -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, diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java index 731838dc7..0b3ca6220 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -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; } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java index 5012f7d28..f5db20afb 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java @@ -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 diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/DetectorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/DetectorScenes.java new file mode 100644 index 000000000..97becf7f4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/DetectorScenes.java @@ -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 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 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 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 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 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 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 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); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ElevatorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ElevatorScenes.java new file mode 100644 index 000000000..5f48deda9 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ElevatorScenes.java @@ -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 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 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 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 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); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java index 76b1b15e4..311dee766 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java @@ -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 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 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 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 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 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); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java index b729686cc..2ad9e4cb0 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java @@ -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) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java index 5f188bf24..e53ce1eb4 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java @@ -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 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); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java new file mode 100644 index 000000000..f36863473 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java @@ -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 birbLink = + scene.special.createBirb(util.vector.centerOf(8, 3, 4), FacePointOfInterestPose::new); + ElementLink 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 gantryLink = scene.world.showIndependentSection(gantryCar, Direction.UP); + scene.world.moveSection(gantryLink, util.vector.of(0, 0, -4), 0); + scene.idle(10); + ElementLink gantryLink2 = scene.world.showIndependentSection(rollers, Direction.EAST); + scene.idle(5); + ElementLink 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 trainLink = scene.world.showIndependentSection(train, Direction.DOWN); + ElementLink 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)); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java index 1b4b34e75..f7241cb9f 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderUI.java @@ -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)); } diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 5288441cb..6df56d4e4 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -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", diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_0.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_0.json index 3be842dcc..0271a29c0 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_0.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_0.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_1.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_1.json index 5c4e856cb..346f112a8 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_1.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_1.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_2.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_2.json index 3da3a805e..63abf0138 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_2.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_2.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_3.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_3.json index c3e33150e..cca5e8b25 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_3.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_3.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_4.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_4.json index 8f4a0a243..fbaaf3f6c 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_4.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_4.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_5.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_5.json index 093fd61d9..8484489f1 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_5.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_5.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_6.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_6.json index 466ed81e6..17e456a3c 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_6.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_6.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/contraption_controls/indicator_7.json b/src/main/resources/assets/create/models/block/contraption_controls/indicator_7.json index 9a7d32687..f0ddc3964 100644 --- a/src/main/resources/assets/create/models/block/contraption_controls/indicator_7.json +++ b/src/main/resources/assets/create/models/block/contraption_controls/indicator_7.json @@ -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] - } - } + ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/ponder/contraption_controls.nbt b/src/main/resources/assets/create/ponder/contraption_controls.nbt new file mode 100644 index 000000000..3619f93d0 Binary files /dev/null and b/src/main/resources/assets/create/ponder/contraption_controls.nbt differ diff --git a/src/main/resources/assets/create/ponder/elevator_pulley/elevator.nbt b/src/main/resources/assets/create/ponder/elevator_pulley/elevator.nbt new file mode 100644 index 000000000..93223ed2f Binary files /dev/null and b/src/main/resources/assets/create/ponder/elevator_pulley/elevator.nbt differ diff --git a/src/main/resources/assets/create/ponder/elevator_pulley/multi_rope.nbt b/src/main/resources/assets/create/ponder/elevator_pulley/multi_rope.nbt new file mode 100644 index 000000000..6c9b2b243 Binary files /dev/null and b/src/main/resources/assets/create/ponder/elevator_pulley/multi_rope.nbt differ diff --git a/src/main/resources/assets/create/ponder/mechanical_roller/clear_and_pave.nbt b/src/main/resources/assets/create/ponder/mechanical_roller/clear_and_pave.nbt new file mode 100644 index 000000000..fa7469dce Binary files /dev/null and b/src/main/resources/assets/create/ponder/mechanical_roller/clear_and_pave.nbt differ diff --git a/src/main/resources/assets/create/ponder/mechanical_roller/fill.nbt b/src/main/resources/assets/create/ponder/mechanical_roller/fill.nbt new file mode 100644 index 000000000..58f464d40 Binary files /dev/null and b/src/main/resources/assets/create/ponder/mechanical_roller/fill.nbt differ diff --git a/src/main/resources/assets/create/ponder/rope_pulley/multi_rope.nbt b/src/main/resources/assets/create/ponder/rope_pulley/multi_rope.nbt new file mode 100644 index 000000000..72787dde4 Binary files /dev/null and b/src/main/resources/assets/create/ponder/rope_pulley/multi_rope.nbt differ diff --git a/src/main/resources/assets/create/ponder/smart_observer.nbt b/src/main/resources/assets/create/ponder/smart_observer.nbt new file mode 100644 index 000000000..8802ec757 Binary files /dev/null and b/src/main/resources/assets/create/ponder/smart_observer.nbt differ diff --git a/src/main/resources/assets/create/ponder/threshold_switch.nbt b/src/main/resources/assets/create/ponder/threshold_switch.nbt new file mode 100644 index 000000000..c76c7e6ee Binary files /dev/null and b/src/main/resources/assets/create/ponder/threshold_switch.nbt differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/idle.png b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/idle.png index 78d598cda..563b1e6ef 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/idle.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/idle.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/item.png b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/item.png index 420b3a152..77fb81753 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/item.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/item.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered.png b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered.png index cfa9d2c38..ffc468830 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered_powering.png b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered_powering.png index 81fa26be5..9786b88fe 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered_powering.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powered_powering.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powering.png b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powering.png index 3e9e50a50..dcc65ac43 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powering.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_extender/powering.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/idle.png b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/idle.png index f61e82a94..709426415 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/idle.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/idle.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/item.png b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/item.png index d21b7e21f..141faff21 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/item.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/item.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered.png b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered.png index 91f84b580..883e26c3e 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered_powering.png b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered_powering.png index 833d7f32d..7a9e08fdb 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered_powering.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powered_powering.png differ diff --git a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powering.png b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powering.png index 2df1cd1ea..e7e02b9c9 100644 Binary files a/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powering.png and b/src/main/resources/assets/create/textures/block/diodes/pulse_repeater/powering.png differ diff --git a/src/main/resources/assets/create/textures/block/threshold_switch/level_0.png b/src/main/resources/assets/create/textures/block/threshold_switch/level_0.png index 64d8206b7..c662934ed 100644 Binary files a/src/main/resources/assets/create/textures/block/threshold_switch/level_0.png and b/src/main/resources/assets/create/textures/block/threshold_switch/level_0.png differ diff --git a/src/main/resources/assets/create/textures/block/threshold_switch/level_1.png b/src/main/resources/assets/create/textures/block/threshold_switch/level_1.png index e350173bd..033dc3481 100644 Binary files a/src/main/resources/assets/create/textures/block/threshold_switch/level_1.png and b/src/main/resources/assets/create/textures/block/threshold_switch/level_1.png differ diff --git a/src/main/resources/assets/create/textures/block/threshold_switch/level_2.png b/src/main/resources/assets/create/textures/block/threshold_switch/level_2.png index 7ed0ef6c3..74a8f8d9d 100644 Binary files a/src/main/resources/assets/create/textures/block/threshold_switch/level_2.png and b/src/main/resources/assets/create/textures/block/threshold_switch/level_2.png differ diff --git a/src/main/resources/assets/create/textures/block/threshold_switch/level_3.png b/src/main/resources/assets/create/textures/block/threshold_switch/level_3.png index b2884e7a1..35385da11 100644 Binary files a/src/main/resources/assets/create/textures/block/threshold_switch/level_3.png and b/src/main/resources/assets/create/textures/block/threshold_switch/level_3.png differ diff --git a/src/main/resources/assets/create/textures/block/threshold_switch/level_4.png b/src/main/resources/assets/create/textures/block/threshold_switch/level_4.png index f3ba863c4..0db270533 100644 Binary files a/src/main/resources/assets/create/textures/block/threshold_switch/level_4.png and b/src/main/resources/assets/create/textures/block/threshold_switch/level_4.png differ diff --git a/src/main/resources/assets/create/textures/block/threshold_switch/level_5.png b/src/main/resources/assets/create/textures/block/threshold_switch/level_5.png index f15811850..93ba619a2 100644 Binary files a/src/main/resources/assets/create/textures/block/threshold_switch/level_5.png and b/src/main/resources/assets/create/textures/block/threshold_switch/level_5.png differ