From 0abbeaebad0f7443283f40bc3f112931626d096e Mon Sep 17 00:00:00 2001 From: simibubi <31564874+simibubi@users.noreply.github.com> Date: Sat, 6 May 2023 02:58:47 +0200 Subject: [PATCH] Will ponders ever cease? - New ponder scenes for Smart Observer, Threshold Switch, Elevator Pulley, Contraption Controls and Mechanical Rollers - Added #contraption_controlled as a tag for items accepted by the contraption controls slot --- src/generated/resources/.cache/cache | 3 +- .../resources/assets/create/lang/en_us.json | 77 ++- .../tags/items/contraption_controlled.json | 25 + .../java/com/simibubi/create/AllBlocks.java | 14 +- .../create/AllMovementBehaviours.java | 1 + .../java/com/simibubi/create/AllTags.java | 1 + .../actors/BellMovementBehaviour.java | 2 +- .../actors/CampfireMovementBehaviour.java | 2 +- .../controls/ContraptionControlsBlock.java | 4 +- .../ContraptionControlsBlockEntity.java | 4 +- .../filtering/FilteringBehaviour.java | 2 +- .../foundation/data/BuilderTransformers.java | 2 + .../create/foundation/data/TagGen.java | 3 + .../create/foundation/ponder/PonderScene.java | 17 +- .../foundation/ponder/SceneBuilder.java | 7 + .../ponder/content/DetectorScenes.java | 401 +++++++++++++ .../ponder/content/ElevatorScenes.java | 512 +++++++++++++++++ .../ponder/content/MovementActorScenes.java | 242 +++++++- .../ponder/content/PonderIndex.java | 21 +- .../ponder/content/PulleyScenes.java | 88 ++- .../ponder/content/RollerScenes.java | 539 ++++++++++++++++++ .../create/foundation/ponder/ui/PonderUI.java | 27 +- .../assets/create/lang/default/interface.json | 4 +- .../contraption_controls/indicator_0.json | 46 +- .../contraption_controls/indicator_1.json | 46 +- .../contraption_controls/indicator_2.json | 46 +- .../contraption_controls/indicator_3.json | 46 +- .../contraption_controls/indicator_4.json | 46 +- .../contraption_controls/indicator_5.json | 46 +- .../contraption_controls/indicator_6.json | 46 +- .../contraption_controls/indicator_7.json | 46 +- .../create/ponder/contraption_controls.nbt | Bin 0 -> 832 bytes .../ponder/elevator_pulley/elevator.nbt | Bin 0 -> 1617 bytes .../ponder/elevator_pulley/multi_rope.nbt | Bin 0 -> 710 bytes .../mechanical_roller/clear_and_pave.nbt | Bin 0 -> 1396 bytes .../create/ponder/mechanical_roller/fill.nbt | Bin 0 -> 1613 bytes .../create/ponder/rope_pulley/multi_rope.nbt | Bin 0 -> 775 bytes .../assets/create/ponder/smart_observer.nbt | Bin 0 -> 1313 bytes .../assets/create/ponder/threshold_switch.nbt | Bin 0 -> 1491 bytes .../block/diodes/pulse_extender/idle.png | Bin 250 -> 311 bytes .../block/diodes/pulse_extender/item.png | Bin 250 -> 311 bytes .../block/diodes/pulse_extender/powered.png | Bin 260 -> 321 bytes .../pulse_extender/powered_powering.png | Bin 251 -> 311 bytes .../block/diodes/pulse_extender/powering.png | Bin 261 -> 321 bytes .../block/diodes/pulse_repeater/idle.png | Bin 257 -> 316 bytes .../block/diodes/pulse_repeater/item.png | Bin 257 -> 316 bytes .../block/diodes/pulse_repeater/powered.png | Bin 267 -> 323 bytes .../pulse_repeater/powered_powering.png | Bin 255 -> 316 bytes .../block/diodes/pulse_repeater/powering.png | Bin 267 -> 324 bytes .../block/threshold_switch/level_0.png | Bin 278 -> 340 bytes .../block/threshold_switch/level_1.png | Bin 312 -> 357 bytes .../block/threshold_switch/level_2.png | Bin 311 -> 357 bytes .../block/threshold_switch/level_3.png | Bin 310 -> 357 bytes .../block/threshold_switch/level_4.png | Bin 324 -> 351 bytes .../block/threshold_switch/level_5.png | Bin 310 -> 337 bytes 55 files changed, 2006 insertions(+), 360 deletions(-) create mode 100644 src/generated/resources/data/create/tags/items/contraption_controlled.json create mode 100644 src/main/java/com/simibubi/create/foundation/ponder/content/DetectorScenes.java create mode 100644 src/main/java/com/simibubi/create/foundation/ponder/content/ElevatorScenes.java create mode 100644 src/main/java/com/simibubi/create/foundation/ponder/content/RollerScenes.java create mode 100644 src/main/resources/assets/create/ponder/contraption_controls.nbt create mode 100644 src/main/resources/assets/create/ponder/elevator_pulley/elevator.nbt create mode 100644 src/main/resources/assets/create/ponder/elevator_pulley/multi_rope.nbt create mode 100644 src/main/resources/assets/create/ponder/mechanical_roller/clear_and_pave.nbt create mode 100644 src/main/resources/assets/create/ponder/mechanical_roller/fill.nbt create mode 100644 src/main/resources/assets/create/ponder/rope_pulley/multi_rope.nbt create mode 100644 src/main/resources/assets/create/ponder/smart_observer.nbt create mode 100644 src/main/resources/assets/create/ponder/threshold_switch.nbt 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 0000000000000000000000000000000000000000..3619f93d051711dbcf41ab36704bef01715f5716 GIT binary patch literal 832 zcmV-G1Hb$qiwFP!00000|IJp(Zrd;r9c{MkByCVMU67yXr6`b7iv~RgL9<*9TBd9w zG%1jDob+eENkApd7L*QH3k?#tl1wL0YLd3Hot=rq*NGY7}ZdI zMlhIince9z{`oqBsF2zw1<-sVNVFk_HW^)*U<(uM!Gt|{q8>bP51z!s6Lzd?A13U9 zi9C8NChozLczB{7URaFJ3ybl2VKF{0EXL=B#rV94dw5|nfv1+m`24aMpI;W^^UGp< zekDEpvKXIV7UT2FVtjsCjL$EN@%c6A;g`ku{IVFIUl!x@%VK0~r4y=A72?;qR3Y zOw3_N2-HG8H$s*ar3jW0KABRY%9P#b-tF5#qiGC-UyS4A)SO34CTONeZq5i(0VF@= zN|=)7u!j9u);HjLop5TqA%#(-FieU`buGCLAU$WAOgSzY*K;Y?R8^PpO>r%|PJegW z5C1!rp-1KOC&p!b*$l?7&X_ce@vAdF)i{D-K{z#rmanTvDa03KN#WDR@AZNiT6%}< zm}C*}HwZ1{dQ!dfw$Trb6e4C+SNTMjkBN<+Y_c;s#Yxac3R>wsm2cB29ITN; zaXFvkcqBRDnx>G>7|ItJh2Tqy@7mHBxon~>|EXJFXC%)hpOqqbB6Cdn)~3AO?ip5h@o`R2bdqx^@u?aX&Dh&@4KQ4)OSD{>MHefl_jum) z=~2riq}t*--QB-7=a|ELqz#@bkCP|;MI!QmlNCJTnbrV|EZpv&G<7&iCu(Bn@de61 z?kca(D~HpjhpVE^_3YYC_VAu5vm(4z(?cRwK?1RF0K4|T@_acbhTKx6@jf06f8if} KE|J1v4gdfF;*;tC literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..93223ed2fbb1e5eacb48f3e147e5e623793bad2c GIT binary patch literal 1617 zcmV-X2Cn%ZiwFP!00000|J7PsZW}igC<&c6p z2yGzD*(nVXLgljs&s}&%8>mfF!33imm5&Y793(=ce(c@!q_;Awd9gdRND!V`MrtT48m6~>mc!q{?F7+cQR zBWH!N<*YEaoE65Fv%=VNjy!T!7+cN?W6N1#Y&k28E$2W!muoc)n5M&*!npdh>F}j6 zu0Cx#d^HT3P5q^7uH$j_sjj(>$JM8>kMgJx4-w2-?`dk$X;j>pxf zy5>3_SD(6a4h@>?cwBwz$~iP>HuZ%oXKc`1$K&c#SI*d=+0+-VoFjwgIv!V_x^j*T znoWJNiR^vakeFr7VGX9?fe9^`(4$u9Q7iPQg*|Fvk6PHHR_Xnc#)A!*9gm!MJaXRg z$k|mZ^r#hj)WROMutzQIQA<6Rc_ITw-$OQQ_LW6qp#_6Ic(4agS!>Hf&z6HHH1Ko`dR(=zN3BxNwuk0zj|^Qr*vQjCVLA{I ziuQ9#<2Pqxzr6=<`Rosm^B9mp2etO7m}bRcgxYsVPKHdJ+?x^OeRf(>UB{?#FGlD! z=#u--BGlX$1?BwC)7jK%uozt#78J;C(sW2Tjr;t7j6?^3*`yfK5C!i6^iz0!|LpAS z8N7Y~pC9SBnWk*JWgFd>Y2&K2!P!xs(EcGysbIr8AD`QN1e%ZD>iYP?=A*GbKEAa1 z2-nBQS2iDbeSCav^AY`@KAvm2`o?BMKLxMwa`mmvM{9ki)ps@@?e+2Tz0JqQ`uO<4 z=A*MdK7O?M=&sFj^^?tp{$+q#u0pi^5R{87rDgSWEDlgren*y1*)gMiF&WUBqwVss zV{>%}`e$20`Vn0XbO-ewkz!26{n3b1QBnfc-;(mIq=c8hfTuIZy$vE38SYAjG2?kc zPWlN;4-E%1{qTQDRzFX|6Be^{+>f)YFr0Ao6W3N{q4^d|1TE%ln@6B8;eNIG(9g3g?Bh3^5B(gh`}k~ieEd=8qudfVlH8qdw#dRi_s zwKidmdN@f_SVg7dYw8}G&?iJ>ML(Y;2|dxBe=ME(XH% zcVx4hEEz5UYOazrrhF!c@RG*6+?4v1)9AWWKovA+jTc zMKM`qb3>QQhh#L$lGvbmo&@GB2J(n!6WEC26jZ^dG%FUL<{lJq<`f05FH9}Qqw+On z1-(!YBB9_WfvuD!F{z{)fThu%Q4c2IJFPJzHP$;r|J|Noo zv{7(ep@P%uEhfi|qu`_}ueO~>RFI@UW8ctfiJ>8h(7Y6LyVZ&#@l9K%84H(oZ#DpY^s7(2ti>juU?P&5m<9u8(s@qIb z9_D~+JUyT^shM)8)n(eoNyk^g&D&pJ(6!CSiz$Ep8G3Ghbn%F0) z6=%lsOi0>Q-UPv;@CxP9w+Y9oCoPse3@WOMCChRAopa{@&x|iUfGz|oIYtHm#onSl zEcPyRQ0PP_sG!)o&>E#OnyMb1Jn90=q%uLG2R8nYhZkbJj@|aV9Ddv zjJcY}FrGsm-ysik$P-xd_zpfB#^$qOY(5*t=CfgJK5zSB$zvFs&xW!2Y#5u*hOzk^ zIQVQBo6m-^`D_@Q&xZNaeD*5i@f#T5fngTLcc|q%)bbr_F^5{rp%$yH)dMC*I)v~b zLyVuT3g-4c{ZyMjUS~0pUJu&)s24JyhS1sL8IKZuG*}f$g9EyGQmRe>{vZZ;xB~Xz zB!t$1&QYnoRdEgcB!-6rP{W2l)3%w5HQGFAznTk?h)FrlyJq^Q_>pUw53_li;t_FgIprpf)Sc(Axhn;g z)f+kt@9QP35261wjxj#7{K={qL1Qyq^;R46xophowlR*5nCHU9hPAFw!&ptjT9tKi zndbcCb#dCXE`l1H+gG{1ZS)XV)Il^CN!DDF;5lN2NHl$&~HwA}6 s=KAn&qiv&Kx{bc1kGFJXics78&$;GrFjt8b0R2z!3uq@YsOb#=0K6V#o&W#< literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..fa7469dce87c8e9fd3d7d8446c9df35101e1bd91 GIT binary patch literal 1396 zcmaKldpHvc7{-Y@8$&zVx=1rZ%4IcbML9*;hIS0;BwF;SMQ4T;GSlX`Z9^e*Td7B5 zQ(&``~N~4ld;>rcb!2Uj8h(GI08((y%cJ5f^Imx z)$QKTMi?>$-GvK_FjbdkX_AA@&v$(einoBc7jAnYK|!5b>12PFFiK{+|AjQOuK;YX539-md-@Xn5K2Fmik zsnru(`w{9y_zKa0;om|5pf%}>Z!P*eTK?bQql{R;Beeu708|cJ$CzFV`5w#7Y*fE| zMrhp-|44S~Yx45OEp6Wp{!1LeOlzWxhrjZ$fs-IS%wxP1q+4-*$hpx!zm-)MCk{co zdw4aGP%!U?(rq>%D1wvdFAjyWNMco}(*PZ4MmftM9vJ61<->Fa3m->FVWTXKmZdYc zU8IpdTke>O^C39VP^AQ-{$MrSGzG&g8Amm9us#M(yv&7g&Phlk+~2{C#p!oeWxCfP zc@Cd>LRP$wBv!C0T4|!vR(T}bkAIIXiaxa&>fkQjDiLc!^m7f$(=~dVY0GLDQhIQ4 zJ<>1~`{%TR>Yxs^8aUz`tPFtDBWUT8R3@+z#!`;p_Y08rhYqp{NzC5aHnPMOK zGPe7Pk1vOS9=?Z7aw)(Wad*&6maHmyw__uSH&-L36qf@Irr@7d2)L6xWofqMKZs2B zR>y~KRm-4SBSq=1uIB<7QH%|l=`BQo+p?~{P?oi~P=9UCYmmFTalsn7?gel9WJEVg z9Gt=zJXUH57KUG0=@Fn_Hd$JGE7P7UyQe_eE^{4gP&bj zbRnwpLv|NKA0r7$jjpN^mO6wh8w&;_D{HGS@m)|9BL7r4CimCuwE>Rnxdj|Tu`(dF z6?2^O5srPBJl#+=iCwPJ8Q`ElSqdp51Q6$+N;$b1A7ext>7HjbQNvTgf>NMT9{{j?1ut6EI zoy>qh3uL{>SH`&JQXeiF)36R8WauYPZH7H|;tz0D2M$ zTvv`BB2wDV0l_whTYez+R?M5ekgI$D| z0QxJ0(LE7fUm$^n0eL?DO(IkZmMPqyWdLYH=@oia+Pfkq0GbS#VEQf90ZceT{0ecR z1Bmbyd;}e$!xspII->p&JPV5TN&%+Cfod?(9<%kJ>S~@_0!UMtRIL2&=({E%Fv}mfI z5)efAP>3hT>T2w5P=sgj=hGK2Zc@;Ez^6|B_6m^($kQh;fy1}Uxr}$)A zhI#5f(CK)n{{0{FA;CS-_9;a=L3XK`TSsCPB=1&-=k0e0ffZtAN=qSOs1;f_tBl@# zfuMJz_4c1e$9{3tpC9h!7HgSjaJ9JhEA*Cix#HCqrP=;7199=3GF9__tJZp3PnS8o zLgk$r+{L~EYj!8gb!1b1#AIWfA$oIliL>$;G2bJcI366}R-kfHA-qhgkB;9|WqaGQ zUJ8ko;HuRMZ-<_iC(9mOrYt)xR<}G6&4tup+Swy=cT>mTt7?v*n=@LBtAYvd$~w1J zNq=w$Bu1&Hb6Cy(R-dL_YnB!p5qM(@{MK~v;d;y=^)^eFAj`6wP@-tAavd`~?xs{n->0tlW;oy*TaowUenzN3>_y_%? zPd|ZIwG0D44qX2fxoUQg`8P>axz?X^<|i}u4H6xw!x_gW(F4#@5|IxyW@GBT#c>p zu&jV}P@sv9lbD6(vR-JGUuucCWQR|NjCZ?kOdWSwdGEE+^!ymk6BF+0z}OT6arykE zcaA$C#N^E z4d#)Ll5-MdAu#PwUuc4m)?AfE5oFlX3~O`BK8}$Svz~0n?IlTzwBBHgIU5_zWjpC? z%B4-M_aUD_tPrkUmW8NyZ`(Nqj>n}1wP9%NV`_QY`**^n0u|i(2V4 zY{Xt)7@9vkhP7UALwLT!6S%f1RYLi)lsuFpk-kJ>TQZ@kh*YR+f_#`= zrJOe+olwzXV;#XV6|Fd=33CDb&#RW{mNbEIyl%yW3N&a24nNtU~E1cjLm0*xvZa^DLw857`Ft5STJshTyBY6Zi!r^L@rVy7b(m& z-dG6CH3jZAly7vqnkA{bKKR=)V_`POaD5#gb@n1((d*!EjBt-hr{&Sy@3%k6gJ(x? z9)9?A@7+@eX10bxM52dj>)RbAIp3kUgr{WV<^5*9yek>Ac0A;qy~d~)6jfl950z6T z1ry{=6+-etuyK}XXE35F)XrrUV0=@w^chiR&*@VUwmXW7L4k?h)Q90+k%<9ZTZ@#E zYPlcrP%$z7+^*7EQ{LHL^Z&;lF@=zGg#<7YQ_hlvrF(d#3f?;1V{m&f5)5a%o6L{; zQNr3CDKIkz8N{tqgcfqt&JF@a|4KS&#~k}cqieOzRJckHaR{aRkp^df5>-&#bWDAO z0L5jmhZg%?$~CJ(rAs?m`2r7T{Rv$`>lQ0Guqwc*XwZc2Fs1Q`hbO9!@DF3W_${Xj F006RNZNvZo literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8802ec75731c0e1a9067de64275ed1e86965fbf8 GIT binary patch literal 1313 zcmV++1>X7}iwFP!00000|IJw4ZsSB0K924DHrp;@wMa-j09PxqAhb8o%~DacYAdz7 z0&b$IJ!z~?Jl4#lZhO^70B*T}7vLp$hUHa|xGHCCkK=V5*Yt-rQj|{e&3DfE&d*HU z2k3z#gL7&FfPS~}?cm$(L6?RqPyv;oUp;6aGVUGAJ}y4%fgN#aHsvoHT&akn*^VlV zRlry)Fs%kWb^{)#hR3S#xy)lQRs)_^10K5pk5j|bYM`^h)ah(6bvheNoz4bRr*oc< z8XkkG)7fC^bT*heoeic=XQzSA22-cA!PMz&Fm*Z`%vCyDC7)XrePNaSu~%S2MP*zzv|rQkNKG~O4TD5?wnLwuYS+?$ z2U);}l&L=S7rtbno@Al^m517e_K3(JJOXEDcjue3HuI$o7Ia4ZgbM0cP3dw~cQTp! z;A|^8OT8Sik*%WB%aQ^4HrAPf#H)&fY6@3x;XGoX}n2V{mX)sz0wu zwOx_wwMs?rb?nDWA+3m`SQ*1Cjsdv4afoeKR^F%KY#uEPhb4{$EUx1*N4_T z%3OJzxiVq%z#m6JL~#=OJPubGD-NYcCDH!8f6>Zk<&tPljcE7U=aBV!QQ-CaKAoWY zbSnF4PA3~S4g?A1go+X8EUhCwM{lO<&=l!B3@KZoUp^}fer-I2#2Uw{2KcpGv7CWN z*S;S(6}t5vf^JSln2#T5L)a@C;!ehJ+1Mk*bRxp2QdB?S`Jju(DVb6DXdz5I4HO+? z9?%eOGKdcs2pRHtoIE9hiv74$(=(|u1Rn2uf=5*7M@$H(1nbI?fls^W7oXz|!wGq) zS0NXRl@rqfFygVkXgOW4oe(CGuIrnmTF>xe zahT*g`!%=laV9jutBcf}SXY{tj>LkTn z6Hr^}9Aojvge@pnO~@MrrsslCcUlBXb-bR3QC-35fT(po>#}^A&W+q+GC0gi4^Bsk zx&9%kyJV4jvph{3XDe~^rpc;|Z^>lVNj)6Mf_RFS`*!ur(s>%Em!al?rB(1B1G8c9 XiYW4y3Yi>!gWup^H~mY(cNhQw@bra& literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c76c7e6eecbf574389002752660ef55c7efa0fb4 GIT binary patch literal 1491 zcmV;^1uXg>iwFP!00000|IJv9*RGbD7%T%7Rj;a^irT{66DavRuV+5VH>rR zw7m#xawQR7?GnpX7zHSrzCqh-5A6%|Df$TM&zltODV^ny#88yNIF2C$f=p>RGv7Dg z%ns!Ow84skr_=-h{c`YS;j7t(7Ue2X0gXWawZS=N!aIpvy!fyUW+ads&msu9{ZU1;u66$^P{L#sGZfypWwev3mSnB9Zyn>a_g8f<$^oU#RTIk zH2V(Uzkc!J#UJ?o4PM`b7C2oJ1$+qB-u~WQ7Xyfi^yrcsK1NW@u6Rr(^~-e6TDCxw zwO%yYZ%$Kdd+*NO!`{&=sk&B!s-iOO^`go;N2)%lK~-aYsWQ)zs_O-+$}=&i%3NQn z8s|vWjT)-5)|V>d9I3ilgDU&=s4~uxDmb&#uifL1abFg4+D7+^j?-8MY#xXRx9G=o zU;3y6C^P!(6pT6rMx9DV7a4p*(o&+{&xneGamZ-@B;Zs9UK!H&3y_xVU_~6w5{}>3 z2gmc-2rc2TD-_;Z|9ae5hQq1AfzIv)Oi`Ie+#F*JPm+PUMFMGn-4zqAG{lzf0I5*5 z2xxyW*r80spC*7dQV-kX)D~{1zAoq4D}1gD0|XGof$~N+H23-TG4{Y`w{>#O?nFwO z+^L)6K*ULN7_gQ7yFEbfcPJxM{Lp$39*L?aFr#$BwdV+TM38j5yY1;#y^m?7lcM!# z6hw-p&%n9@lQ3k{G?C5$iK5)v0B1I;ns@mSS;{AX^C;lHh>Z@|`!Uxu0IZvv|NZ!n zd2RRCAFluW+tr^wcVT0fMCuDJVt%00P73#JR=7WBg`0~5J`IK= zoqD!eY-J1&*d*}#itrN`I!E}XM;tQRg7!WA)gBpBxG*nmj5i@2PF}IA|1Nt(DoWqY z2z_Y+rim1Mdm|dDiU-MZc{-Ul6D}S}!lMC|T_G4U$sq|=OP5Q`>PP+Z2J=Hq_+waI)|Rl^dVsrI!ARWLnTE>`{4wUO!2Nq1hc@q zum1J_PJU7$uyX9JH5b_5=O{3< zB(O_p(+mltN>TlD>$@#nGxdnRQW(*rK+(P@IHrL&_i8H&e0{}*oL^ZnEf|LSv<2g%S+L9VV0a4SG0tf}4kTTOHy|Db zd%%RiLDmej1Kd(_f_@$RHc@YyNbbBaOc}+^qU_Z1(goZe5Eh}EPI725F&yd@B>T_` ziBw=x?ib=D5H)ay-oPCR89c?h5jKlmd>~jBH_LuSSZ5sgKBH$Ixdvh_C8^FVa&;u~ zB#6LxGV`#J?{gz8+UZ_7rWiPgt0z(bXp(SF*O9VW`$!Eoc%|R_&F&F$| z&d7@sC#zZuOeMlumd>$IN{rKr&s;C|e=W%6idbrjfh|UnvI^;^dqf?_v$o1V$S}2W zK1kx>VqOkDi+3e2y~LT?*8=FL3&R^AvSqT0o(-g|*H$5Vd3e-DRIBjm^=njqLDv=M t_G@vQPV905g#)(^tbE?qMul6*9iqrXDx*N)KHB*O{s*jH(BLv0008xI*<1hs literal 0 HcmV?d00001 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 78d598cda7cefecd6cfc86c97181307af93e6ec0..563b1e6eff47064546a46187416e3a15325994c2 100644 GIT binary patch delta 218 zcmV<0044wW0k;B>BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(EY32;bRa{vGi z!vFvd!vV){sAK>D0E$UOK~yMHJ&y|x1R)4RK~Nljxc9&87Twt<2);C8i5Q~Oeq$05 z)|{0kB>^poRkMa-CIZwPe$B)}WVJr+sJEw9qcN8?8<2Hdb6haybbo;d@Vz#S%U=iX z9^miTKIiKI=ob3m4S>5fw)d#BHa>-%IBq$|GRysYh6l97pH|C8TsbgT`FL%@i UffnUVWdHyG07*qoM6N<$g6{cLY5)KL delta 159 zcmV;Q0AT;O0{Q`vB#}Wve}73tK~#9!HH}-20znMK>^uf(?|<2arUR`J{wYUFsX!G_ zxivD=>Mk=P#Vf4pIvj_TYQ<_ye28*zW|-){Ht+bd+*fySXw8H}5S;K|<~}!o&uako z?}NweyHEhWUclcI_|3{7dl*Oo0mMXOie=1-lUtjGI;;>jswjBd6$kfTA?iyEI57YK N002ovPDHLkV1lxeM)d#y 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 420b3a15283d49a8320b19dea49e3f586d00b89f..77fb8175359a684ceb51e1bd252ffc2c2a8deb69 100644 GIT binary patch delta 218 zcmV<0044wW0k;B>BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(EY32;bRa{vGi z!vFvd!vV){sAK>D0E$UOK~yMHJ&y|x1R)4RK~Nljxc9&87Twt<2);C8i5Q~Oeq$05 z)|{0kB>^poRkMa-CIZwPe$B)}WVJr+sJEw9qcN8?8<2Hdb6haybbo;d@Vz#S%U=iX z9^miTKIiKI=ob3m4S>5fw)d#BHa>-%IBq$|GRysYh6l97pH|C8TsbgT`FL%@i UffnUVWdHyG07*qoM6N<$g6{cLY5)KL delta 159 zcmV;Q0AT;O0{Q`vB#}Wve}73tK~#9!HH}-20znMK>^uf(?|<2arUR`J{wYUFsX!G_ zxivD=>Mk=P#Vf4pIvj_TYQ<_ye28*zW|-){Ht+bd+*fySXw8H}5S;K|<~}!o&uako z?}NweyHEhWUclcI_|3{7dl*Oo0mMXOie=1-lUtjGI;;>jswjBd6$kfTA?iyEI57YK N002ovPDHLkV1lxeM)d#y 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 cfa9d2c387b497d2013c7380ca7dda49fc6a67eb..ffc468830df7c2229ae889a8154876cacb2e3c42 100644 GIT binary patch delta 222 zcmV<403rW`0>J{1BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(We32;bRa{vGi z!vFvd!vV){sAK>D0FFsSK~yMHJ&y|x!ypVp0|7$IC#=2yU1!sEmO{dlMX*SKWVhcK zRW+oXbI=$Sw8W57P84Smz?A7vS%QjKt;f05&ZAb7KBk@4A!{~Ae?T9@{RK|oYc3e4 zzYg4;;O|&I#_IrRMt$%(2EennHP&9sk0A*P2S0`cr9{1M*_~MmGTj#mV?L3YnnRHA Y1%n#~*SU~z1ONa407*qoM6N<$g7&mmTmS$7 delta 163 zcmV;U09^mU0)zsPB#}W#e}hRxK~#9!HIGXULNN@)?4&6Y%lGboP<{-1@;KQRKZ-n$<7Cf785IRp@eQ|G7@?MO RDgOWf002ovPDHLkV1hBOL*)Pf 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 81fa26be569d2ba75c7a23214af19d66ff50b8f9..9786b88fe9946ed7e05349cc16a44875aeebd8dd 100644 GIT binary patch delta 218 zcmV<0044wX0k;B>BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(EY32;bRa{vGi z!vFvd!vV){sAK>D0E$UOK~yMHJ&y|x1R)4RK~Nljxc9&87Twt<2);C8i5Q~Oeq$05 z)|{0kB>^poRkMa-CIZwPe$B)}WVJr+sJEw9qcN8?8<2Hdb6haybbo;d@Vz#S%U=iX z9^miTKIiKI=ob3m4S>5fw)d#BHa>-%IBq$|GRysYh6l98UH|C8TsbgT`FL&(* Ug5~ctF#rGn07*qoM6N<$f&$=GQUCw| delta 160 zcmV;R0AK&N0{a1wB#}Wve}G9uK~#9!HH}+t12GK5NIf<{?|<1QuGKh;@MkDMg8@}Q z<<`hdtGmpI6tA$V>u?-Wsuim-@gd5=nPH;)+Wf_v<-WRuLu)1J{1BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(We32;bRa{vGi z!vFvd!vV){sAK>D0FFsSK~yMHJ&y|x#2^SnK~QY{;I{X_>kf9ilOXsq5r>E&+U++c z5n;_)SyB?vl2|osC}tu+&EeNfEJRl8ac;HqsMV;CX{U9_n$6K4(8q9pfd}w47mU+i z2ksu=?^r&@>i}pL`rr*YfM;!MQG0EC3`tNp;$uiqN|NiQ-6Kmuru(`;M1&07*qoM6N<$g6m^i%K!iX delta 164 zcmV;V09*gT0)+yQB#}W#e}qXyK~#9!HP1m#Loo~h(HT1q63hPkACwkiYD#DG94V4z zP=(=tjLdXZEi)p;9j;Ytni*17DXzlA4^bw&n~th|_=#uVo?R78rI|1V!Qhwl>v;gY z?;g+l2OoWgU=2PVz~>!!ua!nl(~trJhzVxw9eKO>Q+yJ6-LC6(8YZeJIN>k0eHfvP SRS1Is0000D0E|gQK~yMHJ&y|x#2^Sn5friYLwovgtt_CGQDxOE%$4B)#Dk*YPC{g@9p_d*kJgOFTz1-ktlOI70b@@04|o8-)&=A8 z&w;xK_&YA2^K$@n3*GoP1K?@fd&F-04u-%HgC)V}EJbPO*rhUy76lOr@azq1h|&+$ Wrw1qpu?MIC0000KU#4rd2(HV$w)%#zzo32?Wt31hkSposL z0ax`xNV~0s(}gqUoJZA>5i^7oaFl|HKcZahZaT)O#XGitSB()|hGudL;tv0$zuyJm zs~TWE9n4RDej1@QAK2?8MvX~1wUWU96QG@ R7uf&+002ovPDHLkV1i`XNPGYQ 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 d21b7e21ffe2d3f909db650a93736a24466fe414..141faff21ef31b960e92ef517c7cc381d1132715 100644 GIT binary patch delta 220 zcmV<203-i_0=xo{BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(Nb32;bRa{vGi z!vFvd!vV){sAK>D0E|gQK~yMHJ&y|x#2^Sn5friYLwovgtt_CGQDxOE%$4B)#Dk*YPC{g@9p_d*kJgOFTz1-ktlOI70b@@04|o8-)&=A8 z&w;xK_&YA2^K$@n3*GoP1K?@fd&F-04u-%HgC)V}EJbPO*rhUy76lOr@azq1h|&+$ Wrw1qpu?MIC0000KU#4rd2(HV$w)%#zzo32?Wt31hkSposL z0ax`xNV~0s(}gqUoJZA>5i^7oaFl|HKcZahZaT)O#XGitSB()|hGudL;tv0$zuyJm zs~TWE9n4RDej1@QAK2?8MvX~1wUWU96QG@ R7uf&+002ovPDHLkV1i`XNPGYQ 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 91f84b580c8688670ea47b3058a6b4f5acd1c2b0..883e26c3ec9e64b4e4999ae2c0c79bbff5228f55 100644 GIT binary patch delta 221 zcmV<303!d30>c83BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(fh32;bRa{vGi z!vFvd!vV){sAK>D0F6mRK~yMHJ&%hLg&+t-5lpdsVDhhyD9oAR0K|hWxjP7vma-p9_1H^MYJKRT4brNkw+FP|%|2ibY>o-z zu+M?JIruxK_5L{ks=7`%`~mQ^t<__-eFsC}@WFy$be8L;m3^1YEcfL^#KE&StS$;a X-^d4h5|QJ9*dIe16**!idR}M}Oo(1*9c@%=L6!kr=?`h} V9F8wX0Nelo002ovPDHLkV1j#%N)!M9 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 833d7f32d99570efaa260a53e8ba443ecb575197..7a9e08fdbff02ca53071d01372484c9cf718fb61 100644 GIT binary patch delta 220 zcmV<203-kZ0lWf`BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(Nb32;bRa{vGi z!vFvd!vV){sAK>D0E|gQK~yMHJ&y?z#2^R+5j-&Q!2JKQJ7}^~g<#hxKolU_=`C4= zC8iupDJ-CcQN^62Fc*dc5D!vzcMu}2^}4s(ebuVe$JARpq)q4O2lO$_K41=P%?0DM z&w;x+_&b)3@i_pRx*q&D0dU&3=CRwpgCTJEU_mfCOUksf?^2j0Cnq8f&fc)PDEt7` Wjt3{Ssyt@^00001p|Nm^078+K{9Be>X0J;H2 zHDIErD2Gdh(lYaiINU5v;5)EF0y%mKi9y{>+gefl?B=VAwTxj&?raR(rjKZLTL3zv z0qWTxyV!vPK-UGlPvAK#8c|I@kFiA#a?3Pd!FHkB%wx^OeFoA97id6#U$z`NcU}Lk P00000NkvXXu0mjfOY%kL 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 2df1cd1ea7d2536a7d4dd31e02a770d03c4b9a50..e7e02b9c9e33bc0f3003b7fc27b24713dc84bf0e 100644 GIT binary patch delta 222 zcmV<403rX20>lE4BpLy8Qb$4nuFf3k00004XF*Lt006O%3;baPks(fh32;bRa{vGi z!vFvd!vV){sAK>D0FFsSK~yMHJ&%hLg&+t-5lpdsVDhhyD9oAR0K|hWxjP7vma-p9_1H^MYJKRT4brNkw+FP|%|2ibY>o-z zu+M?JIruxK_5L{ks=7`&`~mQ^t<__-eFsC}@WFy$be8L;m3^1YEcbPTh&XumhSf#k Y2jAfbeDaReDgXcg07*qoM6N<$g2b0zng9R* delta 167 zcmV;Y09gOT0*eBWB#}W&e}_p#K~#9!HO^6P#4rd&(R(4btNu>*zt2uuQ#+%a51x=f z04}ftH$uu~CR|P&F~&H0KQdy3kOH=@VB(i3n^i?cYkl$;%dfMy7Hmy3xdm~DKT@A| z0{HF)FrNuV&CkLC;B^7tZ{RsAh0LO!$GD3LW{eT}I=NF^5qZAO9h1mRaY4Zi{{dzm8Spw`13;UhctYM*#vr0RdP60ZRb^StKMnBo#g> z7BC(XNiQ2uG8|Jj9swt+asU7T32;bRa{vGi!vFvd!vV){sDESt005XtL_t(2Q&o@A z4#OY_McIT_)Y(G8|NqoMw} z8|F(rg~|FhOfu{OF;lnLYlP4cSEA-_dPgW6pNQ2s2eIVaKLES|wqOcnp!$@200000 LNkvXXu0mjfLy~!{ delta 250 zcmVx}!{efP_3?!jo}w`13;Ue2Iezm8R}c~72cM~6{2 zaz`;}H!M>&9#1kHNiQ2&BqTm57CIyqFdhKmh@K{6$d!0046hWMA6@kqAFukm4M;?_l&GYf)%_!i{1_E`NPIiEpw0%#&s>UniQrM+K)+c zWV>vaB!EfpN*_fw6pV&G5`sc$*l~A`PJwm$z3=z^y|}*YkNt7G{*84yAKmTbDEvp= zPMGJBLNG{Vej%1*M1%)HfZG?AQb+UVs0-_tC-W&gT~=0P%>V!Z07*qoM6N<$g5Rxf ARR910 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 e350173bdf7f05ff2a00e222802c0f99d37cd3f5..033dc34819b8c83fb97f4591793cb49ac83aa157 100644 GIT binary patch delta 330 zcmV-Q0k!_P0_6gbB!2;OQb$4nuFf3k00004XF*Lt006O%3;baP0000{P)t-saz`zm8Spw`13;UhctYM*#vr0RdP60ZRb^StKMnBo#g> z7BC(XNiQ2uG8|Jj9V$G004&o04Ca>#Q*>R32;bRbAJE;4#NNd4#NS*Z>VGd z005myL_t(2Q&o@c4#OY_McKqw)Y(eGe!TyK4*aw1BqTQ{R|5dAKi&{9F6+A37!d(N zObH1M!knXtCFO$kQ$I*$iZvI)R$IkFQ^ZV!TicqwNG>qONZud|_UUBz#y%5thrPj_ zEy5w%RlFfXSwlK>RUYCE(ZT9M`jGQFFB#J1fG)x+_j5lc*u>$ms0z;rf$RudjeHQp cT;m787sIp)tz|%yhyVZp07*qoM6N<$f}?x}!{efP_3?!jo}w`13;Ue2Iezm8R}c~72cM~6{2 zaz`;}H!RHn08=&|Pcj@yFB`4^09hm?mjD1hDHci~5;`OmhX4RU8W1oZ5?BENO925# z0Rlh)0p(AGtpET3nMp)JRCwA|jKOllFbD;gCy*n%=bn=P|9{2CwV?9!lwA(YG6To{ z!55>;zzjpE9}GRV{(tQeTEVv7#`E=jjqnvjWm@I3OadWHX1QE|;}=pXRWotg)*^gF zS)CryHv0y^m6|gJYUi7GyMOTWnzm8Spw`13;UhctYM*#vr0RdP60ZRb^StKMnBo#g> z7BC(XNiQ2uG90b|0L=gZQ#Kx#004&o0Hz}NivR!s32;bRbAJE;4#NNd4#NS*Z>VGd z005myL_t(2Q&o?P4#OY_McKqw)IOll+W!BC4$YEfCn33>Tnz%e{&+*cIL-6q<3t1q zF(o8)2y>1urj!fTr7lQih&dO+wXPKl4G}XDZtJ%CjnoCk7^yeNgFiahdt)C7xFfwG zEFR%dW7G3GFGFo6%D`sQ)X%3{6YD~`eH+Sp0IQ1W{oIcWadC7+%~VE&K>i6|jrt&l cvBnR858@mO`%4X@uK)l507*qoM6N<$f`|uyr2qf` delta 284 zcmV+%0ptGV0=EK?B!5~^OjJex>x}!{efP_3?!jo}w`13;Ue2Iezm8R}c~72cM~6{2 zaz`;}H!RHn08=&|Pcj@yFB`4^09hm?mjD1hDHci~5;`OmhX4RU8W1oZ5?BENO925# z0Rlh)0p(AGtpET3m`OxIRCwB5$k7ghFbqcF(^{9nR1^&X^nd-Ia%&xMrQhF+lal)% z7rLYZA_$76Y?KsXY)VkhN<`EcpX0LypoF`Gw}q&Jp-AIxf`DNK)lk={jzQjx@AbVN z#k5;L>t~r>tyu2EG|Z3d<2v7l*L|`Ycu=fZl^{6fDpqv=6g5wZ;DYwrpTL1-H#bMo iS!&yEi`0?-d=&xk$Tw@=fQ~-^0000zm8Spw`13;UhctYM*#vr0RdP60ZRb^StKN`007MZ z06HWUJ}DM39ui3}8&5JEQ#Kx#004&o0HAs8WB>pF32;bRbAJE;4#NNd4#NS*Z>VGd z005myL_t(2Q&o?P4#OY_McKqw)Y^v>+W!BC4$P8eCn33>Tnz%e{&+*cIL-59V?+c9 zF(o842y>1mrj!fTr7lQih&dO+R$IkFL&QvkYg?P$NG>qONZud|_UK^SkNwz2g6^=L zckXNvPSLL74MVwB!68{OjJex>x}!{efP_3?!jo}w`13;Ue2Iezm8R}c~72cM~6{2 zaz`;}H!O28C(Qr=Q#Kw?G8{=S8?FEVStKNv002HI7D^xzIwTc`002Q65HKDRSOEb` z0Rcw=0zd%)F(pMp0001#Nkl9x z7Y4n_zzjpE?R4F5?f-4HY6`ox(jU*qvsa%&WQ1kRq)8xz$t-3j;P`=*3gsC%wgadh zeq;c5jYXfgkFky6DxWv+;?wZ@#s{5AB&%^+k_b$kt3gUugb{`|Z3P0nbf_d1+o3}D hHnV0etxtXB2NaLqGcQndR$Bl7002ovPDHLkV1j@saO400 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 f3ba863c45a6804b847601ea08927e637e03c6cb..0db27053393e930f3c23468bf493fcfc7aa24fb8 100644 GIT binary patch delta 324 zcmV-K0lWUh0^b6VB!2;OQb$4nuFf3k00004XF*Lt006O%3;baP0000^P)t-saz`zm8Spw`13;UhctYM*#vr0RdP60j>Z5%>V#dBqTZ{ z6+S5zFdh;~FB?xX98)$PmjD2V005vrK$`#n010qNS#tmY4u8V{01m?e$8V@)0001* zNkllE4B!6H~OjJex>x}!{efP_3?!jo}w`13;Ue2Iezm8R}c~7!yMxJR$ zqg_9TQ8#i&F=#g|b1^5)002`q9#1kHNiQ3&003DeB$ogHJ}DMTAQCzx6^8%-K^hP+ z9uimq0Y?D>Kmh?#hp&AA005s!L_t(|+Fgu67K0!R1w#tKVt=UuR){Fx|CS}XY6lko z4f6p1`r!?ZPyr|f3J{PyI2BAhIIR7#f#(nMZ2} z5rn9pb2m?o@~IalDJEGTV4+A+Irj;BiX5vHHN>14IK~{R6eWfnMI;VIiV_m19XO>N v%et*w4JmiAUn11by})VeN3INV;Q#mn!`BYCi#&Ue00000NkvXXu0mjfUIcJ3 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 f158118503b36e92550b9b275c07b4ab1f6de13c..93ba619a28d0f9c4b0ccc74a2f903c47ea1b779d 100644 GIT binary patch delta 310 zcmV-60m=Th0?`7HB!2;OQb$4nuFf3k00004XF*Lt006O%3;baP0000*P)t-saz`zm8Spw`13;UhctYmjD2V007MZ0ImQ4StKMnBo#g> z7BC(XNiQ2uG8|Jj9v|A%=Kufz32;bRa{vGi!vFvd!vV){sDESt005OqL_t(2Q&o=( z4g(|3xY1G|5pgy+LOi;-vvIEkl4v$mG$K6a;+74Yt|lPvIxQRK zQ$2;r{5DMN0WUFAw_GfQhIkS+cheQ2aC{B!5>>OjJex>x}!{efP_3?!jo}w`13;Ue2Iezm8R}c~7!yMxJR$ zqg_9TQ8#i&F=#g|b1^5)002`q9#1kHNiQ3&003DeB$ogHJ}DMTAQCzx6^8%-K^hP+ z9uf$%B8dP10GdfeK~#9!U5-%_!XOL@Yxn{P2WC z=m4Ap2M9%;xlpz1{1{8&u4rzhEQQZIl002ovPDHLkV1oT=bLs#9