diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index eb385b0dd..8c060910d 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -141,8 +141,13 @@ fc652317e03b57c76e23a805da16a28d15254029 assets/create/blockstates/fancy_scoria_ 5864daf839e54789a0dc8a44505f070bf3e184bc assets/create/blockstates/fancy_weathered_limestone_bricks.json fc9ac0a7e7191b93516719455a17177fa6524ecc assets/create/blockstates/fancy_weathered_limestone_bricks_slab.json b2a7c321b1795f20e7433f81a55ce4683de081b8 assets/create/blockstates/fancy_weathered_limestone_bricks_stairs.json +<<<<<<< HEAD 8e532856c3c2b4e4e59c65a2a81a694e35d14658 assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json 65f5fa4b779af5150993b20174404ec93bfc4303 assets/create/blockstates/fluid_pipe.json +======= +6372fe02ba0065acb0758121c45a15a1a8fdc5de assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json +37bc041b7449dc4d7962225e606125ba1b188974 assets/create/blockstates/fluid_pipe.json +>>>>>>> mc1.15/dev f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json 5408d92ab02af86539ac42971d4033545970bb3a assets/create/blockstates/fluid_valve.json e9da1794b6ece7f9aa8bcb43d42c23a55446133b assets/create/blockstates/flywheel.json @@ -339,7 +344,7 @@ e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggl d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json 92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json 61035f8afe75ff7bbd291da5d8690bcbebe679eb assets/create/blockstates/purple_valve_handle.json -4439fc83a8c7370ab44b211a3fd48abde20a4728 assets/create/blockstates/radial_chassis.json +8d7e653bfd9846e684a0d3725595714a19201017 assets/create/blockstates/radial_chassis.json 45877c4d90a7185c2f304edbd67379d800920439 assets/create/blockstates/red_sail.json da1b08387af7afa0855ee8d040f620c01f20660a assets/create/blockstates/red_seat.json 722fc77bbf387af8a4016e42cbf9501d2b968881 assets/create/blockstates/red_valve_handle.json @@ -405,6 +410,7 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j 6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json +<<<<<<< HEAD ff55f756f4bf71c142540d1a415a8dbbae86850e assets/create/lang/en_ud.json eb8e279de2f546a4e285605f2040b4d69a973567 assets/create/lang/en_us.json 75e1aaf752e50a00b9a70769c7e301844e0e091c assets/create/lang/unfinished/de_de.json @@ -425,6 +431,28 @@ b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_windo 1358ff546e99004444fccca5355853d1738ef191 assets/create/models/block/acacia_window_pane_post.json bd33b944ec6ad89850a1d275b3d2843fe6f831cc assets/create/models/block/acacia_window_pane_side.json b272035cd746364a0bd3bf13061f51190e9b46d6 assets/create/models/block/acacia_window_pane_side_alt.json +======= +2b12f3cf99e498899207a8c4855210e7b5dc55cd assets/create/lang/en_ud.json +3522bc1dd15fd219aaf506766fb96be5f65b1939 assets/create/lang/en_us.json +d389c171d3d6a7382fb5b2e80b14e9bee53d8179 assets/create/lang/unfinished/de_de.json +b3caab7bb37be53ea93895cbaae2081452cd095e assets/create/lang/unfinished/es_es.json +0039068794faea032b0a39c954f142e2c8e4dfc1 assets/create/lang/unfinished/es_mx.json +1e34083359caea11cf9fdbb3f04a5881ea62a55e assets/create/lang/unfinished/fr_fr.json +c9abd10d296055f56877317a5c7dee14d0e33bf5 assets/create/lang/unfinished/it_it.json +83298d57034c2bb54924dff2d9b5257502ac3b9a assets/create/lang/unfinished/ja_jp.json +2c0e5fbfc813949d973e9f95af9501ed65b80b82 assets/create/lang/unfinished/ko_kr.json +4b3b113e5f9351b741974bc18d13d9d648d38f91 assets/create/lang/unfinished/nl_nl.json +9bddfffdf5349353d37d7003546c94799c6e812d assets/create/lang/unfinished/pt_br.json +5119b6690e8faa7e25450674caebf3c9c53fd54b assets/create/lang/unfinished/ru_ru.json +f11eb922b49753b60894f0dfe8baabe004d13e05 assets/create/lang/unfinished/zh_cn.json +017a9c9cc6f4538c8c497097cbd59f590b4af160 assets/create/lang/unfinished/zh_tw.json +846200eb548d3bfa2e77b41039de159b4b6cfb45 assets/create/models/block/acacia_window.json +1930fa3a3c98d53dd19e4ee7f55bc27fd47aa281 assets/create/models/block/acacia_window_pane_noside.json +1763ea2c9b981d187f5031ba608f3d5d3be3986a assets/create/models/block/acacia_window_pane_noside_alt.json +7d23c8e4543108f5f53b78ccb4908f7a5bb76c54 assets/create/models/block/acacia_window_pane_post.json +3bdcc6bd616a179ffc22e66307aab538e9bcb75f assets/create/models/block/acacia_window_pane_side.json +7b5b6809e3ef685a497ba15b549d3918aeb6c135 assets/create/models/block/acacia_window_pane_side_alt.json +>>>>>>> mc1.15/dev 8e1e834bab1c09591006a063216e93c832503852 assets/create/models/block/adjustable_chain_gearshift_end_horizontal.json 5d3d8b3989b087a5e9177951e9246f27a1838e84 assets/create/models/block/adjustable_chain_gearshift_end_horizontal_powered.json 0ae6c67468b448f2f05c06f41bb162fafd86846a assets/create/models/block/adjustable_chain_gearshift_end_vertical.json diff --git a/src/generated/resources/assets/create/blockstates/fluid_pipe.json b/src/generated/resources/assets/create/blockstates/fluid_pipe.json index e76540a4a..f7ec39147 100644 --- a/src/generated/resources/assets/create/blockstates/fluid_pipe.json +++ b/src/generated/resources/assets/create/blockstates/fluid_pipe.json @@ -181,9 +181,13 @@ }, { "when": { - "south": "true", - "west": "true", "east": "false", + "west": "true", +<<<<<<< HEAD + "east": "false", +======= + "south": "true", +>>>>>>> mc1.15/dev "north": "false" }, "apply": { @@ -192,9 +196,13 @@ }, { "when": { - "south": "true", - "west": "false", "east": "true", + "west": "false", +<<<<<<< HEAD + "east": "true", +======= + "south": "true", +>>>>>>> mc1.15/dev "north": "false" }, "apply": { @@ -203,9 +211,13 @@ }, { "when": { - "south": "false", - "west": "true", "east": "false", + "west": "true", +<<<<<<< HEAD + "east": "false", +======= + "south": "false", +>>>>>>> mc1.15/dev "north": "true" }, "apply": { @@ -214,9 +226,13 @@ }, { "when": { - "south": "false", - "west": "false", "east": "true", + "west": "false", +<<<<<<< HEAD + "east": "true", +======= + "south": "false", +>>>>>>> mc1.15/dev "north": "true" }, "apply": { @@ -225,9 +241,13 @@ }, { "when": { - "south": "true", - "west": "false", "east": "false", + "west": "false", +<<<<<<< HEAD + "east": "false", +======= + "south": "true", +>>>>>>> mc1.15/dev "north": "true" }, "apply": { @@ -236,9 +256,13 @@ }, { "when": { - "south": "true", - "west": "false", "east": "false", + "west": "false", +<<<<<<< HEAD + "east": "false", +======= + "south": "true", +>>>>>>> mc1.15/dev "north": "false" }, "apply": { @@ -247,9 +271,13 @@ }, { "when": { - "south": "false", - "west": "false", "east": "false", + "west": "false", +<<<<<<< HEAD + "east": "false", +======= + "south": "false", +>>>>>>> mc1.15/dev "north": "true" }, "apply": { @@ -258,31 +286,13 @@ }, { "when": { - "south": "false", - "west": "true", "east": "true", - "north": "false" - }, - "apply": { - "model": "create:block/fluid_pipe/lr_y" - } - }, - { - "when": { - "south": "false", "west": "true", - "east": "false", - "north": "false" - }, - "apply": { - "model": "create:block/fluid_pipe/lr_y" - } - }, - { - "when": { - "south": "false", - "west": "false", +<<<<<<< HEAD "east": "true", +======= + "south": "false", +>>>>>>> mc1.15/dev "north": "false" }, "apply": { @@ -291,9 +301,43 @@ }, { "when": { - "south": "false", - "west": "false", "east": "false", + "west": "true", +<<<<<<< HEAD + "east": "false", +======= + "south": "false", +>>>>>>> mc1.15/dev + "north": "false" + }, + "apply": { + "model": "create:block/fluid_pipe/lr_y" + } + }, + { + "when": { + "east": "true", + "west": "false", +<<<<<<< HEAD + "east": "true", +======= + "south": "false", +>>>>>>> mc1.15/dev + "north": "false" + }, + "apply": { + "model": "create:block/fluid_pipe/lr_y" + } + }, + { + "when": { + "east": "false", + "west": "false", +<<<<<<< HEAD + "east": "false", +======= + "south": "false", +>>>>>>> mc1.15/dev "north": "false" }, "apply": { @@ -302,10 +346,17 @@ }, { "when": { +<<<<<<< HEAD "up": "true", "east": "true", "west": "false", "down": "false" +======= + "down": "false", + "east": "true", + "west": "false", + "up": "true" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/lu_z" @@ -313,10 +364,17 @@ }, { "when": { +<<<<<<< HEAD "up": "true", "east": "false", "west": "true", "down": "false" +======= + "down": "false", + "east": "false", + "west": "true", + "up": "true" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/ru_z" @@ -324,10 +382,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "true", "west": "false", "down": "true" +======= + "down": "true", + "east": "true", + "west": "false", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/ld_z" @@ -335,10 +400,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "false", "west": "true", "down": "true" +======= + "down": "true", + "east": "false", + "west": "true", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/rd_z" @@ -346,10 +418,17 @@ }, { "when": { +<<<<<<< HEAD "up": "true", "east": "false", "west": "false", "down": "true" +======= + "down": "true", + "east": "false", + "west": "false", + "up": "true" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/ud_z" @@ -357,10 +436,17 @@ }, { "when": { +<<<<<<< HEAD "up": "true", "east": "false", "west": "false", "down": "false" +======= + "down": "false", + "east": "false", + "west": "false", + "up": "true" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/ud_z" @@ -368,10 +454,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "false", "west": "false", "down": "true" +======= + "down": "true", + "east": "false", + "west": "false", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/ud_z" @@ -379,10 +472,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "true", "west": "true", "down": "false" +======= + "down": "false", + "east": "true", + "west": "true", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/lr_z" @@ -390,10 +490,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "true", "west": "false", "down": "false" +======= + "down": "false", + "east": "true", + "west": "false", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/lr_z" @@ -401,10 +508,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "false", "west": "true", "down": "false" +======= + "down": "false", + "east": "false", + "west": "true", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/lr_z" @@ -412,10 +526,17 @@ }, { "when": { +<<<<<<< HEAD "up": "false", "east": "false", "west": "false", "down": "false" +======= + "down": "false", + "east": "false", + "west": "false", + "up": "false" +>>>>>>> mc1.15/dev }, "apply": { "model": "create:block/fluid_pipe/none_z" diff --git a/src/generated/resources/assets/create/blockstates/radial_chassis.json b/src/generated/resources/assets/create/blockstates/radial_chassis.json index 8bd829ffc..9d00ea8b1 100644 --- a/src/generated/resources/assets/create/blockstates/radial_chassis.json +++ b/src/generated/resources/assets/create/blockstates/radial_chassis.json @@ -29,8 +29,8 @@ }, { "when": { - "axis": "x", - "sticky_south": "true" + "sticky_south": "true", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -39,8 +39,8 @@ }, { "when": { - "axis": "y", - "sticky_south": "true" + "sticky_south": "true", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky" @@ -48,8 +48,8 @@ }, { "when": { - "axis": "z", - "sticky_south": "true" + "sticky_south": "true", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -59,8 +59,8 @@ }, { "when": { - "axis": "x", - "sticky_south": "false" + "sticky_south": "false", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -69,8 +69,8 @@ }, { "when": { - "axis": "y", - "sticky_south": "false" + "sticky_south": "false", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y" @@ -78,8 +78,8 @@ }, { "when": { - "axis": "z", - "sticky_south": "false" + "sticky_south": "false", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -89,8 +89,8 @@ }, { "when": { - "axis": "x", - "sticky_west": "true" + "sticky_west": "true", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -99,8 +99,8 @@ }, { "when": { - "axis": "y", - "sticky_west": "true" + "sticky_west": "true", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky", @@ -109,8 +109,8 @@ }, { "when": { - "axis": "z", - "sticky_west": "true" + "sticky_west": "true", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z_sticky", @@ -119,8 +119,8 @@ }, { "when": { - "axis": "x", - "sticky_west": "false" + "sticky_west": "false", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -129,8 +129,8 @@ }, { "when": { - "axis": "y", - "sticky_west": "false" + "sticky_west": "false", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y", @@ -139,8 +139,8 @@ }, { "when": { - "axis": "z", - "sticky_west": "false" + "sticky_west": "false", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z", @@ -149,8 +149,8 @@ }, { "when": { - "axis": "x", - "sticky_north": "true" + "sticky_north": "true", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky" @@ -158,8 +158,8 @@ }, { "when": { - "axis": "y", - "sticky_north": "true" + "sticky_north": "true", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky", @@ -168,8 +168,8 @@ }, { "when": { - "axis": "z", - "sticky_north": "true" + "sticky_north": "true", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -178,8 +178,8 @@ }, { "when": { - "axis": "x", - "sticky_north": "false" + "sticky_north": "false", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x" @@ -187,8 +187,8 @@ }, { "when": { - "axis": "y", - "sticky_north": "false" + "sticky_north": "false", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y", @@ -197,8 +197,8 @@ }, { "when": { - "axis": "z", - "sticky_north": "false" + "sticky_north": "false", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -207,8 +207,8 @@ }, { "when": { - "axis": "x", - "sticky_east": "true" + "sticky_east": "true", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -217,8 +217,8 @@ }, { "when": { - "axis": "y", - "sticky_east": "true" + "sticky_east": "true", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky", @@ -227,8 +227,8 @@ }, { "when": { - "axis": "z", - "sticky_east": "true" + "sticky_east": "true", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z_sticky" @@ -236,8 +236,8 @@ }, { "when": { - "axis": "x", - "sticky_east": "false" + "sticky_east": "false", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -246,8 +246,8 @@ }, { "when": { - "axis": "y", - "sticky_east": "false" + "sticky_east": "false", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y", @@ -256,8 +256,8 @@ }, { "when": { - "axis": "z", - "sticky_east": "false" + "sticky_east": "false", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z" diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 8e4b1ef27..679c7bb13 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -1877,6 +1877,17 @@ "create.ponder.analog_lever.text_2": "Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "Processing Items in the Basin", + "create.ponder.basin.text_1": "A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "A number of options are applicable here", + "create.ponder.basin.text_5": "Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1899,12 +1910,18 @@ "create.ponder.belt_directions.text_3": "2. They can connect diagonally", "create.ponder.belt_directions.text_4": "3. They can connect vertically", "create.ponder.belt_directions.text_5": "4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "The Brass Funnel", "create.ponder.brass_funnel.text_1": "Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "Brass Funnels can extract up to a full stack.", @@ -1944,6 +1961,16 @@ "create.ponder.chain_gearshift.text_5": "Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "12 RPM", + "create.ponder.chute.header": "Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1971,6 +1998,12 @@ "create.ponder.creative_motor.text_1": "Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "Using the Deployer", "create.ponder.deployer.text_1": "Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "Right-click the front to give it an Item to use", @@ -2002,6 +2035,19 @@ "create.ponder.deployer_redstone.text_2": "Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "Using Depots", + "create.ponder.depot.text_1": "Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "...as well as provide Items to Mechanical Arms", + + "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", + "create.ponder.empty_blaze_burner.text_3": "You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "Strength and Direction of Flow depends on the Rotational Input", @@ -2042,7 +2088,7 @@ "create.ponder.funnel_intro.text_1": "Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "Redstone control", - "create.ponder.funnel_redstone.text_1": "Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "Direct transfer", "create.ponder.funnel_transfer.text_1": "Funnels cannot ever transfer between closed inventories directly.", @@ -2128,6 +2174,12 @@ "create.ponder.mechanical_harvester.text_1": "Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "Speed and direction of movement depend on the Rotational Input", @@ -2143,6 +2195,18 @@ "create.ponder.mechanical_plough.text_3": "Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "The filter slot can be used in case two recipes are conflicting.", + "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", @@ -2158,6 +2222,13 @@ "create.ponder.mechanical_saw_processing.text_4": "When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "Processing Items in the Millstone", + "create.ponder.millstone.text_1": "Millstones process items by grinding them", + "create.ponder.millstone.text_2": "They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "Throw or Insert items at the top", + "create.ponder.millstone.text_4": "After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "Piston Extension Poles", "create.ponder.piston_pole.text_1": "Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "The Length of pole added at its back determines the Extension Range", @@ -2243,6 +2314,17 @@ "create.ponder.shaft_casing.header": "Encasing Shafts", "create.ponder.shaft_casing.text_1": "Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "..they will attempt to keep themselves upright", @@ -2255,6 +2337,11 @@ "create.ponder.sticker.text_3": "If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/de_de.json b/src/generated/resources/assets/create/lang/unfinished/de_de.json index 35f4fd215..cae3fb801 100644 --- a/src/generated/resources/assets/create/lang/unfinished/de_de.json +++ b/src/generated/resources/assets/create/lang/unfinished/de_de.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 1374", +======= + "_": "Missing Localizations: 1443", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_es.json b/src/generated/resources/assets/create/lang/unfinished/es_es.json index da4aecbc0..8500ec2c6 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_es.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_es.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 405", +======= + "_": "Missing Localizations: 474", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_mx.json b/src/generated/resources/assets/create/lang/unfinished/es_mx.json index 545192c59..f54db61bc 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_mx.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_mx.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1300", + "_": "Missing Localizations: 1373", "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1878,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1911,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1962,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +1999,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2036,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2089,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2175,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2196,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2223,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2315,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2338,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json index ca7931572..d08724ddf 100644 --- a/src/generated/resources/assets/create/lang/unfinished/fr_fr.json +++ b/src/generated/resources/assets/create/lang/unfinished/fr_fr.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 1086", +======= + "_": "Missing Localizations: 1155", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/it_it.json b/src/generated/resources/assets/create/lang/unfinished/it_it.json index 37001890f..4617a3acd 100644 --- a/src/generated/resources/assets/create/lang/unfinished/it_it.json +++ b/src/generated/resources/assets/create/lang/unfinished/it_it.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 422", +======= + "_": "Missing Localizations: 491", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json index 40b5468a0..a08011174 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ja_jp.json +++ b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 429", +======= + "_": "Missing Localizations: 498", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json index cdaa27fe6..72bf61c4f 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ko_kr.json +++ b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 475", +======= + "_": "Missing Localizations: 544", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json index 15e26df3f..bcb61503f 100644 --- a/src/generated/resources/assets/create/lang/unfinished/nl_nl.json +++ b/src/generated/resources/assets/create/lang/unfinished/nl_nl.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 1573", +======= + "_": "Missing Localizations: 1642", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/pt_br.json b/src/generated/resources/assets/create/lang/unfinished/pt_br.json index fb17164bc..e1667f5ae 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pt_br.json +++ b/src/generated/resources/assets/create/lang/unfinished/pt_br.json @@ -1,5 +1,9 @@ { +<<<<<<< HEAD "_": "Missing Localizations: 1639", +======= + "_": "Missing Localizations: 1708", +>>>>>>> mc1.15/dev "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1882,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1915,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1966,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +2003,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2040,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2093,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2179,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2200,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2227,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2319,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2342,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json index 91069ee68..af6eac2d9 100644 --- a/src/generated/resources/assets/create/lang/unfinished/ru_ru.json +++ b/src/generated/resources/assets/create/lang/unfinished/ru_ru.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 421", + "_": "Missing Localizations: 494", "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1878,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1911,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1962,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +1999,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2036,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2089,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2175,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2196,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2223,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2315,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2338,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json index 119f07e52..6cde8bccf 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_cn.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_cn.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 419", + "_": "Missing Localizations: 492", "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1878,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1911,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1962,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +1999,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2036,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2089,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2175,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2196,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2223,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2315,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2338,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/generated/resources/assets/create/lang/unfinished/zh_tw.json b/src/generated/resources/assets/create/lang/unfinished/zh_tw.json index 477a6620e..2611efb61 100644 --- a/src/generated/resources/assets/create/lang/unfinished/zh_tw.json +++ b/src/generated/resources/assets/create/lang/unfinished/zh_tw.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 424", + "_": "Missing Localizations: 497", "_": "->------------------------] Game Elements [------------------------<-", @@ -1878,6 +1878,17 @@ "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", + "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", + "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", + "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", + "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", + "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", + "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", + "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", + "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", + "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", + "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", + "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", @@ -1900,12 +1911,18 @@ "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions.\nBelts can span any Length between 2 and 20 blocks", + "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", + "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", + "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", + "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", + "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", + "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", + "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", @@ -1945,6 +1962,16 @@ "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", + "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", + "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", + "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", + "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", + + "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", + "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", + "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", + "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", + "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", @@ -1972,6 +1999,12 @@ "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", + "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", + "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", + "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", + "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", + "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", + "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", @@ -2003,6 +2036,19 @@ "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", + "create.ponder.depot.header": "UNLOCALIZED: Using Depots", + "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", + "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", + "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", + "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", + + "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", + "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", + "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", + "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", + "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", + "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -2043,7 +2089,7 @@ "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting.", + "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", @@ -2129,6 +2175,12 @@ "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", + "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", + "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", + "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", @@ -2144,6 +2196,18 @@ "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", + "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", + "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", + "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", + "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", + + "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", + "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", + "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", + "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", + "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -2159,6 +2223,13 @@ "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", + "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", + "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", + "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", + "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", + "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", + "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", + "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", @@ -2244,6 +2315,17 @@ "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", + "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", + "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", + "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", + "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", + "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", + "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", + "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2256,6 +2338,11 @@ "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", + "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", + "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", + "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", + "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", + "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index a99929580..6af72073b 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -19,7 +19,6 @@ import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -277,7 +276,7 @@ public class AllBlockPartials { .unCentre(); return stack; }; - return dispatcher.getMaterial(RenderMaterials.MODELS).getModel(this, referenceState, facing, ms); + return dispatcher.getMaterial(RenderMaterials.TRANSFORMED).getModel(this, referenceState, facing, ms); } } diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index 7c102139e..3afa8656a 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -108,9 +108,7 @@ public class AllShapes { PUMP = shape(2, 0, 2, 14, 5, 14).add(4, 0, 4, 12, 16, 12) .add(3, 12, 3, 13, 16, 13) .forDirectional(Direction.UP), - CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16) - .forDirectional(Direction.DOWN) - + CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16).forDirectional(Direction.DOWN) ; @@ -144,12 +142,12 @@ public class AllShapes { .add(2, 0, 2, 14, 2, 14) .build(), SPEED_CONTROLLER = shape(0, 0, 0, 16, 4, 16).add(1, 1, 1, 15, 13, 15) - .add(0, 8, 0, 16, 14, 16).build(), + .add(0, 8, 0, 16, 14, 16) + .build(), HEATER_BLOCK_SHAPE = shape(2, 0, 2, 14, 14, 14).add(0, 0, 0, 16, 4, 16) .build(), HEATER_BLOCK_SPECIAL_COLLISION_SHAPE = shape(0, 0, 0, 16, 4, 16).build(), - CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 16, 16), - SEAT = cuboid(0, 0, 0, 16, 8, 16), + CRUSHING_WHEEL_COLLISION_SHAPE = cuboid(0, 0, 0, 16, 16, 16), SEAT = cuboid(0, 0, 0, 16, 8, 16), SEAT_COLLISION = cuboid(0, 0, 0, 16, 6, 16), MECHANICAL_PROCESSOR_SHAPE = shape(VoxelShapes.fullCube()).erase(4, 0, 4, 12, 16, 12) .build(), @@ -172,8 +170,10 @@ public class AllShapes { GAUGE_SHAPE_UP = shape(1, 0, 0, 15, 2, 16).add(2, 2, 1, 14, 14, 15) .build(), MECHANICAL_ARM = shape(2, 0, 2, 14, 10, 14).add(3, 0, 3, 13, 14, 13) + .add(0, 0, 0, 16, 6, 16) .build(), MECHANICAL_ARM_CEILING = shape(2, 6, 2, 14, 16, 14).add(3, 2, 3, 13, 16, 13) + .add(0, 10, 0, 16, 16, 16) .build(), CHUTE = shape(1, 8, 1, 15, 16, 15).add(2, 0, 2, 14, 8, 14) .build(), diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 88b073b28..914ab8678 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -97,6 +97,7 @@ import com.simibubi.create.content.logistics.block.chute.SmartChuteTileEntity; import com.simibubi.create.content.logistics.block.depot.DepotRenderer; import com.simibubi.create.content.logistics.block.depot.DepotTileEntity; import com.simibubi.create.content.logistics.block.diodes.AdjustablePulseRepeaterTileEntity; +import com.simibubi.create.content.logistics.block.diodes.AdjustableRepeaterInstance; import com.simibubi.create.content.logistics.block.diodes.AdjustableRepeaterRenderer; import com.simibubi.create.content.logistics.block.diodes.AdjustableRepeaterTileEntity; import com.simibubi.create.content.logistics.block.funnel.FunnelInstance; @@ -114,8 +115,6 @@ import com.simibubi.create.content.schematics.block.SchematicannonRenderer; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.tterrag.registrate.util.entry.TileEntityEntry; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.DistExecutor; public class AllTileEntities { @@ -595,6 +594,7 @@ public class AllTileEntities { public static final TileEntityEntry ADJUSTABLE_REPEATER = Create.registrate() .tileEntity("adjustable_repeater", AdjustableRepeaterTileEntity::new) + .instance(() -> AdjustableRepeaterInstance::new) .validBlocks(AllBlocks.ADJUSTABLE_REPEATER) .renderer(() -> AdjustableRepeaterRenderer::new) .register(); @@ -602,6 +602,7 @@ public class AllTileEntities { public static final TileEntityEntry ADJUSTABLE_PULSE_REPEATER = Create.registrate() .tileEntity("adjustable_pulse_repeater", AdjustablePulseRepeaterTileEntity::new) + .instance(() -> AdjustableRepeaterInstance::new) .validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER) .renderer(() -> AdjustableRepeaterRenderer::new) .register(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java index 5c02bd90c..62d152f6c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java @@ -14,10 +14,10 @@ public class HalfShaftInstance extends SingleRotatingInstance { @Override protected InstancedModel getModel() { Direction dir = getShaftDirection(); - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, dir); + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, blockState, dir); } protected Direction getShaftDirection() { - return lastState.get(BlockStateProperties.FACING); + return blockState.get(BlockStateProperties.FACING); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java index 2db938ca4..3e80e8afb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java @@ -12,6 +12,6 @@ public class HorizontalHalfShaftInstance extends HalfShaftInstance { @Override protected Direction getShaftDirection() { - return lastState.get(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); + return blockState.get(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticAttributes.java similarity index 80% rename from src/main/java/com/simibubi/create/content/contraptions/base/KineticVertexAttributes.java rename to src/main/java/com/simibubi/create/content/contraptions/base/KineticAttributes.java index bb6585755..8f7b9b15b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticAttributes.java @@ -5,10 +5,8 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; -public enum KineticVertexAttributes implements IVertexAttrib { +public enum KineticAttributes implements IVertexAttrib { INSTANCE_POSITION("aInstancePos", CommonAttributes.VEC3), - LIGHT("aLight", CommonAttributes.LIGHT), - NETWORK_COLOR("aNetworkTint", CommonAttributes.RGB), SPEED("aSpeed", CommonAttributes.FLOAT), OFFSET("aOffset", CommonAttributes.FLOAT), ; @@ -16,7 +14,7 @@ public enum KineticVertexAttributes implements IVertexAttrib { private final String name; private final VertexAttribSpec spec; - KineticVertexAttributes(String name, VertexAttribSpec spec) { + KineticAttributes(String name, VertexAttribSpec spec) { this.name = name; this.spec = spec; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java index 563e6fbb6..658cd066b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java @@ -1,23 +1,17 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight; +import com.simibubi.create.foundation.render.backend.instancing.impl.BasicData; import com.simibubi.create.foundation.utility.ColorHelper; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; import java.nio.ByteBuffer; -public class KineticData> extends InstanceData implements IFlatLight { +public class KineticData extends BasicData { private float x; private float y; private float z; - private byte blockLight; - private byte skyLight; - private byte r; - private byte g; - private byte b; private float rotationalSpeed; private float rotationOffset; @@ -25,25 +19,25 @@ public class KineticData> extends InstanceData implemen super(owner); } - public D setTileEntity(KineticTileEntity te) { + public KineticData setTileEntity(KineticTileEntity te) { setPosition(te.getPos()); if (te.hasSource()) { setColor(te.network); }else { setColor(0xFF, 0xFF, 0x00); } - return (D) this; + return this; } - public D setPosition(BlockPos pos) { + public KineticData setPosition(BlockPos pos) { return setPosition(pos.getX(), pos.getY(), pos.getZ()); } - public D setPosition(Vector3f pos) { + public KineticData setPosition(Vector3f pos) { return setPosition(pos.getX(), pos.getY(), pos.getZ()); } - public D setPosition(int x, int y, int z) { + public KineticData setPosition(int x, int y, int z) { BlockPos origin = owner.renderer.getOriginCoordinate(); return setPosition((float) (x - origin.getX()), @@ -51,75 +45,62 @@ public class KineticData> extends InstanceData implemen (float) (z - origin.getZ())); } - public D setPosition(float x, float y, float z) { + public KineticData setPosition(float x, float y, float z) { this.x = x; this.y = y; this.z = z; - return (D) this; + return this; } - public D nudge(float x, float y, float z) { + public KineticData nudge(float x, float y, float z) { this.x += x; this.y += y; this.z += z; - return (D) this; + return this; } - @Override - public D setBlockLight(int blockLight) { - this.blockLight = (byte) ((blockLight & 0xF) << 4); - return (D) this; - } - - @Override - public D setSkyLight(int skyLight) { - this.skyLight = (byte) ((skyLight & 0xF) << 4); - return (D) this; - } - - public D setColor(Long l) { + public KineticData setColor(Long l) { if (l != null) return setColor(l.longValue()); - else - return setColor(0xFF, 0xFF, 0xFF); + else { + setColor(0xFF, 0xFF, 0xFF); + return this; + } } - private D setColor(long l) { + private KineticData setColor(long l) { int color = ColorHelper.colorFromLong(l); byte r = (byte) ((color >> 16) & 0xFF); byte g = (byte) ((color >> 8) & 0xFF); byte b = (byte) (color & 0xFF); - return setColor(r, g, b); + setColor(r, g, b); + + return this; } - public D setColor(int r, int g, int b) { - return setColor((byte) r, (byte) g, (byte) b); - } - - public D setColor(byte r, byte g, byte b) { - this.r = r; - this.g = g; - this.b = b; - return (D) this; - } - - public D setRotationalSpeed(float rotationalSpeed) { + public KineticData setRotationalSpeed(float rotationalSpeed) { this.rotationalSpeed = rotationalSpeed; - return (D) this; + return this; } - public D setRotationOffset(float rotationOffset) { + public KineticData setRotationOffset(float rotationOffset) { this.rotationOffset = rotationOffset; - return (D) this; + return this; } @Override public void write(ByteBuffer buf) { - putVec3(buf, x, y, z); - putVec2(buf, blockLight, skyLight); - putVec3(buf, r, g, b); - put(buf, rotationalSpeed); - put(buf, rotationOffset); + super.write(buf); + + buf.asFloatBuffer().put(new float[] { + x, + y, + z, + rotationalSpeed, + rotationOffset + }); + + buf.position(buf.position() + 5 * 4); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticRenderMaterials.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticRenderMaterials.java index 8d3d32d31..2320fcb41 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticRenderMaterials.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticRenderMaterials.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData; +import com.simibubi.create.content.contraptions.components.actors.ActorData; import com.simibubi.create.content.contraptions.relays.belt.BeltData; import com.simibubi.create.content.logistics.block.FlapData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; @@ -10,7 +10,7 @@ public class KineticRenderMaterials { public static final MaterialType> ROTATING = new MaterialType<>(); public static final MaterialType> BELTS = new MaterialType<>(); - public static final MaterialType> ACTORS = new MaterialType<>(); + public static final MaterialType> ACTORS = new MaterialType<>(); public static final MaterialType> FLAPS = new MaterialType<>(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java index d41a11276..a5e516b00 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileInstance.java @@ -15,27 +15,38 @@ public abstract class KineticTileInstance extends T } protected final void updateRotation(InstanceKey key, Direction.Axis axis) { - key.getInstance() - .setColor(tile.network) - .setRotationalSpeed(tile.getSpeed()) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(axis); + updateRotation(key, axis, tile.getSpeed()); + } + + protected final void updateRotation(InstanceKey key, Direction.Axis axis, float speed) { + updateRotation(key.getInstance(), axis, speed); + } + + protected final void updateRotation(RotatingData key, Direction.Axis axis, float speed) { + key.setRotationAxis(axis) + .setRotationOffset(getRotationOffset(axis)) + .setRotationalSpeed(speed) + .setColor(tile.network); + } + + protected final void updateRotation(RotatingData key, Direction.Axis axis) { + updateRotation(key, axis, tile.getSpeed()); } protected final InstanceKey setup(InstanceKey key, float speed, Direction.Axis axis) { key.getInstance() - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)) - .setTileEntity(tile) - .setRotationalSpeed(speed) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(axis); + .setRotationAxis(axis) + .setRotationalSpeed(speed) + .setRotationOffset(getRotationOffset(axis)) + .setTileEntity(tile) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)) + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)); return key; } protected float getRotationOffset(final Direction.Axis axis) { - float offset = CogWheelBlock.isLargeCog(lastState) ? 11.25f : 0; + float offset = CogWheelBlock.isLargeCog(blockState) ? 11.25f : 0; double d = (((axis == Direction.Axis.X) ? 0 : pos.getX()) + ((axis == Direction.Axis.Y) ? 0 : pos.getY()) + ((axis == Direction.Axis.Z) ? 0 : pos.getZ())) % 2; if (d == 0) { @@ -50,7 +61,7 @@ public abstract class KineticTileInstance extends T } public Direction.Axis getRotationAxis() { - return ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + return ((IRotate) blockState.getBlock()).getRotationAxis(blockState); } protected final RenderMaterial> rotatingMaterial() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingAttributes.java similarity index 86% rename from src/main/java/com/simibubi/create/content/contraptions/base/RotatingVertexAttributes.java rename to src/main/java/com/simibubi/create/content/contraptions/base/RotatingAttributes.java index e264731cc..ef0e1122c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingAttributes.java @@ -5,14 +5,14 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; -public enum RotatingVertexAttributes implements IVertexAttrib { +public enum RotatingAttributes implements IVertexAttrib { AXIS("aAxis", CommonAttributes.NORMAL), ; private final String name; private final VertexAttribSpec spec; - RotatingVertexAttributes(String name, VertexAttribSpec spec) { + RotatingAttributes(String name, VertexAttribSpec spec) { this.name = name; this.spec = spec; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java index 6176c132e..d88be6db8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java @@ -2,18 +2,12 @@ package com.simibubi.create.content.contraptions.base; import java.nio.ByteBuffer; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import net.minecraft.util.Direction; import net.minecraft.util.math.vector.Vector3f; -public class RotatingData extends KineticData { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(KineticVertexAttributes.class) - .addAttributes(RotatingVertexAttributes.class) - .build(); - +public class RotatingData extends KineticData { private byte rotationAxisX; private byte rotationAxisY; private byte rotationAxisZ; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingInstancedModel.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingModel.java similarity index 53% rename from src/main/java/com/simibubi/create/content/contraptions/base/RotatingInstancedModel.java rename to src/main/java/com/simibubi/create/content/contraptions/base/RotatingModel.java index 6f439ca42..8c0d77c17 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingInstancedModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingModel.java @@ -3,11 +3,18 @@ package com.simibubi.create.content.contraptions.base; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.impl.BasicAttributes; import net.minecraft.client.renderer.BufferBuilder; -public class RotatingInstancedModel extends InstancedModel { - public RotatingInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { +public class RotatingModel extends InstancedModel { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(BasicAttributes.class) + .addAttributes(KineticAttributes.class) + .addAttributes(RotatingAttributes.class) + .build(); + + public RotatingModel(InstancedTileRenderer renderer, BufferBuilder buf) { super(renderer, buf); } @@ -18,7 +25,7 @@ public class RotatingInstancedModel extends InstancedModel { @Override protected VertexFormat getInstanceFormat() { - return RotatingData.FORMAT; + return FORMAT; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java index 2cd7aac57..759f455c1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java @@ -10,21 +10,18 @@ import static com.simibubi.create.content.contraptions.base.KineticTileEntityRen public class SingleRotatingInstance extends KineticTileInstance { - protected InstanceKey rotatingModelKey; + protected final InstanceKey rotatingModelKey; public SingleRotatingInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + Direction.Axis axis = ((IRotate) blockState.getBlock()).getRotationAxis(blockState); rotatingModelKey = setup(getModel().createInstance(), tile.getSpeed(), axis); } @Override - public void onUpdate() { - Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + public void update() { + Direction.Axis axis = ((IRotate) blockState.getBlock()).getRotationAxis(blockState); updateRotation(rotatingModelKey, axis); } @@ -39,7 +36,7 @@ public class SingleRotatingInstance extends KineticTileInstance getModel() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java similarity index 67% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java rename to src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java index ac65f939b..071e7d13f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java @@ -1,6 +1,5 @@ package com.simibubi.create.content.contraptions.components.actors; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstanceData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import net.minecraft.util.math.BlockPos; @@ -9,11 +8,7 @@ import net.minecraft.util.math.vector.Vector3f; import java.nio.ByteBuffer; -public class ContraptionActorData extends InstanceData { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(ActorVertexAttributes.class) - .build(); - +public class ActorData extends InstanceData { private float x; private float y; private float z; @@ -33,63 +28,63 @@ public class ContraptionActorData extends InstanceData { private float speed; - protected ContraptionActorData(InstancedModel owner) { + protected ActorData(InstancedModel owner) { super(owner); } - public ContraptionActorData setPosition(BlockPos pos) { + public ActorData setPosition(BlockPos pos) { this.x = pos.getX(); this.y = pos.getY(); this.z = pos.getZ(); return this; } - public ContraptionActorData setBlockLight(int blockLight) { + public ActorData setBlockLight(int blockLight) { this.blockLight = (byte) ((blockLight & 0xF) << 4); return this; } - public ContraptionActorData setSkyLight(int skyLight) { + public ActorData setSkyLight(int skyLight) { this.skyLight = (byte) ((skyLight & 0xF) << 4); return this; } - public ContraptionActorData setRotationOffset(float rotationOffset) { + public ActorData setRotationOffset(float rotationOffset) { this.rotationOffset = rotationOffset; return this; } - public ContraptionActorData setSpeed(float speed) { + public ActorData setSpeed(float speed) { this.speed = speed; return this; } - public ContraptionActorData setRotationAxis(Vector3f axis) { + public ActorData setRotationAxis(Vector3f axis) { setRotationAxis(axis.getX(), axis.getY(), axis.getZ()); return this; } - public ContraptionActorData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) { + public ActorData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) { this.rotationAxisX = (byte) (rotationAxisX * 127); this.rotationAxisY = (byte) (rotationAxisY * 127); this.rotationAxisZ = (byte) (rotationAxisZ * 127); return this; } - public ContraptionActorData setRotationCenter(Vector3f axis) { + public ActorData setRotationCenter(Vector3f axis) { setRotationCenter(axis.getX(), axis.getY(), axis.getZ()); return this; } - public ContraptionActorData setRotationCenter(float rotationCenterX, float rotationCenterY, float rotationCenterZ) { + public ActorData setRotationCenter(float rotationCenterX, float rotationCenterY, float rotationCenterZ) { this.rotationCenterX = (byte) (rotationCenterX * 127); this.rotationCenterY = (byte) (rotationCenterY * 127); this.rotationCenterZ = (byte) (rotationCenterZ * 127); return this; } - public ContraptionActorData setLocalRotation(Quaternion q) { + public ActorData setLocalRotation(Quaternion q) { this.qX = q.getX(); this.qY = q.getY(); this.qZ = q.getZ(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/RotatingActorModel.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorModel.java similarity index 56% rename from src/main/java/com/simibubi/create/content/contraptions/components/actors/RotatingActorModel.java rename to src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorModel.java index 8715c6f99..a8fdeac6c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/RotatingActorModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorModel.java @@ -6,18 +6,22 @@ import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRen import net.minecraft.client.renderer.BufferBuilder; -public class RotatingActorModel extends InstancedModel { - public RotatingActorModel(InstancedTileRenderer renderer, BufferBuilder buf) { +public class ActorModel extends InstancedModel { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(ActorVertexAttributes.class) + .build(); + + public ActorModel(InstancedTileRenderer renderer, BufferBuilder buf) { super(renderer, buf); } @Override protected VertexFormat getInstanceFormat() { - return ContraptionActorData.FORMAT; + return FORMAT; } @Override - protected ContraptionActorData newInstance() { - return new ContraptionActorData(this); + protected ActorData newInstance() { + return new ActorData(this); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java index acd1d0dc4..596d540eb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java @@ -2,7 +2,6 @@ package com.simibubi.create.content.contraptions.components.actors; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; @@ -13,15 +12,15 @@ import net.minecraft.block.BlockState; import net.minecraft.util.Direction; import net.minecraft.util.math.vector.Quaternion; -public class DrillActorInstance extends ActorInstance { +public class DrillActorInstance extends com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance { - InstanceKey drillHead; + InstanceKey drillHead; private Direction facing; public DrillActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { super(modelManager, context); - RenderMaterial> renderMaterial = modelManager.getActorMaterial(); + RenderMaterial> renderMaterial = modelManager.getActorMaterial(); BlockState state = context.state; @@ -48,11 +47,10 @@ public class DrillActorInstance extends ActorInstance { } @Override - protected void tick() { + public void beginFrame() { drillHead.getInstance().setSpeed(getSpeed(facing)); } - @Override protected float getSpeed(Direction facing) { if (context.contraption.stalled || !VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) return context.getAnimationSpeed(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java index d70a2c500..44a352b23 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.components.actors; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; @@ -7,44 +8,87 @@ import com.simibubi.create.content.contraptions.components.structureMovement.ren import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; -import net.minecraft.util.math.vector.Quaternion; -import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.util.math.vector.Vector3d; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; public class HarvesterActorInstance extends ActorInstance { + static double oneOverRadius = 16.0 / 6.5; + static float originOffset = 1 / 16f; + static Vector3d rotOffset = new Vector3d(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); - InstanceKey harvester; + + InstanceKey harvester; private Direction facing; + private float horizontalAngle; + + private double rotation; + private double previousRotation; + public HarvesterActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { super(modelManager, context); - RenderMaterial> renderMaterial = modelManager.getActorMaterial(); + RenderMaterial> renderMaterial = modelManager.transformMaterial(); BlockState state = context.state; facing = state.get(HORIZONTAL_FACING); - float originOffset = 1 / 16f; - Vector3f rotOffset = new Vector3f(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); harvester = renderMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance(); - float horizontalAngle = facing.getHorizontalAngle() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); + horizontalAngle = facing.getHorizontalAngle() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); + harvester.getInstance() - .setPosition(context.localPos) - .setBlockLight(localBlockLight()) - .setRotationOffset(0) - .setRotationCenter(rotOffset) - .setRotationAxis(-1, 0, 0) - .setLocalRotation(new Quaternion(Vector3f.POSITIVE_Y, horizontalAngle, true)) - .setSpeed(getSpeed(facing)); + .setBlockLight(localBlockLight()); } @Override - protected void tick() { - harvester.getInstance().setSpeed(getSpeed(facing)); + public void tick() { + super.tick(); + + previousRotation = rotation; + + if (context.contraption.stalled || VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite())) + return; + + double arcLength = context.motion.length(); + + double radians = arcLength * oneOverRadius; + + float deg = AngleHelper.deg(radians); + + deg = (float) (((int) (deg * 3000)) / 3000); + + rotation += deg * 1.25; + + rotation %= 360; + } + + @Override + public void beginFrame() { + MatrixStack ms = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(ms); + + msr.translate(context.localPos) + .centre() + .rotateY(horizontalAngle) + .unCentre() + .translate(rotOffset) + .rotateX(getRotation()) + .translateBack(rotOffset); + + harvester.getInstance().setTransform(ms); + } + + private double getRotation() { + return AngleHelper.angleLerp(AnimationTickHolder.getPartialTicks(), previousRotation, rotation); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java index cb3d68883..22f6e3143 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java @@ -20,7 +20,7 @@ public class MechanicalCrafterInstance extends SingleRotatingInstance { @Override protected InstancedModel getModel() { - Direction facing = lastState.get(MechanicalCrafterBlock.HORIZONTAL_FACING); + Direction facing = blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING); Supplier ms = () -> { MatrixStack stack = new MatrixStack(); @@ -34,6 +34,6 @@ public class MechanicalCrafterInstance extends SingleRotatingInstance { stacker.unCentre(); return stack; }; - return rotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, lastState, facing, ms); + return rotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, blockState, facing, ms); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java index 8968432d9..27b54f003 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterTileEntity.java @@ -37,7 +37,6 @@ import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class MechanicalCrafterTileEntity extends KineticTileEntity { @@ -46,7 +45,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { IDLE, ACCEPTING, ASSEMBLING, EXPORTING, WAITING, CRAFTING, INSERTING; } - static class Inventory extends SmartInventory { + public static class Inventory extends SmartInventory { private MechanicalCrafterTileEntity te; @@ -57,11 +56,11 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { whenContentsChanged(slot -> { if (getStackInSlot(slot).isEmpty()) return; - if(te.phase == Phase.IDLE) + if (te.phase == Phase.IDLE) te.checkCompletedRecipe(false); }); } - + @Override public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { if (te.phase != Phase.IDLE) @@ -70,9 +69,9 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { return stack; return super.insertItem(slot, stack, simulate); } - + } - + protected Inventory inventory; protected GroupedItems groupedItems = new GroupedItems(); protected ConnectedInput input = new ConnectedInput(); @@ -87,13 +86,15 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { private InvManipulationBehaviour inserting; private EdgeInteractionBehaviour connectivity; + private ItemStack scriptedResult = ItemStack.EMPTY; + public MechanicalCrafterTileEntity(TileEntityType type) { super(type); setLazyTickRate(20); phase = Phase.IDLE; groupedItemsBeforeCraft = new GroupedItems(); inventory = new Inventory(this); - + // Does not get serialized due to active checking in tick wasPoweredBefore = true; } @@ -118,7 +119,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { public BlockFace getTargetFace(World world, BlockPos pos, BlockState state) { return new BlockFace(pos, MechanicalCrafterBlock.getTargetDirection(state)); } - + public Direction getTargetDirection() { return MechanicalCrafterBlock.getTargetDirection(getBlockState()); } @@ -140,7 +141,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { compound.putBoolean("Cover", covered); super.write(compound, clientPacket); - + if (clientPacket && reRender) { compound.putBoolean("Redraw", true); reRender = false; @@ -151,7 +152,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { Phase phaseBefore = phase; GroupedItems before = this.groupedItems; - + inventory.deserializeNBT(compound.getCompound("Inventory")); input.read(compound.getCompound("ConnectedInput")); groupedItems = GroupedItems.read(compound.getCompound("GroupedItems")); @@ -164,7 +165,6 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { countDown = compound.getInt("CountDown"); covered = compound.getBoolean("Cover"); super.fromTag(state, compound, clientPacket); - if (!clientPacket) return; if (compound.contains("Redraw")) @@ -200,10 +200,13 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (phase == Phase.ACCEPTING) return; + boolean onClient = world.isRemote; + boolean runLogic = !onClient || isVirtual(); + if (wasPoweredBefore != world.isBlockPowered(pos)) { wasPoweredBefore = world.isBlockPowered(pos); if (wasPoweredBefore) { - if (world.isRemote) + if (!runLogic) return; checkCompletedRecipe(true); } @@ -213,7 +216,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { countDown -= getCountDownSpeed(); if (countDown < 0) { countDown = 0; - if (world.isRemote) + if (!runLogic) return; if (RecipeGridHandler.getTargetingCrafter(this) != null) { phase = Phase.EXPORTING; @@ -221,9 +224,11 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { sendData(); return; } - ItemStack result = RecipeGridHandler.tryToApplyRecipe(world, groupedItems); - if (result != null) { + ItemStack result = + isVirtual() ? scriptedResult : RecipeGridHandler.tryToApplyRecipe(world, groupedItems); + + if (result != null) { List containers = new ArrayList<>(); groupedItems.grid.values() .forEach(stack -> { @@ -232,6 +237,9 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { .copy()); }); + if (isVirtual()) + groupedItemsBeforeCraft = groupedItems; + groupedItems = new GroupedItems(result); for (int i = 0; i < containers.size(); i++) { ItemStack stack = containers.get(i); @@ -255,7 +263,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (countDown < 0) { countDown = 0; - if (world.isRemote) + if (!runLogic) return; MechanicalCrafterTileEntity targetingCrafter = RecipeGridHandler.getTargetingCrafter(this); @@ -278,7 +286,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { if (phase == Phase.CRAFTING) { - if (world.isRemote) { + if (onClient) { Direction facing = getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING); float progress = countDown / 2000f; Vector3d facingVec = Vector3d.of(facing.getDirectionVec()); @@ -314,7 +322,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { countDown -= getCountDownSpeed(); if (countDown < 0) { countDown = 0; - if (world.isRemote) + if (!runLogic) return; tryInsert(); return; @@ -322,7 +330,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } if (phase == Phase.INSERTING) { - if (!world.isRemote && isTargetingBelt()) + if (runLogic && isTargetingBelt()) tryInsert(); return; } @@ -359,7 +367,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { stack.setCount(remainder.getCount()); continue; } - + inserted.add(pair); } @@ -405,7 +413,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { @Override public void lazyTick() { super.lazyTick(); - if (world.isRemote) + if (world.isRemote && !isVirtual()) return; if (phase == Phase.IDLE && craftingItemPresent()) checkCompletedRecipe(false); @@ -426,7 +434,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { protected void checkCompletedRecipe(boolean poweredStart) { if (getSpeed() == 0) return; - if (world.isRemote) + if (world.isRemote && !isVirtual()) return; List chain = RecipeGridHandler.getAllCraftersOfChainIf(this, poweredStart ? MechanicalCrafterTileEntity::craftingItemPresent @@ -466,11 +474,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { @Override public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) { - if (getBlockState().get(HORIZONTAL_FACING) == side) - return LazyOptional.empty(); + if (isItemHandlerCap(cap)) return invSupplier.cast(); - } return super.getCapability(cap, side); } @@ -490,4 +495,8 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { return true; } + public void setScriptedResult(ItemStack scriptedResult) { + this.scriptedResult = scriptedResult; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java index b59c90a42..b2843f376 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java @@ -4,10 +4,10 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.*; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -15,35 +15,30 @@ import net.minecraft.block.Block; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; -public class HandCrankInstance extends SingleRotatingInstance implements ITickableInstance { +public class HandCrankInstance extends SingleRotatingInstance implements IDynamicInstance { private InstanceKey crank; private Direction facing; public HandCrankInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - super.init(); - - Block block = lastState.getBlock(); + Block block = blockState.getBlock(); AllBlockPartials renderedHandle = null; if (block instanceof HandCrankBlock) renderedHandle = ((HandCrankBlock) block).getRenderedHandle(); if (renderedHandle == null) return; - facing = lastState.get(BlockStateProperties.FACING); - InstancedModel model = renderedHandle.renderOnDirectionalSouthModel(modelManager, lastState, facing.getOpposite()); + facing = blockState.get(BlockStateProperties.FACING); + InstancedModel model = renderedHandle.renderOnDirectionalSouthModel(modelManager, blockState, facing.getOpposite()); crank = model.createInstance(); updateLight(); } @Override - public void tick() { + public void beginFrame() { if (crank == null) return; HandCrankTileEntity crankTile = (HandCrankTileEntity) tile; @@ -58,7 +53,7 @@ public class HandCrankInstance extends SingleRotatingInstance implements ITickab .rotate(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis), angle) .unCentre(); - crank.getInstance().setTransformNoCopy(ms); + crank.getInstance().setTransform(ms); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java index b4f44bfdb..5dd6ae531 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java @@ -37,7 +37,7 @@ public class DeployerActorInstance extends ActorInstance { public DeployerActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { super(modelManager, context); - RenderMaterial> mat = modelManager.basicMaterial(); + RenderMaterial> mat = modelManager.transformMaterial(); BlockState state = context.state; DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class); @@ -62,16 +62,16 @@ public class DeployerActorInstance extends ActorInstance { int blockLight = localBlockLight(); shaft.getInstance() - .setBlockLight(blockLight) - .setRotationAxis(axis) - .setPosition(context.localPos); + .setRotationAxis(axis) + .setPosition(context.localPos) + .setBlockLight(blockLight); pole.getInstance().setBlockLight(blockLight); hand.getInstance().setBlockLight(blockLight); } @Override - protected void tick() { + public void beginFrame() { double factor; if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { factor = MathHelper.sin(AnimationTickHolder.getRenderTime() * .5f) * .25f + .25f; @@ -91,6 +91,23 @@ public class DeployerActorInstance extends ActorInstance { msr.translate(context.localPos) .translate(offset); - DeployerInstance.transformModel(msr, pole, hand, yRot, zRot, zRotPole); + transformModel(msr, pole, hand, yRot, zRot, zRotPole); + } + + static void transformModel(MatrixStacker msr, InstanceKey pole, InstanceKey hand, float yRot, float zRot, float zRotPole) { + + msr.centre(); + msr.rotate(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); + msr.rotate(Direction.UP, (float) ((yRot) / 180 * Math.PI)); + + msr.push(); + msr.rotate(Direction.SOUTH, (float) ((zRotPole) / 180 * Math.PI)); + msr.unCentre(); + pole.getInstance().setTransform(msr.unwrap()); + msr.pop(); + + msr.unCentre(); + + hand.getInstance().setTransform(msr.unwrap()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java index 9c16d01a9..65d0102e8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java @@ -1,81 +1,90 @@ package com.simibubi.create.content.contraptions.components.deployer; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.*; +import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedData; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.MatrixStacker; + import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3i; import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; -public class DeployerInstance extends ShaftInstance implements ITickableInstance { +public class DeployerInstance extends ShaftInstance implements IDynamicInstance, ITickableInstance { - DeployerTileEntity tile; + final DeployerTileEntity tile; + final Direction facing; + final float yRot; + final float zRot; + final float zRotPole; - Direction facing; + protected final InstanceKey pole; - InstanceKey pole; + protected InstanceKey hand; AllBlockPartials currentHand; - InstanceKey hand; - - float yRot; - float zRot; - float zRotPole; - float progress = Float.NaN; + private boolean newHand = false; public DeployerInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - } - - @Override - protected void init() { - super.init(); this.tile = (DeployerTileEntity) super.tile; - facing = lastState.get(FACING); + facing = blockState.get(FACING); - boolean rotatePole = lastState.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; + boolean rotatePole = blockState.get(AXIS_ALONG_FIRST_COORDINATE) ^ facing.getAxis() == Direction.Axis.Z; yRot = AngleHelper.horizontalAngle(facing); zRot = facing == Direction.UP ? 270 : facing == Direction.DOWN ? 90 : 0; zRotPole = rotatePole ? 90 : 0; - pole = modelManager.basicMaterial().getModel(AllBlockPartials.DEPLOYER_POLE, lastState).createInstance(); + pole = RenderMaterials.ORIENTED.get(modelManager).getModel(AllBlockPartials.DEPLOYER_POLE, blockState).createInstance(); updateHandPose(); relight(pos, pole.getInstance()); + + updateRotation(pole, hand, yRot, zRot, zRotPole); } @Override public void tick() { + newHand = updateHandPose(); + } - boolean newHand = updateHandPose(); + @Override + public void beginFrame() { float newProgress = getProgress(AnimationTickHolder.getPartialTicks()); if (!newHand && MathHelper.epsilonEquals(newProgress, progress)) return; progress = newProgress; + newHand = false; - MatrixStack ms = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(ms); + float handLength = currentHand == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 + : currentHand == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; + float distance = Math.min(MathHelper.clamp(progress, 0, 1) * (tile.reach + handLength), 21 / 16f); + Vector3i facingVec = facing.getDirectionVec(); + BlockPos blockPos = getFloatingPos(); - msr.translate(getFloatingPos()) - .translate(getHandOffset()); + float x = blockPos.getX() + ((float) facingVec.getX()) * distance; + float y = blockPos.getY() + ((float) facingVec.getY()) * distance; + float z = blockPos.getZ() + ((float) facingVec.getZ()) * distance; - transformModel(msr, pole, hand, yRot, zRot, zRotPole); + pole.getInstance().setPosition(x, y, z); + hand.getInstance().setPosition(x, y, z); } @@ -102,20 +111,14 @@ public class DeployerInstance extends ShaftInstance implements ITickableInstance if (hand != null) hand.delete(); - hand = modelManager.basicMaterial().getModel(currentHand, lastState).createInstance(); + hand = RenderMaterials.ORIENTED.get(modelManager).getModel(currentHand, blockState).createInstance(); relight(pos, hand.getInstance()); + updateRotation(pole, hand, yRot, zRot, zRotPole); return true; } - protected Vector3d getHandOffset() { - float handLength = tile.getHandPose() == AllBlockPartials.DEPLOYER_HAND_POINTING ? 0 - : tile.getHandPose() == AllBlockPartials.DEPLOYER_HAND_HOLDING ? 4 / 16f : 3 / 16f; - float distance = Math.min(MathHelper.clamp(progress, 0, 1) * (tile.reach + handLength), 21 / 16f); - return Vector3d.of(facing.getDirectionVec()).scale(distance); - } - private float getProgress(float partialTicks) { if (tile.state == DeployerTileEntity.State.EXPANDING) return 1 - (tile.timer - partialTicks * tile.getTimerSpeed()) / 1000f; @@ -124,20 +127,15 @@ public class DeployerInstance extends ShaftInstance implements ITickableInstance return 0; } - static void transformModel(MatrixStacker msr, InstanceKey pole, InstanceKey hand, float yRot, float zRot, float zRotPole) { + static void updateRotation(InstanceKey pole, InstanceKey hand, float yRot, float zRot, float zRotPole) { - msr.centre(); - msr.rotate(Direction.SOUTH, (float) ((zRot) / 180 * Math.PI)); - msr.rotate(Direction.UP, (float) ((yRot) / 180 * Math.PI)); + Quaternion q = Direction.SOUTH.getUnitVector().getDegreesQuaternion(zRot); + q.multiply(Direction.UP.getUnitVector().getDegreesQuaternion(yRot)); - msr.push(); - msr.rotate(Direction.SOUTH, (float) ((zRotPole) / 180 * Math.PI)); - msr.unCentre(); - pole.getInstance().setTransform(msr.unwrap()); - msr.pop(); + hand.getInstance().setRotation(q); - msr.unCentre(); + q.multiply(Direction.SOUTH.getUnitVector().getDegreesQuaternion(zRotPole)); - hand.getInstance().setTransform(msr.unwrap()); + pole.getInstance().setRotation(q); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java index 49a38cb42..b32d83a9c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java @@ -5,7 +5,6 @@ import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileInstance; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -15,37 +14,27 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING; public class FanInstance extends KineticTileInstance { - protected InstanceKey shaft; - protected InstanceKey fan; + protected final InstanceKey shaft; + protected final InstanceKey fan; + final Direction.Axis axis; + final Direction direction; public FanInstance(InstancedTileRenderer modelManager, EncasedFanTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - final Direction direction = lastState.get(FACING); - final Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + direction = blockState.get(FACING); + axis = ((IRotate) blockState.getBlock()).getRotationAxis(blockState); - InstancedModel shaftHalf = - AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, direction.getOpposite()); - InstancedModel fanInner = - AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthRotating(modelManager, lastState, direction.getOpposite()); + shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, blockState, direction.getOpposite()).createInstance(); + fan = AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthRotating(modelManager, blockState, direction.getOpposite()).createInstance(); - shaft = shaftHalf.createInstance(); - shaft.getInstance() - .setRotationalSpeed(tile.getSpeed()) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) - .setTileEntity(tile); + RotatingData shaftInstance = shaft.getInstance(); + shaftInstance.setTileEntity(tile); + updateRotation(shaftInstance, axis); - - fan = fanInner.createInstance(); - fan.getInstance() - .setRotationalSpeed(getFanSpeed()) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) - .setTileEntity(tile); + RotatingData fanInstance = fan.getInstance(); + fanInstance.setTileEntity(tile); + updateRotation(fanInstance, axis, getFanSpeed()); updateLight(); } @@ -60,21 +49,13 @@ public class FanInstance extends KineticTileInstance { } @Override - protected void onUpdate() { - Direction.Axis axis = lastState.get(FACING).getAxis(); + protected void update() { updateRotation(shaft, axis); - - fan.getInstance() - .setColor(tile.network) - .setRotationalSpeed(getFanSpeed()) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()); + updateRotation(fan, axis, getFanSpeed()); } @Override public void updateLight() { - final Direction direction = lastState.get(FACING); - BlockPos behind = pos.offset(direction.getOpposite()); relight(behind, shaft.getInstance()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java index cf0713744..5a745a7cc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java @@ -1,5 +1,8 @@ package com.simibubi.create.content.contraptions.components.flywheel; +import java.util.Collections; +import java.util.List; + import com.google.common.collect.Lists; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; @@ -17,26 +20,24 @@ import net.minecraft.util.Direction; import net.minecraft.util.Rotation; import net.minecraft.util.math.MathHelper; -import java.util.Collections; -import java.util.List; +public class FlyWheelInstance extends KineticTileInstance implements IDynamicInstance { -public class FlyWheelInstance extends KineticTileInstance implements ITickableInstance { + protected final Direction facing; + protected final Direction connection; - protected Direction facing; protected boolean connectedLeft; protected float connectorAngleMult; - protected Direction connection; + protected final InstanceKey shaft; - protected InstanceKey shaft; + protected final InstanceKey wheel; - protected InstanceKey wheel; + protected List> connectors; protected InstanceKey upperRotating; protected InstanceKey lowerRotating; protected InstanceKey upperSliding; protected InstanceKey lowerSliding; - protected List> connectors; protected float lastAngle = Float.NaN; @@ -44,31 +45,28 @@ public class FlyWheelInstance extends KineticTileInstance im public FlyWheelInstance(InstancedTileRenderer modelManager, FlywheelTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - facing = lastState.get(BlockStateProperties.HORIZONTAL_FACING); + facing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); - Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + Direction.Axis axis = ((IRotate) blockState.getBlock()).getRotationAxis(blockState); shaft = setup(shaftModel().createInstance(), tile.getSpeed(), axis); - wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontalModel(modelManager, lastState.rotate(Rotation.CLOCKWISE_90)).createInstance(); + wheel = AllBlockPartials.FLYWHEEL.renderOnHorizontalModel(modelManager, blockState.rotate(Rotation.CLOCKWISE_90)).createInstance(); - connection = FlywheelBlock.getConnection(lastState); + connection = FlywheelBlock.getConnection(blockState); if (connection != null) { - connectedLeft = lastState.get(FlywheelBlock.CONNECTION) == FlywheelBlock.ConnectionState.LEFT; + connectedLeft = blockState.get(FlywheelBlock.CONNECTION) == FlywheelBlock.ConnectionState.LEFT; boolean flipAngle = connection.getAxis() == Direction.Axis.X ^ connection.getAxisDirection() == Direction.AxisDirection.NEGATIVE; connectorAngleMult = flipAngle ? -1 : 1; - RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.TRANSFORMED); - upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, lastState).createInstance(); - lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, lastState).createInstance(); - upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, lastState).createInstance(); - lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, lastState).createInstance(); + upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance(); + lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance(); + upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, blockState).createInstance(); + lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, blockState).createInstance(); connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding); } else { @@ -76,11 +74,10 @@ public class FlyWheelInstance extends KineticTileInstance im } updateLight(); - firstFrame = true; } @Override - public void tick() { + public void beginFrame() { float partialTicks = AnimationTickHolder.getPartialTicks(); @@ -127,15 +124,15 @@ public class FlyWheelInstance extends KineticTileInstance im .rotate(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, facing.getAxis()), AngleHelper.rad(angle)) .unCentre(); - wheel.getInstance().setTransformNoCopy(ms); + wheel.getInstance().setTransform(ms); lastAngle = angle; firstFrame = false; } @Override - protected void onUpdate() { - Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + protected void update() { + Direction.Axis axis = ((IRotate) blockState.getBlock()).getRotationAxis(blockState); updateRotation(shaft, axis); } @@ -158,7 +155,7 @@ public class FlyWheelInstance extends KineticTileInstance im } protected InstancedModel shaftModel() { - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, facing.getOpposite()); + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, blockState, facing.getOpposite()); } protected void transformConnector(MatrixStacker ms, boolean upper, boolean rotating, float angle, boolean flip) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java index 30a87e688..b2830d978 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java @@ -19,21 +19,18 @@ public class EngineInstance extends TileEntityInstance { public EngineInstance(InstancedTileRenderer modelManager, EngineTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - Block block = lastState - .getBlock(); + Block block = blockState + .getBlock(); if (!(block instanceof EngineBlock)) return; EngineBlock engineBlock = (EngineBlock) block; AllBlockPartials frame = engineBlock.getFrameModel(); - Direction facing = lastState.get(BlockStateProperties.HORIZONTAL_FACING); + Direction facing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); - this.frame = modelManager.getMaterial(RenderMaterials.MODELS).getModel(frame, lastState).createInstance(); + this.frame = modelManager.getMaterial(RenderMaterials.TRANSFORMED).getModel(frame, blockState).createInstance(); float angle = AngleHelper.rad(AngleHelper.horizontalAngle(facing)); @@ -48,7 +45,7 @@ public class EngineInstance extends TileEntityInstance { .translate(0, 0, -1); this.frame.getInstance() - .setTransformNoCopy(ms); + .setTransform(ms); updateLight(); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java index f12a22c5a..e7785f56a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerTileEntity.java @@ -117,7 +117,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { if (world.isRemote && runningTicks == 20) renderParticles(); - if (!world.isRemote && runningTicks == 20) { + if ((!world.isRemote || isVirtual()) && runningTicks == 20) { if (processingTicks < 0) { processingTicks = MathHelper.clamp((MathHelper.log2((int) (512 / speed))) * 15 + 1, 1, 512); } else { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java index 10f53c990..0c241f384 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java @@ -6,6 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.content.contraptions.base.ShaftlessCogInstance; import com.simibubi.create.foundation.render.backend.RenderMaterials; +import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; @@ -14,27 +15,22 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.util.Direction; -public class MixerInstance extends ShaftlessCogInstance implements ITickableInstance { +public class MixerInstance extends ShaftlessCogInstance implements IDynamicInstance { - private InstanceKey mixerHead; - private InstanceKey mixerPole; + private final InstanceKey mixerHead; + private final InstanceKey mixerPole; public MixerInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - } - @Override - protected void init() { - super.init(); - - mixerHead = rotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD, lastState) + mixerHead = rotatingMaterial().getModel(AllBlockPartials.MECHANICAL_MIXER_HEAD, blockState) .createInstance(); mixerHead.getInstance() .setRotationAxis(Direction.Axis.Y); - mixerPole = modelManager.getMaterial(RenderMaterials.MODELS) - .getModel(AllBlockPartials.MECHANICAL_MIXER_POLE, lastState) + mixerPole = modelManager.getMaterial(RenderMaterials.TRANSFORMED) + .getModel(AllBlockPartials.MECHANICAL_MIXER_POLE, blockState) .createInstance(); @@ -47,7 +43,7 @@ public class MixerInstance extends ShaftlessCogInstance implements ITickableInst } @Override - public void tick() { + public void beginFrame() { MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) tile; float renderedHeadOffset = getRenderedHeadOffset(mixer); @@ -75,7 +71,7 @@ public class MixerInstance extends ShaftlessCogInstance implements ITickableInst msr.translate(getFloatingPos()); msr.translate(0, -renderedHeadOffset, 0); - mixerPole.getInstance().setTransformNoCopy(ms); + mixerPole.getInstance().setTransform(ms); } private float getRenderedHeadOffset(MechanicalMixerTileEntity mixer) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java index 3bcbb592b..8795ff509 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressTileEntity.java @@ -121,6 +121,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { public void start(Mode mode) { this.mode = mode; running = true; + prevRunningTicks = 0; runningTicks = 0; pressedItems.clear(); sendData(); @@ -204,7 +205,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { if (prevRunningTicks < CYCLE / 2 && runningTicks >= CYCLE / 2) { runningTicks = CYCLE / 2; // Pause the ticks until a packet is received - if (world.isRemote) + if (world.isRemote && !isVirtual()) runningTicks = -(CYCLE / 2); } } @@ -343,7 +344,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { return Optional.of(AllTriggers.PRESS_COMPACT); } - enum Mode { + public enum Mode { WORLD(1), BELT(19f / 16f), BASIN(22f / 16f) ; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java index bba66bdf4..cacf1d99d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java @@ -4,36 +4,28 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.RenderMaterials; -import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; +import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; -public class PressInstance extends ShaftInstance implements ITickableInstance { +public class PressInstance extends ShaftInstance implements IDynamicInstance { - private InstanceKey pressHead; + private final InstanceKey pressHead; public PressInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - } - @Override - protected void init() { - super.init(); - - pressHead = modelManager.getMaterial(RenderMaterials.MODELS) - .getModel(AllBlockPartials.MECHANICAL_PRESS_HEAD, lastState) - .createInstance(); + pressHead = AllBlockPartials.MECHANICAL_PRESS_HEAD.renderOnHorizontalModel(dispatcher, blockState).createInstance(); updateLight(); transformModels((MechanicalPressTileEntity) tile); } @Override - public void tick() { + public void beginFrame() { MechanicalPressTileEntity press = (MechanicalPressTileEntity) tile; if (!press.running) return; @@ -51,7 +43,7 @@ public class PressInstance extends ShaftInstance implements ITickableInstance { msr.translate(0, -renderedHeadOffset, 0); pressHead.getInstance() - .setTransformNoCopy(ms); + .setTransform(ms); } private float getRenderedHeadOffset(MechanicalPressTileEntity press) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java index 1e01db67b..3e0a1bbf8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java @@ -19,8 +19,8 @@ public class SawInstance extends SingleRotatingInstance { @Override protected InstancedModel getModel() { - if (lastState.get(FACING).getAxis().isHorizontal()) - return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState.rotate(tile.getWorld(), tile.getPos(), Rotation.CLOCKWISE_180)); + if (blockState.get(FACING).getAxis().isHorizontal()) + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, blockState.rotate(tile.getWorld(), tile.getPos(), Rotation.CLOCKWISE_180)); else return rotatingMaterial().getModel(KineticTileEntityRenderer.KINETIC_TILE, shaft(getRotationAxis())); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java index 45b30f78a..9c3e96f62 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawTileEntity.java @@ -1,5 +1,14 @@ package com.simibubi.create.content.contraptions.components.saw; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import javax.annotation.ParametersAreNonnullByDefault; + import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.AllTags; import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity; @@ -42,21 +51,13 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Random; -import java.util.function.Predicate; -import java.util.stream.Collectors; - - @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class SawTileEntity extends BlockBreakingKineticTileEntity { private static final Object cuttingRecipesKey = new Object(); - public static final LazyValue> woodcuttingRecipeType = new LazyValue<>(() -> Registry.RECIPE_TYPE.getOrDefault(new ResourceLocation("druidcraft", "woodcutting"))); + public static final LazyValue> woodcuttingRecipeType = + new LazyValue<>(() -> Registry.RECIPE_TYPE.getOrDefault(new ResourceLocation("druidcraft", "woodcutting"))); public ProcessingInventory inventory; private int recipeIndex; @@ -137,10 +138,14 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { continue; ItemStack tryExportingToBeltFunnel = getBehaviour(DirectBeltInputBehaviour.TYPE) .tryExportingToBeltFunnel(stack, itemMovementFacing.getOpposite()); - if (tryExportingToBeltFunnel.getCount() != stack.getCount()) { - inventory.setStackInSlot(slot, tryExportingToBeltFunnel); - notifyUpdate(); - return; + if (tryExportingToBeltFunnel != null) { + if (tryExportingToBeltFunnel.getCount() != stack.getCount()) { + inventory.setStackInSlot(slot, tryExportingToBeltFunnel); + notifyUpdate(); + return; + } + if (!tryExportingToBeltFunnel.isEmpty()) + return; } } @@ -263,19 +268,19 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { private List> getRecipes() { /* - Predicate> types = AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() - ? RecipeConditions.isOfType(IRecipeType.STONECUTTING, AllRecipeTypes.CUTTING.getType()) - : RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType()); - + * Predicate> types = + * AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() ? + * RecipeConditions.isOfType(IRecipeType.STONECUTTING, + * AllRecipeTypes.CUTTING.getType()) : + * RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType()); + * */ - Predicate> types = RecipeConditions.isOfType( - AllRecipeTypes.CUTTING.getType(), + Predicate> types = RecipeConditions.isOfType(AllRecipeTypes.CUTTING.getType(), AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() ? IRecipeType.STONECUTTING : null, - AllConfigs.SERVER.recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.getValue() : null - ); + AllConfigs.SERVER.recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.getValue() : null); - List> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, types); + List> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, types); return startedSearch.stream() .filter(RecipeConditions.outputMatchesFilter(filtering)) .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java index 384c64ea0..a50ad664b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/Contraption.java @@ -110,6 +110,8 @@ public abstract class Contraption { public List maybeInstancedTileEntities; public List specialRenderedTileEntities; + protected ContraptionWorld world; + public Contraption() { blocks = new HashMap<>(); storage = new HashMap<>(); @@ -127,6 +129,14 @@ public abstract class Contraption { stabilizedSubContraptions = new HashMap<>(); } + public ContraptionWorld getContraptionWorld() { + if (world == null) { + world = new ContraptionWorld(entity.world, this); + } + + return world; + } + public abstract boolean assemble(World world, BlockPos pos) throws AssemblyException; public abstract boolean canBeStabilized(Direction facing, BlockPos localPos); @@ -1062,7 +1072,7 @@ public abstract class Contraption { GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius); - GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(bounds); + GridAlignedBB contraptionBounds = GridAlignedBB.from(bounds); if (axis == Direction.Axis.X) { betterBounds.maxX = contraptionBounds.maxX; betterBounds.minX = contraptionBounds.minX; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java index b565e6cae..11443ae6e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java @@ -69,7 +69,6 @@ public class ContraptionCollider { Vector3d contraptionPosition = contraptionEntity.getPositionVec(); Vector3d contraptionMotion = contraptionPosition.subtract(contraptionEntity.getPrevPositionVec()); Vector3d anchorVec = contraptionEntity.getAnchorVec(); - Vector3d centerOfBlock = VecHelper.CENTER_OF_ORIGIN; ContraptionRotationState rotation = null; // After death, multiple refs to the client player may show up in the area @@ -102,19 +101,10 @@ public class ContraptionCollider { // Transform entity position and motion to local space Vector3d entityPosition = entity.getPositionVec(); AxisAlignedBB entityBounds = entity.getBoundingBox(); - Vector3d centerY = new Vector3d(0, entityBounds.getYSize() / 2, 0); Vector3d motion = entity.getMotion(); float yawOffset = rotation.getYawOffset(); - Vector3d position = entityPosition; - position = position.add(centerY); - position = position.subtract(centerOfBlock); - position = position.subtract(anchorVec); - position = VecHelper.rotate(position, -yawOffset, Axis.Y); - position = rotationMatrix.transform(position); - position = position.add(centerOfBlock); - position = position.subtract(centerY); - position = position.subtract(entityPosition); + Vector3d position = getWorldToLocalTranslation(entity, anchorVec, rotationMatrix, yawOffset); // Find all potential block shapes to collide with AxisAlignedBB localBB = entityBounds.offset(position) @@ -263,6 +253,48 @@ public class ContraptionCollider { } + public static Vector3d getWorldToLocalTranslation(Entity entity, AbstractContraptionEntity contraptionEntity) { + return getWorldToLocalTranslation(entity, contraptionEntity.getAnchorVec(), contraptionEntity.getRotationState()); + } + + public static Vector3d getWorldToLocalTranslation(Entity entity, Vector3d anchorVec, ContraptionRotationState rotation) { + return getWorldToLocalTranslation(entity, anchorVec, rotation.asMatrix(), rotation.getYawOffset()); + } + + public static Vector3d getWorldToLocalTranslation(Entity entity, Vector3d anchorVec, Matrix3d rotationMatrix, float yawOffset) { + Vector3d entityPosition = entity.getPositionVec(); + Vector3d centerY = new Vector3d(0, entity.getBoundingBox().getYSize() / 2, 0); + Vector3d position = entityPosition; + position = position.add(centerY); + position = position.subtract(VecHelper.CENTER_OF_ORIGIN); + position = position.subtract(anchorVec); + position = VecHelper.rotate(position, -yawOffset, Axis.Y); + position = rotationMatrix.transform(position); + position = position.add(VecHelper.CENTER_OF_ORIGIN); + position = position.subtract(centerY); + position = position.subtract(entityPosition); + return position; + } + + public static Vector3d getWorldToLocalTranslation(Vector3d entity, AbstractContraptionEntity contraptionEntity) { + return getWorldToLocalTranslation(entity, contraptionEntity.getAnchorVec(), contraptionEntity.getRotationState()); + } + + public static Vector3d getWorldToLocalTranslation(Vector3d inPos, Vector3d anchorVec, ContraptionRotationState rotation) { + return getWorldToLocalTranslation(inPos, anchorVec, rotation.asMatrix(), rotation.getYawOffset()); + } + + public static Vector3d getWorldToLocalTranslation(Vector3d inPos, Vector3d anchorVec, Matrix3d rotationMatrix, float yawOffset) { + Vector3d position = inPos; + position = position.subtract(VecHelper.CENTER_OF_ORIGIN); + position = position.subtract(anchorVec); + position = VecHelper.rotate(position, -yawOffset, Axis.Y); + position = rotationMatrix.transform(position); + position = position.add(VecHelper.CENTER_OF_ORIGIN); + position = position.subtract(inPos); + return position; + } + /** From Entity#getAllowedMovement **/ static Vector3d getAllowedMovement(Vector3d movement, Entity e) { AxisAlignedBB bb = e.getBoundingBox(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java index ee1f26352..93733774a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java @@ -1,10 +1,15 @@ package com.simibubi.create.content.contraptions.components.structureMovement; +import net.minecraft.world.IBlockDisplayReader; +import net.minecraft.world.LightType; + import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; +import com.simibubi.create.foundation.render.backend.light.LightUpdateListener; +import com.simibubi.create.foundation.render.backend.light.LightUpdater; import com.simibubi.create.foundation.render.backend.light.LightVolume; -public abstract class ContraptionLighter { +public abstract class ContraptionLighter implements LightUpdateListener { protected final C contraption; public final LightVolume lightVolume; @@ -21,14 +26,8 @@ public abstract class ContraptionLighter { lightVolume.initialize(contraption.entity.world); scheduleRebuild = true; - } - protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) { - bounds.grow(1); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting - bounds.minY = Math.max(bounds.minY, 0); - bounds.maxY = Math.min(bounds.maxY, 255); - - return bounds; + startListening(); } public void tick(RenderedContraption owner) { @@ -39,4 +38,28 @@ public abstract class ContraptionLighter { } public abstract GridAlignedBB getContraptionBounds(); + + @Override + public boolean onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) { + lightVolume.notifyLightUpdate(world, type, changed); + return false; + } + + @Override + public boolean onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { + lightVolume.notifyLightPacket(world, chunkX, chunkZ); + return false; + } + + protected void startListening() { + LightUpdater.getInstance().startListening(bounds, this); + } + + protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) { + bounds.grow(1); // so we have at least enough data on the edges to avoid artifacts and have smooth lighting + bounds.minY = Math.max(bounds.minY, 0); + bounds.maxY = Math.min(bounds.maxY, 255); + + return bounds; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java new file mode 100644 index 000000000..4a83b2b96 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionWorld.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.contraptions.components.structureMovement; + +import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.Template; + +public class ContraptionWorld extends WrappedWorld { + final Contraption contraption; + + public ContraptionWorld(World world, Contraption contraption) { + super(world); + + this.contraption = contraption; + } + + + @Override + public BlockState getBlockState(BlockPos pos) { + Template.BlockInfo blockInfo = contraption.getBlocks().get(pos); + + if (blockInfo != null) + return blockInfo.state; + + return Blocks.AIR.getDefaultState(); + } + + @Override + public void playSound(PlayerEntity player, double x, double y, double z, SoundEvent soundIn, SoundCategory category, float volume, float pitch) { + + Vector3d worldPos = ContraptionCollider.getWorldToLocalTranslation(new Vector3d(x, y, z), this.contraption.entity); + + worldPos = worldPos.add(x, y, z); + + world.playSound(player, worldPos.x, worldPos.y, worldPos.z, soundIn, category, volume, pitch); + } + + @Override + public void playSound(double x, double y, double z, SoundEvent p_184134_7_, SoundCategory p_184134_8_, float p_184134_9_, float p_184134_10_, boolean p_184134_11_) { + world.playSound(x, y, z, p_184134_7_, p_184134_8_, p_184134_9_, p_184134_10_, p_184134_11_); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java index 2eb557510..50ed095c8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java @@ -25,12 +25,14 @@ public class NonStationaryLighter extends ContraptionLigh if (!contraptionBounds.sameAs(bounds)) { lightVolume.move(contraption.entity.world, contraptionBoundsToVolume(contraptionBounds)); bounds = contraptionBounds; + + startListening(); } } @Override public GridAlignedBB getContraptionBounds() { - GridAlignedBB bb = GridAlignedBB.fromAABB(contraption.bounds); + GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); bb.translate(contraption.entity.getBlockPos()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java index 09cfa2a39..b5ed7ee45 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java @@ -12,7 +12,7 @@ public class AnchoredLighter extends ContraptionLighter { @Override public GridAlignedBB getContraptionBounds() { - GridAlignedBB bb = GridAlignedBB.fromAABB(contraption.bounds); + GridAlignedBB bb = GridAlignedBB.from(contraption.bounds); bb.translate(contraption.anchor); return bb; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java index 159056580..16d33de57 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerBlock.java @@ -114,10 +114,10 @@ public class StickerBlock extends ProperDirectionalBlock implements ITE implements ITickableInstance { +public class StickerInstance extends TileEntityInstance implements IDynamicInstance { float lastOffset = Float.NaN; + final Direction facing; + final boolean fakeWorld; + final int offset; - private InstanceKey head; + private final InstanceKey head; public StickerInstance(InstancedTileRenderer modelManager, StickerTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - head = modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.STICKER_HEAD, lastState).createInstance(); + head = modelManager.getMaterial(RenderMaterials.TRANSFORMED).getModel(AllBlockPartials.STICKER_HEAD, blockState).createInstance(); + + fakeWorld = tile.getWorld() != Minecraft.getInstance().world; + facing = blockState.get(StickerBlock.FACING); + offset = blockState.get(StickerBlock.EXTENDED) ? 1 : 0; updateLight(); } @Override - public void tick() { - lastState = world.getBlockState(pos); - + public void beginFrame() { float offset = tile.piston.getValue(AnimationTickHolder.getPartialTicks()); - if (tile.getWorld() != Minecraft.getInstance().world) - offset = lastState.get(StickerBlock.EXTENDED) ? 1 : 0; + if (fakeWorld) + offset = this.offset; - if (Math.abs(offset - lastOffset) < 1e-4) + if (MathHelper.epsilonEquals(offset, lastOffset)) return; - Direction facing = lastState.get(StickerBlock.FACING); MatrixStack stack = new MatrixStack(); MatrixStacker.of(stack) .translate(getFloatingPos()) @@ -55,7 +57,7 @@ public class StickerInstance extends TileEntityInstance imple .translate(0, (offset * offset) * 4 / 16f, 0); head.getInstance() - .setTransformNoCopy(stack); + .setTransform(stack); lastOffset = offset; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java index ccda7d654..7add70e0e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java @@ -4,6 +4,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -68,6 +69,8 @@ public class StickerTileEntity extends SmartTileEntity implements IInstanceRende if (isAttachedToBlock() && target == 0 && piston.getChaseTarget() == 1) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(false)); piston.chase(target, .4f, Chaser.LINEAR); + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); } public boolean isAttachedToBlock() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java index 0793c133d..d9b242fde 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java @@ -6,7 +6,7 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; import com.simibubi.create.foundation.render.backend.RenderMaterials; -import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; +import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; @@ -17,34 +17,35 @@ import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; -public class GantryCarriageInstance extends ShaftInstance implements ITickableInstance { +public class GantryCarriageInstance extends ShaftInstance implements IDynamicInstance { - private InstanceKey gantryCogs; + private final InstanceKey gantryCogs; + + final Direction facing; + final Boolean alongFirst; + final Direction.Axis rotationAxis; + final BlockPos visualPos; public GantryCarriageInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - } - @Override - protected void init() { - super.init(); - - gantryCogs = modelManager.getMaterial(RenderMaterials.MODELS) - .getModel(AllBlockPartials.GANTRY_COGS, lastState) + gantryCogs = modelManager.getMaterial(RenderMaterials.TRANSFORMED) + .getModel(AllBlockPartials.GANTRY_COGS, blockState) .createInstance(); + facing = blockState.get(GantryCarriageBlock.FACING); + alongFirst = blockState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); + rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); + + visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getPos() + : tile.getPos() + .offset(facing.getOpposite()); + updateLight(); } @Override - public void tick() { - lastState = tile.getBlockState(); - Direction facing = lastState.get(GantryCarriageBlock.FACING); - Boolean alongFirst = lastState.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); - Direction.Axis rotationAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); - BlockPos visualPos = facing.getAxisDirection() == Direction.AxisDirection.POSITIVE ? tile.getPos() - : tile.getPos() - .offset(facing.getOpposite()); + public void beginFrame() { float angleForTe = GantryCarriageRenderer.getAngleForTe(tile, visualPos, rotationAxis); Direction.Axis gantryAxis = Direction.Axis.X; @@ -71,7 +72,7 @@ public class GantryCarriageInstance extends ShaftInstance implements ITickableIn .translate(0, 9 / 16f, 0) .unCentre(); - gantryCogs.getInstance().setTransformNoCopy(ms); + gantryCogs.getInstance().setTransform(ms); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java index 96df45479..466d5bae5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java @@ -12,7 +12,7 @@ public class PistonLighter extends ContraptionLighter { @Override public GridAlignedBB getContraptionBounds() { - GridAlignedBB bounds = GridAlignedBB.fromAABB(contraption.bounds); + GridAlignedBB bounds = GridAlignedBB.from(contraption.bounds); bounds.translate(contraption.anchor); int length = contraption.extensionLength; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java index 1cb1d5478..87cc4cacf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java @@ -15,7 +15,7 @@ public class PulleyLighter extends ContraptionLighter { @Override public GridAlignedBB getContraptionBounds() { - GridAlignedBB bounds = GridAlignedBB.fromAABB(contraption.bounds); + GridAlignedBB bounds = GridAlignedBB.from(contraption.bounds); World world = contraption.entity.world; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java index 97d7ecc34..9507a05ef 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java @@ -1,8 +1,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.foundation.utility.VecHelper; -import net.minecraft.util.Direction; import net.minecraft.world.LightType; public abstract class ActorInstance { @@ -14,16 +12,11 @@ public abstract class ActorInstance { this.context = context; } - protected void tick() { } + public void tick() { } - protected float getSpeed(Direction facing) { - if (context.contraption.stalled) - return 0; - - return !VecHelper.isVecPointingTowards(context.relativeMotion, facing.getOpposite()) ? context.getAnimationSpeed() : 0; - } + public void beginFrame() { } protected int localBlockLight() { - return modelManager.contraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos); + return modelManager.getContraption().renderWorld.getLightLevel(LightType.BLOCK, context.localPos); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionAttributes.java similarity index 88% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionVertexAttributes.java rename to src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionAttributes.java index 53e9931f9..4e3d65be9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionAttributes.java @@ -5,7 +5,7 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; -public enum ContraptionVertexAttributes implements IVertexAttrib { +public enum ContraptionAttributes implements IVertexAttrib { VERTEX_POSITION("aPos", CommonAttributes.VEC3), NORMAL("aNormal", CommonAttributes.NORMAL), TEXTURE("aTexCoords", CommonAttributes.UV), @@ -16,7 +16,7 @@ public enum ContraptionVertexAttributes implements IVertexAttrib { private final String name; private final VertexAttribSpec spec; - ContraptionVertexAttributes(String name, VertexAttribSpec spec) { + ContraptionAttributes(String name, VertexAttribSpec spec) { this.name = name; this.spec = spec; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java index 880a7b779..66e7bde86 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java @@ -2,63 +2,71 @@ package com.simibubi.create.content.contraptions.components.structureMovement.re import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; -import com.simibubi.create.content.contraptions.base.RotatingInstancedModel; -import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData; -import com.simibubi.create.content.contraptions.components.actors.RotatingActorModel; +import com.simibubi.create.content.contraptions.base.RotatingModel; +import com.simibubi.create.content.contraptions.components.actors.ActorData; +import com.simibubi.create.content.contraptions.components.actors.ActorModel; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel; -import com.simibubi.create.content.logistics.block.FlapInstancedModel; +import com.simibubi.create.content.logistics.block.FlapModel; import com.simibubi.create.foundation.render.AllProgramSpecs; import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; -import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel; + +import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedModel; import net.minecraft.util.math.BlockPos; import net.minecraft.world.gen.feature.template.Template; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; +import java.lang.ref.WeakReference; import java.util.ArrayList; public class ContraptionKineticRenderer extends InstancedTileRenderer { - protected ArrayList actors = new ArrayList<>(); + protected ArrayList actors = new ArrayList<>(); - public final RenderedContraption contraption; + private final WeakReference contraption; ContraptionKineticRenderer(RenderedContraption contraption) { - this.contraption = contraption; + this.contraption = new WeakReference<>(contraption); } @Override public void registerMaterials() { - materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, BasicInstancedModel::new)); + materials.put(RenderMaterials.TRANSFORMED, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, TransformedModel::new)); + materials.put(RenderMaterials.ORIENTED, new RenderMaterial<>(this, AllProgramSpecs.C_ORIENTED, OrientedModel::new)); materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.C_BELT, BeltInstancedModel::new)); - materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.C_ROTATING, RotatingInstancedModel::new)); - materials.put(KineticRenderMaterials.FLAPS, new RenderMaterial<>(this, AllProgramSpecs.C_FLAPS, FlapInstancedModel::new)); - materials.put(KineticRenderMaterials.ACTORS, new RenderMaterial<>(this, AllProgramSpecs.C_ACTOR, RotatingActorModel::new)); + materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.C_ROTATING, RotatingModel::new)); + materials.put(KineticRenderMaterials.FLAPS, new RenderMaterial<>(this, AllProgramSpecs.C_FLAPS, FlapModel::new)); + materials.put(KineticRenderMaterials.ACTORS, new RenderMaterial<>(this, AllProgramSpecs.C_ACTOR, ActorModel::new)); } + @Override + public void tick() { + actors.forEach(com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance::tick); + } @Override public void beginFrame(double cameraX, double cameraY, double cameraZ) { super.beginFrame(cameraX, cameraY, cameraZ); - actors.forEach(ActorInstance::tick); + actors.forEach(com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance::beginFrame); } @Nullable - public ActorInstance createActor(Pair actor) { + public com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance createActor(Pair actor) { Template.BlockInfo blockInfo = actor.getLeft(); MovementContext context = actor.getRight(); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); if (movementBehaviour != null && movementBehaviour.hasSpecialInstancedRendering()) { - ActorInstance instance = movementBehaviour.createInstance(this, context); + com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance instance = movementBehaviour.createInstance(this, context); actors.add(instance); @@ -68,10 +76,14 @@ public class ContraptionKineticRenderer extends InstancedTileRenderer> getActorMaterial() { + public RenderMaterial> getActorMaterial() { return getMaterial(KineticRenderMaterials.ACTORS); } + public RenderedContraption getContraption() { + return contraption.get(); + } + @Override public BlockPos getOriginCoordinate() { return BlockPos.ZERO; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java index e29b706ad..2157f607f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java @@ -13,7 +13,7 @@ import java.nio.ByteBuffer; public class ContraptionModel extends BufferedModel { public static final VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(ContraptionVertexAttributes.class) + .addAttributes(ContraptionAttributes.class) .build(); protected GlPrimitiveType eboIndexType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java index 6a10841c8..7981413eb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java @@ -1,5 +1,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import java.util.List; +import java.util.Random; + +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.world.IBlockDisplayReader; +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.*; + import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.CreateClient; @@ -7,48 +15,44 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.foundation.render.*; +import com.simibubi.create.foundation.render.AllProgramSpecs; +import com.simibubi.create.foundation.render.Compartment; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBufferCache; +import com.simibubi.create.foundation.render.TileEntityRenderHelper; import com.simibubi.create.foundation.render.backend.Backend; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.BlockModelRenderer; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderTypeLookup; +import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.SectionPos; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.model.data.EmptyModelData; -import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL13; -import org.lwjgl.opengl.GL40; - -import java.util.List; -import java.util.Random; public class ContraptionRenderDispatcher { public static final Int2ObjectMap renderers = new Int2ObjectOpenHashMap<>(); public static final Compartment> CONTRAPTION = new Compartment<>(); protected static PlacementSimulationWorld renderWorld; - public static void notifyLightUpdate(IBlockDisplayReader world, LightType type, SectionPos pos) { - for (RenderedContraption renderer : renderers.values()) { - renderer.getLighter().lightVolume.notifyLightUpdate(world, type, pos); - } - } - public static void notifyLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { for (RenderedContraption renderer : renderers.values()) { renderer.getLighter().lightVolume.notifyLightPacket(world, chunkX, chunkZ); @@ -56,7 +60,7 @@ public class ContraptionRenderDispatcher { } public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { + IRenderTypeBuffer buffer) { PlacementSimulationWorld renderWorld = null; if (Backend.canUseVBOs()) { RenderedContraption renderer = getRenderer(world, c); @@ -68,8 +72,12 @@ public class ContraptionRenderDispatcher { } public static void tick() { + if (Minecraft.getInstance().isGamePaused()) return; + for (RenderedContraption contraption : renderers.values()) { contraption.getLighter().tick(contraption); + + contraption.kinetics.tick(); } } @@ -157,7 +165,7 @@ public class ContraptionRenderDispatcher { } public static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { + IRenderTypeBuffer buffer) { SuperByteBufferCache bufferCache = CreateClient.bufferCache; List blockLayers = RenderType.getBlockLayers(); @@ -187,17 +195,19 @@ public class ContraptionRenderDispatcher { ForgeHooksClient.setRenderLayer(layer); MatrixStack ms = new MatrixStack(); BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .getBlockRendererDispatcher(); + .getBlockRendererDispatcher(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); Random random = new Random(); BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); renderWorld.setTileEntities(c.presentTileEntities.values()); - for (Template.BlockInfo info : c.getBlocks().values()) + for (Template.BlockInfo info : c.getBlocks() + .values()) renderWorld.setBlockState(info.pos, info.state); - for (Template.BlockInfo info : c.getBlocks().values()) { + for (Template.BlockInfo info : c.getBlocks() + .values()) { BlockState state = info.state; if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) @@ -209,7 +219,7 @@ public class ContraptionRenderDispatcher { ms.push(); ms.translate(info.pos.getX(), info.pos.getY(), info.pos.getZ()); blockRenderer.renderModel(renderWorld, originalModel, state, info.pos, ms, builder, true, random, 42, - OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); + OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); ms.pop(); } @@ -232,7 +242,7 @@ public class ContraptionRenderDispatcher { for (MatrixStack m : matrixStacks) { m.push(); MatrixStacker.of(m) - .translate(blockInfo.pos); + .translate(blockInfo.pos); } MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java index 06c768fb4..564f0e9ac 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -1,5 +1,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Random; + +import org.lwjgl.opengl.GL11; + import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java index 892d0de19..aebbd074c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartSim2020.java @@ -106,10 +106,10 @@ public class MinecartSim2020 { } Pair pair = MATRIX.get(railshape); - Vector3i vec3i = pair.getFirst(); - Vector3i vec3i1 = pair.getSecond(); - double d4 = (double) (vec3i1.getX() - vec3i.getX()); - double d5 = (double) (vec3i1.getZ() - vec3i.getZ()); + Vector3i Vector3i = pair.getFirst(); + Vector3i Vector3i1 = pair.getSecond(); + double d4 = (double) (Vector3i1.getX() - Vector3i.getX()); + double d5 = (double) (Vector3i1.getZ() - Vector3i.getZ()); // double d6 = Math.sqrt(d4 * d4 + d5 * d5); double d7 = forcedMovement.x * d4 + forcedMovement.z * d5; if (d7 < 0.0D) { @@ -117,10 +117,10 @@ public class MinecartSim2020 { d5 = -d5; } - double d23 = (double) cartPos.getX() + 0.5D + (double) vec3i.getX() * 0.5D; - double d10 = (double) cartPos.getZ() + 0.5D + (double) vec3i.getZ() * 0.5D; - double d12 = (double) cartPos.getX() + 0.5D + (double) vec3i1.getX() * 0.5D; - double d13 = (double) cartPos.getZ() + 0.5D + (double) vec3i1.getZ() * 0.5D; + double d23 = (double) cartPos.getX() + 0.5D + (double) Vector3i.getX() * 0.5D; + double d10 = (double) cartPos.getZ() + 0.5D + (double) Vector3i.getZ() * 0.5D; + double d12 = (double) cartPos.getX() + 0.5D + (double) Vector3i1.getX() * 0.5D; + double d13 = (double) cartPos.getZ() + 0.5D + (double) Vector3i1.getZ() * 0.5D; d4 = d12 - d23; d5 = d13 - d10; double d14; @@ -145,12 +145,12 @@ public class MinecartSim2020 { y = cart.getY(); z = cart.getZ(); - if (vec3i.getY() != 0 && MathHelper.floor(x) - cartPos.getX() == vec3i.getX() - && MathHelper.floor(z) - cartPos.getZ() == vec3i.getZ()) { - cart.setPosition(x, y + (double) vec3i.getY(), z); - } else if (vec3i1.getY() != 0 && MathHelper.floor(x) - cartPos.getX() == vec3i1.getX() - && MathHelper.floor(z) - cartPos.getZ() == vec3i1.getZ()) { - cart.setPosition(x, y + (double) vec3i1.getY(), z); + if (Vector3i.getY() != 0 && MathHelper.floor(x) - cartPos.getX() == Vector3i.getX() + && MathHelper.floor(z) - cartPos.getZ() == Vector3i.getZ()) { + cart.setPosition(x, y + (double) Vector3i.getY(), z); + } else if (Vector3i1.getY() != 0 && MathHelper.floor(x) - cartPos.getX() == Vector3i1.getX() + && MathHelper.floor(z) - cartPos.getZ() == Vector3i1.getZ()) { + cart.setPosition(x, y + (double) Vector3i1.getY(), z); } x = cart.getX(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java index c8e9af941..1a54e0ad5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainTileEntity.java @@ -100,7 +100,7 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI } boolean onClient = world.isRemote && !isVirtual(); - + if (processingTicks > 0) { heldItem.prevBeltPosition = .5f; boolean wasAtBeginning = processingTicks == FILLING_TIME; @@ -130,13 +130,17 @@ public class ItemDrainTileEntity extends SmartTileEntity implements IHaveGoggleI ItemStack tryExportingToBeltFunnel = getBehaviour(DirectBeltInputBehaviour.TYPE) .tryExportingToBeltFunnel(heldItem.stack, side.getOpposite()); - if (tryExportingToBeltFunnel.getCount() != heldItem.stack.getCount()) { - if (tryExportingToBeltFunnel.isEmpty()) - heldItem = null; - else - heldItem.stack = tryExportingToBeltFunnel; - notifyUpdate(); - return; + if (tryExportingToBeltFunnel != null) { + if (tryExportingToBeltFunnel.getCount() != heldItem.stack.getCount()) { + if (tryExportingToBeltFunnel.isEmpty()) + heldItem = null; + else + heldItem.stack = tryExportingToBeltFunnel; + notifyUpdate(); + return; + } + if (!tryExportingToBeltFunnel.isEmpty()) + return; } BlockPos nextPosition = pos.offset(side); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java index 5125f5d19..c21a668ae 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveInstance.java @@ -5,7 +5,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; +import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; import com.simibubi.create.foundation.render.backend.instancing.InstanceKey; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; @@ -15,42 +15,36 @@ import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.util.Direction; import net.minecraft.util.math.MathHelper; -public class FluidValveInstance extends ShaftInstance implements ITickableInstance { +public class FluidValveInstance extends ShaftInstance implements IDynamicInstance { protected InstanceKey pointer; - protected double xRot; - protected double yRot; - protected int pointerRotationOffset; + protected final double xRot; + protected final double yRot; + protected final int pointerRotationOffset; public FluidValveInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - } - @Override - protected void init() { - super.init(); - - Direction facing = lastState.get(FluidValveBlock.FACING); + Direction facing = blockState.get(FluidValveBlock.FACING); yRot = AngleHelper.horizontalAngle(facing); xRot = facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90; - Direction.Axis pipeAxis = FluidValveBlock.getPipeAxis(lastState); + Direction.Axis pipeAxis = FluidValveBlock.getPipeAxis(blockState); Direction.Axis shaftAxis = KineticTileEntityRenderer.getRotationAxisOf(tile); - pointerRotationOffset = 0; - if (pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.Z || pipeAxis.isVertical()) - pointerRotationOffset = 90; + boolean twist = pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.Z || pipeAxis.isVertical(); + pointerRotationOffset = twist ? 90 : 0; - pointer = modelManager.basicMaterial().getModel(AllBlockPartials.FLUID_VALVE_POINTER, lastState).createInstance(); + pointer = modelManager.transformMaterial().getModel(AllBlockPartials.FLUID_VALVE_POINTER, blockState).createInstance(); updateLight(); transformPointer((FluidValveTileEntity) tile); } @Override - public void tick() { + public void beginFrame() { FluidValveTileEntity valve = (FluidValveTileEntity) tile; diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java index fd500a67e..c53e9d192 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/IHaveGoggleInformation.java @@ -1,6 +1,12 @@ package com.simibubi.create.content.contraptions.goggles; +import java.text.NumberFormat; +import java.util.List; +import java.util.Locale; +import java.util.Optional; + import com.simibubi.create.foundation.utility.Lang; + import net.minecraft.client.Minecraft; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; @@ -10,11 +16,6 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; -import java.text.NumberFormat; -import java.util.List; -import java.util.Locale; -import java.util.Optional; - /* * Implement this Interface in the TileEntity class that wants to add info to the screen * */ @@ -36,7 +37,8 @@ public interface IHaveGoggleInformation { } static String format(double d) { - return numberFormat.get().format(d); + return numberFormat.get() + .format(d); } default boolean containedFluidTooltip(List tooltip, boolean isPlayerSneaking, LazyOptional handler) { @@ -73,7 +75,13 @@ public interface IHaveGoggleInformation { isEmpty = false; } - if (tank.getTanks() > 1 || !isEmpty) + if (tank.getTanks() > 1) { + if (isEmpty) + tooltip.remove(tooltip.size() - 1); + return true; + } + + if (!isEmpty) return true; ITextComponent capacity = Lang.translate("gui.goggles.fluid_container.capacity").formatted(TextFormatting.GRAY); @@ -96,7 +104,10 @@ public interface IHaveGoggleInformation { } public void update() { - format = NumberFormat.getInstance(Minecraft.getInstance().getLanguageManager().getCurrentLanguage().getJavaLocale()); + format = NumberFormat.getInstance(Minecraft.getInstance() + .getLanguageManager() + .getCurrentLanguage() + .getJavaLocale()); format.setMaximumFractionDigits(2); format.setMinimumFractionDigits(0); format.setGroupingUsed(true); diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java index 4de4ba7ce..32cd04ed5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java @@ -21,6 +21,7 @@ import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; +import net.minecraft.item.Items; import net.minecraft.state.DirectionProperty; import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; @@ -35,6 +36,10 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.ItemStackHandler; @@ -94,6 +99,11 @@ public class BasinBlock extends Block implements ITE, IWrenchab if (EmptyingByBasin.canItemBeEmptied(worldIn, heldItem) || GenericItemFilling.canItemBeFilled(worldIn, heldItem)) return ActionResultType.SUCCESS; + if (heldItem.getItem().equals(Items.SPONGE) && + !te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY).map(iFluidHandler -> + iFluidHandler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.EXECUTE)).orElse(FluidStack.EMPTY).isEmpty()) { + return ActionResultType.SUCCESS; + } return ActionResultType.PASS; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java index f486a4003..346cd8832 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerTileEntity.java @@ -75,8 +75,14 @@ public class BlazeBurnerTileEntity extends SmartTileEntity { ClientPlayerEntity player = Minecraft.getInstance().player; float target = 0; if (player != null) { - double dx = player.getX() - (getPos().getX() + 0.5); - double dz = player.getZ() - (getPos().getZ() + 0.5); + double x = player.getX(); + double z = player.getZ(); + if (isVirtual()) { + x = -4; + z = -10; + } + double dx = x - (getPos().getX() + 0.5); + double dz = z - (getPos().getZ() + 0.5); target = AngleHelper.deg(-MathHelper.atan2(dz, dx)) - 90; } target = headAngle.getValue() + AngleHelper.getShortestAngleDiff(headAngle.getValue(), target); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltAttributes.java similarity index 89% rename from src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java rename to src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltAttributes.java index b5888c49b..4753f1eb2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltAttributes.java @@ -5,7 +5,7 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; -public enum BeltVertexAttributes implements IVertexAttrib { +public enum BeltAttributes implements IVertexAttrib { INSTANCE_ROTATION("aInstanceRot", CommonAttributes.QUATERNION), SOURCE_TEX("aSourceTexture", CommonAttributes.UV), SCROLL_TEX("aScrollTexture", CommonAttributes.VEC4), @@ -15,7 +15,7 @@ public enum BeltVertexAttributes implements IVertexAttrib { private final String name; private final VertexAttribSpec spec; - BeltVertexAttributes(String name, VertexAttribSpec spec) { + BeltAttributes(String name, VertexAttribSpec spec) { this.name = name; this.spec = spec; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java index 25cb9e3ac..440e8046e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java @@ -1,21 +1,14 @@ package com.simibubi.create.content.contraptions.relays.belt; import com.simibubi.create.content.contraptions.base.KineticData; -import com.simibubi.create.content.contraptions.base.KineticVertexAttributes; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.math.vector.Quaternion; import java.nio.ByteBuffer; -public class BeltData extends KineticData { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(KineticVertexAttributes.class) - .addAttributes(BeltVertexAttributes.class) - .build(); - +public class BeltData extends KineticData { private float qX; private float qY; private float qZ; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java index 90e118f75..2a239ed81 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java @@ -21,30 +21,27 @@ import java.util.function.Supplier; public class BeltInstance extends KineticTileInstance { - private boolean upward; - private boolean diagonal; - private boolean sideways; - private boolean vertical; - private boolean alongX; - private boolean alongZ; - private BeltSlope beltSlope; - private Direction facing; + boolean upward; + boolean diagonal; + boolean sideways; + boolean vertical; + boolean alongX; + boolean alongZ; + BeltSlope beltSlope; + Direction facing; protected ArrayList> keys; protected InstanceKey pulleyKey; public BeltInstance(InstancedTileRenderer modelManager, BeltTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - if (!AllBlocks.BELT.has(lastState)) + if (!AllBlocks.BELT.has(blockState)) return; keys = new ArrayList<>(2); - beltSlope = lastState.get(BeltBlock.SLOPE); - facing = lastState.get(BeltBlock.HORIZONTAL_FACING); + beltSlope = blockState.get(BeltBlock.SLOPE); + facing = blockState.get(BeltBlock.HORIZONTAL_FACING); upward = beltSlope == BeltSlope.UPWARD; diagonal = beltSlope.isDiagonal(); sideways = beltSlope == BeltSlope.SIDEWAYS; @@ -52,7 +49,7 @@ public class BeltInstance extends KineticTileInstance { alongX = facing.getAxis() == Direction.Axis.X; alongZ = facing.getAxis() == Direction.Axis.Z; - BeltPart part = lastState.get(BeltBlock.PART); + BeltPart part = blockState.get(BeltBlock.PART); boolean start = part == BeltPart.START; boolean end = part == BeltPart.END; DyeColor color = tile.color.orElse(null); @@ -61,7 +58,7 @@ public class BeltInstance extends KineticTileInstance { AllBlockPartials beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom); SpriteShiftEntry spriteShift = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom); - InstancedModel beltModel = beltPartial.renderOnBelt(modelManager, lastState); + InstancedModel beltModel = beltPartial.renderOnBelt(modelManager, blockState); keys.add(setup(beltModel.createInstance(), bottom, spriteShift)); @@ -76,7 +73,7 @@ public class BeltInstance extends KineticTileInstance { } @Override - public void onUpdate() { + public void update() { DyeColor color = tile.color.orElse(null); boolean bottom = true; @@ -141,11 +138,11 @@ public class BeltInstance extends KineticTileInstance { return modelTransform; }; - return rotatingMaterial().getModel(AllBlockPartials.BELT_PULLEY, lastState, dir, ms); + return rotatingMaterial().getModel(AllBlockPartials.BELT_PULLEY, blockState, dir, ms); } private Direction getOrientation() { - Direction dir = lastState.get(BeltBlock.HORIZONTAL_FACING) + Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING) .rotateY(); if (beltSlope == BeltSlope.SIDEWAYS) dir = Direction.UP; @@ -162,14 +159,14 @@ public class BeltInstance extends KineticTileInstance { Quaternion q = new Quaternion(rotX, rotY, rotZ, true); key.getInstance() - .setTileEntity(tile) - .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) - .setSkyLight(world.getLightLevel(LightType.SKY, pos)) - .setRotation(q) - .setRotationalSpeed(getScrollSpeed()) - .setRotationOffset(bottom ? 0.5f : 0f) - .setScrollTexture(spriteShift) - .setScrollMult(diagonal ? 3f / 8f : 0.5f); + .setScrollTexture(spriteShift) + .setScrollMult(diagonal ? 3f / 8f : 0.5f) + .setRotation(q) + .setRotationalSpeed(getScrollSpeed()) + .setRotationOffset(bottom ? 0.5f : 0f) + .setTileEntity(tile) + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); return key; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java index 86e7e26ef..efbb86b44 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java @@ -1,24 +1,32 @@ package com.simibubi.create.content.contraptions.relays.belt; +import com.simibubi.create.content.contraptions.base.KineticAttributes; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.impl.BasicAttributes; import net.minecraft.client.renderer.BufferBuilder; public class BeltInstancedModel extends InstancedModel { - public BeltInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(BasicAttributes.class) + .addAttributes(KineticAttributes.class) + .addAttributes(BeltAttributes.class) + .build(); + + public BeltInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { super(renderer, buf); } - @Override - protected BeltData newInstance() { + @Override + protected BeltData newInstance() { return new BeltData(this); } @Override - protected VertexFormat getInstanceFormat() { - return BeltData.FORMAT; + protected VertexFormat getInstanceFormat() { + return FORMAT; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java index 75388e44a..41eb7511e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java @@ -294,10 +294,10 @@ public class BeltRenderer extends SafeTileEntityRenderer { } protected int getPackedLight(BeltTileEntity controller, float beltPos) { - BeltTileEntity belt = BeltHelper.getBeltForOffset(controller, beltPos); + int segment = (int) Math.floor(beltPos) * 2; - if (belt == null) return 0; + if (controller.light == null || segment >= controller.light.length) return 0; - return (belt.skyLight << 20) | (belt.blockLight << 4); + return (controller.light[segment + 1] << 20) | (controller.light[segment] << 4); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java index 59af9d694..7ba72a2fc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java @@ -7,7 +7,9 @@ import com.simibubi.create.content.contraptions.relays.belt.transport.*; import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo; import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity; import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.light.ILightListener; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; +import com.simibubi.create.foundation.render.backend.light.LightUpdateListener; +import com.simibubi.create.foundation.render.backend.light.LightUpdater; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; @@ -29,6 +31,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3i; +import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.LightType; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.model.data.IModelData; @@ -48,7 +51,8 @@ import static com.simibubi.create.content.contraptions.relays.belt.BeltSlope.HOR import static net.minecraft.util.Direction.AxisDirection.NEGATIVE; import static net.minecraft.util.Direction.AxisDirection.POSITIVE; -public class BeltTileEntity extends KineticTileEntity implements ILightListener { + +public class BeltTileEntity extends KineticTileEntity implements LightUpdateListener { public Map passengers; public Optional color; @@ -64,8 +68,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightListener public CompoundNBT trackerUpdateTag; // client - public byte blockLight = -1; - public byte skyLight = -1; + public byte[] light; public static enum CasingType { NONE, ANDESITE, BRASS; @@ -100,12 +103,15 @@ public class BeltTileEntity extends KineticTileEntity implements ILightListener initializeItemHandler(); - if (blockLight == -1) - updateLight(); - // Move Items if (!isController()) return; + + if (light == null && world.isRemote) { + initializeLight(); + LightUpdater.getInstance().startListening(getBeltVolume(), this); + } + getInventory().tick(); if (getSpeed() == 0) @@ -223,7 +229,8 @@ public class BeltTileEntity extends KineticTileEntity implements ILightListener if (casingBefore == casing) return; - requestModelDataUpdate(); + if (!isVirtual()) + requestModelDataUpdate(); if (hasWorld()) world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16); } @@ -276,10 +283,8 @@ public class BeltTileEntity extends KineticTileEntity implements ILightListener } public boolean isController() { - return controller != null && - pos.getX() == controller.getX() && - pos.getY() == controller.getY() && - pos.getZ() == controller.getZ(); + return controller != null && pos.getX() == controller.getX() && pos.getY() == controller.getY() + && pos.getZ() == controller.getZ(); } public float getBeltMovementSpeed() { @@ -297,7 +302,7 @@ public class BeltTileEntity extends KineticTileEntity implements ILightListener public boolean hasPulley() { if (!AllBlocks.BELT.has(getBlockState())) return false; - return getBlockState().get(BeltBlock.PART) != BeltPart.MIDDLE; + return getBlockState().get(BeltBlock.PART) != MIDDLE; } protected boolean isLastBelt() { @@ -500,23 +505,77 @@ public class BeltTileEntity extends KineticTileEntity implements ILightListener return 0; } - @Override - public void onChunkLightUpdate() { - updateLight(); - } - @Override public boolean shouldRenderAsTE() { return isController(); } - private void updateLight() { - if (world != null) { - skyLight = (byte) world.getLightLevel(LightType.SKY, pos); - blockLight = (byte) world.getLightLevel(LightType.BLOCK, pos); - } else { - skyLight = -1; - blockLight = -1; + @Override + public boolean onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed) { + if (this.removed) { + return true; + } + + GridAlignedBB beltVolume = getBeltVolume(); + + if (beltVolume.intersects(changed)) { + if (type == LightType.BLOCK) + updateBlockLight(); + + if (type == LightType.SKY) + updateSkyLight(); + } + + return false; + } + + private GridAlignedBB getBeltVolume() { + BlockPos endPos = BeltHelper.getPositionForOffset(this, beltLength - 1); + + GridAlignedBB bb = GridAlignedBB.from(pos, endPos); + bb.fixMinMax(); + return bb; + } + + private void initializeLight() { + light = new byte[beltLength * 2]; + + Vector3i vec = getBeltFacing().getDirectionVec(); + BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + BlockPos.Mutable pos = new BlockPos.Mutable(controller.getX(), controller.getY(), controller.getZ()); + for (int i = 0; i < beltLength * 2; i += 2) { + light[i] = (byte) world.getLightLevel(LightType.BLOCK, pos); + light[i + 1] = (byte) world.getLightLevel(LightType.SKY, pos); + + pos.move(vec.getX(), verticality, vec.getZ()); + } + } + + private void updateBlockLight() { + Vector3i vec = getBeltFacing().getDirectionVec(); + BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + BlockPos.Mutable pos = new BlockPos.Mutable(controller.getX(), controller.getY(), controller.getZ()); + for (int i = 0; i < beltLength * 2; i += 2) { + light[i] = (byte) world.getLightLevel(LightType.BLOCK, pos); + + pos.move(vec.getX(), verticality, vec.getZ()); + } + } + + private void updateSkyLight() { + Vector3i vec = getBeltFacing().getDirectionVec(); + BeltSlope slope = getBlockState().get(BeltBlock.SLOPE); + int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; + + BlockPos.Mutable pos = new BlockPos.Mutable(controller.getX(), controller.getY(), controller.getZ()); + for (int i = 1; i < beltLength * 2; i += 2) { + light[i] = (byte) world.getLightLevel(LightType.SKY, pos); + + pos.move(vec.getX(), verticality, vec.getZ()); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java index 956f0bc12..267070dc2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java @@ -106,6 +106,12 @@ public class BeltInventory { // Don't move if held by processing (client) if (world.isRemote && currentItem.locked) continue; + + // Don't move if held by external components + if (currentItem.lockedExternally) { + currentItem.lockedExternally = false; + continue; + } // Don't move if other items are waiting in front float currentPos = currentItem.beltPosition; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java index 6dffb5056..5202ea1df 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java @@ -20,6 +20,7 @@ public class TransportedItemStack implements Comparable { public int insertedAt; public Direction insertedFrom; public boolean locked; + public boolean lockedExternally; public float prevBeltPosition; public float prevSideOffset; @@ -73,7 +74,10 @@ public class TransportedItemStack implements Comparable { nbt.putInt("InSegment", insertedAt); nbt.putInt("Angle", angle); nbt.putInt("InDirection", insertedFrom.getIndex()); - nbt.putBoolean("Locked", locked); + if (locked) + nbt.putBoolean("Locked", locked); + if (lockedExternally) + nbt.putBoolean("LockedExternally", lockedExternally); return nbt; } @@ -87,6 +91,7 @@ public class TransportedItemStack implements Comparable { stack.angle = nbt.getInt("Angle"); stack.insertedFrom = Direction.byIndex(nbt.getInt("InDirection")); stack.locked = nbt.getBoolean("Locked"); + stack.lockedExternally = nbt.getBoolean("LockedExternally"); return stack; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java index 4928ebf04..123c02369 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java @@ -25,103 +25,114 @@ import net.minecraft.world.IWorldReader; import net.minecraft.world.World; public class CogWheelBlock extends AbstractShaftBlock { + boolean isLarge; - boolean isLarge; + private CogWheelBlock(boolean large, Properties properties) { + super(properties); + isLarge = large; + } - private CogWheelBlock(boolean large, Properties properties) { - super(properties); - isLarge = large; - } + public static CogWheelBlock small(Properties properties) { + return new CogWheelBlock(false, properties); + } - public static CogWheelBlock small(Properties properties) { - return new CogWheelBlock(false, properties); - } + public static CogWheelBlock large(Properties properties) { + return new CogWheelBlock(true, properties); + } - public static CogWheelBlock large(Properties properties) { - return new CogWheelBlock(true, properties); - } + public static boolean isSmallCog(BlockState state) { + return AllBlocks.COGWHEEL.has(state); + } - public static boolean isSmallCog(BlockState state) { - return AllBlocks.COGWHEEL.has(state); - } + public static boolean isLargeCog(BlockState state) { + return AllBlocks.LARGE_COGWHEEL.has(state); + } - public static boolean isLargeCog(BlockState state) { - return AllBlocks.LARGE_COGWHEEL.has(state); - } + @Override + public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.get(AXIS)); + } - @Override - public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { - return (isLarge ? AllShapes.LARGE_GEAR : AllShapes.SMALL_GEAR).get(state.get(AXIS)); - } + @Override + public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { + for (Direction facing : Iterate.directions) { + if (facing.getAxis() == state.get(AXIS)) + continue; - @Override - public boolean isValidPosition(BlockState state, IWorldReader worldIn, BlockPos pos) { - for (Direction facing : Iterate.directions) { - if (facing.getAxis() == state.get(AXIS)) - continue; + BlockPos offsetPos = pos.offset(facing); + BlockState blockState = worldIn.getBlockState(offsetPos); + if (blockState.contains(AXIS) && facing.getAxis() == blockState.get(AXIS)) + continue; - BlockState blockState = worldIn.getBlockState(pos.offset(facing)); - if (blockState.contains(AXIS) && facing.getAxis() == blockState.get(AXIS)) - continue; - - if (isLargeCog(blockState) || isLarge && isSmallCog(blockState)) - return false; - } - return true; - } + boolean smallCog = isSmallCog(blockState); + if (!smallCog && blockState.getBlock() instanceof IRotate) + smallCog = ((IRotate) blockState.getBlock()).hasIntegratedCogwheel(worldIn, offsetPos, blockState); - @Override - public BlockState getStateForPlacement(BlockItemUseContext context) { - BlockPos placedOnPos = context.getPos().offset(context.getFace().getOpposite()); - World world = context.getWorld(); - BlockState placedAgainst = world.getBlockState(placedOnPos); - Block block = placedAgainst.getBlock(); + if (isLargeCog(blockState) || isLarge && smallCog) + return false; + } + return true; + } - if (context.getPlayer() != null && context.getPlayer().isSneaking()) - return this.getDefaultState().with(AXIS, context.getFace().getAxis()); - - BlockState stateBelow = world.getBlockState(context.getPos() - .down()); - FluidState FluidState = context.getWorld().getFluidState(context.getPos()); - if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLarge) { - return this.getDefaultState() - .with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER) - .with(AXIS, stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X); - } + @Override + public BlockState getStateForPlacement(BlockItemUseContext context) { + BlockPos placedOnPos = context.getPos() + .offset(context.getFace() + .getOpposite()); + World world = context.getWorld(); + BlockState placedAgainst = world.getBlockState(placedOnPos); + Block block = placedAgainst.getBlock(); - if (!(block instanceof IRotate) - || !(((IRotate) block).hasIntegratedCogwheel(world, placedOnPos, placedAgainst))) { - Axis preferredAxis = getPreferredAxis(context); - if (preferredAxis != null) - return this.getDefaultState() - .with(AXIS, preferredAxis) - .with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER); - return this.getDefaultState() - .with(AXIS, context.getFace().getAxis()) - .with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER); - } + if (context.getPlayer() != null && context.getPlayer() + .isSneaking()) + return this.getDefaultState() + .with(AXIS, context.getFace() + .getAxis()); - return getDefaultState().with(AXIS, ((IRotate) block).getRotationAxis(placedAgainst)); - } + BlockState stateBelow = world.getBlockState(context.getPos() + .down()); + FluidState ifluidstate = context.getWorld() + .getFluidState(context.getPos()); + if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLarge) { + return this.getDefaultState() + .with(BlockStateProperties.WATERLOGGED, ifluidstate.getFluid() == Fluids.WATER) + .with(AXIS, stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X); + } - @Override - public float getParticleTargetRadius() { - return isLarge ? 1.125f : .65f; - } + if (!(block instanceof IRotate) + || !(((IRotate) block).hasIntegratedCogwheel(world, placedOnPos, placedAgainst))) { + Axis preferredAxis = getPreferredAxis(context); + if (preferredAxis != null) + return this.getDefaultState() + .with(AXIS, preferredAxis) + .with(BlockStateProperties.WATERLOGGED, ifluidstate.getFluid() == Fluids.WATER); + return this.getDefaultState() + .with(AXIS, context.getFace() + .getAxis()) + .with(BlockStateProperties.WATERLOGGED, ifluidstate.getFluid() == Fluids.WATER); + } - @Override - public float getParticleInitialRadius() { - return isLarge ? 1f : .75f; - } + return getDefaultState().with(AXIS, ((IRotate) block).getRotationAxis(placedAgainst)); + } - public void fillItemGroup(ItemGroup group, NonNullList items) { - items.add(new ItemStack(this)); - } + @Override + public float getParticleTargetRadius() { + return isLarge ? 1.125f : .65f; + } - // IRotate + @Override + public float getParticleInitialRadius() { + return isLarge ? 1f : .75f; + } - @Override - public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) { - return !isLarge; - } + public void fillItemGroup(ItemGroup group, NonNullList items) { + items.add(new ItemStack(this)); + } + + // IRotate + + @Override + public boolean hasIntegratedCogwheel(IWorldReader world, BlockPos pos, BlockState state) { + return !isLarge; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java index 4e6285722..93951cb82 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java @@ -16,24 +16,21 @@ import java.util.ArrayList; public class SplitShaftInstance extends KineticTileInstance { - protected ArrayList> keys; + protected final ArrayList> keys; public SplitShaftInstance(InstancedTileRenderer modelManager, SplitShaftTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { keys = new ArrayList<>(2); - Block block = lastState.getBlock(); - final Direction.Axis boxAxis = ((IRotate) block).getRotationAxis(lastState); + Block block = blockState.getBlock(); + final Direction.Axis boxAxis = ((IRotate) block).getRotationAxis(blockState); float speed = tile.getSpeed(); for (Direction dir : Iterate.directionsInAxis(boxAxis)) { - InstancedModel half = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, dir); + InstancedModel half = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, blockState, dir); float splitSpeed = speed * tile.getRotationSpeedModifier(dir); @@ -42,9 +39,9 @@ public class SplitShaftInstance extends KineticTileInstance relight(pos, ((InstanceKey>) key).getInstance())); + keys.forEach(key -> relight(pos, ((InstanceKey) key).getInstance())); } @Override @@ -68,9 +65,9 @@ public class SplitShaftInstance extends KineticTileInstance faces; + protected final ArrayList faces; protected MatrixStack ms; protected GaugeInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { super(dispatcher, tile); - } - - @Override - protected void init() { - super.init(); faces = new ArrayList<>(2); GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; - GaugeBlock gaugeBlock = (GaugeBlock) lastState.getBlock(); + GaugeBlock gaugeBlock = (GaugeBlock) blockState.getBlock(); - InstancedModel dialModel = modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_DIAL, lastState); + InstancedModel dialModel = modelManager.getMaterial(RenderMaterials.TRANSFORMED).getModel(AllBlockPartials.GAUGE_DIAL, blockState); InstancedModel headModel = getHeadModel(); ms = new MatrixStack(); @@ -48,7 +43,7 @@ public abstract class GaugeInstance extends ShaftInstance implements ITickableIn float progress = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), gaugeTile.prevDialState, gaugeTile.dialState); for (Direction facing : Iterate.directions) { - if (!gaugeBlock.shouldRenderHeadOnFace(world, pos, lastState, facing)) + if (!gaugeBlock.shouldRenderHeadOnFace(world, pos, blockState, facing)) continue; DialFace face = makeFace(facing, dialModel, headModel); @@ -66,7 +61,7 @@ public abstract class GaugeInstance extends ShaftInstance implements ITickableIn } @Override - public void tick() { + public void beginFrame() { GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; if (MathHelper.epsilonEquals(gaugeTile.prevDialState, gaugeTile.dialState)) @@ -159,7 +154,7 @@ public abstract class GaugeInstance extends ShaftInstance implements ITickableIn @Override protected InstancedModel getHeadModel() { - return modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_HEAD_SPEED, lastState); + return modelManager.getMaterial(RenderMaterials.TRANSFORMED).getModel(AllBlockPartials.GAUGE_HEAD_SPEED, blockState); } } @@ -170,7 +165,7 @@ public abstract class GaugeInstance extends ShaftInstance implements ITickableIn @Override protected InstancedModel getHeadModel() { - return modelManager.getMaterial(RenderMaterials.MODELS).getModel(AllBlockPartials.GAUGE_HEAD_STRESS, lastState); + return modelManager.getMaterial(RenderMaterials.TRANSFORMED).getModel(AllBlockPartials.GAUGE_HEAD_STRESS, blockState); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java index e0c10fe92..637132f25 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java @@ -17,18 +17,15 @@ import java.util.Map; public class GearboxInstance extends KineticTileInstance { - protected EnumMap> keys; + protected final EnumMap> keys; protected Direction sourceFacing; public GearboxInstance(InstancedTileRenderer modelManager, GearboxTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { keys = new EnumMap<>(Direction.class); - final Direction.Axis boxAxis = lastState.get(BlockStateProperties.AXIS); + final Direction.Axis boxAxis = blockState.get(BlockStateProperties.AXIS); int blockLight = world.getLightLevel(LightType.BLOCK, pos); int skyLight = world.getLightLevel(LightType.SKY, pos); @@ -39,17 +36,17 @@ public class GearboxInstance extends KineticTileInstance { if (boxAxis == axis) continue; - InstancedModel shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, direction); + InstancedModel shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, blockState, direction); InstanceKey key = shaft.createInstance(); key.getInstance() - .setBlockLight(blockLight) - .setSkyLight(skyLight) - .setRotationalSpeed(getSpeed(direction)) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) - .setTileEntity(tile); + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setRotationalSpeed(getSpeed(direction)) + .setRotationOffset(getRotationOffset(axis)) + .setTileEntity(tile) + .setBlockLight(blockLight) + .setSkyLight(skyLight); keys.put(direction, key); } @@ -77,18 +74,18 @@ public class GearboxInstance extends KineticTileInstance { } @Override - public void onUpdate() { + public void update() { updateSourceFacing(); for (Map.Entry> key : keys.entrySet()) { Direction direction = key.getKey(); Direction.Axis axis = direction.getAxis(); key.getValue() - .getInstance() - .setColor(tile.network) - .setRotationalSpeed(getSpeed(direction)) - .setRotationOffset(getRotationOffset(axis)) - .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()); + .getInstance() + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setRotationalSpeed(getSpeed(direction)) + .setRotationOffset(getRotationOffset(axis)) + .setColor(tile.network); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapVertexAttributes.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapAttributes.java similarity index 90% rename from src/main/java/com/simibubi/create/content/logistics/block/FlapVertexAttributes.java rename to src/main/java/com/simibubi/create/content/logistics/block/FlapAttributes.java index 6bf8a85d5..71a8db0af 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/FlapVertexAttributes.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/FlapAttributes.java @@ -5,7 +5,7 @@ import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; -public enum FlapVertexAttributes implements IVertexAttrib { +public enum FlapAttributes implements IVertexAttrib { INSTANCE_POSITION("aInstancePos",CommonAttributes.VEC3), LIGHT("aLight", CommonAttributes.LIGHT), SEGMENT_OFFSET("aSegmentOffset", CommonAttributes.VEC3), @@ -19,7 +19,7 @@ public enum FlapVertexAttributes implements IVertexAttrib { private final String name; private final VertexAttribSpec spec; - FlapVertexAttributes(String name, VertexAttribSpec spec) { + FlapAttributes(String name, VertexAttribSpec spec) { this.name = name; this.spec = spec; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java index 367289962..176171fba 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java @@ -1,122 +1,120 @@ package com.simibubi.create.content.logistics.block; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstanceData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; import java.nio.ByteBuffer; -public class FlapData extends InstanceData { +public class FlapData extends InstanceData implements IFlatLight { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(FlapVertexAttributes.class) - .build(); + private float x; + private float y; + private float z; + private byte blockLight; + private byte skyLight; - private float x; - private float y; - private float z; - private byte blockLight; - private byte skyLight; + private float segmentOffsetX; + private float segmentOffsetY; + private float segmentOffsetZ; - private float segmentOffsetX; - private float segmentOffsetY; - private float segmentOffsetZ; + private float pivotX; + private float pivotY; + private float pivotZ; - private float pivotX; - private float pivotY; - private float pivotZ; + private float horizontalAngle; + private float intensity; + private float flapScale; - private float horizontalAngle; - private float intensity; - private float flapScale; + private float flapness; - private float flapness; + public FlapData(InstancedModel owner) { + super(owner); + } - public FlapData(InstancedModel owner) { - super(owner); - } + public FlapData setPosition(BlockPos pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } - public FlapData setPosition(BlockPos pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } + public FlapData setPosition(Vector3f pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } - public FlapData setPosition(Vector3f pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } + public FlapData setPosition(int x, int y, int z) { + BlockPos origin = owner.renderer.getOriginCoordinate(); - public FlapData setPosition(int x, int y, int z) { - BlockPos origin = owner.renderer.getOriginCoordinate(); + return setPosition((float) (x - origin.getX()), + (float) (y - origin.getY()), + (float) (z - origin.getZ())); + } - return setPosition((float) (x - origin.getX()), - (float) (y - origin.getY()), - (float) (z - origin.getZ())); - } + public FlapData setPosition(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + return this; + } - public FlapData setPosition(float x, float y, float z) { - this.x = x; - this.y = y; - this.z = z; - return this; - } + @Override + public FlapData setBlockLight(int blockLight) { + this.blockLight = (byte) ((blockLight & 0xF) << 4); + return this; + } - public FlapData setBlockLight(int blockLight) { - this.blockLight = (byte) ((blockLight & 0xF) << 4); - return this; - } + @Override + public FlapData setSkyLight(int skyLight) { + this.skyLight = (byte) ((skyLight & 0xF) << 4); + return this; + } - public FlapData setSkyLight(int skyLight) { - this.skyLight = (byte) ((skyLight & 0xF) << 4); - return this; - } + public FlapData setSegmentOffset(float x, float y, float z) { + this.segmentOffsetX = x; + this.segmentOffsetY = y; + this.segmentOffsetZ = z; + return this; + } - public FlapData setSegmentOffset(float x, float y, float z) { - this.segmentOffsetX = x; - this.segmentOffsetY = y; - this.segmentOffsetZ = z; - return this; - } + public FlapData setIntensity(float intensity) { + this.intensity = intensity; + return this; + } - public FlapData setIntensity(float intensity) { - this.intensity = intensity; - return this; - } + public FlapData setHorizontalAngle(float horizontalAngle) { + this.horizontalAngle = horizontalAngle; + return this; + } - public FlapData setHorizontalAngle(float horizontalAngle) { - this.horizontalAngle = horizontalAngle; - return this; - } + public FlapData setFlapScale(float flapScale) { + this.flapScale = flapScale; + return this; + } - public FlapData setFlapScale(float flapScale) { - this.flapScale = flapScale; - return this; - } + public FlapData setFlapness(float flapness) { + this.flapness = flapness; + return this; + } - public FlapData setFlapness(float flapness) { - this.flapness = flapness; - return this; - } + public FlapData setPivotVoxelSpace(float x, float y, float z) { + pivotX = x / 16f; + pivotY = y / 16f; + pivotZ = z / 16f; + return this; + } - public FlapData setPivotVoxelSpace(float x, float y, float z) { - pivotX = x / 16f; - pivotY = y / 16f; - pivotZ = z / 16f; - return this; - } + @Override + public void write(ByteBuffer buf) { + putVec3(buf, x, y, z); + putVec2(buf, blockLight, skyLight); - @Override - public void write(ByteBuffer buf) { - putVec3(buf, x, y, z); - putVec2(buf, blockLight, skyLight); + putVec3(buf, segmentOffsetX, segmentOffsetY, segmentOffsetZ); + putVec3(buf, pivotX, pivotY, pivotZ); - putVec3(buf, segmentOffsetX, segmentOffsetY, segmentOffsetZ); - putVec3(buf, pivotX, pivotY, pivotZ); + put(buf, horizontalAngle); + put(buf, intensity); + put(buf, flapScale); - put(buf, horizontalAngle); - put(buf, intensity); - put(buf, flapScale); - - put(buf, flapness); - } + put(buf, flapness); + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapInstancedModel.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapInstancedModel.java deleted file mode 100644 index d9502bb4d..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/FlapInstancedModel.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.simibubi.create.content.logistics.block; - -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import net.minecraft.client.renderer.BufferBuilder; - -public class FlapInstancedModel extends InstancedModel { - public FlapInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected FlapData newInstance() { - return new FlapData(this); - } - - @Override - protected VertexFormat getInstanceFormat() { - return FlapData.FORMAT; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapModel.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapModel.java new file mode 100644 index 000000000..fb4731bc7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/block/FlapModel.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.logistics.block; + +import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import net.minecraft.client.renderer.BufferBuilder; + +public class FlapModel extends InstancedModel { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(FlapAttributes.class) + .build(); + + public FlapModel(InstancedTileRenderer renderer, BufferBuilder buf) { + super(renderer, buf); + } + + @Override + protected FlapData newInstance() { + return new FlapData(this); + } + + @Override + protected VertexFormat getInstanceFormat() { + return FORMAT; + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java index 956ac0d97..48f643efa 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java @@ -14,21 +14,17 @@ import java.util.Collection; import java.util.EnumMap; import java.util.Map; -public class BeltTunnelInstance extends TileEntityInstance implements ITickableInstance { +public class BeltTunnelInstance extends TileEntityInstance implements IDynamicInstance { - - private Map>> tunnelFlaps; + private final Map>> tunnelFlaps; public BeltTunnelInstance(InstancedTileRenderer modelManager, BeltTunnelTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { tunnelFlaps = new EnumMap<>(Direction.class); InstancedModel model = modelManager.getMaterial(KineticRenderMaterials.FLAPS) - .getModel(AllBlockPartials.BELT_TUNNEL_FLAP, lastState); + .getModel(AllBlockPartials.BELT_TUNNEL_FLAP, blockState); int blockLight = world.getLightLevel(LightType.BLOCK, pos); int skyLight = world.getLightLevel(LightType.SKY, pos); @@ -68,7 +64,7 @@ public class BeltTunnelInstance extends TileEntityInstance } @Override - public void tick() { + public void beginFrame() { tunnelFlaps.forEach((direction, keys) -> { InterpolatedValue flapValue = tile.flaps.get(direction); if (flapValue == null) { @@ -82,9 +78,6 @@ public class BeltTunnelInstance extends TileEntityInstance }); } - @Override - protected void onUpdate() { } - @Override public void updateLight() { int blockLight = world.getLightLevel(LightType.BLOCK, pos); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java index 06b8a10e5..03228e47e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelTileEntity.java @@ -1,5 +1,14 @@ package com.simibubi.create.content.logistics.block.belts.tunnel; +import java.util.EnumMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.AllBlocks; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock.Shape; import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; @@ -29,9 +38,6 @@ import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.*; public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRendered { @@ -98,7 +104,7 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe super.fromTag(state, compound, clientPacket); if (clientPacket) - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); } public void updateTunnelConnections() { @@ -170,6 +176,11 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe flapsToSend.clear(); } + @Override + public boolean shouldRenderAsTE() { + return true; + } + @Override public void addBehaviours(List behaviours) {} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java index 53c466fff..ec9fd955a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java @@ -7,6 +7,7 @@ import com.simibubi.create.content.contraptions.components.fan.EncasedFanBlock; import com.simibubi.create.content.contraptions.components.fan.EncasedFanTileEntity; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.particle.AirParticleData; +import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.widgets.InterpolatedValue; @@ -154,7 +155,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor if (!handleDownwardOutput(true)) nextOffset = .5f; else if (nextOffset < 0) { - handleDownwardOutput(world.isRemote); + handleDownwardOutput(world.isRemote && !isVirtual()); return; } } @@ -165,7 +166,7 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor if (!handleUpwardOutput(true)) nextOffset = .5f; else if (nextOffset > 1) { - handleUpwardOutput(world.isRemote); + handleUpwardOutput(world.isRemote && !isVirtual()); return; } } @@ -379,6 +380,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor .isHorizontal()) return false; + if (FunnelBlock.getFunnelFacing(world.getBlockState(pos.down())) == Direction.DOWN) + return false; if (Block.hasSolidSideOnTop(world, pos.down())) return false; @@ -433,6 +436,8 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor return true; } + if (FunnelBlock.getFunnelFacing(world.getBlockState(pos.up())) == Direction.UP) + return false; if (BlockHelper.hasBlockSolidSide(stateAbove, world, pos.up(), Direction.DOWN)) return false; if (!inputChutes.isEmpty()) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java index 3f45a4320..5a867753a 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotTileEntity.java @@ -99,6 +99,8 @@ public class DepotTileEntity extends SmartTileEntity { continue; ItemStack afterInsert = getBehaviour(DirectBeltInputBehaviour.TYPE).tryExportingToBeltFunnel(previousItem, null); + if (afterInsert == null) + return false; if (previousItem.getCount() != afterInsert.getCount()) { processingOutputBuffer.setStackInSlot(slot, afterInsert); notifyUpdate(); @@ -109,6 +111,8 @@ public class DepotTileEntity extends SmartTileEntity { ItemStack previousItem = heldItem.stack; ItemStack afterInsert = getBehaviour(DirectBeltInputBehaviour.TYPE).tryExportingToBeltFunnel(previousItem, null); + if (afterInsert == null) + return false; if (previousItem.getCount() != afterInsert.getCount()) { if (afterInsert.isEmpty()) heldItem = null; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java new file mode 100644 index 000000000..a0a6c33ea --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java @@ -0,0 +1,55 @@ +package com.simibubi.create.content.logistics.block.diodes; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.render.backend.instancing.*; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.MatrixStacker; + +public class AdjustableRepeaterInstance extends TileEntityInstance implements ITickableInstance { + + protected final InstanceKey indicator; + + protected int previousState; + + public AdjustableRepeaterInstance(InstancedTileRenderer modelManager, AdjustableRepeaterTileEntity tile) { + super(modelManager, tile); + + indicator = modelManager.transformMaterial().getModel(AllBlockPartials.FLEXPEATER_INDICATOR, blockState).createInstance(); + + MatrixStack ms = new MatrixStack(); + MatrixStacker.of(ms).translate(getFloatingPos()); + + indicator.getInstance() + .setTransform(ms) + .setColor(getColor()); + + previousState = tile.state; + + updateLight(); + } + + @Override + public void tick() { + if (previousState == tile.state) return; + + indicator.getInstance().setColor(getColor()); + + previousState = tile.state; + } + + @Override + public void updateLight() { + relight(pos, indicator.getInstance()); + } + + @Override + public void remove() { + indicator.delete(); + } + + protected int getColor() { + return ColorHelper.mixColors(0x2C0300, 0xCD0000, tile.state / (float) tile.maxState.getValue()); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java index f10a96462..363daea76 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java @@ -5,6 +5,7 @@ import static net.minecraft.block.RedstoneDiodeBlock.POWERED; import java.util.List; +import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; @@ -17,7 +18,7 @@ import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; -public class AdjustableRepeaterTileEntity extends SmartTileEntity { +public class AdjustableRepeaterTileEntity extends SmartTileEntity implements IInstanceRendered { public int state; public boolean charging; @@ -116,5 +117,4 @@ public class AdjustableRepeaterTileEntity extends SmartTileEntity { state += charging ? 1 : -1; } - } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java index 64d87de29..9d2e4fb25 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java @@ -10,29 +10,26 @@ import net.minecraft.world.LightType; import java.util.ArrayList; -public class FunnelInstance extends TileEntityInstance implements ITickableInstance { +public class FunnelInstance extends TileEntityInstance implements IDynamicInstance { - private ArrayList> flaps; + private final ArrayList> flaps; public FunnelInstance(InstancedTileRenderer modelManager, FunnelTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { flaps = new ArrayList<>(4); if (!tile.hasFlap()) return; - AllBlockPartials flapPartial = (lastState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP + AllBlockPartials flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP : AllBlockPartials.BELT_FUNNEL_FLAP); InstancedModel model = modelManager.getMaterial(KineticRenderMaterials.FLAPS) - .getModel(flapPartial, lastState); + .getModel(flapPartial, blockState); int blockLight = world.getLightLevel(LightType.BLOCK, pos); int skyLight = world.getLightLevel(LightType.SKY, pos); - Direction direction = FunnelBlock.getFunnelFacing(lastState); + Direction direction = FunnelBlock.getFunnelFacing(blockState); float flapness = tile.flap.get(AnimationTickHolder.getPartialTicks()); float horizontalAngle = direction.getOpposite().getHorizontalAngle(); @@ -59,7 +56,7 @@ public class FunnelInstance extends TileEntityInstance impleme } @Override - public void tick() { + public void beginFrame() { if (flaps == null) return; float flapness = tile.flap.get(AnimationTickHolder.getPartialTicks()); @@ -71,16 +68,8 @@ public class FunnelInstance extends TileEntityInstance impleme @Override public void updateLight() { - if (flaps == null) return; - - int blockLight = world.getLightLevel(LightType.BLOCK, pos); - int skyLight = world.getLightLevel(LightType.SKY, pos); - - for (InstanceKey it : flaps) { - it.getInstance() - .setBlockLight(blockLight) - .setSkyLight(skyLight); - } + if (flaps != null) + relight(pos, flaps.stream().map(InstanceKey::getInstance)); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java index 7fdc583de..f0ea6a15e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java @@ -263,6 +263,8 @@ public class FunnelTileEntity extends SmartTileEntity implements IHaveHoveringIn return false; if (!(blockState.getBlock() instanceof FunnelBlock)) return false; + if (blockState.get(FunnelBlock.EXTRACTING)) + return false; return FunnelBlock.getFunnelFacing(blockState) == Direction.UP; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java index c3cf73af8..e3b7fb14e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java @@ -21,144 +21,137 @@ import net.minecraft.util.math.MathHelper; import java.util.ArrayList; -public class ArmInstance extends SingleRotatingInstance implements ITickableInstance { +public class ArmInstance extends SingleRotatingInstance implements IDynamicInstance { - private InstanceKey base; - private InstanceKey lowerBody; - private InstanceKey upperBody; - private InstanceKey head; - private InstanceKey claw; - private ArrayList> clawGrips; + final InstanceKey base; + final InstanceKey lowerBody; + final InstanceKey upperBody; + final InstanceKey head; + final InstanceKey claw; + private final ArrayList> clawGrips; - private ArrayList> models; + private final ArrayList> models; - private boolean firstTick = true; + private boolean firstTick = true; - public ArmInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { - super(modelManager, tile); - } + public ArmInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); - @Override - protected void init() { - super.init(); + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.TRANSFORMED); - RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); + base = mat.getModel(AllBlockPartials.ARM_BASE, blockState).createInstance(); + lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState).createInstance(); + upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY, blockState).createInstance(); + head = mat.getModel(AllBlockPartials.ARM_HEAD, blockState).createInstance(); + claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, blockState).createInstance(); - base = mat.getModel(AllBlockPartials.ARM_BASE, lastState).createInstance(); - lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, lastState).createInstance(); - upperBody = mat.getModel(AllBlockPartials.ARM_UPPER_BODY, lastState).createInstance(); - head = mat.getModel(AllBlockPartials.ARM_HEAD, lastState).createInstance(); - claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, lastState).createInstance(); + InstancedModel clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, blockState); + InstanceKey clawGrip1 = clawHalfModel.createInstance(); + InstanceKey clawGrip2 = clawHalfModel.createInstance(); - InstancedModel clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, lastState); - InstanceKey clawGrip1 = clawHalfModel.createInstance(); - InstanceKey clawGrip2 = clawHalfModel.createInstance(); + clawGrips = Lists.newArrayList(clawGrip1, clawGrip2); + models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2); - clawGrips = Lists.newArrayList(clawGrip1, clawGrip2); - models = Lists.newArrayList(base, lowerBody, upperBody, head, claw, clawGrip1, clawGrip2); + updateLight(); + } - firstTick = true; - tick(); - updateLight(); - } + @Override + public void beginFrame() { + ArmTileEntity arm = (ArmTileEntity) tile; - @Override - public void tick() { - ArmTileEntity arm = (ArmTileEntity) tile; + boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled(); + boolean rave = arm.phase == ArmTileEntity.Phase.DANCING; - boolean settled = arm.baseAngle.settled() && arm.lowerArmAngle.settled() && arm.upperArmAngle.settled() && arm.headAngle.settled(); - boolean rave = arm.phase == ArmTileEntity.Phase.DANCING; + if (!settled || rave || firstTick) + transformModels(arm, rave); - if (!settled || rave || firstTick) - transformModels(arm, rave); + if (settled) + firstTick = false; + } - if (settled) - firstTick = false; - } + private void transformModels(ArmTileEntity arm, boolean rave) { + float pt = AnimationTickHolder.getPartialTicks(); + int color = 0xFFFFFF; - private void transformModels(ArmTileEntity arm, boolean rave) { - float pt = AnimationTickHolder.getPartialTicks(); - int color = 0xFFFFFF; + float baseAngle = arm.baseAngle.get(pt); + float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; + float upperArmAngle = arm.upperArmAngle.get(pt) - 90; + float headAngle = arm.headAngle.get(pt); - float baseAngle = arm.baseAngle.get(pt); - float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; - float upperArmAngle = arm.upperArmAngle.get(pt) - 90; - float headAngle = arm.headAngle.get(pt); - - if (rave) { - float renderTick = AnimationTickHolder.getRenderTime(arm.getWorld()) + (tile.hashCode() % 64); - baseAngle = (renderTick * 10) % 360; - lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); - upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); - headAngle = -lowerArmAngle; - color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); - } + if (rave) { + float renderTick = AnimationTickHolder.getRenderTime(arm.getWorld()) + (tile.hashCode() % 64); + baseAngle = (renderTick * 10) % 360; + lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); + upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); + headAngle = -lowerArmAngle; + color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); + } - MatrixStack msLocal = new MatrixStack(); - MatrixStacker msr = MatrixStacker.of(msLocal); - msr.translate(getFloatingPos()); - msr.centre(); + MatrixStack msLocal = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(msLocal); + msr.translate(getFloatingPos()); + msr.centre(); - if (lastState.get(ArmBlock.CEILING)) - msr.rotateX(180); + if (blockState.get(ArmBlock.CEILING)) + msr.rotateX(180); - ArmRenderer.transformBase(msr, baseAngle); - base.getInstance() - .setTransform(msLocal); + ArmRenderer.transformBase(msr, baseAngle); + base.getInstance() + .setTransform(msLocal); - ArmRenderer.transformLowerArm(msr, lowerArmAngle); - lowerBody.getInstance() - .setColor(color) - .setTransform(msLocal); + ArmRenderer.transformLowerArm(msr, lowerArmAngle); + lowerBody.getInstance() + .setTransform(msLocal) + .setColor(color); - ArmRenderer.transformUpperArm(msr, upperArmAngle); - upperBody.getInstance() - .setColor(color) - .setTransform(msLocal); + ArmRenderer.transformUpperArm(msr, upperArmAngle); + upperBody.getInstance() + .setTransform(msLocal) + .setColor(color); - ArmRenderer.transformHead(msr, headAngle); - head.getInstance() - .setTransform(msLocal); + ArmRenderer.transformHead(msr, headAngle); + head.getInstance() + .setTransform(msLocal); - ArmRenderer.transformClaw(msr); - claw.getInstance() - .setTransform(msLocal); + ArmRenderer.transformClaw(msr); + claw.getInstance() + .setTransform(msLocal); - ItemStack item = arm.heldItem; - ItemRenderer itemRenderer = Minecraft.getInstance() - .getItemRenderer(); - boolean hasItem = !item.isEmpty(); - boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) - && itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null) - .isGui3d(); + ItemStack item = arm.heldItem; + ItemRenderer itemRenderer = Minecraft.getInstance() + .getItemRenderer(); + boolean hasItem = !item.isEmpty(); + boolean isBlockItem = hasItem && (item.getItem() instanceof BlockItem) + && itemRenderer.getItemModelWithOverrides(item, Minecraft.getInstance().world, null) + .isGui3d(); - for (int index : Iterate.zeroAndOne) { - msLocal.push(); - int flip = index * 2 - 1; - ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip); - clawGrips.get(index) - .getInstance() - .setTransform(msLocal); - msLocal.pop(); - } - } + for (int index : Iterate.zeroAndOne) { + msLocal.push(); + int flip = index * 2 - 1; + ArmRenderer.transformClawHalf(msr, hasItem, isBlockItem, flip); + clawGrips.get(index) + .getInstance() + .setTransform(msLocal); + msLocal.pop(); + } + } - @Override - public void updateLight() { - super.updateLight(); + @Override + public void updateLight() { + super.updateLight(); - relight(pos, models.stream().map(InstanceKey::getInstance)); - } + relight(pos, models.stream().map(InstanceKey::getInstance)); + } - @Override - protected InstancedModel getModel() { - return AllBlockPartials.ARM_COG.renderOnRotating(modelManager, tile.getBlockState()); - } + @Override + protected InstancedModel getModel() { + return AllBlockPartials.ARM_COG.renderOnRotating(modelManager, tile.getBlockState()); + } - @Override - public void remove() { - super.remove(); - models.forEach(InstanceKey::delete); - } + @Override + public void remove() { + super.remove(); + models.forEach(InstanceKey::delete); + } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java index 3f7f79b68..984c74df1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java @@ -1,5 +1,11 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; +import java.util.function.Supplier; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.mutable.MutableBoolean; + import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; @@ -10,17 +16,25 @@ import com.simibubi.create.content.contraptions.components.crafter.MechanicalCra import com.simibubi.create.content.contraptions.components.deployer.DeployerBlock; import com.simibubi.create.content.contraptions.components.saw.SawBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; +import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.block.chute.AbstractChuteBlock; +import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock; +import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock; +import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock.Shape; import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.item.SmartInventory; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; + import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.ComposterBlock; @@ -39,6 +53,7 @@ import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.IBlockReader; +import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -48,9 +63,6 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.items.wrapper.InvWrapper; -import javax.annotation.Nullable; -import java.util.function.Supplier; - public abstract class ArmInteractionPoint { enum Mode { @@ -65,21 +77,21 @@ public abstract class ArmInteractionPoint { private ArmAngleTarget cachedAngles; private static ImmutableMap> POINTS = - ImmutableMap.>builder() - .put(new Saw(), Saw::new) - .put(new Belt(), Belt::new) - .put(new Depot(), Depot::new) - .put(new Chute(), Chute::new) - .put(new Basin(), Basin::new) - .put(new Funnel(), Funnel::new) - .put(new Jukebox(), Jukebox::new) - .put(new Crafter(), Crafter::new) - .put(new Deployer(), Deployer::new) - .put(new Composter(), Composter::new) - .put(new Millstone(), Millstone::new) - .put(new BlazeBurner(), BlazeBurner::new) - .put(new CrushingWheels(), CrushingWheels::new) - .build(); + ImmutableMap.>builder() + .put(new Saw(), Saw::new) + .put(new Belt(), Belt::new) + .put(new Depot(), Depot::new) + .put(new Chute(), Chute::new) + .put(new Basin(), Basin::new) + .put(new Funnel(), Funnel::new) + .put(new Jukebox(), Jukebox::new) + .put(new Crafter(), Crafter::new) + .put(new Deployer(), Deployer::new) + .put(new Composter(), Composter::new) + .put(new Millstone(), Millstone::new) + .put(new BlazeBurner(), BlazeBurner::new) + .put(new CrushingWheels(), CrushingWheels::new) + .build(); public ArmInteractionPoint() { cachedHandler = LazyOptional.empty(); @@ -108,6 +120,8 @@ public abstract class ArmInteractionPoint { return isValid(reader, pos, reader.getBlockState(pos)); } + void keepAlive(IWorld world) {} + abstract boolean isValid(IBlockReader reader, BlockPos pos, BlockState state); static boolean isInteractable(IBlockReader reader, BlockPos pos, BlockState state) { @@ -119,7 +133,8 @@ public abstract class ArmInteractionPoint { ArmAngleTarget getTargetAngles(BlockPos armPos, boolean ceiling) { if (cachedAngles == null) - cachedAngles = new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection(), ceiling); + cachedAngles = + new ArmAngleTarget(armPos, getInteractionPositionVector(), getInteractionDirection(), ceiling); return cachedAngles; } @@ -167,7 +182,8 @@ public abstract class ArmInteractionPoint { for (ArmInteractionPoint armInteractionPoint : POINTS.keySet()) if (armInteractionPoint.isValid(world, pos, state)) - point = POINTS.get(armInteractionPoint).get(); + point = POINTS.get(armInteractionPoint) + .get(); if (point != null) { point.state = state; @@ -222,7 +238,7 @@ public abstract class ArmInteractionPoint { @Override boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { return AllBlocks.MECHANICAL_SAW.has(state) && state.get(SawBlock.FACING) == Direction.UP - && ((KineticTileEntity) reader.getTileEntity(pos)).getSpeed() != 0; + && ((KineticTileEntity) reader.getTileEntity(pos)).getSpeed() != 0; } } @@ -260,7 +276,8 @@ public abstract class ArmInteractionPoint { @Nullable @Override IItemHandler getHandler(World world) { - return new InvWrapper(((ComposterBlock) Blocks.COMPOSTER).createInventory(world.getBlockState(pos), world, pos)); + return new InvWrapper( + ((ComposterBlock) Blocks.COMPOSTER).createInventory(world.getBlockState(pos), world, pos)); } } @@ -273,7 +290,8 @@ public abstract class ArmInteractionPoint { @Override Direction getInteractionDirection() { - return state.get(DeployerBlock.FACING).getOpposite(); + return state.get(DeployerBlock.FACING) + .getOpposite(); } @Override @@ -299,13 +317,15 @@ public abstract class ArmInteractionPoint { @Override ItemStack insert(World world, ItemStack stack, boolean simulate) { ItemStack input = stack.copy(); - if (!BlazeBurnerBlock.tryInsert(state, world, pos, input, false, true).getResult().isEmpty()) { + if (!BlazeBurnerBlock.tryInsert(state, world, pos, input, false, true) + .getResult() + .isEmpty()) { return stack; } ActionResult res = BlazeBurnerBlock.tryInsert(state, world, pos, input, false, simulate); return res.getType() == ActionResultType.SUCCESS - ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - 1) - : stack; + ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - 1) + : stack; } @Override @@ -322,7 +342,8 @@ public abstract class ArmInteractionPoint { @Override Direction getInteractionDirection() { - return state.get(MechanicalCrafterBlock.HORIZONTAL_FACING).getOpposite(); + return state.get(MechanicalCrafterBlock.HORIZONTAL_FACING) + .getOpposite(); } @Override @@ -376,7 +397,8 @@ public abstract class ArmInteractionPoint { return stack; JukeboxBlock jukeboxBlock = (JukeboxBlock) state.getBlock(); JukeboxTileEntity jukeboxTE = (JukeboxTileEntity) tileEntity; - if (!jukeboxTE.getRecord().isEmpty()) + if (!jukeboxTE.getRecord() + .isEmpty()) return stack; if (!(stack.getItem() instanceof MusicDiscItem)) return stack; @@ -415,8 +437,30 @@ public abstract class ArmInteractionPoint { @Override boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { - return AllBlocks.BELT.has(state) && !(reader.getBlockState(pos.up()).getBlock() instanceof BeltTunnelBlock); + return AllBlocks.BELT.has(state) && !(reader.getBlockState(pos.up()) + .getBlock() instanceof BeltTunnelBlock); } + + @Override + void keepAlive(IWorld world) { + super.keepAlive(world); + BeltTileEntity beltTE = BeltHelper.getSegmentTE(world, pos); + if (beltTE == null) + return; + TransportedItemStackHandlerBehaviour transport = + beltTE.getBehaviour(TransportedItemStackHandlerBehaviour.TYPE); + if (transport == null) + return; + MutableBoolean found = new MutableBoolean(false); + transport.handleProcessingOnAllItems(tis -> { + if (found.isTrue()) + return TransportedResult.doNothing(); + tis.lockedExternally = true; + found.setTrue(); + return TransportedResult.doNothing(); + }); + } + } static class Chute extends TopFaceArmInteractionPoint { @@ -448,7 +492,8 @@ public abstract class ArmInteractionPoint { @Override Direction getInteractionDirection() { - return FunnelBlock.getFunnelFacing(state).getOpposite(); + return FunnelBlock.getFunnelFacing(state) + .getOpposite(); } @Override @@ -479,7 +524,9 @@ public abstract class ArmInteractionPoint { @Override boolean isValid(IBlockReader reader, BlockPos pos, BlockState state) { - return state.getBlock() instanceof FunnelBlock && !state.get(FunnelBlock.EXTRACTING); + return state.getBlock() instanceof AbstractFunnelBlock + && !(state.contains(FunnelBlock.EXTRACTING) && state.get(FunnelBlock.EXTRACTING)) + && !(state.contains(BeltFunnelBlock.SHAPE) && state.get(BeltFunnelBlock.SHAPE) == Shape.PUSHING); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java index 930de6e3f..a2ac81ef8 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmTileEntity.java @@ -65,7 +65,7 @@ public class ArmTileEntity extends KineticTileEntity { protected int lastOutputIndex = -1; protected boolean redstoneLocked; - enum Phase { + public enum Phase { SEARCH_INPUTS, MOVE_TO_INPUT, SEARCH_OUTPUTS, MOVE_TO_OUTPUT, DANCING } @@ -107,9 +107,15 @@ public class ArmTileEntity extends KineticTileEntity { initInteractionPoints(); boolean targetReached = tickMovementProgress(); - if (world.isRemote) + if (chasedPointProgress < 1) { + if (phase == Phase.MOVE_TO_INPUT) { + ArmInteractionPoint point = getTargetedInteractionPoint(); + if (point != null) + point.keepAlive(world); + } return; - if (chasedPointProgress < 1) + } + if (world.isRemote) return; if (phase == Phase.MOVE_TO_INPUT) @@ -491,7 +497,7 @@ public class ArmTileEntity extends KineticTileEntity { @Override protected Vector3d getLocalOffset(BlockState state) { int yPos = state.get(ArmBlock.CEILING) ? 16 - 3 : 3; - Vector3d location = VecHelper.voxelSpace(8, yPos, 14.5); + Vector3d location = VecHelper.voxelSpace(8, yPos, 15.95); location = VecHelper.rotateCentered(location, AngleHelper.horizontalAngle(getSide()), Direction.Axis.Y); return location; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java index 99680aac1..78fffc5c5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java @@ -12,35 +12,32 @@ import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.state.properties.AttachFace; import net.minecraft.util.Direction; -public class AnalogLeverInstance extends TileEntityInstance implements ITickableInstance { +public class AnalogLeverInstance extends TileEntityInstance implements IDynamicInstance { - protected InstanceKey handle; - protected InstanceKey indicator; + protected final InstanceKey handle; + protected final InstanceKey indicator; - private float rX; - private float rY; + final float rX; + final float rY; public AnalogLeverInstance(InstancedTileRenderer modelManager, AnalogLeverTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { - RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.TRANSFORMED); - handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, lastState).createInstance(); - indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, lastState).createInstance(); + handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState).createInstance(); + indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState).createInstance(); - AttachFace face = lastState.get(AnalogLeverBlock.FACE); + AttachFace face = blockState.get(AnalogLeverBlock.FACE); rX = face == AttachFace.FLOOR ? 0 : face == AttachFace.WALL ? 90 : 180; - rY = AngleHelper.horizontalAngle(lastState.get(AnalogLeverBlock.HORIZONTAL_FACING)); + rY = AngleHelper.horizontalAngle(blockState.get(AnalogLeverBlock.HORIZONTAL_FACING)); setupModel(); updateLight(); } @Override - public void tick() { + public void beginFrame() { if (!tile.clientState.settled()) setupModel(); } @@ -65,7 +62,7 @@ public class AnalogLeverInstance extends TileEntityInstance implements ITickableInstance { +public class SchematicannonInstance extends TileEntityInstance implements IDynamicInstance { - private InstanceKey connector; - private InstanceKey pipe; + private final InstanceKey connector; + private final InstanceKey pipe; public SchematicannonInstance(InstancedTileRenderer modelManager, SchematicannonTileEntity tile) { super(modelManager, tile); - } - @Override - protected void init() { + RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.TRANSFORMED); - RenderMaterial> mat = modelManager.getMaterial(RenderMaterials.MODELS); - - connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, lastState).createInstance(); - pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, lastState).createInstance(); + connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance(); + pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance(); updateLight(); } @Override - public void tick() { + public void beginFrame() { float partialTicks = AnimationTickHolder.getPartialTicks(); double[] cannonAngles = SchematicannonRenderer.getCannonAngles(tile, pos, partialTicks); @@ -58,7 +54,7 @@ public class SchematicannonInstance extends TileEntityInstance { CreateClient.kineticRenderer.get(world).onLightUpdate(tile); - - if (tile instanceof ILightListener) - ((ILightListener) tile).onChunkLightUpdate(); }); } - ContraptionRenderDispatcher.notifyLightUpdate((IBlockDisplayReader) thi.getWorld(), type, pos); + LightUpdater.getInstance().onLightUpdate(world, type, pos.asLong()); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java index a40c2c088..e3eda853e 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java @@ -1,13 +1,18 @@ package com.simibubi.create.foundation.mixin; +import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.backend.RenderWork; -import com.simibubi.create.foundation.render.backend.light.ILightListener; +import com.simibubi.create.foundation.render.backend.light.LightUpdater; + import net.minecraft.client.Minecraft; import net.minecraft.client.network.play.ClientPlayNetHandler; import net.minecraft.client.world.ClientWorld; import net.minecraft.network.play.server.SUpdateLightPacket; +import net.minecraft.util.math.SectionPos; import net.minecraft.world.chunk.Chunk; + +import java.util.Map; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -30,14 +35,13 @@ public class NetworkLightUpdateMixin { if (chunk != null) { chunk.getTileEntityMap() - .values() - .stream() - .filter(tile -> tile instanceof ILightListener) - .map(tile -> (ILightListener) tile) - .forEach(ILightListener::onChunkLightUpdate); + .values() + .forEach(tile -> { + CreateClient.kineticRenderer.get(world).onLightUpdate(tile); + }); } - ContraptionRenderDispatcher.notifyLightPacket(world, chunkX, chunkZ); + LightUpdater.getInstance().onLightPacket(world, chunkX, chunkZ); }); } } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java index 163f6e6a7..16f07d2bc 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java @@ -1,8 +1,11 @@ package com.simibubi.create.foundation.mixin; import com.simibubi.create.foundation.render.KineticRenderer; + +import net.minecraft.block.BlockState; import net.minecraft.client.renderer.*; import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.BlockPos; import org.lwjgl.opengl.GL20; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -60,6 +63,11 @@ public class RenderHooksMixin { ContraptionRenderDispatcher.beginFrame(camX, camY, camZ); } + @Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded") + private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { + CreateClient.kineticRenderer.get(world).update(world.getTileEntity(pos)); + } + @Inject(at = @At("TAIL"), method = "loadRenderers") private void refresh(CallbackInfo ci) { ContraptionRenderDispatcher.invalidateAll(); diff --git a/src/main/java/com/simibubi/create/foundation/mixin/StepSoundMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/StepSoundMixin.java new file mode 100644 index 000000000..de6a50ee7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/StepSoundMixin.java @@ -0,0 +1,129 @@ +package com.simibubi.create.foundation.mixin; + +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.MoverType; +import net.minecraft.particles.BlockParticleData; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.Template; +import org.apache.logging.log4j.util.TriConsumer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.lang.ref.Reference; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +@Mixin(Entity.class) +public abstract class StepSoundMixin { + + @Shadow + public World world; + + @Shadow + protected Random rand; + + @Shadow + private float nextStepDistance; + + @Shadow + public abstract BlockPos getBlockPos(); + + @Shadow + public abstract Vector3d getPositionVec(); + + @Shadow + protected abstract float determineNextStepDistance(); + + @Shadow + public abstract AxisAlignedBB getBoundingBox(); + + @Shadow + protected abstract void playStepSound(BlockPos p_180429_1_, BlockState p_180429_2_); + + private Set getIntersectingContraptions(Entity entity) { + Set contraptions = ContraptionHandler.loadedContraptions.get(entity.world) + .values() + .stream() + .map(Reference::get) + .filter(cEntity -> cEntity != null && cEntity.collidingEntities.containsKey(entity)) + .collect(Collectors.toSet()); + + contraptions.addAll(entity.world.getEntitiesWithinAABB(AbstractContraptionEntity.class, getBoundingBox().grow(1f))); + return contraptions; + } + + private void forCollision(Vector3d anchorPos, TriConsumer action) { + Entity thi = (Entity) (Object) this; + getIntersectingContraptions(thi).forEach(cEntity -> { + Vector3d localPos = ContraptionCollider.getWorldToLocalTranslation(anchorPos, cEntity); + + localPos = anchorPos.add(localPos); + + BlockPos blockPos = new BlockPos(localPos); + Contraption contraption = cEntity.getContraption(); + Template.BlockInfo info = contraption.getBlocks().get(blockPos); + + if (info != null) { + BlockState blockstate = info.state; + action.accept(contraption, blockstate, blockPos); + } + }); + } + + @Inject(at = @At( + value = "JUMP", + opcode = 154, //IFNE + ordinal = 4 + ), + method = "move" + ) + private void movementMixin(MoverType mover, Vector3d movement, CallbackInfo ci) { + Entity thi = (Entity) (Object) this; + World entityWorld = world; + Vector3d worldPos = thi.getPositionVec().add(0, -0.2, 0); + AtomicBoolean stepped = new AtomicBoolean(false); + + forCollision(worldPos, (contraption, blockstate, blockPos) -> { + this.world = contraption.getContraptionWorld(); + this.playStepSound(blockPos, blockstate); + stepped.set(true); + }); + + if (stepped.get()) + this.nextStepDistance = this.determineNextStepDistance(); + + world = entityWorld; + } + + @Inject(method = {"Lnet/minecraft/entity/Entity;spawnSprintingParticles()V"}, at = @At(value = "TAIL")) + private void createRunningParticlesMixin(CallbackInfo ci) { + Entity thi = (Entity) (Object) this; + Vector3d worldPos = thi.getPositionVec().add(0, -0.2, 0); + BlockPos pos = new BlockPos(worldPos); // pos where particles are spawned + + forCollision(worldPos, (contraption, blockstate, blockpos) -> { + if (!blockstate.addRunningEffects(world, blockpos, thi) && blockstate.getRenderType() != BlockRenderType.INVISIBLE) { + Vector3d Vector3d = thi.getMotion(); + this.world.addParticle(new BlockParticleData(ParticleTypes.BLOCK, blockstate).setPos(pos), + thi.getX() + ((double) rand.nextFloat() - 0.5D) * (double) thi.getWidth(), + thi.getY() + 0.1D, thi.getZ() + ((double) rand.nextFloat() - 0.5D) * (double) thi.getWidth(), + Vector3d.x * -4.0D, 1.5D, Vector3d.z * -4.0D); + } + }); + } +} 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 c1bf33394..6d1235190 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -453,14 +453,14 @@ public class PonderScene { return ms; } - public void updateSceneRVE() { - Vector3d v = screenToScene(width / 2, height / 2, 500); + + public void updateSceneRVE(float pt) { + Vector3d v = screenToScene(width / 2, height / 2, 500, pt); renderViewEntity.setPosition(v.x, v.y, v.z); } - public Vector3d screenToScene(double x, double y, int depth) { - refreshMatrix(); - float pt = AnimationTickHolder.getPartialTicks(); + public Vector3d screenToScene(double x, double y, int depth, float pt) { + refreshMatrix(pt); Vector3d vec = new Vector3d(x, y, depth); vec = vec.subtract(width / 2, height / 2, 200 + offset); @@ -481,17 +481,17 @@ public class PonderScene { return vec; } - public Vector2f sceneToScreen(Vector3d vec) { - refreshMatrix(); + public Vector2f sceneToScreen(Vector3d vec, float pt) { + refreshMatrix(pt); Vector4f vec4 = new Vector4f((float) vec.x, (float) vec.y, (float) vec.z, 1); vec4.transform(cachedMat); return new Vector2f(vec4.getX(), vec4.getY()); } - protected void refreshMatrix() { + protected void refreshMatrix(float pt) { if (cachedMat != null) return; - cachedMat = apply(new MatrixStack()).peek() + cachedMat = apply(new MatrixStack(), pt, false).peek() .getModel(); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java index 7ce4e557b..a69ba1377 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java @@ -295,8 +295,8 @@ public class PonderUI extends NavigatableSimiScreen { double mouseX = client.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); double mouseY = client.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); SceneTransform t = activeScene.getTransform(); - Vector3d vec1 = t.screenToScene(mouseX, mouseY, 1000); - Vector3d vec2 = t.screenToScene(mouseX, mouseY, -100); + Vector3d vec1 = t.screenToScene(mouseX, mouseY, 1000, 0); + Vector3d vec2 = t.screenToScene(mouseX, mouseY, -100, 0); Pair pair = activeScene.rayTraceScene(vec1, vec2); hoveredTooltipItem = pair.getFirst(); hoveredBlockPos = pair.getSecond(); @@ -380,7 +380,7 @@ public class PonderUI extends NavigatableSimiScreen { ms.push(); story.transform.updateScreenParams(width, height, slide); story.transform.apply(ms, partialTicks, false); - story.transform.updateSceneRVE(); + story.transform.updateSceneRVE(partialTicks); story.renderScene(buffer, ms, partialTicks); buffer.draw(); @@ -434,6 +434,7 @@ public class PonderUI extends NavigatableSimiScreen { // X AXIS ms.push(); ms.translate(4, -3, 0); + ms.translate(0, 0, -2 / 1024f); for (int x = 0; x <= bounds.getXSize(); x++) { ms.translate(-16, 0, 0); textRenderer.draw(ms, x == bounds.getXSize() ? "x" : "" + x, 0, 0, 0xFFFFFFFF); @@ -685,7 +686,7 @@ public class PonderUI extends NavigatableSimiScreen { return; ms.push(); PonderScene story = scenes.get(i); - story.renderOverlay(this, ms, partialTicks); + story.renderOverlay(this, ms, skipCooling > 0 ? 0 : identifyMode ? ponderPartialTicksPaused : partialTicks); ms.pop(); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java index 21e7451e7..f5ed911cc 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java @@ -93,14 +93,14 @@ public class PonderWorld extends SchematicWorld { originalBlocks.forEach((k, v) -> blocks.put(k, v)); originalTileEntities.forEach((k, v) -> { TileEntity te = TileEntity.createFromTag(originalBlocks.get(k), v.write(new CompoundNBT())); - te.setLocation(this, te.getPos()); + onTEadded(te, te.getPos()); tileEntities.put(k, te); renderedTileEntities.add(te); }); originalEntities.forEach(e -> EntityType.loadEntityUnchecked(e.serializeNBT(), this) .ifPresent(entities::add)); particles.clearEffects(); - fixVirtualTileEntities(); + fixBeltTileEntities(); } public void restoreBlocks(Selection selection) { @@ -207,6 +207,11 @@ public class PonderWorld extends SchematicWorld { addParticle(makeParticle(data, x, y, z, mx, my, mz)); } + @Override + public void addOptionalParticle(IParticleData data, double x, double y, double z, double mx, double my, double mz) { + addParticle(data, x, y, z, mx, my, mz); + } + @Nullable @SuppressWarnings("unchecked") private Particle makeParticle(T data, double x, double y, double z, double mx, double my, @@ -221,16 +226,20 @@ public class PonderWorld extends SchematicWorld { particles.addParticle(p); } - public void fixVirtualTileEntities() { - for (TileEntity tileEntity : tileEntities.values()) { - if (!(tileEntity instanceof SmartTileEntity)) - continue; - SmartTileEntity smartTileEntity = (SmartTileEntity) tileEntity; - smartTileEntity.markVirtual(); + @Override + protected void onTEadded(TileEntity tileEntity, BlockPos pos) { + super.onTEadded(tileEntity, pos); + if (!(tileEntity instanceof SmartTileEntity)) + return; + SmartTileEntity smartTileEntity = (SmartTileEntity) tileEntity; + smartTileEntity.markVirtual(); + } - if (!(smartTileEntity instanceof BeltTileEntity)) + public void fixBeltTileEntities() { + for (TileEntity tileEntity : tileEntities.values()) { + if (!(tileEntity instanceof BeltTileEntity)) continue; - BeltTileEntity beltTileEntity = (BeltTileEntity) smartTileEntity; + BeltTileEntity beltTileEntity = (BeltTileEntity) tileEntity; if (!beltTileEntity.isController()) continue; BlockPos controllerPos = tileEntity.getPos(); @@ -302,4 +311,9 @@ public class PonderWorld extends SchematicWorld { @Override public void markChunkDirty(BlockPos p_175646_1_, TileEntity p_175646_2_) { } + + @Override + public boolean isPlayerWithin(double p_217358_1_, double p_217358_3_, double p_217358_5_, double p_217358_7_) { + return true; // always enable spawner animations + } } 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 8c49383b6..93f719c52 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java @@ -10,12 +10,15 @@ import java.util.function.UnaryOperator; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; import com.simibubi.create.content.contraptions.base.KineticBlock; import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler; +import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; +import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity; import com.simibubi.create.foundation.ponder.content.PonderPalette; import com.simibubi.create.foundation.ponder.elements.AnimatedSceneElement; import com.simibubi.create.foundation.ponder.elements.BeltItemElement; @@ -56,6 +59,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputB import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -367,10 +371,6 @@ public class SceneBuilder { addInstruction(new OutlineSelectionInstruction(color, slot, selection, duration)); } - public void hideElement(ElementLink link, Direction direction) { - addInstruction(new FadeOutOfSceneInstruction<>(15, direction, link)); - } - } public class SpecialInstructions { @@ -430,6 +430,10 @@ public class SceneBuilder { addInstruction(AnimateMinecartInstruction.move(link, offset, duration)); } + public void hideElement(ElementLink link, Direction direction) { + addInstruction(new FadeOutOfSceneInstruction<>(15, direction, link)); + } + } public class WorldInstructions { @@ -689,11 +693,13 @@ public class SceneBuilder { addInstruction(scene -> { PonderWorld world = scene.getWorld(); TileEntity tileEntity = world.getTileEntity(beltLocation); - if (!(tileEntity instanceof BeltTileEntity)) + if (!(tileEntity instanceof SmartTileEntity)) return; - BeltTileEntity beltTileEntity = (BeltTileEntity) tileEntity; + SmartTileEntity beltTileEntity = (SmartTileEntity) tileEntity; TransportedItemStackHandlerBehaviour transporter = beltTileEntity.getBehaviour(TransportedItemStackHandlerBehaviour.TYPE); + if (transporter == null) + return; transporter.handleCenteredProcessingOnAllItems(.52f, tis -> TransportedResult.removeItem()); }); } @@ -759,10 +765,31 @@ public class SceneBuilder { }, reDrawBlocks)); } + public void instructArm(BlockPos armLocation, ArmTileEntity.Phase phase, ItemStack heldItem, + int targetedPoint) { + modifyTileNBT(scene.getSceneBuildingUtil().select.position(armLocation), ArmTileEntity.class, compound -> { + NBTHelper.writeEnum(compound, "Phase", phase); + compound.put("HeldItem", heldItem.serializeNBT()); + compound.putInt("TargetPointIndex", targetedPoint); + compound.putFloat("MovementProgress", 0); + }); + } + public void flapFunnel(BlockPos position, boolean outward) { modifyTileEntity(position, FunnelTileEntity.class, funnel -> funnel.flap(!outward)); } + public void setCraftingResult(BlockPos crafter, ItemStack output) { + modifyTileEntity(crafter, MechanicalCrafterTileEntity.class, mct -> mct.setScriptedResult(output)); + } + + public void connectCrafterInvs(BlockPos position1, BlockPos position2) { + addInstruction(s -> { + ConnectedInputHandler.toggleConnection(s.getWorld(), position1, position2); + s.forEach(WorldSectionElement.class, WorldSectionElement::queueRedraw); + }); + } + } public class DebugInstructions { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java new file mode 100644 index 000000000..af26370f7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ArmScenes.java @@ -0,0 +1,611 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllShapes; +import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; +import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; +import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; + +public class ArmScenes { + + public static void setup(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_arm", "Setting up Mechanical Arms"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + + ItemStack armItem = AllBlocks.MECHANICAL_ARM.asStack(); + BlockPos armPos = util.grid.at(2, 1, 2); + Selection armSel = util.select.position(armPos); + BlockPos inputDepot = util.grid.at(4, 2, 1); + Vector3d depotSurface = util.vector.blockSurface(inputDepot, Direction.NORTH); + Vector3d armSurface = util.vector.blockSurface(armPos, Direction.WEST); + + scene.idle(20); + + scene.world.setKineticSpeed(armSel, 0); + scene.world.showSection(armSel, Direction.DOWN); + scene.idle(10); + scene.effects.indicateRedstone(armPos); + scene.overlay.showSelectionWithText(armSel, 70) + .attachKeyFrame() + .colored(PonderPalette.RED) + .text("Mechanical Arms have to be assigned their in- and outputs before they are placed") + .pointAt(armSurface) + .placeNearTarget(); + scene.idle(80); + scene.world.showSection(util.select.fromTo(4, 1, 1, 4, 2, 1), Direction.DOWN); + scene.world.showSection(util.select.fromTo(0, 1, 1, 0, 2, 1), Direction.DOWN); + scene.world.hideSection(armSel, Direction.UP); + scene.idle(20); + scene.overlay.showControls(new InputWindowElement(depotSurface, Pointing.RIGHT).rightClick() + .withItem(armItem), 50); + scene.idle(7); + AxisAlignedBB depotBounds = AllShapes.DEPOT.getBoundingBox(); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(4, 2, 1), 400); + + scene.overlay.showText(70) + .attachKeyFrame() + .colored(PonderPalette.INPUT) + .text("Right-Click inventories while holding the Arm to assign them as Targets") + .pointAt(util.vector.blockSurface(inputDepot, Direction.WEST)) + .placeNearTarget(); + scene.idle(80); + + BlockPos outputDepot = util.grid.at(0, 2, 1); + InputWindowElement input = + new InputWindowElement(util.vector.blockSurface(outputDepot, Direction.NORTH), Pointing.RIGHT).rightClick() + .withItem(armItem); + scene.overlay.showControls(input, 20); + scene.idle(7); + Object second = new Object(); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, second, depotBounds.offset(0, 2, 1), 100); + scene.idle(25); + scene.overlay.showControls(input, 30); + scene.idle(7); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, second, depotBounds.offset(0, 2, 1), 280); + scene.overlay.showText(70) + .colored(PonderPalette.OUTPUT) + .text("Right-Click again to toggle between Input (Blue) and Output (Orange)") + .pointAt(util.vector.blockSurface(outputDepot, Direction.WEST)) + .placeNearTarget(); + + scene.idle(80); + scene.world.showSection(util.select.position(1, 1, 0), Direction.DOWN); + scene.idle(15); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(1, 1, 0), 43); + + scene.overlay.showText(50) + .colored(PonderPalette.WHITE) + .text("Left-Click components to remove their Selection") + .pointAt(util.vector.blockSurface(util.grid.at(1, 1, 0), Direction.WEST)) + .placeNearTarget(); + + scene.idle(35); + scene.overlay + .showControls(new InputWindowElement(util.vector.topOf(util.grid.at(1, 1, 0)), Pointing.DOWN).leftClick() + .withItem(armItem), 30); + scene.idle(50); + + scene.world.showSection(armSel, Direction.DOWN); + scene.idle(10); + Vector3d armTop = armSurface.add(0.5, 1.5, 0); + scene.overlay.showText(70) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .text("Once placed, the Mechanical Arm will target the blocks selected previously") + .pointAt(armTop) + .placeNearTarget(); + scene.idle(80); + + scene.effects.indicateSuccess(armPos); + scene.world.showSection(util.select.fromTo(2, 1, 5, 2, 1, 3) + .add(util.select.position(2, 0, 5)), Direction.DOWN); + ItemStack copper = AllItems.COPPER_INGOT.asStack(); + scene.world.createItemOnBeltLike(inputDepot, Direction.SOUTH, copper); + scene.idle(10); + + scene.world.setKineticSpeed(armSel, -48); + scene.idle(20); + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 0); + scene.idle(24); + scene.world.removeItemsFromBelt(inputDepot); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, copper, -1); + scene.idle(20); + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, copper, 0); + scene.idle(24); + scene.world.createItemOnBeltLike(outputDepot, Direction.UP, copper); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, ItemStack.EMPTY, -1); + scene.idle(44); + + scene.world.showSection(util.select.fromTo(1, 1, 4, 1, 3, 4), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(4, 1, 2), Direction.DOWN); + scene.idle(5); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, new Object(), depotBounds.offset(0, 2, 1), 60); + scene.idle(5); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(4, 2, 1), 60); + scene.idle(5); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, new Object(), depotBounds.offset(1, 1, 0), 60); + scene.idle(5); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(1, 3, 4), 60); + scene.idle(5); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, new Object(), depotBounds.offset(4, 1, 2), 60); + scene.idle(5); + + scene.overlay.showText(80) + .attachKeyFrame() + .text("They can have any amount of in- and outputs within their range") + .pointAt(util.vector.blockSurface(util.grid.at(1, 3, 4), Direction.WEST)) + .placeNearTarget(); + + inputDepot = util.grid.at(1, 3, 4); + outputDepot = util.grid.at(1, 1, 0); + copper = AllBlocks.COPPER_BLOCK.asStack(); + scene.world.createItemOnBeltLike(inputDepot, Direction.SOUTH, copper); + scene.idle(20); + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 2); + scene.idle(24); + scene.world.removeItemsFromBelt(inputDepot); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, copper, -1); + scene.idle(20); + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, copper, 2); + scene.idle(24); + scene.world.createItemOnBeltLike(outputDepot, Direction.UP, copper); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, ItemStack.EMPTY, -1); + + scene.world.hideSection(util.select.fromTo(4, 2, 1, 4, 1, 1), Direction.UP); + scene.idle(2); + scene.world.hideSection(util.select.fromTo(1, 1, 4, 1, 3, 4), Direction.UP); + scene.idle(5); + scene.world.hideSection(util.select.fromTo(0, 1, 1, 0, 2, 1), Direction.UP); + scene.idle(2); + scene.world.hideSection(util.select.position(1, 1, 0), Direction.UP); + scene.idle(5); + scene.world.hideSection(util.select.position(4, 1, 2), Direction.UP); + scene.idle(15); + + scene.world.showSection(util.select.fromTo(4, 1, 3, 4, 2, 3), Direction.NORTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(0, 1, 3, 0, 2, 3), Direction.NORTH); + scene.idle(15); + + Object in = new Object(); + Object out = new Object(); + AxisAlignedBB chestBounds = new AxisAlignedBB(1 / 16f, 0, 1 / 16f, 15 / 16f, 14 / 16f, 15 / 16f); + AxisAlignedBB funnelBounds = new AxisAlignedBB(0, 0, 8 / 16f, 16 / 16f, 16 / 16f, 16 / 16f); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, in, chestBounds.offset(4, 2, 3), 120); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, out, chestBounds.offset(0, 2, 3), 120); + scene.overlay.showText(80) + .attachKeyFrame() + .text("However, not every type of Inventory can be interacted with directly") + .colored(PonderPalette.RED) + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(0, 2, 3), Direction.WEST)); + scene.idle(90); + + scene.world.showSection(util.select.fromTo(4, 1, 2, 4, 2, 2), Direction.SOUTH); + scene.idle(5); + scene.world.showSection(util.select.position(0, 2, 2), Direction.SOUTH); + scene.idle(10); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, in, depotBounds.offset(4, 1, 2), 80); + scene.idle(5); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, out, funnelBounds.offset(0, 2, 2), 80); + scene.idle(5); + + scene.overlay.showText(60) + .text("Funnels and Depots can help to Bridge that gap") + .colored(PonderPalette.OUTPUT) + .placeNearTarget() + .pointAt(util.vector.topOf(util.grid.at(0, 2, 2)) + .add(0, 0, 0.25)); + scene.idle(70); + ItemStack sword = new ItemStack(Items.GOLDEN_SWORD); + inputDepot = util.grid.at(4, 1, 2); + scene.overlay + .showControls(new InputWindowElement(util.vector.topOf(inputDepot), Pointing.RIGHT).withItem(sword), 30); + scene.world.createItemOnBeltLike(inputDepot, Direction.SOUTH, sword); + + scene.idle(20); + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 1); + scene.idle(24); + scene.world.removeItemsFromBelt(inputDepot); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, sword, -1); + scene.idle(20); + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, sword, 1); + scene.idle(24); + scene.world.flapFunnel(util.grid.at(0, 2, 2), false); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, ItemStack.EMPTY, -1); + scene.idle(5); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(0, 2, 3), Direction.WEST), Pointing.LEFT) + .withItem(sword), + 30); + + } + + public static void filtering(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_arm_filtering", "Filtering Outputs of the Mechanical Arm"); + scene.configureBasePlate(0, 0, 6); + scene.scaleSceneView(0.9f); + scene.world.setKineticSpeed(util.select.fromTo(4, 1, 4, 6, 0, 5), 0); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(10); + scene.world.showSection(util.select.fromTo(4, 1, 4, 5, 1, 5), Direction.DOWN); + scene.idle(10); + + for (int x = 0; x < 2; x++) { + scene.idle(3); + scene.world.showSection(util.select.position(x + 1, 1, 4), Direction.DOWN); + } + + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + scene.world.showSection(util.select.position(y == 1 ? x + 3 : 5 - x, y + 1, 1), Direction.DOWN); + scene.idle(2); + } + } + scene.world.showSection(util.select.position(2, 1, 1), Direction.EAST); + + ItemStack sand = new ItemStack(Items.SAND, 64); + ItemStack sulphur = new ItemStack(Items.GUNPOWDER, 64); + scene.world.createItemOnBeltLike(util.grid.at(2, 1, 4), Direction.SOUTH, sand); + scene.world.createItemOnBeltLike(util.grid.at(1, 1, 4), Direction.SOUTH, sulphur); + + scene.overlay.showSelectionWithText(util.select.fromTo(2, 1, 4, 1, 1, 4), 60) + .text("Inputs") + .placeNearTarget() + .colored(PonderPalette.INPUT); + scene.idle(50); + scene.overlay.showSelectionWithText(util.select.fromTo(5, 3, 1, 3, 1, 1), 40) + .text("Outputs") + .placeNearTarget() + .colored(PonderPalette.OUTPUT); + scene.idle(50); + + scene.overlay.showText(80) + .attachKeyFrame() + .text("Sometimes it is desirable to restrict targets of the Arm by matching a filter") + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(3, 3, 1), Direction.WEST)); + + scene.idle(90); + scene.rotateCameraY(-90 - 30); + scene.idle(20); + + scene.overlay.showSelectionWithText(util.select.position(4, 1, 4), 80) + .colored(PonderPalette.RED) + .text("Mechanical Arms by themselves do not provide any options for filtering") + .placeNearTarget(); + scene.idle(90); + + for (int y = 0; y < 3; y++) { + scene.world.showSection(util.select.fromTo(5, y + 1, 2, 3, y + 1, 2), Direction.NORTH); + scene.idle(2); + } + + Vector3d filterSlot = util.vector.of(3.5, 3.75, 2.6); + scene.overlay.showFilterSlotInput(filterSlot, 80); + scene.idle(10); + scene.overlay.showText(80) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .pointAt(filterSlot) + .text("Brass Funnels as Targets do however communicate their own filter to the Arm") + .placeNearTarget(); + scene.idle(90); + + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + ItemStack item = (x + y) % 2 == 0 ? sulphur : sand; + scene.overlay + .showControls(new InputWindowElement(filterSlot.add(2 - x, -y, 0), Pointing.LEFT).rightClick() + .withItem(item), 5); + scene.idle(7); + scene.world.setFilterData(util.select.position(5 - x, 3 - y, 2), FunnelTileEntity.class, item); + scene.idle(4); + } + } + + scene.world.setKineticSpeed(util.select.fromTo(4, 1, 4, 6, 0, 5), 24); + scene.world.multiplyKineticSpeed(util.select.position(5, 1, 5), -1); + scene.world.multiplyKineticSpeed(util.select.position(4, 1, 4), 2); + scene.idle(10); + + BlockPos armPos = util.grid.at(4, 1, 4); + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 1); + scene.idle(24); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, sand, -1); + scene.idle(20); + + scene.overlay.showText(80) + .attachKeyFrame() + .pointAt(util.vector.topOf(2, 1, 4)) + .text("The Arm is smart enough not to pick up items it couldn't distribute") + .placeNearTarget(); + scene.idle(90); + + for (int i = 0; i < 4; i++) { + int index = i * 2 + 1; + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, sand, index); + scene.idle(24); + BlockPos funnelPos = util.grid.at(5 - index % 3, 1 + index / 3, 2); + scene.world.flapFunnel(funnelPos, false); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, i == 3 ? ItemStack.EMPTY : sand, -1); + scene.world.modifyTileEntity(funnelPos.north(), MechanicalCrafterTileEntity.class, mct -> mct.getInventory() + .insertItem(0, sand.copy(), false)); + scene.idle(10); + } + + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 0); + scene.idle(24); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, sulphur, -1); + scene.idle(20); + + scene.rotateCameraY(120); + scene.world.setCraftingResult(util.grid.at(3, 1, 1), new ItemStack(Blocks.TNT)); + + for (int i = 0; i < 5; i++) { + int index = i * 2; + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, sulphur, index); + scene.idle(24); + BlockPos funnelPos = util.grid.at(3 + index % 3, 1 + index / 3, 2); + scene.world.flapFunnel(funnelPos, false); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, i == 4 ? ItemStack.EMPTY : sulphur, -1); + scene.world.modifyTileEntity(funnelPos.north(), MechanicalCrafterTileEntity.class, mct -> mct.getInventory() + .insertItem(0, sulphur.copy(), false)); + scene.idle(10); + } + + scene.idle(120); + } + + public static void modes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_arm_modes", "Distribution modes of the Mechanical Arm"); + scene.configureBasePlate(0, 1, 5); + scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.BARRIER.getDefaultState(), false); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 4, 4, 1, 5), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 1, 4, 1, 2, 5), Direction.NORTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 1, 1, 5, 1, 2), Direction.SOUTH); + scene.idle(10); + + AxisAlignedBB depotBox = AllShapes.DEPOT.getBoundingBox(); + AxisAlignedBB beltBox = depotBox.contract(0, -3 / 16f, 0) + .grow(1, 0, 0); + BlockPos depotPos = util.grid.at(1, 1, 4); + BlockPos armPos = util.grid.at(3, 1, 4); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.INPUT, depotBox, depotBox.offset(1, 1, 4), 60); + scene.overlay.showText(30) + .text("Input") + .pointAt(util.vector.blockSurface(depotPos, Direction.WEST)) + .placeNearTarget() + .colored(PonderPalette.INPUT); + scene.idle(40); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.OUTPUT, depotBox, beltBox.offset(2, 1, 2), 40); + scene.overlay.showText(40) + .text("Outputs") + .pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.WEST)) + .placeNearTarget() + .colored(PonderPalette.OUTPUT); + scene.idle(50); + + ItemStack item = new ItemStack(Items.SNOWBALL); + + scene.world.createItemOnBeltLike(depotPos, Direction.SOUTH, item); + scene.overlay.showText(60) + .attachKeyFrame() + .text("Whenever an Arm has to choose between multiple valid outputs...") + .pointAt(util.vector.blockSurface(util.grid.at(2, 1, 2), Direction.UP)) + .placeNearTarget() + .colored(PonderPalette.OUTPUT); + scene.idle(70); + + Vector3d scrollSlot = util.vector.of(3.5, 1.25, 4); + scene.overlay.showFilterSlotInput(scrollSlot, 120); + scene.overlay.showText(50) + .text("...it will act according to its setting") + .pointAt(scrollSlot) + .placeNearTarget(); + scene.idle(60); + + scene.overlay.showControls(new InputWindowElement(scrollSlot, Pointing.RIGHT).scroll() + .withWrench(), 40); + scene.idle(10); + scene.overlay.showText(50) + .text("Scrolling with a Wrench will allow you to configure it") + .pointAt(scrollSlot) + .placeNearTarget(); + scene.idle(60); + + ElementLink blockage = + scene.world.showIndependentSection(util.select.position(4, 1, 0), Direction.UP); + scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 0); + + for (int i = 0; i < 20; i++) { + + if (i == 2) { + scene.overlay.showText(60) + .attachKeyFrame() + .text("Round Robin mode simply cycles through all outputs that are available") + .pointAt(util.vector.blockSurface(util.grid.at(2, 1, 2), Direction.UP)) + .placeNearTarget() + .colored(PonderPalette.OUTPUT); + } + if (i == 6) + continue; + if (i == 7) { + scene.overlay.showText(60) + .attachKeyFrame() + .text("If an output is unable to take more items, it will be skipped") + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.UP)) + .placeNearTarget() + .colored(PonderPalette.GREEN); + } + + if (i == 12) { + scene.world.moveSection(blockage, util.vector.of(-1, 0, 0), 10); + scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.BARRIER.getDefaultState(), false); + } + + int index = i % 3; + + if (i == 13) { + scene.world.setBlock(util.grid.at(2, 1, 0), Blocks.BARRIER.getDefaultState(), false); + ElementLink blockage2 = + scene.world.showIndependentSection(util.select.position(4, 1, 0), Direction.UP); + scene.world.moveSection(blockage2, util.vector.of(-2, 0, 0), 0); + scene.overlay.showText(60) + .attachKeyFrame() + .text("Prefer First prioritizes the outputs selected earliest when configuring this Arm") + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.UP)) + .placeNearTarget() + .colored(PonderPalette.GREEN); + index = 0; + } + + if (i == 14) + index = 1; + if (i == 15) + index = 1; + if (i >= 16) + index = 2; + + scene.idle(5); + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 0); + scene.idle(12); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, item, -1); + scene.world.removeItemsFromBelt(depotPos); + scene.idle(5); + + if (i == 9) { + scene.overlay.showText(80) + .attachKeyFrame() + .text("Forced Round Robin mode will never skip outputs, and instead wait until they are free") + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.UP)) + .placeNearTarget() + .colored(PonderPalette.RED); + scene.idle(40); + scene.world.moveSection(blockage, util.vector.of(1, 0, 0), 10); + scene.world.setBlock(util.grid.at(3, 1, 0), Blocks.AIR.getDefaultState(), false); + scene.idle(50); + scene.world.multiplyKineticSpeed(util.select.fromTo(1, 1, 1, 5, 0, 3), 2); + } + + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, item, index); + scene.world.createItemOnBeltLike(depotPos, Direction.SOUTH, item); + scene.idle(12); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, ItemStack.EMPTY, -1); + scene.world.createItemOnBelt(util.grid.at(3 - index, 1, 2), Direction.UP, item); + } + + } + + public static void redstone(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_arm_redstone", "Controlling Mechanical Arms with Redstone"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 1, 3, 2, 1, 4), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 5, 4, 1, 3), Direction.WEST); + scene.idle(5); + scene.world.showSection(util.select.position(4, 1, 2), Direction.SOUTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(2, 1, 1, 4, 1, 1), Direction.EAST); + scene.idle(10); + Selection redstone = util.select.fromTo(1, 1, 0, 1, 1, 2); + scene.world.showSection(redstone, Direction.SOUTH); + + BlockPos armPos = util.grid.at(1, 1, 3); + BlockPos leverPos = util.grid.at(1, 1, 0); + ItemStack item = new ItemStack(Items.REDSTONE_ORE); + + scene.world.createItemOnBeltLike(util.grid.at(4, 1, 1), Direction.SOUTH, item); + + for (int i = 0; i < 3; i++) { + scene.idle(12); + + if (i == 1) { + scene.world.toggleRedstonePower(redstone); + scene.effects.indicateRedstone(leverPos); + scene.idle(10); + + scene.overlay.showText(60) + .colored(PonderPalette.RED) + .attachKeyFrame() + .pointAt(util.vector.topOf(armPos.up())) + .placeNearTarget() + .text("When powered by Redstone, Mechanical Arms will not activate"); + scene.idle(70); + scene.world.toggleRedstonePower(redstone); + } + + if (i == 2) { + scene.idle(60); + scene.world.toggleRedstonePower(redstone); + scene.idle(3); + scene.world.toggleRedstonePower(redstone); + scene.effects.indicateRedstone(leverPos); + } + + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 0); + scene.idle(18); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, item, -1); + scene.world.removeItemsFromBelt(util.grid.at(3, 1, 1)); + scene.idle(5); + + if (i == 1) { + scene.world.toggleRedstonePower(redstone); + scene.effects.indicateRedstone(leverPos); + scene.overlay.showText(60) + .pointAt(util.vector.topOf(armPos.up())) + .placeNearTarget() + .text("Before stopping, it will finish any started cycles"); + } + + scene.idle(10); + + if (i == 2) { + scene.overlay.showText(100) + .colored(PonderPalette.GREEN) + .attachKeyFrame() + .pointAt(util.vector.topOf(armPos.up())) + .placeNearTarget() + .text("Thus, a negative pulse can be used to trigger exactly one activation cycle"); + } + + scene.world.instructArm(armPos, Phase.MOVE_TO_OUTPUT, item, 0); + scene.world.createItemOnBeltLike(util.grid.at(4, 1, 1), Direction.SOUTH, item); + scene.idle(18); + scene.world.instructArm(armPos, Phase.SEARCH_INPUTS, ItemStack.EMPTY, -1); + scene.world.createItemOnBelt(util.grid.at(3, 1, 3), Direction.UP, item); + } + + scene.idle(5); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java index 8cd5baa56..843f8a622 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.ponder.content; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.actors.HarvesterTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlock; +import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.foundation.ponder.ElementLink; import com.simibubi.create.foundation.ponder.SceneBuilder; import com.simibubi.create.foundation.ponder.SceneBuildingUtil; @@ -12,6 +13,10 @@ import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Pointing; +import net.minecraft.entity.Entity; +import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; @@ -23,7 +28,7 @@ public class BearingScenes { scene.title("windmill_source", "Generating Rotational Force using Windmill Bearings"); scene.configureBasePlate(1, 1, 5); scene.setSceneOffsetY(-1); - + scene.world.showSection(util.select.fromTo(1, 0, 1, 5, 0, 5), Direction.UP); scene.world.setBlock(util.grid.at(2, -1, 0), AllBlocks.SAIL.getDefaultState() .with(SailBlock.FACING, Direction.NORTH), false); @@ -149,6 +154,7 @@ public class BearingScenes { scene.title("windmill_structure", "Windmill Contraptions"); scene.configureBasePlate(1, 1, 5); scene.setSceneOffsetY(-1); + scene.world.modifyEntities(SuperGlueEntity.class, Entity::remove); scene.world.showSection(util.select.layer(0), Direction.UP); scene.idle(5); @@ -277,7 +283,7 @@ public class BearingScenes { scene.title("bearing_modes", "Movement Modes of the Mechanical Bearing"); scene.configureBasePlate(1, 1, 6); scene.setSceneOffsetY(-1); - + Selection sideCog = util.select.position(util.grid.at(7, 0, 3)); Selection cogColumn = util.select.fromTo(6, 1, 3, 6, 4, 3); Selection cogAndClutch = util.select.fromTo(5, 3, 1, 5, 4, 2); @@ -563,4 +569,116 @@ public class BearingScenes { } } + public static void sail(SceneBuilder scene, SceneBuildingUtil util) { + sails(scene, util, false); + } + + public static void sailFrame(SceneBuilder scene, SceneBuildingUtil util) { + sails(scene, util, true); + } + + private static void sails(SceneBuilder scene, SceneBuildingUtil util, boolean frame) { + String plural = frame ? "Sail Frames" : "Sails"; + scene.title(frame ? "sail_frame" : "sail", "Assembling Windmills using " + plural); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(0.9f); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + BlockPos bearingPos = util.grid.at(2, 1, 2); + scene.world.showSection(util.select.position(bearingPos), Direction.DOWN); + scene.idle(5); + ElementLink plank = + scene.world.showIndependentSection(util.select.position(bearingPos.up()), Direction.DOWN); + scene.idle(10); + + for (int i = 0; i < 3; i++) { + for (Direction d : Iterate.horizontalDirections) { + BlockPos location = bearingPos.up(i + 1) + .offset(d); + if (frame) + scene.world.modifyBlock(location, s -> AllBlocks.SAIL_FRAME.getDefaultState() + .with(SailBlock.FACING, s.get(SailBlock.FACING)), false); + scene.world.showSectionAndMerge(util.select.position(location), d.getOpposite(), plank); + scene.idle(2); + } + } + + scene.overlay.showText(70) + .text(plural + " are handy blocks to create Windmills with") + .pointAt(util.vector.blockSurface(util.grid.at(1, 3, 2), Direction.WEST)) + .placeNearTarget() + .attachKeyFrame(); + scene.idle(80); + + scene.overlay.showSelectionWithText(util.select.position(bearingPos.up()), 80) + .colored(PonderPalette.GREEN) + .text("They will attach to blocks and each other without the need of Super Glue or Chassis Blocks") + .attachKeyFrame() + .placeNearTarget(); + scene.idle(40); + scene.world.configureCenterOfRotation(plank, util.vector.centerOf(bearingPos)); + + if (!frame) { + scene.world.rotateBearing(bearingPos, 180, 75); + scene.world.rotateSection(plank, 0, 180, 0, 75); + scene.idle(76); + scene.world.rotateBearing(bearingPos, 180, 0); + scene.world.rotateSection(plank, 0, 180, 0, 0); + scene.rotateCameraY(-30); + scene.idle(10); + InputWindowElement input = + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.NORTH), Pointing.RIGHT) + .withItem(new ItemStack(Items.BLUE_DYE)); + scene.overlay.showControls(input, 30); + scene.idle(7); + scene.world.setBlock(util.grid.at(2, 3, 1), AllBlocks.DYED_SAILS[DyeColor.BLUE.ordinal()].getDefaultState() + .with(SailBlock.FACING, Direction.WEST), false); + scene.idle(10); + scene.overlay.showText(40) + .colored(PonderPalette.BLUE) + .text("Right-Click with Dye to paint them") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.WEST)) + .placeNearTarget(); + scene.idle(20); + scene.overlay.showControls(input, 30); + scene.idle(7); + scene.world.replaceBlocks(util.select.fromTo(2, 2, 1, 2, 4, 1), + AllBlocks.DYED_SAILS[DyeColor.BLUE.ordinal()].getDefaultState() + .with(SailBlock.FACING, Direction.WEST), + false); + + scene.idle(20); + scene.world.rotateBearing(bearingPos, 90, 33); + scene.world.rotateSection(plank, 0, 90, 0, 33); + scene.idle(40); + + input = + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.NORTH), Pointing.RIGHT) + .withItem(new ItemStack(Items.SHEARS)); + + scene.overlay.showControls(input, 30); + scene.idle(7); + scene.world.setBlock(util.grid.at(3, 3, 2), AllBlocks.SAIL_FRAME.getDefaultState() + .with(SailBlock.FACING, Direction.NORTH), false); + scene.idle(10); + scene.overlay.showText(40) + .text("Right-Click with Shears to turn them back into frames") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.WEST)) + .placeNearTarget(); + scene.idle(20); + scene.overlay.showControls(input, 30); + scene.idle(7); + scene.world.replaceBlocks(util.select.fromTo(3, 2, 2, 3, 4, 2), AllBlocks.SAIL_FRAME.getDefaultState() + .with(SailBlock.FACING, Direction.NORTH), false); + scene.idle(20); + } + + scene.world.rotateBearing(bearingPos, 720, 300); + scene.world.rotateSection(plank, 0, 720, 0, 300); + + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java index bc5bea25f..0a5f454b9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java @@ -6,10 +6,14 @@ import java.util.List; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode; +import com.simibubi.create.content.contraptions.fluids.actors.SpoutTileEntity; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltPart; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; +import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; import com.simibubi.create.foundation.ponder.ElementLink; import com.simibubi.create.foundation.ponder.SceneBuilder; import com.simibubi.create.foundation.ponder.SceneBuildingUtil; @@ -23,6 +27,7 @@ import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.Pointing; +import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.DyeColor; @@ -299,7 +304,7 @@ public class BeltScenes { scene.idle(10); scene.overlay.showText(160) - .text("These are all possible directions.\nBelts can span any Length between 2 and 20 blocks"); + .text("These are all possible directions. Belts can span any Length between 2 and 20 blocks"); scene.markAsFinished(); } @@ -461,4 +466,112 @@ public class BeltScenes { .pointAt(util.vector.blockSurface(beltPos.south(), Direction.WEST)); } + public static void depot(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("depot", "Using Depots"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + scene.idle(5); + scene.world.setBlock(util.grid.at(3, 2, 2), Blocks.WATER.getDefaultState(), false); + + BlockPos depotPos = util.grid.at(2, 1, 2); + scene.world.showSection(util.select.position(2, 1, 2), Direction.DOWN); + Vector3d topOf = util.vector.topOf(depotPos); + scene.overlay.showText(60) + .attachKeyFrame() + .text("Depots can serve as 'stationary' belt elements") + .placeNearTarget() + .pointAt(topOf); + scene.idle(70); + + scene.overlay.showControls(new InputWindowElement(topOf, Pointing.DOWN).rightClick() + .withItem(AllBlocks.COPPER_BLOCK.asStack()), 20); + scene.idle(7); + scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, AllBlocks.COPPER_BLOCK.asStack()); + scene.idle(10); + scene.overlay.showText(70) + .attachKeyFrame() + .text("Right-Click to manually place or remove Items from it") + .placeNearTarget() + .pointAt(topOf); + scene.idle(80); + + scene.overlay.showControls(new InputWindowElement(topOf, Pointing.DOWN).rightClick(), 20); + scene.idle(7); + scene.world.removeItemsFromBelt(depotPos); + scene.effects.indicateSuccess(depotPos); + scene.idle(20); + + scene.world.showSection(util.select.position(depotPos.up(2)), Direction.SOUTH); + scene.overlay.showText(70) + .attachKeyFrame() + .text("Just like Mechanical Belts, it can provide items to processing") + .placeNearTarget() + .pointAt(util.vector.blockSurface(depotPos.up(2), Direction.WEST)); + ItemStack bottle = new ItemStack(Items.BUCKET); + scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, bottle); + scene.idle(20); + scene.world.modifyTileNBT(util.select.position(depotPos.up(2)), SpoutTileEntity.class, + nbt -> nbt.putInt("ProcessingTicks", 20)); + scene.idle(20); + scene.world.removeItemsFromBelt(depotPos); + scene.world.createItemOnBeltLike(depotPos, Direction.UP, new ItemStack(Items.WATER_BUCKET)); + scene.world.modifyTileNBT(util.select.position(depotPos.up(2)), SpoutTileEntity.class, + nbt -> nbt.putBoolean("Splash", true)); + scene.idle(30); + scene.world.removeItemsFromBelt(depotPos); + scene.world.hideSection(util.select.position(depotPos.up(2)), Direction.SOUTH); + scene.idle(20); + ElementLink spout = scene.world.showIndependentSection(util.select.position(depotPos.up(2) + .west()), Direction.SOUTH); + scene.world.moveSection(spout, util.vector.of(1, 0, 0), 0); + + BlockPos pressPos = depotPos.up(2) + .west(); + ItemStack copper = AllItems.COPPER_INGOT.asStack(); + scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, copper); + Vector3d depotCenter = util.vector.centerOf(depotPos); + scene.idle(10); + + Class type = MechanicalPressTileEntity.class; + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT)); + scene.idle(15); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper)); + scene.world.removeItemsFromBelt(depotPos); + ItemStack sheet = AllItems.COPPER_SHEET.asStack(); + scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet); + + scene.idle(20); + scene.world.hideIndependentSection(spout, Direction.SOUTH); + scene.idle(10); + + Selection fanSelect = util.select.fromTo(4, 1, 3, 5, 2, 2) + .add(util.select.position(3, 1, 2)) + .add(util.select.position(5, 0, 2)); + scene.world.showSection(fanSelect, Direction.SOUTH); + ElementLink water = + scene.world.showIndependentSection(util.select.position(3, 1, 0), Direction.SOUTH); + scene.world.moveSection(water, util.vector.of(0, 1, 2), 0); + scene.idle(30); + + scene.world.hideSection(fanSelect, Direction.SOUTH); + scene.world.hideIndependentSection(water, Direction.SOUTH); + scene.idle(30); + + scene.world.showSection(util.select.fromTo(2, 1, 4, 2, 1, 5) + .add(util.select.position(2, 0, 5)), Direction.DOWN); + BlockPos armPos = util.grid.at(2, 1, 4); + scene.overlay.showText(70) + .attachKeyFrame() + .text("...as well as provide Items to Mechanical Arms") + .placeNearTarget() + .pointAt(util.vector.blockSurface(armPos, Direction.WEST)); + scene.idle(20); + + scene.world.instructArm(armPos, Phase.MOVE_TO_INPUT, ItemStack.EMPTY, 0); + scene.idle(37); + scene.world.removeItemsFromBelt(depotPos); + scene.world.instructArm(armPos, Phase.SEARCH_OUTPUTS, sheet, -1); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java index 60915ee5c..51616a4bf 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/CartAssemblerScenes.java @@ -237,7 +237,7 @@ public class CartAssemblerScenes { scene.world.hideIndependentSection(contraption, Direction.UP); scene.world.hideIndependentSection(anchor, Direction.UP); - scene.overlay.hideElement(cart, Direction.UP); + scene.special.hideElement(cart, Direction.UP); scene.idle(25); Vector3d blockSurface = util.vector.blockSurface(assemblerPos, Direction.NORTH) @@ -440,7 +440,7 @@ public class CartAssemblerScenes { scene.world.moveSection(anchor, util.vector.of(-2, 0, 0), 10); scene.special.moveCart(cart, util.vector.of(-5, 0, 0), 25); scene.idle(30); - scene.overlay.hideElement(cart, Direction.UP); + scene.special.hideElement(cart, Direction.UP); scene.world.hideIndependentSection(contraption, Direction.UP); scene.world.moveSection(anchor, util.vector.of(0, -3, 0), 0); scene.idle(30); @@ -482,7 +482,7 @@ public class CartAssemblerScenes { scene.special.moveCart(cart, util.vector.of(-3, 0, 0), 15); scene.idle(30); - scene.overlay.hideElement(cart, Direction.UP); + scene.special.hideElement(cart, Direction.UP); scene.world.hideIndependentSection(anchor, Direction.UP); scene.world.hideIndependentSection(contraption, Direction.UP); scene.idle(20); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java new file mode 100644 index 000000000..0c168ee13 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ChuteScenes.java @@ -0,0 +1,265 @@ +package com.simibubi.create.foundation.ponder.content; + +import static com.simibubi.create.content.logistics.block.chute.ChuteBlock.SHAPE; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.logistics.block.chute.ChuteBlock; +import com.simibubi.create.content.logistics.block.chute.ChuteBlock.Shape; +import com.simibubi.create.content.logistics.block.chute.SmartChuteTileEntity; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.EntityElement; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; + +public class ChuteScenes { + + public static void downward(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("chute", "Transporting Items downward via Chutes"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(.9f); + scene.world.showSection(util.select.layer(0), Direction.UP); + + ElementLink top = + scene.world.showIndependentSection(util.select.fromTo(3, 3, 3, 3, 4, 3), Direction.DOWN); + ElementLink bottom = + scene.world.showIndependentSection(util.select.fromTo(3, 2, 3, 3, 1, 3), Direction.DOWN); + scene.world.moveSection(bottom, util.vector.of(-2, 0, -1), 0); + scene.world.moveSection(top, util.vector.of(0, 0, -1), 0); + scene.idle(20); + + ItemStack stack = AllBlocks.COPPER_BLOCK.asStack(); + scene.world.createItemEntity(util.vector.centerOf(util.grid.at(3, 3, 2)), util.vector.of(0, -0.1, 0), stack); + scene.idle(20); + ElementLink remove = + scene.world.createItemEntity(util.vector.centerOf(util.grid.at(1, 5, 2)), util.vector.of(0, 0.1, 0), stack); + scene.idle(15); + scene.world.modifyEntity(remove, Entity::remove); + + scene.overlay.showText(60) + .attachKeyFrame() + .pointAt(util.vector.topOf(util.grid.at(1, 2, 2))) + .placeNearTarget() + .text("Chutes can transport items vertically from and to inventories"); + scene.idle(70); + scene.world.modifyEntities(ItemEntity.class, Entity::remove); + scene.world.moveSection(bottom, util.vector.of(1, 0, 0), 10); + scene.world.moveSection(top, util.vector.of(-1, 0, 0), 10); + scene.idle(20); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.NORTH), Pointing.RIGHT) + .rightClick() + .withWrench(), + 40); + scene.idle(7); + scene.world.modifyBlock(util.grid.at(3, 3, 3), s -> s.with(ChuteBlock.SHAPE, ChuteBlock.Shape.WINDOW), false); + scene.overlay.showText(50) + .attachKeyFrame() + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.WEST)) + .placeNearTarget() + .text("Using the Wrench, a window can be created"); + + scene.idle(10); + scene.world.modifyBlock(util.grid.at(3, 2, 3), s -> s.with(SHAPE, Shape.WINDOW), false); + + for (int i = 0; i < 8; i++) { + scene.idle(10); + scene.world.createItemOnBeltLike(util.grid.at(3, 3, 3), Direction.UP, stack); + } + scene.idle(20); + scene.world.hideIndependentSection(bottom, Direction.EAST); + scene.world.hideIndependentSection(top, Direction.EAST); + scene.idle(15); + + scene.rotateCameraY(-90); + scene.world.modifyBlock(util.grid.at(2, 2, 1), s -> s.with(SHAPE, Shape.NORMAL), false); + scene.world.showSection(util.select.fromTo(2, 1, 1, 2, 2, 1), Direction.DOWN); + scene.idle(30); + ItemStack chuteItem = AllBlocks.CHUTE.asStack(); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 2, 1), Direction.SOUTH), Pointing.LEFT) + .rightClick() + .withItem(chuteItem), + 30); + scene.idle(7); + scene.world.showSection(util.select.position(2, 3, 2), Direction.NORTH); + scene.world.restoreBlocks(util.select.position(2, 2, 1)); + scene.idle(35); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.SOUTH), Pointing.LEFT) + .rightClick() + .withItem(chuteItem), + 30); + scene.idle(7); + scene.world.showSection(util.select.position(2, 4, 3), Direction.NORTH); + scene.idle(35); + + scene.overlay.showText(70) + .attachKeyFrame() + .pointAt(util.vector.blockSurface(util.grid.at(2, 4, 3), Direction.WEST)) + .placeNearTarget() + .text("Placing chutes targeting the side faces of another will make it diagonal"); + scene.idle(15); + scene.rotateCameraY(90); + + scene.idle(35); + + Direction offset = Direction.NORTH; + for (int i = 0; i < 3; i++) { + remove = scene.world.createItemEntity(util.vector.centerOf(util.grid.at(2, 6, 3) + .offset(offset)), util.vector.of(0, 0.1, 0) + .add(Vector3d.of(offset.getDirectionVec()).scale(-.1)), + stack); + scene.idle(12); + scene.world.createItemOnBeltLike(util.grid.at(2, 4, 3), Direction.UP, stack); + scene.world.modifyEntity(remove, Entity::remove); + scene.idle(3); + offset = offset.rotateY(); + } + + scene.idle(10); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 1, 1), Direction.NORTH), Pointing.RIGHT) + .withItem(stack), + 50); + } + + public static void upward(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("chute_upward", "Transporting Items upward via Chutes"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(.9f); + scene.showBasePlate(); + Selection chute = util.select.fromTo(1, 2, 2, 1, 4, 2); + scene.world.setBlocks(chute, Blocks.AIR.getDefaultState(), false); + scene.world.showSection(util.select.position(1, 1, 2), Direction.UP); + scene.idle(20); + + scene.world.restoreBlocks(chute); + scene.world.showSection(chute, Direction.DOWN); + scene.idle(20); + scene.world.setKineticSpeed(util.select.position(1, 1, 2), 0); + Vector3d surface = util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.WEST); + scene.overlay.showText(70) + .text("Using Encased Fans at the top or bottom, a Chute can move items upward") + .attachKeyFrame() + .pointAt(surface) + .placeNearTarget(); + scene.idle(80); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.NORTH), Pointing.RIGHT) + .withItem(AllItems.GOGGLES.asStack()), + 50); + scene.overlay.showText(70) + .text("Inspecting chutes with Engineers' Goggles reveals information about the movement direction") + .attachKeyFrame() + .pointAt(surface) + .placeNearTarget(); + scene.idle(80); + + scene.world.showSection(util.select.fromTo(2, 2, 2, 4, 1, 5) + .add(util.select.position(3, 0, 5)), Direction.DOWN); + ItemStack stack = AllBlocks.COPPER_BLOCK.asStack(); + scene.world.createItemOnBelt(util.grid.at(4, 1, 2), Direction.EAST, stack); + scene.idle(10); + scene.rotateCameraY(60); + scene.overlay.showText(70) + .text("On the 'blocked' end, items will have to be inserted/taken from the sides") + .attachKeyFrame() + .pointAt(util.vector.centerOf(util.grid.at(3, 1, 2)) + .add(0, 3 / 16f, 0)) + .placeNearTarget(); + scene.idle(32); + scene.world.flapFunnel(util.grid.at(2, 2, 2), false); + scene.world.removeItemsFromBelt(util.grid.at(2, 1, 2)); + scene.world.createItemOnBeltLike(util.grid.at(1, 2, 2), Direction.EAST, stack); + } + + public static void smart(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("smart_chute", "Filtering Items using Smart Chutes"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(.9f); + + Selection lever = util.select.fromTo(0, 1, 2, 1, 3, 2); + BlockPos smarty = util.grid.at(2, 3, 2); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(2, 1, 2, 2, 2, 2), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(2, 3, 2), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(2, 4, 2), Direction.DOWN); + + scene.overlay.showText(60) + .text("Smart Chutes are vertical chutes with additional control") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(smarty, Direction.WEST)) + .placeNearTarget(); + scene.idle(70); + + Vector3d filter = util.vector.blockSurface(smarty, Direction.NORTH) + .add(0, 0.25, 0); + scene.overlay.showFilterSlotInput(filter, 60); + ItemStack copper = new ItemStack(Items.IRON_INGOT); + scene.overlay.showControls(new InputWindowElement(filter, Pointing.DOWN).rightClick() + .withItem(copper), 40); + scene.idle(7); + scene.world.setFilterData(util.select.position(smarty), SmartChuteTileEntity.class, copper); + scene.idle(10); + scene.rotateCameraY(20); + scene.overlay.showText(60) + .text("Items in the filter slot specify what exactly they can extract and transfer") + .attachKeyFrame() + .pointAt(filter) + .placeNearTarget(); + scene.idle(10); + + for (int i = 0; i < 18; i++) { + scene.idle(10); + scene.world.createItemOnBeltLike(util.grid.at(2, 2, 2), Direction.UP, copper); + if (i == 8) { + scene.rotateCameraY(-20); + scene.overlay.showControls(new InputWindowElement(filter, Pointing.DOWN).scroll(), 40); + scene.overlay.showText(50) + .text("Use the Mouse Wheel to specify the extracted stack size") + .attachKeyFrame() + .pointAt(filter) + .placeNearTarget(); + } + if (i == 13) + scene.world.showSection(lever, Direction.NORTH); + } + + scene.world.toggleRedstonePower(lever.add(util.select.position(smarty))); + scene.effects.indicateRedstone(util.grid.at(0, 3, 2)); + scene.overlay.showText(50) + .text("Redstone power will prevent Smart Chutes from acting.") + .attachKeyFrame() + .colored(PonderPalette.RED) + .pointAt(util.vector.blockSurface(util.grid.at(0, 2, 2), Direction.UP)) + .placeNearTarget(); + scene.idle(70); + + scene.world.toggleRedstonePower(lever.add(util.select.position(smarty))); + scene.markAsFinished(); + for (int i = 0; i < 8; i++) { + scene.idle(10); + scene.world.createItemOnBeltLike(util.grid.at(2, 2, 2), Direction.UP, copper); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java new file mode 100644 index 000000000..a4da5da9f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/CrafterScenes.java @@ -0,0 +1,453 @@ +package com.simibubi.create.foundation.ponder.content; + +import java.util.Collection; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterBlock; +import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.EntityElement; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.items.ItemHandlerHelper; + +public class CrafterScenes { + + public static void setup(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_crafter", "Setting up Mechanical Crafters"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.world.modifyKineticSpeed(util.select.everywhere(), f -> 1.5f * f); + + Selection redstone = util.select.fromTo(3, 1, 0, 3, 1, 1); + Selection kinetics = util.select.fromTo(4, 1, 2, 4, 1, 5); + BlockPos depotPos = util.grid.at(0, 1, 2); + Selection crafters = util.select.fromTo(1, 1, 2, 3, 3, 2); + + scene.world.modifyBlocks(crafters, s -> s.with(MechanicalCrafterBlock.POINTING, Pointing.DOWN), false); + scene.world.setKineticSpeed(crafters, 0); + + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + scene.world.showSection(util.select.position(y == 1 ? x + 1 : 3 - x, y + 1, 2), Direction.DOWN); + scene.idle(2); + } + } + + scene.overlay.showText(70) + .text("An array of Mechanical Crafters can be used to automate any Crafting Recipe") + .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.WEST)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(80); + + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.NORTH), Pointing.RIGHT) + .rightClick() + .withWrench(), + 40); + scene.idle(7); + scene.world.cycleBlockProperty(util.grid.at(2, 3, 2), MechanicalCrafterBlock.POINTING); + scene.idle(10); + scene.overlay.showText(50) + .text("Using a Wrench, the Crafters' paths can be arranged") + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.NORTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(60); + + BlockPos[] positions = new BlockPos[] { util.grid.at(3, 1, 2), util.grid.at(2, 1, 2), util.grid.at(1, 1, 2) }; + + for (BlockPos pos : positions) { + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(pos, Direction.NORTH), Pointing.RIGHT).rightClick() + .withWrench(), + 10); + scene.idle(7); + scene.world.cycleBlockProperty(pos, MechanicalCrafterBlock.POINTING); + scene.idle(15); + } + + scene.overlay.showText(100) + .text("For a valid setup, all paths have to converge into one exit at any side") + .pointAt(util.vector.blockSurface(util.grid.at(1, 1, 2), Direction.WEST) + .add(0, 0, -.5f)) + .colored(PonderPalette.GREEN) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(60); + + Collection> couples = + ImmutableList.of(Couple.create(util.grid.at(3, 3, 2), util.grid.at(3, 2, 2)), + Couple.create(util.grid.at(3, 2, 2), util.grid.at(3, 1, 2)), + Couple.create(util.grid.at(2, 3, 2), util.grid.at(1, 3, 2)), + Couple.create(util.grid.at(3, 1, 2), util.grid.at(2, 1, 2)), + Couple.create(util.grid.at(1, 3, 2), util.grid.at(1, 2, 2)), + Couple.create(util.grid.at(2, 2, 2), util.grid.at(2, 1, 2)), + Couple.create(util.grid.at(1, 2, 2), util.grid.at(1, 1, 2)), + Couple.create(util.grid.at(2, 1, 2), util.grid.at(1, 1, 2)), + Couple.create(util.grid.at(1, 1, 2), util.grid.at(0, 1, 2))); + + for (Couple c : couples) { + scene.idle(5); + Vector3d p1 = util.vector.blockSurface(c.getFirst(), Direction.NORTH) + .add(0, 0, -0.125); + Vector3d p2 = util.vector.blockSurface(c.getSecond(), Direction.NORTH) + .add(0, 0, -0.125); + AxisAlignedBB point = new AxisAlignedBB(p1, p1); + AxisAlignedBB line = new AxisAlignedBB(p1, p2); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, p1, point, 2); + scene.idle(1); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.GREEN, p1, line, 30); + } + + scene.world.showSection(util.select.position(depotPos), Direction.EAST); + scene.idle(20); + scene.overlay.showText(60) + .text("The outputs will be placed into the inventory at the exit") + .pointAt(util.vector.blockSurface(util.grid.at(0, 1, 2), Direction.NORTH)) + .placeNearTarget(); + scene.idle(70); + + scene.rotateCameraY(60); + scene.idle(20); + scene.world.showSection(kinetics, Direction.NORTH); + scene.overlay.showText(60) + .text("Mechanical Crafters require Rotational Force to operate") + .pointAt(util.vector.blockSurface(util.grid.at(4, 1, 2), Direction.NORTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(8); + scene.world.setKineticSpeed(crafters, -48); + scene.world.multiplyKineticSpeed(util.select.position(3, 2, 2) + .add(util.select.position(2, 3, 2)) + .add(util.select.position(1, 2, 2)) + .add(util.select.position(2, 1, 2)), -1); + scene.idle(55); + scene.rotateCameraY(-60); + + scene.idle(40); + ItemStack planks = new ItemStack(Items.OAK_PLANKS); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(1, 3, 2), Direction.NORTH), Pointing.RIGHT) + .rightClick() + .withItem(planks), + 40); + scene.idle(7); + Class type = MechanicalCrafterTileEntity.class; + scene.world.modifyTileEntity(util.grid.at(1, 3, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + + scene.idle(10); + scene.overlay.showText(50) + .text("Right-Click the front to insert Items manually") + .pointAt(util.vector.blockSurface(util.grid.at(1, 3, 2), Direction.NORTH)) + .attachKeyFrame() + .placeNearTarget(); + scene.idle(60); + + ItemStack alloy = AllItems.ANDESITE_ALLOY.asStack(); + ItemStack log = new ItemStack(Items.OAK_LOG); + + scene.world.setCraftingResult(util.grid.at(1, 1, 2), AllBlocks.ANDESITE_CASING.asStack(4)); + + scene.world.modifyTileEntity(util.grid.at(2, 3, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(3, 3, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(3, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, alloy.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(2, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, log.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(1, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, alloy.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(1, 1, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(2, 1, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(3, 1, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + + scene.overlay.showText(80) + .attachKeyFrame() + .text("Once every slot of a path contains an Item, the crafting process will begin") + .pointAt(util.vector.blockSurface(util.grid.at(1, 3, 2), Direction.WEST)) + .placeNearTarget(); + scene.idle(180); + + scene.world.removeItemsFromBelt(depotPos); + + ItemStack stick = new ItemStack(Items.STICK); + ItemStack iron = new ItemStack(Items.IRON_INGOT); + + scene.world.setCraftingResult(util.grid.at(1, 1, 2), new ItemStack(Items.IRON_PICKAXE)); + + scene.world.modifyTileEntity(util.grid.at(1, 3, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + scene.idle(2); + scene.world.modifyTileEntity(util.grid.at(2, 3, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + scene.idle(2); + scene.world.modifyTileEntity(util.grid.at(3, 3, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + scene.idle(2); + scene.world.modifyTileEntity(util.grid.at(2, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, stick.copy(), false)); + scene.idle(2); + scene.world.modifyTileEntity(util.grid.at(2, 1, 2), type, mct -> mct.getInventory() + .insertItem(0, stick.copy(), false)); + scene.world.showSection(redstone, Direction.SOUTH); + scene.idle(10); + + scene.overlay.showText(90) + .attachKeyFrame() + .colored(PonderPalette.RED) + .text("For recipes not fully occupying the crafter setup, the start can be forced using a Redstone Pulse") + .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.NORTH)) + .placeNearTarget(); + scene.idle(100); + scene.effects.indicateRedstone(util.grid.at(3, 1, 0)); + scene.world.toggleRedstonePower(redstone); + scene.idle(20); + scene.world.toggleRedstonePower(redstone); + } + + public static void connect(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_crafter_connect", "Connecting Inventories of Crafters"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 2; x++) { + scene.world.showSection(util.select.position(y == 1 ? x + 1 : 2 - x, y + 1, 2), Direction.DOWN); + scene.idle(2); + } + } + + Class type = MechanicalCrafterTileEntity.class; + BlockPos depotPos = util.grid.at(0, 1, 2); + Selection funnel = util.select.fromTo(4, 1, 5, 4, 1, 2) + .add(util.select.fromTo(3, 2, 2, 3, 1, 2)); + Selection kinetics = util.select.position(3, 3, 2) + .add(util.select.fromTo(3, 3, 3, 3, 1, 3)); + scene.idle(5); + + scene.world.showSection(kinetics, Direction.NORTH); + scene.idle(5); + scene.world.showSection(util.select.position(depotPos), Direction.EAST); + scene.idle(10); + scene.world.showSection(funnel, Direction.WEST); + scene.rotateCameraY(60); + ItemStack planks = new ItemStack(Items.OAK_PLANKS); + scene.world.createItemOnBelt(util.grid.at(4, 1, 2), Direction.EAST, planks.copy()); + scene.idle(22); + + scene.world.modifyTileEntity(util.grid.at(2, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + scene.world.removeItemsFromBelt(util.grid.at(3, 1, 2)); + scene.world.flapFunnel(util.grid.at(3, 2, 2), false); + + scene.overlay.showSelectionWithText(util.select.position(2, 2, 2), 70) + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH)) + .text("Items can be inserted to Crafters automatically"); + scene.idle(80); + + scene.rotateCameraY(-60 - 90 - 30); + scene.idle(40); + + Vector3d v = util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.WEST); + AxisAlignedBB bb = new AxisAlignedBB(v, v).grow(.125f, .5, .5); + v = v.add(0, 0, .5); + + scene.overlay.chaseBoundingBoxOutline(PonderPalette.WHITE, new Object(), bb, 45); + scene.overlay.showControls(new InputWindowElement(v, Pointing.LEFT).rightClick() + .withWrench(), 40); + scene.idle(7); + scene.world.connectCrafterInvs(util.grid.at(2, 2, 2), util.grid.at(1, 2, 2)); + scene.idle(40); + scene.overlay.showSelectionWithText(util.select.fromTo(2, 2, 2, 1, 2, 2), 70) + .attachKeyFrame() + .placeNearTarget() + .pointAt(v) + .text("Using the Wrench at their backs, Mechanical Crafter inputs can be combined"); + scene.idle(80); + scene.overlay.showControls(new InputWindowElement(v.add(0, 1, 0), Pointing.LEFT).rightClick() + .withWrench(), 20); + scene.idle(7); + scene.world.connectCrafterInvs(util.grid.at(2, 3, 2), util.grid.at(1, 3, 2)); + scene.idle(20); + scene.overlay.showControls(new InputWindowElement(v.add(0, -1, 0), Pointing.LEFT).rightClick() + .withWrench(), 20); + scene.idle(7); + scene.world.connectCrafterInvs(util.grid.at(2, 1, 2), util.grid.at(1, 1, 2)); + scene.idle(20); + scene.overlay.showControls(new InputWindowElement(v.add(.5, -.5, 0), Pointing.LEFT).rightClick() + .withWrench(), 20); + scene.idle(7); + scene.world.connectCrafterInvs(util.grid.at(2, 1, 2), util.grid.at(2, 2, 2)); + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(v.add(.5, .5, 0), Pointing.LEFT).rightClick() + .withWrench(), 20); + scene.idle(7); + scene.world.connectCrafterInvs(util.grid.at(2, 2, 2), util.grid.at(2, 3, 2)); + scene.idle(20); + + scene.rotateCameraY(90 + 30); + scene.idle(40); + scene.overlay.showSelectionWithText(util.select.fromTo(1, 1, 2, 2, 3, 2), 70) + .attachKeyFrame() + .placeNearTarget() + .text("All connected Crafters can now be accessed by the same input location"); + scene.idle(60); + scene.overlay.showControls( + new InputWindowElement(util.vector.centerOf(util.grid.at(4, 2, 2)), Pointing.DOWN).withItem(planks), 40); + scene.idle(7); + scene.world.createItemOnBelt(util.grid.at(4, 1, 2), Direction.EAST, + ItemHandlerHelper.copyStackWithSize(planks, 16)); + scene.idle(22); + + scene.world.removeItemsFromBelt(util.grid.at(3, 1, 2)); + BlockPos[] positions = new BlockPos[] { util.grid.at(2, 3, 2), util.grid.at(1, 3, 2), util.grid.at(1, 2, 2), + util.grid.at(2, 1, 2), util.grid.at(1, 1, 2) }; + + scene.world.setCraftingResult(util.grid.at(1, 1, 2), new ItemStack(Items.OAK_DOOR, 3)); + for (BlockPos pos : positions) { + scene.world.modifyTileEntity(pos, type, mct -> mct.getInventory() + .insertItem(0, planks.copy(), false)); + scene.idle(1); + } + + } + + public static void covers(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_crafter_covers", "Covering slots of Mechanical Crafters"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + + scene.world.setBlock(util.grid.at(2, 2, 2), Blocks.AIR.getDefaultState(), false); + + Selection kinetics = util.select.fromTo(3, 1, 2, 3, 1, 5); + scene.world.setKineticSpeed(util.select.fromTo(1, 2, 2, 3, 1, 2), 0); + + scene.world.showSection(util.select.position(3, 2, 2), Direction.EAST); + scene.idle(5); + scene.world.showSection(util.select.position(2, 1, 2), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 2, 2), Direction.WEST); + scene.idle(5); + + ItemStack iron = new ItemStack(Items.IRON_INGOT); + + Class type = MechanicalCrafterTileEntity.class; + scene.world.modifyTileEntity(util.grid.at(3, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(2, 1, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + scene.idle(5); + scene.world.modifyTileEntity(util.grid.at(1, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + scene.idle(5); + + Selection emptyCrafter = util.select.position(2, 2, 2); + scene.overlay.showSelectionWithText(emptyCrafter, 90) + .attachKeyFrame() + .colored(PonderPalette.RED) + .text("Some recipes will require additional Crafters to bridge gaps in the path") + .placeNearTarget(); + scene.idle(70); + scene.world.restoreBlocks(emptyCrafter); + scene.world.setCraftingResult(util.grid.at(2, 2, 2), new ItemStack(Items.BUCKET)); + scene.world.showSection(emptyCrafter, Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(2, 3, 2), Direction.DOWN); + scene.world.showSection(kinetics, Direction.NORTH); + scene.idle(5); + scene.world.setKineticSpeed(util.select.fromTo(3, 1, 2, 1, 2, 2), -32); + scene.world.setKineticSpeed(util.select.position(3, 1, 2) + .add(emptyCrafter), 32); + + scene.idle(20); + + scene.overlay.showText(90) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH)) + .text("Using Slot Covers, Crafters can be set to act as an Empty Slot in the arrangement") + .placeNearTarget(); + scene.idle(100); + scene.overlay + .showControls(new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH) + .add(0.5, 0, 0), Pointing.RIGHT).withItem(AllItems.CRAFTER_SLOT_COVER.asStack()) + .rightClick(), + 50); + scene.idle(7); + scene.world.modifyTileNBT(emptyCrafter, type, compound -> compound.putBoolean("Cover", true)); + scene.idle(130); + + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 2), Direction.WEST), Pointing.LEFT) + .withItem(new ItemStack(Items.BUCKET)), + 40); + scene.idle(50); + scene.world.showSection(util.select.position(4, 2, 2), Direction.DOWN); + + scene.world.connectCrafterInvs(util.grid.at(3, 2, 2), util.grid.at(2, 2, 2)); + scene.idle(5); + scene.world.connectCrafterInvs(util.grid.at(2, 1, 2), util.grid.at(2, 2, 2)); + scene.idle(5); + scene.world.connectCrafterInvs(util.grid.at(1, 2, 2), util.grid.at(2, 2, 2)); + scene.idle(10); + + scene.overlay.showSelectionWithText(util.select.fromTo(3, 2, 2, 1, 2, 2) + .add(util.select.position(2, 1, 2)), 80) + .attachKeyFrame() + .pointAt(util.vector.blockSurface(util.grid.at(2, 2, 2), Direction.NORTH)) + .text("Shared Inputs created with the Wrench at the back can also reach across covered Crafters") + .placeNearTarget(); + scene.idle(60); + + ElementLink ingot = + scene.world.createItemEntity(util.vector.centerOf(4, 4, 2), util.vector.of(0, 0.2, 0), iron); + scene.idle(17); + scene.world.modifyEntity(ingot, Entity::remove); + scene.world.modifyTileEntity(util.grid.at(3, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + ingot = scene.world.createItemEntity(util.vector.centerOf(4, 4, 2), util.vector.of(0, 0.2, 0), iron); + scene.idle(17); + scene.world.modifyEntity(ingot, Entity::remove); + scene.world.modifyTileEntity(util.grid.at(2, 1, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + ingot = scene.world.createItemEntity(util.vector.centerOf(4, 4, 2), util.vector.of(0, 0.2, 0), iron); + scene.idle(17); + scene.world.modifyEntity(ingot, Entity::remove); + scene.world.modifyTileEntity(util.grid.at(1, 2, 2), type, mct -> mct.getInventory() + .insertItem(0, iron.copy(), false)); + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java index 216539a0b..85b728ee4 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java @@ -332,7 +332,7 @@ public class FunnelScenes { scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, funnel, redstoneBB, 80); scene.overlay.showText(80) .colored(PonderPalette.RED) - .text("Redstone power will prevent any funnel from acting.") + .text("Redstone power will prevent any funnel from acting") .pointAt(util.vector.blockSurface(funnel, Direction.DOWN)); } else { scene.idle(4); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java index 1f0246f2e..d290bcfb5 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java @@ -1,12 +1,16 @@ package com.simibubi.create.foundation.ponder.content; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.crank.ValveHandleBlock; +import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelBlock; import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelBlock; import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftBlock; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock; import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock; +import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock; +import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; import com.simibubi.create.content.logistics.block.redstone.NixieTubeTileEntity; import com.simibubi.create.foundation.ponder.ElementLink; import com.simibubi.create.foundation.ponder.SceneBuilder; @@ -1010,4 +1014,97 @@ public class KineticsScenes { scene.idle(35); } + public static void speedometer(SceneBuilder scene, SceneBuildingUtil util) { + gauge(scene, util, true); + } + + public static void stressometer(SceneBuilder scene, SceneBuildingUtil util) { + gauge(scene, util, false); + } + + private static void gauge(SceneBuilder scene, SceneBuildingUtil util, boolean speed) { + String component = speed ? "Speedometer" : "Stressometer"; + String title = "Monitoring Kinetic information using the " + component; + scene.title(speed ? "speedometer" : "stressometer", title); + scene.configureBasePlate(1, 0, 5); + + BlockPos gaugePos = util.grid.at(2, 1, 3); + + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + for (int x = 6; x >= 0; x--) { + scene.idle(2); + scene.world.showSection(util.select.position(x, 1, 3), Direction.DOWN); + } + scene.idle(10); + + scene.world.setBlock(gaugePos, (speed ? AllBlocks.SPEEDOMETER : AllBlocks.STRESSOMETER).getDefaultState() + .with(GaugeBlock.FACING, Direction.UP), true); + scene.world.setKineticSpeed(util.select.position(gaugePos), 32); + scene.idle(10); + + scene.overlay.showText(80) + .text("The " + component + " displays the current " + (speed ? "Speed" : "Stress Capacity") + + " of the attached " + (speed ? "components" : "kinetic network")) + .attachKeyFrame() + .pointAt(util.vector.topOf(gaugePos)) + .placeNearTarget(); + scene.idle(90); + + if (speed) { + scene.world.multiplyKineticSpeed(util.select.everywhere(), 4); + scene.effects.rotationSpeedIndicator(util.grid.at(6, 1, 3)); + scene.idle(5); + scene.effects.indicateSuccess(gaugePos); + + } else { + BlockState state = AllBlocks.CRUSHING_WHEEL.getDefaultState() + .with(CrushingWheelBlock.AXIS, Axis.X); + scene.world.setBlock(util.grid.at(5, 1, 3), state, true); + scene.world.setKineticSpeed(util.select.position(5, 1, 3), 32); + scene.world.modifyTileNBT(util.select.position(gaugePos), StressGaugeTileEntity.class, + nbt -> nbt.putFloat("Value", .5f)); + scene.effects.indicateRedstone(gaugePos); + scene.idle(20); + scene.world.setBlock(util.grid.at(4, 1, 3), state, true); + scene.world.setKineticSpeed(util.select.position(4, 1, 3), 32); + scene.world.modifyTileNBT(util.select.position(gaugePos), StressGaugeTileEntity.class, + nbt -> nbt.putFloat("Value", .9f)); + scene.effects.indicateRedstone(gaugePos); + scene.idle(10); + } + + scene.idle(30); + + Vector3d blockSurface = util.vector.blockSurface(gaugePos, Direction.NORTH); + scene.overlay.showControls( + new InputWindowElement(blockSurface, Pointing.RIGHT).withItem(AllItems.GOGGLES.asStack()), 40); + scene.idle(7); + scene.overlay.showText(80) + .text("When wearing Engineers' Goggles, the player can get more detailed information from the Gauge") + .attachKeyFrame() + .colored(PonderPalette.MEDIUM) + .pointAt(blockSurface) + .placeNearTarget(); + scene.idle(100); + + Selection comparator = util.select.fromTo(2, 1, 1, 2, 1, 2); + scene.world.showSection(comparator, Direction.SOUTH); + scene.idle(10); + scene.world.toggleRedstonePower(comparator); + scene.effects.indicateRedstone(util.grid.at(2, 1, 2)); + scene.idle(20); + + scene.overlay.showText(120) + .text("Comparators can emit analog Restone Signals relative to the " + component + "'s measurements") + .attachKeyFrame() + .colored(PonderPalette.RED) + .pointAt(util.vector.centerOf(2, 1, 2) + .add(0, -0.35, 0)) + .placeNearTarget(); + scene.idle(130); + scene.markAsFinished(); + } + } 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 d5a31962b..eb46df8fb 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 @@ -77,6 +77,40 @@ public class PonderIndex { PonderRegistry.forComponents(AllBlocks.ROTATION_SPEED_CONTROLLER) .addStoryBoard("speed_controller", KineticsScenes::speedController); + // Gauges + PonderRegistry.addStoryBoard(AllBlocks.SPEEDOMETER, "gauges", KineticsScenes::speedometer); + PonderRegistry.addStoryBoard(AllBlocks.STRESSOMETER, "gauges", KineticsScenes::stressometer); + + // Item Processing + PonderRegistry.addStoryBoard(AllBlocks.MILLSTONE, "millstone", ProcessingScenes::millstone); + PonderRegistry.addStoryBoard(AllBlocks.CRUSHING_WHEEL, "crushing_wheel", ProcessingScenes::crushingWheels); + PonderRegistry.addStoryBoard(AllBlocks.MECHANICAL_MIXER, "mechanical_mixer/mixing", ProcessingScenes::mixing); + PonderRegistry.forComponents(AllBlocks.MECHANICAL_PRESS) + .addStoryBoard("mechanical_press/pressing", ProcessingScenes::pressing) + .addStoryBoard("mechanical_press/compacting", ProcessingScenes::compacting); + PonderRegistry.forComponents(AllBlocks.BASIN) + .addStoryBoard("basin", ProcessingScenes::basin) + .addStoryBoard("mechanical_mixer/mixing", ProcessingScenes::mixing) + .addStoryBoard("mechanical_press/compacting", ProcessingScenes::compacting); + PonderRegistry.addStoryBoard(AllItems.EMPTY_BLAZE_BURNER, "empty_blaze_burner", + ProcessingScenes::emptyBlazeBurner); + PonderRegistry.addStoryBoard(AllBlocks.BLAZE_BURNER, "blaze_burner", ProcessingScenes::blazeBurner); + PonderRegistry.addStoryBoard(AllBlocks.DEPOT, "depot", BeltScenes::depot); + + // Crafters + PonderRegistry.forComponents(AllBlocks.MECHANICAL_CRAFTER) + .addStoryBoard("mechanical_crafter/setup", CrafterScenes::setup) + .addStoryBoard("mechanical_crafter/connect", CrafterScenes::connect); + PonderRegistry.forComponents(AllBlocks.MECHANICAL_CRAFTER, AllItems.CRAFTER_SLOT_COVER) + .addStoryBoard("mechanical_crafter/covers", CrafterScenes::covers); + + // Chutes + PonderRegistry.forComponents(AllBlocks.CHUTE) + .addStoryBoard("chute/downward", ChuteScenes::downward, PonderTag.LOGISTICS) + .addStoryBoard("chute/upward", ChuteScenes::upward); + PonderRegistry.forComponents(AllBlocks.CHUTE, AllBlocks.SMART_CHUTE) + .addStoryBoard("chute/smart", ChuteScenes::smart); + // Funnels PonderRegistry.addStoryBoard(AllBlocks.BRASS_FUNNEL, "funnels/brass", FunnelScenes::brass); PonderRegistry.forComponents(AllBlocks.ANDESITE_FUNNEL, AllBlocks.BRASS_FUNNEL) @@ -98,6 +132,13 @@ public class PonderIndex { PonderRegistry.forComponents(AllBlocks.STICKER) .addStoryBoard("sticker", RedstoneScenes::sticker, PonderTag.CONTRAPTION_ASSEMBLY); + // Mechanical Arm + PonderRegistry.forComponents(AllBlocks.MECHANICAL_ARM) + .addStoryBoard("mechanical_arm/setup", ArmScenes::setup, PonderTag.ARM_TARGETS) + .addStoryBoard("mechanical_arm/filter", ArmScenes::filtering) + .addStoryBoard("mechanical_arm/modes", ArmScenes::modes) + .addStoryBoard("mechanical_arm/redstone", ArmScenes::redstone); + // Mechanical Piston PonderRegistry.forComponents(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) .addStoryBoard("mechanical_piston/anchor", PistonScenes::movement, PonderTag.KINETIC_APPLIANCES, @@ -121,6 +162,10 @@ public class PonderIndex { .addStoryBoard("windmill_bearing/source", BearingScenes::windmillsAsSource, PonderTag.KINETIC_SOURCES) .addStoryBoard("windmill_bearing/structure", BearingScenes::windmillsAnyStructure, PonderTag.MOVEMENT_ANCHOR); + PonderRegistry.forComponents(AllBlocks.SAIL) + .addStoryBoard("sail", BearingScenes::sail); + PonderRegistry.forComponents(AllBlocks.SAIL_FRAME) + .addStoryBoard("sail", BearingScenes::sailFrame); // Mechanical Bearing PonderRegistry.forComponents(AllBlocks.MECHANICAL_BEARING) @@ -258,6 +303,7 @@ public class PonderIndex { .add(AllBlocks.CREATIVE_FLUID_TANK); PonderRegistry.tags.forTag(PonderTag.ARM_TARGETS) + .add(AllBlocks.MECHANICAL_ARM) .add(AllItems.BELT_CONNECTOR) .add(AllBlocks.CHUTE) .add(AllBlocks.DEPOT) @@ -268,10 +314,10 @@ public class PonderIndex { .add(AllBlocks.MILLSTONE) .add(AllBlocks.DEPLOYER) .add(AllBlocks.MECHANICAL_SAW) - .add(Blocks.COMPOSTER) .add(AllBlocks.BLAZE_BURNER) - .add(Blocks.JUKEBOX) - .add(AllBlocks.CRUSHING_WHEEL); + .add(AllBlocks.CRUSHING_WHEEL) + .add(Blocks.COMPOSTER) + .add(Blocks.JUKEBOX); PonderRegistry.tags.forTag(PonderTag.LOGISTICS) .add(AllItems.BELT_CONNECTOR) @@ -305,6 +351,11 @@ public class PonderIndex { .add(AllBlocks.CREATIVE_FLUID_TANK) .add(AllBlocks.CREATIVE_MOTOR); + PonderRegistry.tags.forTag(PonderTag.SAILS) + .add(AllBlocks.SAIL) + .add(AllBlocks.SAIL_FRAME) + .add(Blocks.WHITE_WOOL); + PonderRegistry.tags.forTag(PonderTag.REDSTONE) .add(AllBlocks.NIXIE_TUBE) .add(AllBlocks.REDSTONE_CONTACT) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java index ede4108ed..5e5fbae39 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderPalette.java @@ -13,6 +13,9 @@ public enum PonderPalette { MEDIUM(0xFF_0084ff), FAST(0xFF_ff55ff), + INPUT(0xFF_4f8a8b), + OUTPUT(0xFF_ffcb74), + ; private int color; diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java index b9fad939d..c5ef66ffb 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTag.java @@ -60,6 +60,10 @@ public class PonderTag implements IScreenRenderable { .defaultLang("Block Attachment Utility", "Tools and Components used to assemble structures moved as an animated Contraption"), + SAILS = new PonderTag("windmill_sails").item(AllBlocks.WINDMILL_BEARING.get(), true, true) + .defaultLang("Sails for Windmill Bearings", + "Blocks that count towards the strength of a Windmill Contraption when assembled. Each of these have equal efficiency in doing so."), + // FLUID_TRANSFER = new PonderTag("fluid_transfer").idAsIcon(), // // OPEN_INVENTORY = new PonderTag("open_inventory").item(AllBlocks.BASIN.get() diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java index eee09f6ad..3303055cb 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderTagScreen.java @@ -8,6 +8,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import org.apache.commons.lang3.mutable.MutableBoolean; import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.Create; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.ponder.NavigatableSimiScreen; @@ -26,6 +27,7 @@ import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.renderer.Rectangle2d; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraftforge.registries.ForgeRegistries; @@ -60,6 +62,12 @@ public class PonderTagScreen extends NavigatableSimiScreen { items.clear(); PonderRegistry.tags.getItems(tag) .stream() + .filter(rl -> tag.getMainItem() + .isEmpty() + || tag.getMainItem() + .getItem() + .getRegistryName() + .equals(rl)) .map(key -> { Item item = ForgeRegistries.ITEMS.getValue(key); if (item == null) { @@ -88,7 +96,12 @@ public class PonderTagScreen extends NavigatableSimiScreen { ScreenOpener.transitionTo(PonderUI.of(new ItemStack(i), tag)); }).showing(new ItemStack(i)); if (!canClick) - button.noClickEvent(); + if (i.getRegistryName() + .getNamespace() + .equals(Create.ID)) + button.customColors(0x70984500, 0x70692400); + else + button.customColors(0x505000FF, 0x50300077); button.fade(1); widgets.add(button); @@ -97,9 +110,10 @@ public class PonderTagScreen extends NavigatableSimiScreen { if (!tag.getMainItem() .isEmpty()) { - final boolean canClick = PonderRegistry.all.containsKey(tag.getMainItem() + ResourceLocation registryName = tag.getMainItem() .getItem() - .getRegistryName()); + .getRegistryName(); + final boolean canClick = PonderRegistry.all.containsKey(registryName); PonderButton button = new PonderButton(itemCenterX - layout.getTotalWidth() / 2 - 42, itemCenterY - 10, (mouseX, mouseY) -> { if (!canClick) @@ -108,7 +122,11 @@ public class PonderTagScreen extends NavigatableSimiScreen { ScreenOpener.transitionTo(PonderUI.of(tag.getMainItem(), tag)); }).showing(tag.getMainItem()); if (!canClick) - button.noClickEvent(); + if (registryName.getNamespace() + .equals(Create.ID)) + button.customColors(0x70984500, 0x70692400); + else + button.customColors(0x505000FF, 0x50300077); button.fade(1); widgets.add(button); @@ -199,11 +217,11 @@ public class PonderTagScreen extends NavigatableSimiScreen { String desc = tag.getDescription(); int h = textRenderer.getWordWrappedHeight(desc, w); + PonderUI.renderBox(ms, x - 3, y - 3, w + 6, h + 6, false); ms.translate(0, 0, 100); FontHelper.drawSplitString(textRenderer, desc, x, y, w, 0xeeeeee); ms.pop(); - } protected void renderItems(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { @@ -302,7 +320,7 @@ public class PonderTagScreen extends NavigatableSimiScreen { return tag == ((PonderTagScreen) other).tag; return super.isEquivalentTo(other); } - + @Override public boolean isPauseScreen() { return true; diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java new file mode 100644 index 000000000..d852322d9 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ProcessingScenes.java @@ -0,0 +1,895 @@ +package com.simibubi.create.foundation.ponder.content; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity; +import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity; +import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerTileEntity; +import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode; +import com.simibubi.create.content.contraptions.processing.BasinBlock; +import com.simibubi.create.content.contraptions.processing.BasinTileEntity; +import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; +import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.BeltItemElement; +import com.simibubi.create.foundation.ponder.elements.EntityElement; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.ponder.instructions.EmitParticlesInstruction.Emitter; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.NBTHelper; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.item.ItemEntity; +import net.minecraft.entity.monster.BlazeEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.particles.ItemParticleData; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; + +public class ProcessingScenes { + + public static void millstone(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("millstone", "Processing Items in the Millstone"); + scene.configureBasePlate(0, 0, 5); + + Selection belt = util.select.fromTo(1, 1, 5, 0, 1, 2) + .add(util.select.position(1, 2, 2)); + Selection beltCog = util.select.position(2, 0, 5); + + scene.world.showSection(util.select.layer(0) + .substract(beltCog), Direction.UP); + + BlockPos millstone = util.grid.at(2, 2, 2); + Selection millstoneSelect = util.select.position(2, 2, 2); + Selection cogs = util.select.fromTo(3, 1, 2, 3, 2, 2); + scene.world.setKineticSpeed(millstoneSelect, 0); + + scene.idle(5); + scene.world.showSection(util.select.position(4, 1, 3), Direction.DOWN); + scene.world.showSection(util.select.position(2, 1, 2), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(millstone), Direction.DOWN); + scene.idle(10); + Vector3d millstoneTop = util.vector.topOf(millstone); + scene.overlay.showText(60) + .attachKeyFrame() + .text("Millstones process items by grinding them") + .pointAt(millstoneTop) + .placeNearTarget(); + scene.idle(70); + + scene.world.showSection(cogs, Direction.DOWN); + scene.idle(10); + scene.world.setKineticSpeed(millstoneSelect, 32); + scene.effects.indicateSuccess(millstone); + scene.idle(10); + + scene.overlay.showText(60) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .text("They can be powered from the side using cogwheels") + .pointAt(util.vector.topOf(millstone.east())) + .placeNearTarget(); + scene.idle(70); + + ItemStack itemStack = new ItemStack(Items.WHEAT); + Vector3d entitySpawn = util.vector.topOf(millstone.up(3)); + + ElementLink entity1 = + scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), itemStack); + scene.idle(18); + scene.world.modifyEntity(entity1, Entity::remove); + scene.world.modifyTileEntity(millstone, MillstoneTileEntity.class, + ms -> ms.inputInv.setStackInSlot(0, itemStack)); + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(millstoneTop, Pointing.DOWN).withItem(itemStack), 30); + scene.idle(7); + + scene.overlay.showText(40) + .attachKeyFrame() + .text("Throw or Insert items at the top") + .pointAt(millstoneTop) + .placeNearTarget(); + scene.idle(60); + + scene.world.modifyTileEntity(millstone, MillstoneTileEntity.class, + ms -> ms.inputInv.setStackInSlot(0, ItemStack.EMPTY)); + + scene.overlay.showText(50) + .text("After some time, the result can be obtained via Right-click") + .pointAt(util.vector.blockSurface(millstone, Direction.WEST)) + .placeNearTarget(); + scene.idle(60); + + ItemStack flour = AllItems.WHEAT_FLOUR.asStack(); + scene.overlay.showControls( + new InputWindowElement(util.vector.blockSurface(millstone, Direction.NORTH), Pointing.RIGHT).rightClick() + .withItem(flour), + 40); + scene.idle(50); + + scene.addKeyframe(); + scene.world.showSection(beltCog, Direction.UP); + scene.world.showSection(belt, Direction.EAST); + scene.idle(15); + + BlockPos beltPos = util.grid.at(1, 1, 2); + scene.world.createItemOnBelt(beltPos, Direction.EAST, flour); + scene.idle(15); + scene.world.createItemOnBelt(beltPos, Direction.EAST, new ItemStack(Items.WHEAT_SEEDS)); + scene.idle(20); + + scene.overlay.showText(50) + .text("The outputs can also be extracted by automation") + .pointAt(util.vector.blockSurface(millstone, Direction.WEST) + .add(-.5, .4, 0)) + .placeNearTarget(); + scene.idle(60); + } + + public static void crushingWheels(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("crushing_wheels", "Processing Items with Crushing Wheels"); + scene.configureBasePlate(0, 0, 5); + scene.scaleSceneView(.9f); + + Selection wheels = util.select.fromTo(3, 2, 2, 1, 2, 2); + Selection kinetics = util.select.fromTo(0, 1, 5, 4, 1, 3); + Selection kinetics2 = util.select.fromTo(0, 2, 5, 4, 2, 3); + Selection beltCog = util.select.position(5, 0, 1); + scene.world.setKineticSpeed(wheels, 0); + scene.world.setBlock(util.grid.at(2, 3, 2), Blocks.AIR.getDefaultState(), false); + + scene.world.showSection(util.select.layer(0) + .substract(beltCog), Direction.UP); + scene.idle(5); + + Selection belt = util.select.fromTo(4, 1, 2, 4, 4, 2) + .add(util.select.fromTo(4, 3, 3, 4, 4, 3)) + .add(util.select.position(3, 3, 2)) + .add(util.select.position(2, 3, 2)); + Selection bottomBelt = util.select.fromTo(5, 1, 0, 2, 1, 0) + .add(util.select.fromTo(2, 1, 2, 2, 1, 1)); + + BlockPos center = util.grid.at(2, 2, 2); + Selection wWheel = util.select.position(center.west()); + Selection eWheel = util.select.position(center.east()); + + scene.world.showSection(wWheel, Direction.SOUTH); + scene.idle(3); + scene.world.showSection(eWheel, Direction.SOUTH); + scene.idle(10); + + Vector3d centerTop = util.vector.topOf(center); + scene.overlay.showText(60) + .attachKeyFrame() + .text("A pair of Crushing Wheels can grind items very effectively") + .pointAt(centerTop) + .placeNearTarget(); + scene.idle(70); + + scene.world.showSection(kinetics, Direction.DOWN); + scene.idle(3); + scene.world.showSection(kinetics2, Direction.DOWN); + scene.world.setKineticSpeed(wWheel, -16); + scene.world.setKineticSpeed(eWheel, 16); + scene.idle(5); + scene.effects.rotationDirectionIndicator(center.west()); + scene.effects.rotationDirectionIndicator(center.east()); + scene.idle(10); + + scene.overlay.showText(60) + .attachKeyFrame() + .text("Their Rotational Input has to make them spin into each other") + .pointAt(util.vector.blockSurface(center.west(), Direction.NORTH)) + .placeNearTarget(); + scene.idle(40); + scene.effects.rotationDirectionIndicator(center.west()); + scene.effects.rotationDirectionIndicator(center.east()); + scene.idle(30); + + ItemStack input = new ItemStack(Items.GOLD_ORE); + ItemStack output = AllItems.CRUSHED_GOLD.asStack(); + Vector3d entitySpawn = util.vector.topOf(center.up(2)); + + ElementLink entity1 = + scene.world.createItemEntity(entitySpawn, util.vector.of(0, 0.2, 0), input); + scene.idle(18); + scene.world.modifyEntity(entity1, Entity::remove); + Emitter blockSpace = + Emitter.withinBlockSpace(new ItemParticleData(ParticleTypes.ITEM, input), util.vector.of(0, 0, 0)); + scene.effects.emitParticles(util.vector.centerOf(center) + .add(0, -0.2, 0), blockSpace, 3, 40); + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(centerTop, Pointing.DOWN).withItem(input), 30); + scene.idle(7); + + scene.overlay.showText(50) + .attachKeyFrame() + .text("Items thrown or inserted into the top will get processed") + .pointAt(centerTop) + .placeNearTarget(); + scene.idle(60); + + scene.world.createItemEntity(centerTop.add(0, -1.4, 0), util.vector.of(0, 0, 0), output); + scene.idle(10); + scene.world.createItemEntity(centerTop.add(0, -1.4, 0), util.vector.of(0, 0, 0), output); + scene.overlay.showControls(new InputWindowElement(centerTop.add(0, -2, 0), Pointing.UP).withItem(output), 30); + scene.idle(40); + + scene.world.restoreBlocks(util.select.position(2, 3, 2)); + scene.world.showSection(belt, Direction.DOWN); + scene.idle(5); + scene.world.showSection(beltCog, Direction.UP); + scene.idle(5); + scene.world.modifyEntities(ItemEntity.class, Entity::remove); + scene.world.showSection(bottomBelt, Direction.SOUTH); + scene.idle(5); + + scene.overlay.showText(50) + .attachKeyFrame() + .text("Items can be inserted and picked up through automated means as well") + .pointAt(centerTop.add(0, .5, 0)) + .placeNearTarget(); + scene.idle(40); + + for (int i = 0; i < 5; i++) { + if (i < 4) + scene.world.createItemOnBelt(util.grid.at(4, 4, 2), Direction.EAST, input); + scene.idle(15); + if (i < 3) + scene.world.createItemOnBelt(util.grid.at(4, 4, 2), Direction.EAST, input); + scene.idle(15); + if (i > 0) { + scene.world.createItemOnBelt(center.down(), Direction.UP, output); + scene.idle(15); + scene.world.createItemOnBelt(center.down(), Direction.UP, output); + } + scene.world.removeItemsFromBelt(util.grid.at(3, 3, 2)); + if (i < 4) + scene.effects.emitParticles(util.vector.centerOf(center) + .add(0, -0.2, 0), blockSpace, 3, 28); + if (i == 0) + scene.markAsFinished(); + } + } + + public static void pressing(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_press", "Processing Items with the Mechanical Press"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + ElementLink depot = + scene.world.showIndependentSection(util.select.position(2, 1, 1), Direction.DOWN); + scene.world.moveSection(depot, util.vector.of(0, 0, 1), 0); + scene.idle(10); + + Selection pressS = util.select.position(2, 3, 2); + BlockPos pressPos = util.grid.at(2, 3, 2); + BlockPos depotPos = util.grid.at(2, 1, 1); + scene.world.setKineticSpeed(pressS, 0); + scene.world.showSection(pressS, Direction.DOWN); + scene.idle(10); + + scene.world.showSection(util.select.fromTo(2, 1, 3, 2, 1, 5), Direction.NORTH); + scene.idle(3); + scene.world.showSection(util.select.position(2, 2, 3), Direction.SOUTH); + scene.idle(3); + scene.world.showSection(util.select.position(2, 3, 3), Direction.NORTH); + scene.world.setKineticSpeed(pressS, -32); + scene.effects.indicateSuccess(pressPos); + scene.idle(10); + + Vector3d pressSide = util.vector.blockSurface(pressPos, Direction.WEST); + scene.overlay.showText(60) + .pointAt(pressSide) + .placeNearTarget() + .attachKeyFrame() + .text("The Mechanical Press can process items provided beneath it"); + scene.idle(70); + scene.overlay.showText(60) + .pointAt(pressSide.subtract(0, 2, 0)) + .placeNearTarget() + .text("The Input items can be dropped or placed on a Depot under the Press"); + scene.idle(50); + ItemStack copper = AllItems.COPPER_INGOT.asStack(); + scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, copper); + Vector3d depotCenter = util.vector.centerOf(depotPos.south()); + scene.overlay.showControls(new InputWindowElement(depotCenter, Pointing.UP).withItem(copper), 30); + scene.idle(10); + + Class type = MechanicalPressTileEntity.class; + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper)); + scene.world.removeItemsFromBelt(depotPos); + ItemStack sheet = AllItems.COPPER_SHEET.asStack(); + scene.world.createItemOnBeltLike(depotPos, Direction.UP, sheet); + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(depotCenter, Pointing.UP).withItem(sheet), 50); + scene.idle(60); + + scene.world.hideIndependentSection(depot, Direction.NORTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(0, 1, 3, 0, 2, 3), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.fromTo(4, 1, 2, 0, 2, 2), Direction.SOUTH); + scene.idle(20); + BlockPos beltPos = util.grid.at(0, 1, 2); + scene.overlay.showText(40) + .pointAt(util.vector.blockSurface(beltPos, Direction.WEST)) + .placeNearTarget() + .attachKeyFrame() + .text("When items are provided on a belt..."); + scene.idle(30); + + ElementLink ingot = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, copper); + scene.idle(15); + ElementLink ingot2 = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, copper); + scene.idle(15); + scene.world.stallBeltItem(ingot, true); + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT)); + + scene.overlay.showText(50) + .pointAt(pressSide) + .placeNearTarget() + .attachKeyFrame() + .text("The Press will hold and process them automatically"); + + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper)); + scene.world.removeItemsFromBelt(pressPos.down(2)); + ingot = scene.world.createItemOnBelt(pressPos.down(2), Direction.UP, sheet); + scene.world.stallBeltItem(ingot, true); + scene.idle(15); + scene.world.stallBeltItem(ingot, false); + scene.idle(15); + scene.world.stallBeltItem(ingot2, true); + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BELT)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makePressingParticleEffect(depotCenter.add(0, 8 / 16f, 0), copper)); + scene.world.removeItemsFromBelt(pressPos.down(2)); + ingot2 = scene.world.createItemOnBelt(pressPos.down(2), Direction.UP, sheet); + scene.world.stallBeltItem(ingot2, true); + scene.idle(15); + scene.world.stallBeltItem(ingot2, false); + + } + + public static void mixing(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_mixer", "Processing Items with the Mechanical Mixer"); + scene.configureBasePlate(0, 0, 5); + scene.world.setBlock(util.grid.at(1, 1, 2), AllBlocks.ANDESITE_CASING.getDefaultState(), false); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 1, 1, 5), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 1, 2), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 2, 2), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 4, 2), Direction.SOUTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 1, 1, 1, 1), Direction.SOUTH); + scene.world.showSection(util.select.fromTo(3, 1, 5, 3, 1, 2), Direction.SOUTH); + scene.idle(20); + + BlockPos basin = util.grid.at(1, 2, 2); + BlockPos pressPos = util.grid.at(1, 4, 2); + Vector3d basinSide = util.vector.blockSurface(basin, Direction.WEST); + + ItemStack blue = new ItemStack(Items.BLUE_DYE); + ItemStack red = new ItemStack(Items.RED_DYE); + ItemStack purple = new ItemStack(Items.PURPLE_DYE); + + scene.overlay.showText(60) + .pointAt(basinSide) + .placeNearTarget() + .attachKeyFrame() + .text("With a Mixer and Basin, some Crafting Recipes can be automated"); + scene.idle(40); + + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basin), Pointing.LEFT).withItem(blue), 30); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basin), Pointing.RIGHT).withItem(red), 30); + scene.idle(30); + Class type = MechanicalMixerTileEntity.class; + scene.world.modifyTileEntity(pressPos, type, pte -> pte.startProcessingBasin()); + scene.world.createItemOnBeltLike(basin, Direction.UP, red); + scene.world.createItemOnBeltLike(basin, Direction.UP, blue); + scene.idle(80); + scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> { + nbt.put("VisualizedItems", + NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, purple)), ia -> ia.getValue() + .serializeNBT())); + }); + scene.idle(4); + scene.world.createItemOnBelt(util.grid.at(1, 1, 1), Direction.UP, purple); + scene.idle(30); + + scene.overlay.showText(80) + .pointAt(basinSide) + .placeNearTarget() + .attachKeyFrame() + .text("Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones"); + scene.idle(80); + + scene.rotateCameraY(-30); + scene.idle(10); + scene.world.setBlock(util.grid.at(1, 1, 2), AllBlocks.BLAZE_BURNER.getDefaultState() + .with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), true); + scene.idle(10); + + scene.overlay.showText(80) + .pointAt(basinSide.subtract(0, 1, 0)) + .placeNearTarget() + .text("Some of those recipes may require the heat of a Blaze Burner"); + scene.idle(40); + + scene.rotateCameraY(30); + + scene.idle(60); + Vector3d filterPos = util.vector.of(1, 2.75f, 2.5f); + scene.overlay.showFilterSlotInput(filterPos, 100); + scene.overlay.showText(120) + .pointAt(filterPos) + .placeNearTarget() + .attachKeyFrame() + .text("The filter slot can be used in case two recipes are conflicting."); + scene.idle(60); + } + + public static void compacting(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_press_compacting", "Compacting items with the Mechanical Press"); + scene.configureBasePlate(0, 0, 5); + scene.world.setBlock(util.grid.at(1, 1, 2), AllBlocks.ANDESITE_CASING.getDefaultState(), false); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 1, 1, 5), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 1, 2), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 2, 2), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.position(1, 4, 2), Direction.SOUTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(3, 1, 1, 1, 1, 1), Direction.SOUTH); + scene.world.showSection(util.select.fromTo(3, 1, 5, 3, 1, 2), Direction.SOUTH); + scene.idle(20); + + BlockPos basin = util.grid.at(1, 2, 2); + BlockPos pressPos = util.grid.at(1, 4, 2); + Vector3d basinSide = util.vector.blockSurface(basin, Direction.WEST); + + ItemStack copper = AllItems.COPPER_INGOT.asStack(); + ItemStack copperBlock = AllBlocks.COPPER_BLOCK.asStack(); + + scene.overlay.showText(60) + .pointAt(basinSide) + .placeNearTarget() + .attachKeyFrame() + .text("Pressing items held in a Basin will cause them to be Compacted"); + scene.idle(40); + + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basin), Pointing.DOWN).withItem(copper), + 30); + scene.idle(30); + Class type = MechanicalPressTileEntity.class; + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basin), copper)); + scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> { + nbt.put("VisualizedItems", + NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, copperBlock)), ia -> ia.getValue() + .serializeNBT())); + }); + scene.idle(4); + scene.world.createItemOnBelt(util.grid.at(1, 1, 1), Direction.UP, copperBlock); + scene.idle(30); + + scene.overlay.showText(80) + .pointAt(basinSide) + .placeNearTarget() + .attachKeyFrame() + .text("Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones"); + + scene.idle(30); + ItemStack log = new ItemStack(Items.OAK_LOG); + ItemStack bark = new ItemStack(Items.OAK_WOOD); + + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basin), Pointing.DOWN).withItem(log), 30); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basin), log)); + scene.world.modifyTileNBT(util.select.position(basin), BasinTileEntity.class, nbt -> { + nbt.put("VisualizedItems", + NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, bark)), ia -> ia.getValue() + .serializeNBT())); + }); + scene.idle(4); + scene.world.createItemOnBelt(util.grid.at(1, 1, 1), Direction.UP, bark); + scene.idle(30); + + scene.rotateCameraY(-30); + scene.idle(10); + scene.world.setBlock(util.grid.at(1, 1, 2), AllBlocks.BLAZE_BURNER.getDefaultState() + .with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), true); + scene.idle(10); + + scene.overlay.showText(80) + .pointAt(basinSide.subtract(0, 1, 0)) + .placeNearTarget() + .text("Some of those recipes may require the heat of a Blaze Burner"); + scene.idle(40); + + scene.rotateCameraY(30); + + scene.idle(60); + Vector3d filterPos = util.vector.of(1, 2.75f, 2.5f); + scene.overlay.showFilterSlotInput(filterPos, 100); + scene.overlay.showText(120) + .pointAt(filterPos) + .placeNearTarget() + .attachKeyFrame() + .text("The filter slot can be used in case two recipes are conflicting."); + scene.idle(60); + } + + public static void emptyBlazeBurner(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("empty_blaze_burner", "Using Empty Blaze Burners"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(10); + BlockPos center = util.grid.at(2, 0, 2); + + scene.world.createEntity(w -> { + BlazeEntity blazeEntity = EntityType.BLAZE.create(w); + Vector3d v = util.vector.topOf(center); + blazeEntity.setPos(v.x, v.y, v.z); + blazeEntity.prevRotationYaw = blazeEntity.rotationYaw = 180; + return blazeEntity; + }); + + scene.idle(20); + scene.overlay + .showControls(new InputWindowElement(util.vector.centerOf(center.up(2)), Pointing.DOWN).rightClick() + .withItem(AllItems.EMPTY_BLAZE_BURNER.asStack()), 40); + scene.idle(10); + scene.overlay.showText(60) + .text("Right-click a Blaze with the empty burner to capture it") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(center.up(2), Direction.WEST)) + .placeNearTarget(); + scene.idle(50); + + scene.world.modifyEntities(BlazeEntity.class, Entity::remove); + scene.idle(20); + + scene.world.showSection(util.select.position(2, 1, 2), Direction.DOWN); + scene.idle(20); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(center.up()), Pointing.DOWN).rightClick() + .withItem(AllItems.EMPTY_BLAZE_BURNER.asStack()), 40); + scene.idle(10); + scene.overlay.showText(60) + .text("Alternatively, Blazes can be collected from their Spawners directly") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(center.up(), Direction.WEST)) + .placeNearTarget(); + scene.idle(50); + scene.world.hideSection(util.select.position(2, 1, 2), Direction.UP); + scene.idle(20); + scene.world.showSection(util.select.position(1, 1, 2), Direction.DOWN); + scene.idle(20); + + scene.world.modifyBlock(util.grid.at(1, 1, 2), s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), + false); + scene.overlay.showText(70) + .text("You now have an ideal heat source for various machines") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(center.west() + .up(), Direction.WEST)) + .placeNearTarget(); + scene.idle(80); + + scene.world.showSection(util.select.position(3, 1, 2), Direction.DOWN); + scene.idle(20); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(center.east() + .up()), Pointing.DOWN).rightClick() + .withItem(new ItemStack(Items.FLINT_AND_STEEL)), + 40); + scene.idle(7); + scene.world.setBlock(util.grid.at(3, 1, 2), AllBlocks.LIT_BLAZE_BURNER.getDefaultState(), true); + scene.idle(10); + scene.overlay.showText(70) + .text("For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(center.east() + .up(), Direction.UP)) + .placeNearTarget(); + scene.idle(80); + scene.overlay.showText(60) + .colored(PonderPalette.RED) + .text("However, these are not suitable for industrial heating") + .pointAt(util.vector.blockSurface(center.east() + .up(), Direction.UP)) + .placeNearTarget(); + scene.idle(70); + } + + public static void blazeBurner(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("blaze_burner", "Feeding Blaze Burners"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + scene.idle(10); + + BlockPos burner = util.grid.at(2, 1, 2); + scene.world.showSection(util.select.position(burner), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.position(burner.up()), Direction.DOWN); + scene.idle(10); + + scene.overlay.showText(70) + .attachKeyFrame() + .text("Blaze Burners can provide Heat to Items processed in a Basin") + .pointAt(util.vector.blockSurface(burner, Direction.WEST)) + .placeNearTarget(); + scene.idle(80); + + scene.world.hideSection(util.select.position(burner.up()), Direction.UP); + scene.idle(20); + scene.world.setBlock(burner.up(), Blocks.AIR.getDefaultState(), false); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(burner), Pointing.DOWN).rightClick() + .withItem(new ItemStack(Items.OAK_PLANKS)), 15); + scene.idle(7); + scene.world.modifyBlock(burner, s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.FADING), false); + scene.idle(15); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(burner), Pointing.DOWN).rightClick() + .withItem(new ItemStack(Items.OAK_PLANKS)), 15); + scene.idle(7); + scene.world.modifyBlock(burner, s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.KINDLED), false); + scene.idle(20); + + scene.overlay.showText(70) + .attachKeyFrame() + .text("For this, the Blaze has to be fed with flammable items") + .pointAt(util.vector.blockSurface(burner, Direction.WEST)) + .placeNearTarget(); + scene.idle(80); + + scene.idle(20); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(burner), Pointing.DOWN).rightClick() + .withItem(AllItems.BLAZE_CAKE.asStack()), 30); + scene.idle(7); + scene.world.modifyBlock(burner, s -> s.with(BlazeBurnerBlock.HEAT_LEVEL, HeatLevel.SEETHING), false); + scene.idle(20); + + scene.overlay.showText(80) + .attachKeyFrame() + .colored(PonderPalette.MEDIUM) + .text("With a Blaze Cake, the Burner can reach an even stronger level of heat") + .pointAt(util.vector.blockSurface(burner, Direction.WEST)) + .placeNearTarget(); + scene.idle(90); + + Class teType = DeployerTileEntity.class; + scene.world.modifyTileNBT(util.select.position(4, 1, 2), teType, + nbt -> nbt.put("HeldItem", AllItems.BLAZE_CAKE.asStack() + .serializeNBT())); + + scene.world.showSection(util.select.fromTo(3, 0, 5, 2, 0, 5), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.fromTo(4, 1, 2, 4, 1, 5), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.fromTo(2, 1, 4, 2, 1, 5), Direction.DOWN); + scene.idle(10); + + scene.overlay.showText(80) + .attachKeyFrame() + .text("The feeding process can be automated using Deployers or Mechanical Arms") + .pointAt(util.vector.blockSurface(burner.east(2), Direction.UP)); + scene.idle(90); + } + + public static void basin(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("basin", "Processing Items in the Basin"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + scene.world.showSection(util.select.position(1, 1, 2), Direction.DOWN); + scene.idle(10); + BlockPos basinPos = util.grid.at(1, 2, 2); + scene.world.modifyBlock(basinPos, s -> s.with(BasinBlock.FACING, Direction.DOWN), false); + scene.world.showSection(util.select.position(basinPos), Direction.DOWN); + scene.idle(10); + Vector3d basinSide = util.vector.blockSurface(basinPos, Direction.WEST); + scene.overlay.showText(80) + .attachKeyFrame() + .text("A Basin can hold Items and Fluids for Processing") + .pointAt(basinSide) + .placeNearTarget(); + scene.idle(10); + + ItemStack stack = new ItemStack(Items.BRICK); + for (int i = 0; i < 4; i++) { + scene.world.createItemEntity(util.vector.centerOf(basinPos.up(3)), util.vector.of(0, 0, 0), stack); + scene.idle(10); + } + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.DOWN).withItem(stack), + 30); + scene.idle(30); + + for (Direction d : Iterate.horizontalDirections) { + scene.overlay.showOutline(PonderPalette.GREEN, new Object(), util.select.position(basinPos.down() + .offset(d)), 60); + scene.idle(4); + } + + scene.overlay.showText(80) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .text("After a processing step, basins try to output below to the side of them") + .pointAt(basinSide) + .placeNearTarget(); + scene.idle(90); + + ElementLink depot = + scene.world.showIndependentSection(util.select.position(3, 1, 1), Direction.EAST); + scene.world.moveSection(depot, util.vector.of(-2, 0, 0), 0); + scene.idle(10); + scene.world.modifyBlock(basinPos, s -> s.with(BasinBlock.FACING, Direction.NORTH), false); + scene.idle(10); + + scene.overlay.showText(80) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .text("When a valid component is present, the Basin will show an output faucet") + .pointAt(basinSide.add(0.15, 0, -0.5)) + .placeNearTarget(); + scene.idle(90); + + scene.world.hideIndependentSection(depot, Direction.EAST); + scene.idle(15); + depot = scene.world.showIndependentSection(util.select.position(0, 1, 1), Direction.EAST); + scene.world.moveSection(depot, util.vector.of(1, 0, 0), 0); + scene.idle(20); + scene.world.hideIndependentSection(depot, Direction.EAST); + + scene.overlay.showText(80) + .text("A number of options are applicable here") + .pointAt(util.vector.centerOf(util.grid.at(1, 1, 1))) + .placeNearTarget(); + + scene.idle(15); + depot = scene.world.showIndependentSection(util.select.position(1, 1, 0), Direction.EAST); + scene.world.moveSection(depot, util.vector.of(0, 0, 1), 0); + scene.idle(20); + scene.world.hideIndependentSection(depot, Direction.EAST); + scene.idle(15); + depot = scene.world.showIndependentSection(util.select.position(1, 1, 1), Direction.EAST); + scene.idle(20); + scene.world.hideIndependentSection(depot, Direction.EAST); + scene.idle(15); + depot = scene.world.showIndependentSection(util.select.fromTo(3, 1, 0, 2, 1, 0), Direction.EAST); + scene.world.moveSection(depot, util.vector.of(-2, 0, 1), 0); + scene.idle(20); + scene.world.hideIndependentSection(depot, Direction.EAST); + scene.idle(15); + depot = scene.world.showIndependentSection(util.select.position(2, 1, 1), Direction.EAST); + scene.world.moveSection(depot, util.vector.of(-1, 0, 0), 0); + + scene.idle(25); + + BlockPos pressPos = util.grid.at(1, 4, 2); + scene.world.showSection(util.select.position(pressPos), Direction.DOWN); + scene.idle(5); + scene.world.showSection(util.select.fromTo(1, 4, 3, 1, 1, 5), Direction.NORTH); + scene.idle(10); + + Class type = MechanicalPressTileEntity.class; + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), stack)); + scene.world.modifyTileNBT(util.select.position(basinPos), BasinTileEntity.class, nbt -> { + nbt.put("VisualizedItems", + NBTHelper.writeCompoundList(ImmutableList.of(IntAttached.with(1, new ItemStack(Blocks.BRICKS))), + ia -> ia.getValue() + .serializeNBT())); + }); + scene.idle(4); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos.down() + .north()), Pointing.RIGHT).withItem(new ItemStack(Items.BRICKS)), 30); + + scene.overlay.showText(60) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .text("Outputs will be caught by the inventory below") + .pointAt(basinSide.add(0, -1, -1)) + .placeNearTarget(); + scene.idle(70); + + scene.world.hideIndependentSection(depot, Direction.NORTH); + scene.idle(10); + scene.world.modifyBlock(basinPos, s -> s.with(BasinBlock.FACING, Direction.DOWN), false); + scene.idle(20); + + scene.overlay.showText(80) + .attachKeyFrame() + .text("Without output faucet, the Basin will retain items created in its processing") + .pointAt(basinSide) + .placeNearTarget(); + scene.idle(50); + + ItemStack nugget = AllItems.COPPER_NUGGET.asStack(); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(nugget), + 30); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), nugget)); + + ItemStack ingot = AllItems.COPPER_INGOT.asStack(); + scene.idle(30); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(ingot), + 30); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, pte -> pte.start(Mode.BASIN)); + scene.idle(30); + scene.world.modifyTileEntity(pressPos, type, + pte -> pte.makeCompactingParticleEffect(util.vector.centerOf(basinPos), ingot)); + + ItemStack block = AllBlocks.COPPER_BLOCK.asStack(); + scene.idle(30); + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(basinPos), Pointing.RIGHT).withItem(block), + 30); + scene.overlay.showText(70) + .attachKeyFrame() + .colored(PonderPalette.GREEN) + .text("This can be useful if outputs should be re-used as ingredients") + .pointAt(basinSide) + .placeNearTarget(); + scene.idle(80); + + scene.world.showSection(util.select.fromTo(2, 2, 5, 4, 1, 2), Direction.DOWN); + scene.rotateCameraY(70); + scene.world.createItemOnBelt(util.grid.at(2, 1, 2), Direction.WEST, block); + scene.idle(40); + scene.overlay.showText(70) + .text("Desired outputs will then have to be extracted from the basin") + .pointAt(util.vector.topOf(util.grid.at(3, 1, 2)) + .subtract(0, 3 / 16f, 0)) + .placeNearTarget(); + scene.idle(80); + + Vector3d filter = util.vector.of(2.5, 2.85, 2.5); + scene.overlay.showFilterSlotInput(filter, 80); + scene.overlay.showText(70) + .text("A Filter might be necessary to avoid pulling out un-processed items") + .pointAt(filter) + .placeNearTarget(); + scene.idle(40); + scene.markAsFinished(); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java index 5e1c2c472..4b25a517f 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/InputWindowElement.java @@ -92,7 +92,8 @@ public class InputWindowElement extends AnimatedOverlayElement { if (fade < 1 / 16f) return; - Vector2f sceneToScreen = scene.getTransform().sceneToScreen(sceneSpace); + Vector2f sceneToScreen = scene.getTransform() + .sceneToScreen(sceneSpace, partialTicks); if (hasIcon) { width += 24; diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java index 6f647b9f5..7456ff92b 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java @@ -246,7 +246,7 @@ public class ParrotElement extends AnimatedSceneElement { double mouseX = minecraft.mouseHelper.getMouseX() * w.getScaledWidth() / w.getWidth(); double mouseY = minecraft.mouseHelper.getMouseY() * w.getScaledHeight() / w.getHeight(); return scene.getTransform() - .screenToScene(mouseX, mouseY, 300); + .screenToScene(mouseX, mouseY, 300, 0); } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java index b2d8fcb62..4c98c7450 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/TextWindowElement.java @@ -9,7 +9,6 @@ import com.simibubi.create.foundation.ponder.PonderScene; import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.content.PonderPalette; import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.FontHelper; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Matrix4f; @@ -89,7 +88,7 @@ public class TextWindowElement extends AnimatedOverlayElement { if (fade < 1 / 16f) return; Vector2f sceneToScreen = vec != null ? scene.getTransform() - .sceneToScreen(vec) : new Vector2f(screen.width / 2f, (screen.height - 200) / 2f + y - 8); + .sceneToScreen(vec, partialTicks) : new Vector2f(screen.width / 2, (screen.height - 200) / 2 + y - 8); float yDiff = (screen.height / 2f - sceneToScreen.y - 10) / 100f; int targetX = (int) (screen.width * MathHelper.lerp(yDiff * yDiff, 6f / 8, 5f / 8)); @@ -125,8 +124,12 @@ public class TextWindowElement extends AnimatedOverlayElement { ms.pop(); } - FontHelper.drawSplitString(screen.getFontRenderer(), bakedText, targetX - 10, 3, textWidth, - ColorHelper.applyAlpha(brighterColor, fade)); + for (int i = 0; i < lines.size(); i++) { + ITextProperties s = lines.get(i); + // FIXME: Probably completely broken + screen.getFontRenderer() + .drawTrimmed(s, 20, targetX - 10, 3 + 9 * i, ColorHelper.applyAlpha(brighterColor, fade)); + } ms.pop(); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java index c02751d5d..391b73063 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/TileEntityDataInstruction.java @@ -37,9 +37,9 @@ public class TileEntityDataInstruction extends WorldModifyInstruction { return; CompoundNBT apply = data.apply(tileEntity.write(new CompoundNBT())); BlockState state = world.getBlockState(pos); - tileEntity.fromTag(state, apply); if (tileEntity instanceof SyncedTileEntity) ((SyncedTileEntity) tileEntity).readClientUpdate(state, apply); + tileEntity.fromTag(state, apply); }); } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java index 9f7f8fefb..b100a4a6f 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java @@ -9,6 +9,7 @@ import com.simibubi.create.foundation.gui.IScreenRenderable; import com.simibubi.create.foundation.gui.widgets.AbstractSimiWidget; import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.utility.ColorHelper; +import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.animation.LerpedFloat; import net.minecraft.client.Minecraft; @@ -26,7 +27,7 @@ public class PonderButton extends AbstractSimiWidget { private float fade; private KeyBinding shortcut; private LerpedFloat flash; - private boolean noClickEvent; + private Couple customPassiveBorder; public static final int SIZE = 20; @@ -55,8 +56,8 @@ public class PonderButton extends AbstractSimiWidget { return this; } - public PonderButton noClickEvent() { - this.noClickEvent = true; + public PonderButton customColors(int start, int end) { + this.customPassiveBorder = Couple.create(start, end); return this; } @@ -104,10 +105,10 @@ public class PonderButton extends AbstractSimiWidget { fade *= 3 * flashValue + Math.sin((PonderUI.ponderTicks + partialTicks) / 6); int backgroundColor = ColorHelper.applyAlpha(0xdd000000, fade); - int borderColorStart = - ColorHelper.applyAlpha(noClickEvent ? 0x70984500 : hovered ? 0x70ffffff : 0x40aa9999, fade); - int borderColorEnd = - ColorHelper.applyAlpha(noClickEvent ? 0x70692400 : hovered ? 0x30ffffff : 0x20aa9999, fade); + int borderColorStart = customPassiveBorder != null ? customPassiveBorder.getFirst() : hovered ? 0x70ffffff : 0x40aa9999; + int borderColorEnd = customPassiveBorder != null ? customPassiveBorder.getSecond() : hovered ? 0x30ffffff : 0x20aa9999; + borderColorStart = ColorHelper.applyAlpha(borderColorStart, fade); + borderColorEnd = ColorHelper.applyAlpha(borderColorEnd, fade); PonderUI.renderBox(ms, x, y, width, height, backgroundColor, borderColorStart, borderColorEnd); ms.translate(0, 0, 800); diff --git a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java index 485eb3889..502f4ee3e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java +++ b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java @@ -3,112 +3,137 @@ package com.simibubi.create.foundation.render; import static com.simibubi.create.foundation.render.backend.Backend.register; import com.simibubi.create.Create; -import com.simibubi.create.content.contraptions.base.KineticVertexAttributes; -import com.simibubi.create.content.contraptions.base.RotatingVertexAttributes; +import com.simibubi.create.content.contraptions.base.KineticAttributes; +import com.simibubi.create.content.contraptions.base.RotatingAttributes; import com.simibubi.create.content.contraptions.components.actors.ActorVertexAttributes; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionProgram; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionVertexAttributes; -import com.simibubi.create.content.contraptions.relays.belt.BeltVertexAttributes; -import com.simibubi.create.content.logistics.block.FlapVertexAttributes; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionAttributes; +import com.simibubi.create.content.contraptions.relays.belt.BeltAttributes; +import com.simibubi.create.content.logistics.block.FlapAttributes; import com.simibubi.create.foundation.render.backend.gl.BasicProgram; -import com.simibubi.create.foundation.render.backend.gl.attrib.InstanceVertexAttributes; -import com.simibubi.create.foundation.render.backend.gl.attrib.ModelVertexAttributes; +import com.simibubi.create.foundation.render.backend.instancing.impl.BasicAttributes; +import com.simibubi.create.foundation.render.backend.instancing.impl.TransformAttributes; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelAttributes; +import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedAttributes; import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec; import com.simibubi.create.foundation.render.backend.gl.shader.ShaderConstants; import net.minecraft.util.ResourceLocation; public class AllProgramSpecs { - public static void init() { - // noop, make sure the static field are loaded. - } + public static void init() { + // noop, make sure the static field are loaded. + } - public static final ProgramSpec MODEL = register(ProgramSpec.builder("model", BasicProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(InstanceVertexAttributes.class) - .setVert(Locations.MODEL_VERT) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); + public static final ProgramSpec MODEL = register(ProgramSpec.builder("model", BasicProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(TransformAttributes.class) + .setVert(Locations.MODEL_VERT) + .setFrag(Locations.MODEL_FRAG) + .createProgramSpec()); - public static final ProgramSpec ROTATING = register(ProgramSpec.builder("rotating", BasicProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(KineticVertexAttributes.class) - .addAttributes(RotatingVertexAttributes.class) - .setVert(Locations.ROTATING) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); + public static final ProgramSpec ORIENTED = register(ProgramSpec.builder("oriented", BasicProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(OrientedAttributes.class) + .setVert(Locations.ORIENTED) + .setFrag(Locations.MODEL_FRAG) + .createProgramSpec()); - public static final ProgramSpec BELT = register(ProgramSpec.builder("belt", BasicProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(KineticVertexAttributes.class) - .addAttributes(BeltVertexAttributes.class) - .setVert(Locations.BELT) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); + public static final ProgramSpec ROTATING = register(ProgramSpec.builder("rotating", BasicProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(KineticAttributes.class) + .addAttributes(RotatingAttributes.class) + .setVert(Locations.ROTATING) + .setFrag(Locations.MODEL_FRAG) + .createProgramSpec()); - public static final ProgramSpec FLAPS = register(ProgramSpec.builder("flap", BasicProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(FlapVertexAttributes.class) - .setVert(Locations.FLAP) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); - public static final ProgramSpec C_STRUCTURE = register(ProgramSpec.builder("contraption_structure", ContraptionProgram::new) - .addAttributes(ContraptionVertexAttributes.class) - .setVert(Locations.CONTRAPTION_STRUCTURE) - .setFrag(Locations.CONTRAPTION) - .createProgramSpec()); - public static final ProgramSpec C_MODEL = register(ProgramSpec.builder("contraption_model", ContraptionProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(InstanceVertexAttributes.class) - .setVert(Locations.MODEL_VERT) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_ROTATING = register(ProgramSpec.builder("contraption_rotating", ContraptionProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(KineticVertexAttributes.class) - .addAttributes(RotatingVertexAttributes.class) - .setVert(Locations.ROTATING) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_BELT = register(ProgramSpec.builder("contraption_belt", ContraptionProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(KineticVertexAttributes.class) - .addAttributes(BeltVertexAttributes.class) - .setVert(Locations.BELT) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_FLAPS = register(ProgramSpec.builder("contraption_flap", ContraptionProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(FlapVertexAttributes.class) - .setVert(Locations.FLAP) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_ACTOR = register(ProgramSpec.builder("contraption_actor", ContraptionProgram::new) - .addAttributes(ModelVertexAttributes.class) - .addAttributes(ActorVertexAttributes.class) - .setVert(Locations.CONTRAPTION_ACTOR) - .setFrag(Locations.CONTRAPTION) - .createProgramSpec()); + public static final ProgramSpec BELT = register(ProgramSpec.builder("belt", BasicProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(KineticAttributes.class) + .addAttributes(BeltAttributes.class) + .setVert(Locations.BELT) + .setFrag(Locations.MODEL_FRAG) + .createProgramSpec()); + + public static final ProgramSpec FLAPS = register(ProgramSpec.builder("flap", BasicProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(FlapAttributes.class) + .setVert(Locations.FLAP) + .setFrag(Locations.MODEL_FRAG) + .createProgramSpec()); + public static final ProgramSpec C_STRUCTURE = register(ProgramSpec.builder("contraption_structure", ContraptionProgram::new) + .addAttributes(ContraptionAttributes.class) + .setVert(Locations.CONTRAPTION_STRUCTURE) + .setFrag(Locations.CONTRAPTION) + .createProgramSpec()); + public static final ProgramSpec C_MODEL = register(ProgramSpec.builder("contraption_model", ContraptionProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(TransformAttributes.class) + .setVert(Locations.MODEL_VERT) + .setFrag(Locations.CONTRAPTION) + .setDefines(ShaderConstants.define("CONTRAPTION")) + .createProgramSpec()); + public static final ProgramSpec C_ORIENTED = register(ProgramSpec.builder("contraption_oriented", ContraptionProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(OrientedAttributes.class) + .setVert(Locations.ORIENTED) + .setFrag(Locations.CONTRAPTION) + .setDefines(ShaderConstants.define("CONTRAPTION")) + .createProgramSpec()); + public static final ProgramSpec C_ROTATING = register(ProgramSpec.builder("contraption_rotating", ContraptionProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(KineticAttributes.class) + .addAttributes(RotatingAttributes.class) + .setVert(Locations.ROTATING) + .setFrag(Locations.CONTRAPTION) + .setDefines(ShaderConstants.define("CONTRAPTION")) + .createProgramSpec()); + public static final ProgramSpec C_BELT = register(ProgramSpec.builder("contraption_belt", ContraptionProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(BasicAttributes.class) + .addAttributes(KineticAttributes.class) + .addAttributes(BeltAttributes.class) + .setVert(Locations.BELT) + .setFrag(Locations.CONTRAPTION) + .setDefines(ShaderConstants.define("CONTRAPTION")) + .createProgramSpec()); + public static final ProgramSpec C_FLAPS = register(ProgramSpec.builder("contraption_flap", ContraptionProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(FlapAttributes.class) + .setVert(Locations.FLAP) + .setFrag(Locations.CONTRAPTION) + .setDefines(ShaderConstants.define("CONTRAPTION")) + .createProgramSpec()); + public static final ProgramSpec C_ACTOR = register(ProgramSpec.builder("contraption_actor", ContraptionProgram::new) + .addAttributes(ModelAttributes.class) + .addAttributes(ActorVertexAttributes.class) + .setVert(Locations.CONTRAPTION_ACTOR) + .setFrag(Locations.CONTRAPTION) + .createProgramSpec()); - public static class Locations { - public static final ResourceLocation MODEL_FRAG = loc("model.frag"); - public static final ResourceLocation MODEL_VERT = loc("model.vert"); - public static final ResourceLocation CONTRAPTION = loc("contraption.frag"); + public static class Locations { + public static final ResourceLocation MODEL_FRAG = loc("model.frag"); + public static final ResourceLocation MODEL_VERT = loc("model.vert"); + public static final ResourceLocation ORIENTED = loc("oriented.vert"); + public static final ResourceLocation CONTRAPTION = loc("contraption.frag"); - public static final ResourceLocation ROTATING = loc("rotating.vert"); - public static final ResourceLocation BELT = loc("belt.vert"); - public static final ResourceLocation FLAP = loc("flap.vert"); - public static final ResourceLocation CONTRAPTION_STRUCTURE = loc("contraption_structure.vert"); - public static final ResourceLocation CONTRAPTION_ACTOR = loc("contraption_actor.vert"); + public static final ResourceLocation ROTATING = loc("rotating.vert"); + public static final ResourceLocation BELT = loc("belt.vert"); + public static final ResourceLocation FLAP = loc("flap.vert"); + public static final ResourceLocation CONTRAPTION_STRUCTURE = loc("contraption_structure.vert"); + public static final ResourceLocation CONTRAPTION_ACTOR = loc("contraption_actor.vert"); - private static ResourceLocation loc(String name) { - return new ResourceLocation(Create.ID, name); - } - } + private static ResourceLocation loc(String name) { + return new ResourceLocation(Create.ID, name); + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java index e092ffba5..a94b144f0 100644 --- a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java @@ -3,16 +3,18 @@ package com.simibubi.create.foundation.render; import java.util.ArrayList; import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; -import com.simibubi.create.content.contraptions.base.RotatingInstancedModel; +import com.simibubi.create.content.contraptions.base.RotatingModel; import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel; -import com.simibubi.create.content.logistics.block.FlapInstancedModel; +import com.simibubi.create.content.logistics.block.FlapModel; import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.gl.BasicProgram; import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; -import com.simibubi.create.foundation.render.backend.instancing.impl.BasicInstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedModel; +import com.simibubi.create.foundation.render.backend.instancing.impl.TransformedModel; + import net.minecraft.client.renderer.RenderType; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -26,11 +28,12 @@ public class KineticRenderer extends InstancedTileRenderer { @Override public void registerMaterials() { - materials.put(RenderMaterials.MODELS, new RenderMaterial<>(this, AllProgramSpecs.MODEL, BasicInstancedModel::new)); + materials.put(RenderMaterials.TRANSFORMED, new RenderMaterial<>(this, AllProgramSpecs.MODEL, TransformedModel::new)); + materials.put(RenderMaterials.ORIENTED, new RenderMaterial<>(this, AllProgramSpecs.ORIENTED, OrientedModel::new)); materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.BELT, BeltInstancedModel::new)); - materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.ROTATING, RotatingInstancedModel::new)); - materials.put(KineticRenderMaterials.FLAPS, new RenderMaterial<>(this, AllProgramSpecs.FLAPS, FlapInstancedModel::new)); + materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.ROTATING, RotatingModel::new)); + materials.put(KineticRenderMaterials.FLAPS, new RenderMaterial<>(this, AllProgramSpecs.FLAPS, FlapModel::new)); } @Override diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java b/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java index b1a09fc0a..927b81601 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/RenderMaterials.java @@ -3,7 +3,9 @@ package com.simibubi.create.foundation.render.backend; import com.simibubi.create.foundation.render.backend.instancing.MaterialType; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedData; public class RenderMaterials { - public static final MaterialType> MODELS = new MaterialType<>(); + public static final MaterialType> TRANSFORMED = new MaterialType<>(); + public static final MaterialType> ORIENTED = new MaterialType<>(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java b/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java index af4a78175..ab54cfcaa 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java @@ -6,50 +6,45 @@ import net.minecraft.util.math.vector.Matrix4f; import java.nio.ByteBuffer; public class RenderUtil { - public static int nextPowerOf2(int a) { - int h = Integer.highestOneBit(a); - return (h == a) ? h : (h << 1); - } + public static int nextPowerOf2(int a) { + int h = Integer.highestOneBit(a); + return (h == a) ? h : (h << 1); + } - public static boolean isPowerOf2(int n) { - int b = n & (n - 1); - return b == 0 && n != 0; - } + public static boolean isPowerOf2(int n) { + int b = n & (n - 1); + return b == 0 && n != 0; + } - // GPUs want matrices in column major order. + // GPUs want matrices in column major order. - public static void writeMat3(ByteBuffer buf, Matrix3f mat) { - buf.putFloat(mat.a00); - buf.putFloat(mat.a10); - buf.putFloat(mat.a20); - buf.putFloat(mat.a01); - buf.putFloat(mat.a11); - buf.putFloat(mat.a21); - buf.putFloat(mat.a02); - buf.putFloat(mat.a12); - buf.putFloat(mat.a22); - } - - public static void writeMat4(ByteBuffer buf, Matrix4f mat) { - buf.putFloat(mat.a00); - buf.putFloat(mat.a10); - buf.putFloat(mat.a20); - buf.putFloat(mat.a30); - buf.putFloat(mat.a01); - buf.putFloat(mat.a11); - buf.putFloat(mat.a21); - buf.putFloat(mat.a31); - buf.putFloat(mat.a02); - buf.putFloat(mat.a12); - buf.putFloat(mat.a22); - buf.putFloat(mat.a32); - buf.putFloat(mat.a03); - buf.putFloat(mat.a13); - buf.putFloat(mat.a23); - buf.putFloat(mat.a33); - - - - - } + public static float[] bufferMatrices(Matrix4f model, Matrix3f normal) { + return new float[] { + model.a00, + model.a10, + model.a20, + model.a30, + model.a01, + model.a11, + model.a21, + model.a31, + model.a02, + model.a12, + model.a22, + model.a32, + model.a03, + model.a13, + model.a23, + model.a33, + normal.a00, + normal.a10, + normal.a20, + normal.a01, + normal.a11, + normal.a21, + normal.a02, + normal.a12, + normal.a22, + }; + } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/ModelVertexAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/ModelVertexAttributes.java deleted file mode 100644 index 5fec24349..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/ModelVertexAttributes.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.attrib; - -public enum ModelVertexAttributes implements IVertexAttrib { - VERTEX_POSITION("aPos", CommonAttributes.VEC3), - NORMAL("aNormal", CommonAttributes.NORMAL), - TEXTURE("aTexCoords", CommonAttributes.UV), - ; - - private final String name; - private final VertexAttribSpec spec; - - ModelVertexAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 0; - } - - @Override - public int getBufferIndex() { - return 0; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java new file mode 100644 index 000000000..0af4bc1eb --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +public interface IDynamicInstance { + /** + * Called every frame, this can be used to make more dynamic animations. + */ + void beginFrame(); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java index 4d79545a4..04a6f7ec0 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java @@ -1,8 +1,6 @@ package com.simibubi.create.foundation.render.backend.instancing; public interface ITickableInstance { - /** - * Called every frame, this can be used to make more dynamic animations. - */ + void tick(); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceKey.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceKey.java index 6a3ec6d1e..9927128c2 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceKey.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceKey.java @@ -1,7 +1,5 @@ package com.simibubi.create.foundation.render.backend.instancing; -import java.util.function.Consumer; - public class InstanceKey { public static final int INVALID = -1; diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java index b3f6aa49e..2cefbb58a 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java @@ -3,7 +3,6 @@ package com.simibubi.create.foundation.render.backend.instancing; import java.nio.ByteBuffer; import java.util.*; -import java.util.function.Consumer; import com.simibubi.create.foundation.render.backend.Backend; import com.simibubi.create.foundation.render.backend.RenderUtil; @@ -14,13 +13,13 @@ import org.lwjgl.opengl.GL20; import com.simibubi.create.foundation.render.backend.BufferedModel; import com.simibubi.create.foundation.render.backend.gl.GlBuffer; import com.simibubi.create.foundation.render.backend.gl.GlVertexArray; -import com.simibubi.create.foundation.render.backend.gl.attrib.ModelVertexAttributes; +import com.simibubi.create.foundation.render.backend.instancing.impl.ModelAttributes; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import net.minecraft.client.renderer.BufferBuilder; public abstract class InstancedModel extends BufferedModel { - public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelVertexAttributes.class).build(); + public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build(); public final InstancedTileRenderer renderer; diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java index 6928d8feb..9efc8dc1e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java @@ -4,12 +4,12 @@ import java.util.*; import javax.annotation.Nullable; -import com.simibubi.create.foundation.ponder.PonderWorld; import com.simibubi.create.foundation.render.backend.Backend; import com.simibubi.create.foundation.render.backend.RenderMaterials; import com.simibubi.create.foundation.render.backend.gl.BasicProgram; import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; +import com.simibubi.create.foundation.render.backend.instancing.impl.OrientedData; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; @@ -26,6 +26,7 @@ public abstract class InstancedTileRenderer

{ protected Map> instances = new HashMap<>(); protected Map tickableInstances = new HashMap<>(); + protected Map dynamicInstances = new HashMap<>(); protected Map, RenderMaterial> materials = new HashMap<>(); @@ -45,12 +46,18 @@ public abstract class InstancedTileRenderer

{ if (ticks % 10 == 0) { clean(); } + + if (tickableInstances.size() > 0) + tickableInstances.values().forEach(ITickableInstance::tick); } public void beginFrame(double cameraX, double cameraY, double cameraZ) { - queuedAdditions.forEach(this::add); - queuedAdditions.clear(); - tickableInstances.values().forEach(ITickableInstance::tick); + if (queuedAdditions.size() > 0) { + queuedAdditions.forEach(this::addInternal); + queuedAdditions.clear(); + } + if (dynamicInstances.size() > 0) + dynamicInstances.values().forEach(IDynamicInstance::beginFrame); } public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { @@ -69,35 +76,25 @@ public abstract class InstancedTileRenderer

{ return (RenderMaterial) materials.get(materialType); } - public RenderMaterial> basicMaterial() { - return getMaterial(RenderMaterials.MODELS); + public RenderMaterial> transformMaterial() { + return getMaterial(RenderMaterials.TRANSFORMED); } - @Nullable - public TileEntityInstance getInstance(T tile) { - return getInstance(tile, true); + public RenderMaterial> orientedMaterial() { + return getMaterial(RenderMaterials.ORIENTED); } @SuppressWarnings("unchecked") @Nullable public TileEntityInstance getInstance(T tile, boolean create) { - if (!Backend.canUseInstancing() || !canCreateInstance(tile)) return null; + if (!Backend.canUseInstancing()) return null; TileEntityInstance instance = instances.get(tile); if (instance != null) { return (TileEntityInstance) instance; - } else if (create) { - TileEntityInstance renderer = InstancedTileRenderRegistry.instance.create(this, tile); - - if (renderer != null) { - instances.put(tile, renderer); - - if (renderer instanceof ITickableInstance) - tickableInstances.put(tile, (ITickableInstance) renderer); - } - - return renderer; + } else if (create && canCreateInstance(tile)) { + return createInternal(tile); } else { return null; } @@ -118,7 +115,7 @@ public abstract class InstancedTileRenderer

{ if (!Backend.canUseInstancing()) return; if (tile instanceof IInstanceRendered) { - getInstance(tile); + addInternal(tile); } } @@ -134,8 +131,16 @@ public abstract class InstancedTileRenderer

{ if (tile instanceof IInstanceRendered) { TileEntityInstance instance = getInstance(tile, false); - if (instance != null) - instance.update(); + if (instance != null) { + + if (instance.shouldReset()) { + removeInternal(tile, instance); + + createInternal(tile); + } else { + instance.update(); + } + } } } @@ -143,17 +148,46 @@ public abstract class InstancedTileRenderer

{ if (!Backend.canUseInstancing()) return; if (tile instanceof IInstanceRendered) { - TileEntityInstance instance = getInstance(tile, false); - - if (instance != null) { - instance.remove(); - instances.remove(tile); - tickableInstances.remove(tile); - } + removeInternal(tile); } } - public void clean() { + private void addInternal(TileEntity tile) { + getInstance(tile, true); + } + + private void removeInternal(T tile) { + TileEntityInstance instance = getInstance(tile, false); + + if (instance != null) { + removeInternal(tile, instance); + } + } + + private void removeInternal(TileEntity tile, TileEntityInstance instance) { + instance.remove(); + instances.remove(tile); + dynamicInstances.remove(tile); + tickableInstances.remove(tile); + } + + private TileEntityInstance createInternal(T tile) { + TileEntityInstance renderer = InstancedTileRenderRegistry.instance.create(this, tile); + + if (renderer != null) { + instances.put(tile, renderer); + + if (renderer instanceof IDynamicInstance) + dynamicInstances.put(tile, (IDynamicInstance) renderer); + + if (renderer instanceof ITickableInstance) + tickableInstances.put(tile, ((ITickableInstance) renderer)); + } + + return renderer; + } + + private void clean() { instances.keySet().removeIf(TileEntity::isRemoved); } @@ -162,7 +196,7 @@ public abstract class InstancedTileRenderer

{ material.delete(); } instances.clear(); - tickableInstances.clear(); + dynamicInstances.clear(); } public boolean canCreateInstance(TileEntity tile) { diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/MaterialType.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/MaterialType.java index 48ade4b2a..bda912737 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/MaterialType.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/MaterialType.java @@ -1,3 +1,10 @@ package com.simibubi.create.foundation.render.backend.instancing; -public class MaterialType { } +import com.simibubi.create.foundation.render.backend.gl.BasicProgram; + +public class MaterialType> { + + public

RenderMaterial get(InstancedTileRenderer

renderer) { + return renderer.getMaterial(this); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java index b5241999c..4c66529da 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java @@ -1,7 +1,6 @@ package com.simibubi.create.foundation.render.backend.instancing; import com.simibubi.create.foundation.render.backend.instancing.impl.IFlatLight; -import com.simibubi.create.foundation.render.backend.instancing.impl.ModelData; import net.minecraft.block.BlockState; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; @@ -17,38 +16,23 @@ public abstract class TileEntityInstance { protected final T tile; protected final World world; protected final BlockPos pos; - protected BlockState lastState; + protected final BlockState blockState; public TileEntityInstance(InstancedTileRenderer modelManager, T tile) { this.modelManager = modelManager; this.tile = tile; this.world = tile.getWorld(); this.pos = tile.getPos(); - this.lastState = tile.getBlockState(); - init(); - } - - public final void update() { - BlockState currentState = tile.getBlockState(); - if (lastState == currentState) { - onUpdate(); - } else { - remove(); - lastState = currentState; - init(); - } + this.blockState = tile.getBlockState(); } /** - * Acquire all {@link InstanceKey}s and initialize any data you may need to calculate the instance properties. + * Update instance data here. Good for when data doesn't change very often and when animations are GPU based. + * Don't query lighting data here, that's handled separately in {@link #updateLight()}. + * + * If your animations are complex and more CPU driven, use {@link IDynamicInstance} or {@link ITickableInstance}. */ - protected abstract void init(); - - /** - * Update changed instance data using the {@link InstanceKey}s you got in {@link #init()}. - * You don't have to update light data. That should be done in {@link #updateLight()} - */ - protected void onUpdate() { } + protected void update() { } /** * Called when a light update occurs in the world. If your model needs it, update light here. @@ -60,23 +44,27 @@ public abstract class TileEntityInstance { */ public abstract void remove(); + public boolean shouldReset() { + return tile.getBlockState() != blockState; + } + public BlockPos getFloatingPos() { return pos.subtract(modelManager.getOriginCoordinate()); } - protected > void relight(BlockPos pos, IFlatLight... models) { + protected void relight(BlockPos pos, IFlatLight... models) { relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models); } - protected > void relight(BlockPos pos, Stream> models) { + protected void relight(BlockPos pos, Stream> models) { relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models); } - protected > void relight(int block, int sky, IFlatLight... models) { + protected void relight(int block, int sky, IFlatLight... models) { relight(block, sky, Arrays.stream(models)); } - protected > void relight(int block, int sky, Stream> models) { + protected void relight(int block, int sky, Stream> models) { models.forEach(model -> model.setBlockLight(block).setSkyLight(sky)); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicAttributes.java new file mode 100644 index 000000000..0223037a7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicAttributes.java @@ -0,0 +1,39 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; + +public enum BasicAttributes implements IVertexAttrib { + LIGHT("aLight", CommonAttributes.LIGHT), + COLOR("aColor", CommonAttributes.RGBA), + ; + + private final String name; + private final IAttribSpec spec; + + BasicAttributes(String name, IAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public IAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 0; + } + + @Override + public int getBufferIndex() { + return 0; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicData.java new file mode 100644 index 000000000..38fba8424 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicData.java @@ -0,0 +1,73 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import java.nio.ByteBuffer; +import com.simibubi.create.foundation.render.backend.instancing.InstanceData; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; + +public class BasicData extends InstanceData implements IFlatLight { + + protected byte blockLight; + protected byte skyLight; + + protected byte r = (byte) 0xFF; + protected byte g = (byte) 0xFF; + protected byte b = (byte) 0xFF; + protected byte a = (byte) 0xFF; + + public BasicData(InstancedModel owner) { + super(owner); + } + + @Override + public BasicData setBlockLight(int blockLight) { + this.blockLight = (byte) (blockLight << 4); + return this; + } + + @Override + public BasicData setSkyLight(int skyLight) { + this.skyLight = (byte) (skyLight << 4); + return this; + } + + public BasicData setColor(int color) { + return setColor(color, false); + } + + public BasicData setColor(int color, boolean alpha) { + byte r = (byte) ((color >> 16) & 0xFF); + byte g = (byte) ((color >> 8) & 0xFF); + byte b = (byte) (color & 0xFF); + + if (alpha) { + byte a = (byte) ((color >> 24) & 0xFF); + return setColor(r, g, b, a); + } else { + return setColor(r, g, b); + } + } + + public BasicData setColor(int r, int g, int b) { + return setColor((byte) r, (byte) g, (byte) b); + } + + public BasicData setColor(byte r, byte g, byte b) { + this.r = r; + this.g = g; + this.b = b; + return this; + } + + public BasicData setColor(byte r, byte g, byte b, byte a) { + this.r = r; + this.g = g; + this.b = b; + this.a = a; + return this; + } + + @Override + public void write(ByteBuffer buf) { + buf.put(new byte[] { blockLight, skyLight, r, g, b, a }); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelAttributes.java new file mode 100644 index 000000000..8854f3550 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelAttributes.java @@ -0,0 +1,41 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; +import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; + +public enum ModelAttributes implements IVertexAttrib { + VERTEX_POSITION("aPos", CommonAttributes.VEC3), + NORMAL("aNormal", CommonAttributes.NORMAL), + TEXTURE("aTexCoords", CommonAttributes.UV), + ; + + private final String name; + private final VertexAttribSpec spec; + + ModelAttributes(String name, VertexAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public IAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 0; + } + + @Override + public int getBufferIndex() { + return 0; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java index 827dad117..170d555a7 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/ModelData.java @@ -2,101 +2,28 @@ package com.simibubi.create.foundation.render.backend.instancing.impl; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.render.backend.RenderUtil; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import net.minecraft.util.math.vector.Matrix3f; -import net.minecraft.util.math.vector.Matrix4f; import java.nio.ByteBuffer; -public class ModelData extends InstanceData implements IFlatLight { - private static final Matrix4f IDENT4 = new Matrix4f(); - private static final Matrix3f IDENT3 = new Matrix3f(); - static { - IDENT4.loadIdentity(); - IDENT3.loadIdentity(); - } +public class ModelData extends BasicData { + private static final float[] empty = new float[25]; - private Matrix4f modelMat = IDENT4; - private Matrix3f normalMat = IDENT3; - - private byte blockLight; - private byte skyLight; - - private byte r = (byte) 0xFF; - private byte g = (byte) 0xFF; - private byte b = (byte) 0xFF; - private byte a = (byte) 0xFF; + private float[] matrices = empty; public ModelData(InstancedModel owner) { super(owner); } - public ModelData setModelMat(Matrix4f modelMat) { - this.modelMat = modelMat; - return this; - } - - public ModelData setNormalMat(Matrix3f normalMat) { - this.normalMat = normalMat; - return this; - } - public ModelData setTransform(MatrixStack stack) { - this.modelMat = stack.peek().getModel().copy(); - this.normalMat = stack.peek().getNormal().copy(); - return this; - } - - public ModelData setTransformNoCopy(MatrixStack stack) { - this.modelMat = stack.peek().getModel(); - this.normalMat = stack.peek().getNormal(); - return this; - } - - @Override - public ModelData setBlockLight(int blockLight) { - this.blockLight = (byte) (blockLight << 4); - return this; - } - - @Override - public ModelData setSkyLight(int skyLight) { - this.skyLight = (byte) (skyLight << 4); - return this; - } - - public ModelData setColor(int color) { - byte a = (byte) ((color >> 24) & 0xFF); - byte r = (byte) ((color >> 16) & 0xFF); - byte g = (byte) ((color >> 8) & 0xFF); - byte b = (byte) (color & 0xFF); - return setColor(r, g, b); - } - - public ModelData setColor(int r, int g, int b) { - return setColor((byte) r, (byte) g, (byte) b); - } - - public ModelData setColor(byte r, byte g, byte b) { - this.r = r; - this.g = g; - this.b = b; - return this; - } - - public ModelData setColor(byte r, byte g, byte b, byte a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; + matrices = RenderUtil.bufferMatrices(stack.peek().getModel(), stack.peek().getNormal()); return this; } @Override public void write(ByteBuffer buf) { - RenderUtil.writeMat4(buf, modelMat); - RenderUtil.writeMat3(buf, normalMat); - buf.put(new byte[] { blockLight, skyLight, r, g, b, a }); + super.write(buf); + buf.asFloatBuffer().put(matrices); + buf.position(buf.position() + matrices.length * 4); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedAttributes.java new file mode 100644 index 000000000..a5a7cef0d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedAttributes.java @@ -0,0 +1,40 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; + +public enum OrientedAttributes implements IVertexAttrib { + INSTANCE_POS("aInstancePos", CommonAttributes.VEC3), + PIVOT("aPivot", CommonAttributes.VEC3), + ROTATION("aRotation", CommonAttributes.QUATERNION), + ; + + private final String name; + private final IAttribSpec spec; + + OrientedAttributes(String name, IAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public IAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 0; + } + + @Override + public int getBufferIndex() { + return 0; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedData.java new file mode 100644 index 000000000..be5fdf8f7 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedData.java @@ -0,0 +1,107 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import net.minecraft.util.math.BlockPos; + +import java.nio.ByteBuffer; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3f; + +public class OrientedData extends BasicData { + + private float posX; + private float posY; + private float posZ; + private float pivotX = 0.5f; + private float pivotY = 0.5f; + private float pivotZ = 0.5f; + private float qX; + private float qY; + private float qZ; + private float qW; + + + public OrientedData(InstancedModel owner) { + super(owner); + } + + + public OrientedData setPosition(BlockPos pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + public OrientedData setPosition(Vector3f pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + public OrientedData setPosition(int x, int y, int z) { + BlockPos origin = owner.renderer.getOriginCoordinate(); + + return setPosition((float) (x - origin.getX()), + (float) (y - origin.getY()), + (float) (z - origin.getZ())); + } + + public OrientedData setPosition(float x, float y, float z) { + this.posX = x; + this.posY = y; + this.posZ = z; + return this; + } + + public OrientedData nudge(float x, float y, float z) { + this.posX += x; + this.posY += y; + this.posZ += z; + return this; + } + + public OrientedData setPivot(Vector3f pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + public OrientedData setPivot(Vector3d pos) { + return setPosition((float) pos.getX(), (float) pos.getY(), (float) pos.getZ()); + } + + public OrientedData setPivot(float x, float y, float z) { + this.pivotX = x; + this.pivotY = y; + this.pivotZ = z; + return this; + } + + public OrientedData setRotation(Quaternion q) { + return setRotation(q.getX(), q.getY(), q.getZ(), q.getW()); + } + + public OrientedData setRotation(float x, float y, float z, float w) { + this.qX = x; + this.qY = y; + this.qZ = z; + this.qW = w; + return this; + } + + @Override + public void write(ByteBuffer buf) { + super.write(buf); + + buf.asFloatBuffer().put(new float[] { + posX, + posY, + posZ, + pivotX, + pivotY, + pivotZ, + qX, + qY, + qZ, + qW + }); + + buf.position(buf.position() + 10 * 4); + } +} + diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedModel.java new file mode 100644 index 000000000..0389d119c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/OrientedModel.java @@ -0,0 +1,28 @@ +package com.simibubi.create.foundation.render.backend.instancing.impl; + +import net.minecraft.client.renderer.BufferBuilder; + +import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +public class OrientedModel extends InstancedModel { + public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder() + .addAttributes(BasicAttributes.class) + .addAttributes(OrientedAttributes.class) + .build(); + + public OrientedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + super(renderer, buf); + } + + @Override + protected OrientedData newInstance() { + return new OrientedData(this); + } + + @Override + protected VertexFormat getInstanceFormat() { + return INSTANCE_FORMAT; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformAttributes.java similarity index 56% rename from src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java rename to src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformAttributes.java index dacecf161..31daa9542 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/InstanceVertexAttributes.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformAttributes.java @@ -1,16 +1,18 @@ -package com.simibubi.create.foundation.render.backend.gl.attrib; +package com.simibubi.create.foundation.render.backend.instancing.impl; -public enum InstanceVertexAttributes implements IVertexAttrib { +import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; +import com.simibubi.create.foundation.render.backend.gl.attrib.MatrixAttributes; + +public enum TransformAttributes implements IVertexAttrib { TRANSFORM("aTransform", MatrixAttributes.MAT4), NORMAL_MAT("aNormalMat", MatrixAttributes.MAT3), - LIGHT("aLight", CommonAttributes.LIGHT), - COLOR("aColor", CommonAttributes.RGBA), ; private final String name; private final IAttribSpec spec; - InstanceVertexAttributes(String name, IAttribSpec spec) { + TransformAttributes(String name, IAttribSpec spec) { this.name = name; this.spec = spec; } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicInstancedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformedModel.java similarity index 68% rename from src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicInstancedModel.java rename to src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformedModel.java index cd67de720..27fef7d04 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/BasicInstancedModel.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/impl/TransformedModel.java @@ -1,15 +1,17 @@ package com.simibubi.create.foundation.render.backend.instancing.impl; -import com.simibubi.create.foundation.render.backend.gl.attrib.InstanceVertexAttributes; import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import net.minecraft.client.renderer.BufferBuilder; -public class BasicInstancedModel extends InstancedModel { - public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder().addAttributes(InstanceVertexAttributes.class).build(); +public class TransformedModel extends InstancedModel { + public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder() + .addAttributes(BasicAttributes.class) + .addAttributes(TransformAttributes.class) + .build(); - public BasicInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + public TransformedModel(InstancedTileRenderer renderer, BufferBuilder buf) { super(renderer, buf); } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java index 82ecd770d..b8d499010 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java @@ -6,6 +6,7 @@ import com.simibubi.create.foundation.render.backend.RenderUtil; import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.SectionPos; import net.minecraft.util.math.vector.Vector3i; @@ -34,7 +35,7 @@ public class GridAlignedBB { return new GridAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); } - public static GridAlignedBB fromAABB(AxisAlignedBB aabb) { + public static GridAlignedBB from(AxisAlignedBB aabb) { int minX = (int) Math.floor(aabb.minX); int minY = (int) Math.floor(aabb.minY); int minZ = (int) Math.floor(aabb.minZ); @@ -44,7 +45,7 @@ public class GridAlignedBB { return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); } - public static GridAlignedBB fromSection(SectionPos pos) { + public static GridAlignedBB from(SectionPos pos) { return new GridAlignedBB(pos.getWorldStartX(), pos.getWorldStartY(), pos.getWorldStartZ(), @@ -53,7 +54,16 @@ public class GridAlignedBB { pos.getWorldEndZ() + 1); } - public static GridAlignedBB fromChunk(int sectionX, int sectionZ) { + public static GridAlignedBB from(BlockPos start, BlockPos end) { + return new GridAlignedBB(start.getX(), + start.getY(), + start.getZ(), + end.getX() + 1, + end.getY() + 1, + end.getZ() + 1); + } + + public static GridAlignedBB from(int sectionX, int sectionZ) { int startX = sectionX << 4; int startZ = sectionZ << 4; return new GridAlignedBB(startX, @@ -81,6 +91,22 @@ public class GridAlignedBB { maxZ == other.maxZ; } + public void fixMinMax() { + int minX = Math.min(this.minX, this.maxX); + int minY = Math.min(this.minY, this.maxY); + int minZ = Math.min(this.minZ, this.maxZ); + int maxX = Math.max(this.minX, this.maxX); + int maxY = Math.max(this.minY, this.maxY); + int maxZ = Math.max(this.minZ, this.maxZ); + + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + } + public int sizeX() { return maxX - minX; } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/ILightListener.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/ILightListener.java deleted file mode 100644 index 5fd2ff8bd..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/ILightListener.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.simibubi.create.foundation.render.backend.light; - -public interface ILightListener { - void onChunkLightUpdate(); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdateListener.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdateListener.java new file mode 100644 index 000000000..09ea1a04d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdateListener.java @@ -0,0 +1,32 @@ +package com.simibubi.create.foundation.render.backend.light; + +import net.minecraft.world.IBlockDisplayReader; +import net.minecraft.world.LightType; + +/** + * Anything can implement this, implementors should call {@link LightUpdater#startListening} + * appropriately to make sure they get the updates they want. + */ +public interface LightUpdateListener { + + /** + * Called when a light updates in a chunk the implementor cares about. + * + * @return true if this object is no longer valid and should not receive any more updates. + */ + boolean onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed); + + /** + * Called when the server sends light data to the client. + * + * @return true if this object is no longer valid and should not receive any more updates. + */ + default boolean onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { + GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ); + + if (onLightUpdate(world, LightType.BLOCK, changedVolume)) + return true; + + return onLightUpdate(world, LightType.SKY, changedVolume); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdater.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdater.java new file mode 100644 index 000000000..6c77f3180 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdater.java @@ -0,0 +1,192 @@ +package com.simibubi.create.foundation.render.backend.light; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.LongRBTreeSet; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.SectionPos; +import net.minecraft.world.IBlockDisplayReader; +import net.minecraft.world.LightType; + +import java.util.*; +import java.util.function.LongConsumer; +import com.simibubi.create.foundation.utility.WeakHashSet; + +/** + * By using WeakReferences we can automatically remove listeners when they are garbage collected. + * This allows us to easily be more clever about how we store the listeners. Each listener is associated + * with 2 sets of longs indicating what chunks and sections each listener is in. Additionally, a reverse + * mapping is created to allow for fast lookups when light updates. The reverse mapping is more interesting, + * but {@link #listenersToSections}, and {@link #listenersToChunks} are used to know what sections and + * chunks we need to remove the listeners from if they re-subscribe. Otherwise, listeners could get updates + * they no longer care about. This is done in {@link #clearSections} and {@link #clearChunks} + */ +public class LightUpdater { + + private static LightUpdater instance; + + public static LightUpdater getInstance() { + if (instance == null) + instance = new LightUpdater(); + + return instance; + } + + private final Long2ObjectMap> sections; + private final WeakHashMap listenersToSections; + + private final Long2ObjectMap> chunks; + private final WeakHashMap listenersToChunks; + + public LightUpdater() { + sections = new Long2ObjectOpenHashMap<>(); + listenersToSections = new WeakHashMap<>(); + + chunks = new Long2ObjectOpenHashMap<>(); + listenersToChunks = new WeakHashMap<>(); + } + + /** + * Add a listener associated with the given {@link BlockPos}. + * + * When a light update occurs in the chunk the position is contained in, + * {@link LightUpdateListener#onLightUpdate} will be called. + * + * @param pos The position in the world that the listener cares about. + * @param listener The object that wants to receive light update notifications. + */ + public void startListening(BlockPos pos, LightUpdateListener listener) { + LongRBTreeSet sections = clearSections(listener); + LongRBTreeSet chunks = clearChunks(listener); + + long sectionPos = worldToSection(pos); + addToSection(sectionPos, listener); + sections.add(sectionPos); + + long chunkPos = sectionToChunk(sectionPos); + addToChunk(chunkPos, listener); + chunks.add(chunkPos); + } + + /** + * Add a listener associated with the given {@link GridAlignedBB}. + * + * When a light update occurs in any chunk spanning the given volume, + * {@link LightUpdateListener#onLightUpdate} will be called. + * + * @param volume The volume in the world that the listener cares about. + * @param listener The object that wants to receive light update notifications. + */ + public void startListening(GridAlignedBB volume, LightUpdateListener listener) { + LongRBTreeSet sections = clearSections(listener); + LongRBTreeSet chunks = clearSections(listener); + + int minX = SectionPos.toChunk(volume.minX); + int minY = SectionPos.toChunk(volume.minY); + int minZ = SectionPos.toChunk(volume.minZ); + int maxX = SectionPos.toChunk(volume.maxX); + int maxY = SectionPos.toChunk(volume.maxY); + int maxZ = SectionPos.toChunk(volume.maxZ); + + for (int x = minX; x <= maxX; x++) { + for (int z = minZ; z <= maxZ; z++) { + for (int y = minY; y <= maxY; y++) { + long sectionPos = SectionPos.asLong(x, y, z); + addToSection(sectionPos, listener); + sections.add(sectionPos); + } + long chunkPos = SectionPos.asLong(x, 0, z); + addToChunk(chunkPos, listener); + chunks.add(chunkPos); + } + } + } + + /** + * Dispatch light updates to all registered {@link LightUpdateListener}s. + * + * @param world The world in which light was updated. + * @param type The type of light that changed. + * @param sectionPos A long representing the section position where light changed. + */ + public void onLightUpdate(IBlockDisplayReader world, LightType type, long sectionPos) { + WeakHashSet set = sections.get(sectionPos); + + if (set == null || set.isEmpty()) return; + + GridAlignedBB chunkBox = GridAlignedBB.from(SectionPos.from(sectionPos)); + + set.removeIf(listener -> listener.onLightUpdate(world, type, chunkBox.copy())); + } + + /** + * Dispatch light updates to all registered {@link LightUpdateListener}s + * when the server sends lighting data for an entire chunk. + * + * @param world The world in which light was updated. + */ + public void onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { + + long chunkPos = SectionPos.asLong(chunkX, 0, chunkZ); + + WeakHashSet set = chunks.get(chunkPos); + + if (set == null || set.isEmpty()) return; + + set.removeIf(listener -> listener.onLightPacket(world, chunkX, chunkZ)); + } + + private LongRBTreeSet clearChunks(LightUpdateListener listener) { + return clear(listener, listenersToChunks, chunks); + } + + private LongRBTreeSet clearSections(LightUpdateListener listener) { + return clear(listener, listenersToSections, sections); + } + + private LongRBTreeSet clear(LightUpdateListener listener, WeakHashMap listeners, Long2ObjectMap> lookup) { + LongRBTreeSet set = listeners.get(listener); + + if (set == null) { + set = new LongRBTreeSet(); + listeners.put(listener, set); + } else { + set.forEach((LongConsumer) l -> { + WeakHashSet listeningSections = lookup.get(l); + + if (listeningSections != null) listeningSections.remove(listener); + }); + + set.clear(); + } + + return set; + } + + private void addToSection(long sectionPos, LightUpdateListener listener) { + getOrCreate(sections, sectionPos).add(listener); + } + + private void addToChunk(long chunkPos, LightUpdateListener listener) { + getOrCreate(chunks, chunkPos).add(listener); + } + + private WeakHashSet getOrCreate(Long2ObjectMap> sections, long chunkPos) { + WeakHashSet set = sections.get(chunkPos); + + if (set == null) { + set = new WeakHashSet<>(); + sections.put(chunkPos, set); + } + + return set; + } + + public static long worldToSection(BlockPos pos) { + return SectionPos.asLong(pos.getX(), pos.getY(), pos.getZ()); + } + + public static long sectionToChunk(long sectionPos) { + return sectionPos & 0xFFFFFFFFFFF_00000L; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java index 933f99e35..095d179db 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java @@ -123,18 +123,22 @@ public class LightVolume { } } - public void notifyLightUpdate(IBlockDisplayReader world, LightType type, SectionPos location) { - GridAlignedBB changedVolume = GridAlignedBB.fromSection(location); + public void notifyLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changedVolume) { + if (removed) + return; + if (!changedVolume.intersects(sampleVolume)) return; - changedVolume.intersectAssign(sampleVolume); // compute the region contained by us that has dirty lighting data. + changedVolume = changedVolume.intersect(sampleVolume); // compute the region contained by us that has dirty lighting data. if (type == LightType.BLOCK) copyBlock(world, changedVolume); else if (type == LightType.SKY) copySky(world, changedVolume); } public void notifyLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { - GridAlignedBB changedVolume = GridAlignedBB.fromChunk(chunkX, chunkZ); + if (removed) return; + + GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ); if (!changedVolume.intersects(sampleVolume)) return; changedVolume.intersectAssign(sampleVolume); // compute the region contained by us that has dirty lighting data. diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java index ed571d3a5..f7f0164e0 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/belt/DirectBeltInputBehaviour.java @@ -47,7 +47,7 @@ public class DirectBeltInputBehaviour extends TileEntityBehaviour { supportsBeltFunnels = pred; return this; } - + public DirectBeltInputBehaviour allowingBeltFunnels() { supportsBeltFunnels = () -> true; return this; @@ -97,20 +97,21 @@ public class DirectBeltInputBehaviour extends TileEntityBehaviour { public boolean test(Direction side); } + @Nullable public ItemStack tryExportingToBeltFunnel(ItemStack stack, @Nullable Direction side) { BlockPos funnelPos = tileEntity.getPos() .up(); World world = getWorld(); BlockState funnelState = world.getBlockState(funnelPos); if (!(funnelState.getBlock() instanceof BeltFunnelBlock)) - return stack; + return null; if (funnelState.get(BeltFunnelBlock.SHAPE) != Shape.PULLING) - return stack; + return null; if (side != null && FunnelBlock.getFunnelFacing(funnelState) != side) - return stack; + return null; TileEntity te = world.getTileEntity(funnelPos); if (!(te instanceof FunnelTileEntity)) - return stack; + return null; ItemStack insert = FunnelBlock.tryInsert(world, funnelPos, stack, false); if (insert.getCount() != stack.getCount()) ((FunnelTileEntity) te).flap(true); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java index 23df51f8f..a72e40dc2 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.tileEntity.renderer; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -21,8 +22,10 @@ public abstract class ColoredOverlayTileEntityRenderer ext @Override protected void renderSafe(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - SuperByteBuffer render = render(te.getWorld(), te.getPos(), te.getBlockState(), getOverlayBuffer(te), - getColor(te, partialTicks)); + + if (FastRenderDispatcher.available(te.getWorld())) return; + + SuperByteBuffer render = render(getOverlayBuffer(te), getColor(te, partialTicks), light); render.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); } @@ -30,10 +33,8 @@ public abstract class ColoredOverlayTileEntityRenderer ext protected abstract SuperByteBuffer getOverlayBuffer(T te); - public static SuperByteBuffer render(World world, BlockPos pos, BlockState state, SuperByteBuffer buffer, - int color) { - int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(world, state, pos); - return buffer.color(color).light(packedLightmapCoords); + public static SuperByteBuffer render(SuperByteBuffer buffer, int color, int light) { + return buffer.color(color).light(light); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java index 1f39b14ae..713d9bedf 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -61,7 +61,7 @@ public class VecHelper { public static boolean isVecPointingTowards(Vector3d vec, Direction direction) { return Vector3d.of(direction.getDirectionVec()).dotProduct(vec.normalize()) > 0; - //return new Vec3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75; + //return new Vector3d(direction.getDirectionVec()).distanceTo(vec.normalize()) < .75; } public static Vector3d getCenterOf(Vector3i pos) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/WeakHashSet.java b/src/main/java/com/simibubi/create/foundation/utility/WeakHashSet.java new file mode 100644 index 000000000..e4c5c6688 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/WeakHashSet.java @@ -0,0 +1,114 @@ +package com.simibubi.create.foundation.utility; + +import net.minecraft.util.Unit; + +import java.util.*; + +public class WeakHashSet extends AbstractSet { + + WeakHashMap map; + + public WeakHashSet() { + map = new WeakHashMap<>(); + } + + /** + * Constructs a new set containing the elements in the specified + * collection. The HashMap is created with default load factor + * (0.75) and an initial capacity sufficient to contain the elements in + * the specified collection. + * + * @param c the collection whose elements are to be placed into this set + * @throws NullPointerException if the specified collection is null + */ + public WeakHashSet(Collection c) { + map = new WeakHashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); + addAll(c); + } + + /** + * Constructs a new, empty set; the backing HashMap instance has + * the specified initial capacity and the specified load factor. + * + * @param initialCapacity the initial capacity of the hash map + * @param loadFactor the load factor of the hash map + * @throws IllegalArgumentException if the initial capacity is less + * than zero, or if the load factor is nonpositive + */ + public WeakHashSet(int initialCapacity, float loadFactor) { + map = new WeakHashMap<>(initialCapacity, loadFactor); + } + + /** + * Constructs a new, empty set; the backing HashMap instance has + * the specified initial capacity and default load factor (0.75). + * + * @param initialCapacity the initial capacity of the hash table + * @throws IllegalArgumentException if the initial capacity is less + * than zero + */ + public WeakHashSet(int initialCapacity) { + map = new WeakHashMap<>(initialCapacity); + } + + + @Override + public Iterator iterator() { + return map.keySet().iterator(); + } + + @Override + public int size() { + return map.size(); + } + + @Override + public boolean add(T t) { + return map.put(t, Unit.INSTANCE) == null; + } + + @Override + public boolean remove(Object o) { + return map.remove((T) o) != null; + } + + @Override + public boolean isEmpty() { + return map.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return map.containsKey((T) o); + } + + @Override + public Object[] toArray() { + return map.keySet().toArray(); + } + + @Override + public boolean containsAll(Collection c) { + return c.stream().allMatch(map::containsKey); + } + + @Override + public boolean addAll(Collection c) { + return false; + } + + @Override + public boolean retainAll(Collection c) { + return false; + } + + @Override + public boolean removeAll(Collection c) { + return false; + } + + @Override + public void clear() { + map.clear(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java index 0a30866a8..d0c37472e 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java @@ -138,8 +138,8 @@ public abstract class GhostBlockRenderer { //IVertexBuilder static void quad(float alpha, IVertexBuilder vb, MatrixStack.Entry p_227890_1_, BakedQuad p_227890_2_, float[] p_227890_3_, float p_227890_4_, float p_227890_5_, float p_227890_6_, int[] p_227890_7_, int p_227890_8_) { int[] aint = p_227890_2_.getVertexData(); - Vector3i vec3i = p_227890_2_.getFace().getDirectionVec(); - Vector3f vector3f = new Vector3f((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ()); + Vector3i Vector3i = p_227890_2_.getFace().getDirectionVec(); + Vector3f vector3f = new Vector3f((float) Vector3i.getX(), (float) Vector3i.getY(), (float) Vector3i.getZ()); Matrix4f matrix4f = p_227890_1_.getModel(); vector3f.transform(p_227890_1_.getNormal()); int vertexSize = DefaultVertexFormats.BLOCK.getIntegerSize(); diff --git a/src/main/resources/assets/create/flywheel/shaders/belt.vert b/src/main/resources/assets/create/flywheel/shaders/belt.vert index 08e776ef6..3a5fefcec 100644 --- a/src/main/resources/assets/create/flywheel/shaders/belt.vert +++ b/src/main/resources/assets/create/flywheel/shaders/belt.vert @@ -9,9 +9,9 @@ attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; -attribute vec3 aInstancePos; attribute vec2 aLight; -attribute vec3 aNetworkTint; +attribute vec4 aColor; +attribute vec3 aInstancePos; attribute float aSpeed; attribute float aOffset; attribute vec4 aInstanceRot; @@ -77,7 +77,7 @@ void main() { } #else if (uDebug == 1) { - Color = vec4(aNetworkTint, 1.); + Color = aColor; } else if (uDebug == 2) { Color = vec4(norm, 1.); } else { diff --git a/src/main/resources/assets/create/flywheel/shaders/model.vert b/src/main/resources/assets/create/flywheel/shaders/model.vert index 9767a122c..ea4503b75 100644 --- a/src/main/resources/assets/create/flywheel/shaders/model.vert +++ b/src/main/resources/assets/create/flywheel/shaders/model.vert @@ -7,10 +7,10 @@ attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; -attribute mat4 aTransform; -attribute mat3 aNormalMat; attribute vec2 aLight; attribute vec4 aColor; +attribute mat4 aTransform; +attribute mat3 aNormalMat; varying vec2 TexCoords; varying vec4 Color; @@ -38,11 +38,11 @@ varying float FragDistance; void main() { vec4 worldPos = aTransform * vec4(aPos, 1.); - mat3 normalMat = aNormalMat; + vec3 norm = aNormalMat * aNormal; #ifdef CONTRAPTION worldPos = uModel * worldPos; - normalMat *= modelToNormal(uModel); + norm = modelToNormal(uModel) * norm; BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; #if defined(USE_FOG) @@ -52,7 +52,7 @@ void main() { FragDistance = length(worldPos.xyz - uCameraPos); #endif - vec3 norm = normalize(normalMat * aNormal); + norm = normalize(norm); Diffuse = diffuse(norm); TexCoords = aTexCoords; diff --git a/src/main/resources/assets/create/flywheel/shaders/oriented.vert b/src/main/resources/assets/create/flywheel/shaders/oriented.vert new file mode 100644 index 000000000..d32feca3b --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/oriented.vert @@ -0,0 +1,63 @@ +#version 110 + +#flwinclude <"create:core/matutils.glsl"> +#flwinclude <"create:core/quaternion.glsl"> +#flwinclude <"create:core/diffuse.glsl"> + +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; + +attribute vec2 aLight; +attribute vec4 aColor; +attribute vec3 aInstancePos; +attribute vec3 aPivot; +attribute vec4 aRotation; + +varying vec2 TexCoords; +varying vec4 Color; +varying float Diffuse; +varying vec2 Light; + +#if defined(CONTRAPTION) +varying vec3 BoxCoord; + +uniform vec3 uLightBoxSize; +uniform vec3 uLightBoxMin; +uniform mat4 uModel; +#endif + +uniform float uTime; +uniform mat4 uViewProjection; +uniform int uDebug; + +uniform vec3 uCameraPos; + +#if defined(USE_FOG) +varying float FragDistance; +#endif + +void main() { + vec4 worldPos = vec4(rotateVertexByQuat(aPos - aPivot, aRotation) + aPivot + aInstancePos, 1.); + + vec3 norm = rotateVertexByQuat(aNormal, aRotation); + +#ifdef CONTRAPTION + worldPos = uModel * worldPos; + norm = normalize(modelToNormal(uModel) * norm); + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz); + #endif +#elif defined(USE_FOG) + FragDistance = length(worldPos.xyz - uCameraPos); +#endif + + Diffuse = diffuse(norm); + TexCoords = aTexCoords; + Light = aLight; + gl_Position = uViewProjection * worldPos; + + Color = aColor; +} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/rotating.vert b/src/main/resources/assets/create/flywheel/shaders/rotating.vert index 53d258bfd..091e16faa 100644 --- a/src/main/resources/assets/create/flywheel/shaders/rotating.vert +++ b/src/main/resources/assets/create/flywheel/shaders/rotating.vert @@ -9,9 +9,9 @@ attribute vec3 aPos; attribute vec3 aNormal; attribute vec2 aTexCoords; -attribute vec3 aInstancePos; attribute vec2 aLight; -attribute vec3 aNetworkTint; +attribute vec4 aColor; +attribute vec3 aInstancePos; attribute float aSpeed; attribute float aOffset; attribute vec3 aAxis; @@ -39,17 +39,22 @@ uniform vec3 uCameraPos; varying float FragDistance; #endif -void main() { +mat4 kineticRotation() { float degrees = aOffset + uTime * aSpeed * 3./10.; - vec4 kineticRot = quat(aAxis, degrees); + float angle = fract(degrees / 360.) * PI * 2.; - vec4 worldPos = vec4(rotateVertexByQuat(aPos - .5, kineticRot) + aInstancePos + .5, 1.); + return rotate(aAxis, angle); +} - vec3 norm = rotateVertexByQuat(aNormal, kineticRot); +void main() { + mat4 kineticRotation = kineticRotation(); + vec4 worldPos = kineticRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.); + + vec3 norm = modelToNormal(kineticRotation) * aNormal; #ifdef CONTRAPTION worldPos = uModel * worldPos; - norm = modelToNormal(uModel) * norm; + norm = normalize(modelToNormal(uModel) * norm); BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; #if defined(USE_FOG) @@ -72,7 +77,7 @@ void main() { } #else if (uDebug == 1) { - Color = vec4(aNetworkTint, 1.); + Color = aColor; } else if (uDebug == 2) { Color = vec4(norm, 1.); } else { diff --git a/src/main/resources/assets/create/models/block/funnel/block_vertical.json b/src/main/resources/assets/create/models/block/funnel/block_vertical.json index 9af30934a..e72ebfa9d 100644 --- a/src/main/resources/assets/create/models/block/funnel/block_vertical.json +++ b/src/main/resources/assets/create/models/block/funnel/block_vertical.json @@ -113,8 +113,8 @@ }, { "name": "Back", - "from": [1.95, -1.95, 1.95], - "to": [14.05, 2, 14.05], + "from": [1.925, -1.95, 1.925], + "to": [14.075, 2, 14.075], "rotation": {"angle": 0, "axis": "y", "origin": [8, 0.025, 8]}, "faces": { "north": {"uv": [2, 12, 14, 16], "texture": "#9"}, @@ -179,7 +179,6 @@ } } ], - "display": {}, "groups": [ { "name": "block_retracted", diff --git a/src/main/resources/assets/create/models/block/funnel/block_vertical_filterless.json b/src/main/resources/assets/create/models/block/funnel/block_vertical_filterless.json index ca31358f9..6d16d099c 100644 --- a/src/main/resources/assets/create/models/block/funnel/block_vertical_filterless.json +++ b/src/main/resources/assets/create/models/block/funnel/block_vertical_filterless.json @@ -4,7 +4,6 @@ "textures": { "3": "create:block/brass_funnel_back", "5": "create:block/brass_funnel_tall", - "7": "create:block/brass_funnel_plating", "8": "create:block/brass_storage_block", "9": "create:block/brass_funnel_slope", "10": "create:block/funnel_closed", @@ -113,8 +112,8 @@ }, { "name": "Back", - "from": [1.95, -1.95, 1.95], - "to": [14.05, 2, 14.05], + "from": [1.925, -1.95, 1.925], + "to": [14.075, 2, 14.075], "rotation": {"angle": 0, "axis": "y", "origin": [8, 0.025, 8]}, "faces": { "north": {"uv": [2, 12, 14, 16], "texture": "#9"}, @@ -135,7 +134,6 @@ } } ], - "display": {}, "groups": [ { "name": "block_retracted", @@ -162,7 +160,7 @@ { "name": "Item Filter", "origin": [8, 0, 8], - "children": [12, 13, 14, 15] + "children": [] } ] } \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/mechanical_arm/block.json b/src/main/resources/assets/create/models/block/mechanical_arm/block.json index f815bab53..0031d075b 100644 --- a/src/main/resources/assets/create/models/block/mechanical_arm/block.json +++ b/src/main/resources/assets/create/models/block/mechanical_arm/block.json @@ -2,6 +2,7 @@ "credit": "Made with Blockbench", "parent": "block/block", "textures": { + "2": "create:block/brass_casing_belt", "6": "create:block/crafter_top", "7": "create:block/brass_block", "particle": "create:block/crafter_top" @@ -9,15 +10,15 @@ "elements": [ { "name": "Base", - "from": [2, 0, 2], - "to": [14, 6, 14], + "from": [0, 0, 0], + "to": [16, 6, 16], "faces": { - "north": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "east": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "south": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "west": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "up": {"uv": [2, 2, 14, 14], "texture": "#7"}, - "down": {"uv": [2, 2, 14, 14], "texture": "#6"} + "north": {"uv": [8, 12.5, 16, 15.5], "texture": "#2"}, + "east": {"uv": [8, 12.5, 16, 15.5], "texture": "#2"}, + "south": {"uv": [8, 12.5, 16, 15.5], "texture": "#2"}, + "west": {"uv": [8, 12.5, 16, 15.5], "texture": "#2"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#7"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#6"} } } ], diff --git a/src/main/resources/assets/create/models/block/mechanical_arm/item.json b/src/main/resources/assets/create/models/block/mechanical_arm/item.json index 8df140ad6..d02438478 100644 --- a/src/main/resources/assets/create/models/block/mechanical_arm/item.json +++ b/src/main/resources/assets/create/models/block/mechanical_arm/item.json @@ -2,6 +2,7 @@ "credit": "Made with Blockbench", "parent": "block/block", "textures": { + "3": "create:block/brass_casing_belt", "5": "create:block/mechanical_arm", "6": "create:block/crafter_top", "7": "create:block/brass_block", @@ -52,9 +53,9 @@ }, { "name": "ConnectorR", - "from": [5, 12, 0], - "to": [7, 14, 6], - "rotation": {"angle": 45, "axis": "x", "origin": [8, -4, 5]}, + "from": [5, 7.02944, 12], + "to": [7, 9.02944, 18], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 17]}, "faces": { "east": {"uv": [15, 0, 16, 3], "rotation": 90, "texture": "#5"}, "south": {"uv": [15, 0, 16, 1], "rotation": 90, "texture": "#5"}, @@ -65,9 +66,9 @@ }, { "name": "ConnectorR", - "from": [9, 12, 0], - "to": [11, 14, 6], - "rotation": {"angle": 45, "axis": "x", "origin": [12, -4, 5]}, + "from": [9, 7.02944, 12], + "to": [11, 9.02944, 18], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 17]}, "faces": { "east": {"uv": [15, 0, 16, 3], "rotation": 90, "texture": "#5"}, "south": {"uv": [15, 0, 16, 1], "rotation": 90, "texture": "#5"}, @@ -78,9 +79,9 @@ }, { "name": "UpperBody", - "from": [4.5, 11, -10], - "to": [11.5, 15, 1], - "rotation": {"angle": 45, "axis": "x", "origin": [8, -4, 5]}, + "from": [4.5, 6.02944, 2], + "to": [11.5, 10.02944, 13], + "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 8, 17]}, "faces": { "north": {"uv": [11, 9, 14.5, 11], "texture": "#5"}, "east": {"uv": [14, 3.5, 16, 9], "rotation": 270, "texture": "#5"}, @@ -92,9 +93,9 @@ }, { "name": "Head", - "from": [4, 16.5, 4], - "to": [12, 20.5, 8], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 2, 8]}, + "from": [4, 11.59915, 0.63821], + "to": [12, 15.59915, 4.63821], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 14, 3]}, "faces": { "north": {"uv": [7, 9.5, 9, 13.5], "rotation": 90, "texture": "#5"}, "east": {"uv": [7, 13.5, 9, 15.5], "texture": "#5"}, @@ -106,23 +107,23 @@ }, { "name": "Base", - "from": [2, -16, 2], - "to": [14, -10, 14], + "from": [0, -16, 0], + "to": [16, -10, 16], "rotation": {"angle": 0, "axis": "y", "origin": [8, -8, 8]}, "faces": { - "north": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "east": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "south": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "west": {"uv": [2, 0, 14, 6], "texture": "#6"}, - "up": {"uv": [2, 2, 14, 14], "texture": "#7"}, - "down": {"uv": [2, 2, 14, 14], "texture": "#6"} + "north": {"uv": [8, 12.5, 16, 15.5], "texture": "#3"}, + "east": {"uv": [8, 12.5, 16, 15.5], "texture": "#3"}, + "south": {"uv": [8, 12.5, 16, 15.5], "texture": "#3"}, + "west": {"uv": [8, 12.5, 16, 15.5], "texture": "#3"}, + "up": {"uv": [0, 0, 16, 16], "texture": "#7"}, + "down": {"uv": [0, 0, 16, 16], "texture": "#6"} } }, { "name": "ClawBase", - "from": [5, 15.5, 1], - "to": [11, 21.5, 3], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 2, 8]}, + "from": [5, 10.59915, -2.36179], + "to": [11, 16.59915, -0.36179], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 14, 3]}, "faces": { "north": {"uv": [12, 0, 15, 3], "texture": "#5"}, "east": {"uv": [12, 0, 13, 3], "texture": "#5"}, @@ -134,23 +135,23 @@ }, { "name": "ClawTop", - "from": [5.5, 20.5, -3], - "to": [10.5, 22.5, 2], - "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 21.5, 2]}, + "from": [5.5, 5.96489, -2.07049], + "to": [10.5, 10.96489, -0.07049], + "rotation": {"angle": 45, "axis": "x", "origin": [8, 14, 3]}, "faces": { - "north": {"uv": [9.5, 1.5, 12, 2.5], "rotation": 180, "texture": "#5"}, - "east": {"uv": [9.5, 0, 12, 1], "rotation": 180, "texture": "#5"}, - "south": {"uv": [9.5, 0, 12, 1], "rotation": 180, "texture": "#5"}, - "west": {"uv": [9.5, 0, 12, 1], "rotation": 180, "texture": "#5"}, - "up": {"uv": [9.5, 0, 12, 2.5], "rotation": 180, "texture": "#5"}, - "down": {"uv": [9.5, 0, 12, 2.5], "rotation": 180, "texture": "#5"} + "north": {"uv": [9.5, 0, 12, 2.5], "texture": "#5"}, + "east": {"uv": [9.5, 0, 12, 1], "rotation": 270, "texture": "#5"}, + "south": {"uv": [9.5, 0, 12, 2.5], "rotation": 180, "texture": "#5"}, + "west": {"uv": [9.5, 0, 12, 1], "rotation": 90, "texture": "#5"}, + "up": {"uv": [9.5, 0, 12, 1], "rotation": 180, "texture": "#5"}, + "down": {"uv": [9.5, 1.5, 12, 2.5], "texture": "#5"} } }, { "name": "ClawBottom", - "from": [5.5, 14.5, -3], - "to": [10.5, 16.5, 2], - "rotation": {"angle": 22.5, "axis": "x", "origin": [8, 15.5, 2]}, + "from": [5.5, 8.18885, -4.72832], + "to": [10.5, 10.18885, 0.27168], + "rotation": {"angle": 0, "axis": "x", "origin": [8, 14, 3]}, "faces": { "north": {"uv": [9.5, 0, 12, 1], "rotation": 180, "texture": "#5"}, "east": {"uv": [9.5, 1.5, 12, 2.5], "rotation": 180, "texture": "#5"}, @@ -162,9 +163,9 @@ }, { "name": "ClawConnector", - "from": [6.5, 17.5, 3], - "to": [9.5, 19.5, 4], - "rotation": {"angle": 0, "axis": "y", "origin": [8, 2, 8]}, + "from": [6.5, 12.59915, -0.36179], + "to": [9.5, 14.59915, 0.63821], + "rotation": {"angle": -22.5, "axis": "x", "origin": [8, 14, 3]}, "faces": { "east": {"uv": [10.5, 2.5, 11, 3.5], "texture": "#5"}, "west": {"uv": [11.5, 2.5, 12, 3.5], "texture": "#5"}, @@ -282,8 +283,8 @@ "scale": [0.25, 0.25, 0.25] }, "gui": { - "rotation": [30, 225, 0], - "translation": [0, 3, 0], + "rotation": [30, 135, 0], + "translation": [0, 4.25, 0], "scale": [0.45, 0.45, 0.45] }, "head": { diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 37137f8a6..285af7c77 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -3,17 +3,9 @@ "package": "com.simibubi.create.foundation.mixin", "compatibilityLevel": "JAVA_8", "refmap": "create.refmap.json", - "client": [ - "AddRemoveTileMixin", - "ShaderCloseMixin", - "CancelTileEntityRenderMixin", - "LightUpdateMixin", - "RenderHooksMixin", - "FogColorTrackerMixin", - "NetworkLightUpdateMixin" - ], + "client": ["AddRemoveTileMixin", "CancelTileEntityRenderMixin", "FogColorTrackerMixin", "LightUpdateMixin", "NetworkLightUpdateMixin", "RenderHooksMixin", "ShaderCloseMixin"], "injectors": { "defaultRequire": 1 }, - "minVersion": "0.8" + "minVersion": "0.8", "mixins": ["StepSoundMixin"] } \ No newline at end of file diff --git a/src/main/resources/ponder/basin.nbt b/src/main/resources/ponder/basin.nbt new file mode 100644 index 000000000..e5340dadf Binary files /dev/null and b/src/main/resources/ponder/basin.nbt differ diff --git a/src/main/resources/ponder/blaze_burner.nbt b/src/main/resources/ponder/blaze_burner.nbt new file mode 100644 index 000000000..e83a31408 Binary files /dev/null and b/src/main/resources/ponder/blaze_burner.nbt differ diff --git a/src/main/resources/ponder/chute/downward.nbt b/src/main/resources/ponder/chute/downward.nbt new file mode 100644 index 000000000..9ed648941 Binary files /dev/null and b/src/main/resources/ponder/chute/downward.nbt differ diff --git a/src/main/resources/ponder/chute/smart.nbt b/src/main/resources/ponder/chute/smart.nbt new file mode 100644 index 000000000..eb4f6dc6e Binary files /dev/null and b/src/main/resources/ponder/chute/smart.nbt differ diff --git a/src/main/resources/ponder/chute/upward.nbt b/src/main/resources/ponder/chute/upward.nbt new file mode 100644 index 000000000..d067f7490 Binary files /dev/null and b/src/main/resources/ponder/chute/upward.nbt differ diff --git a/src/main/resources/ponder/crushing_wheel.nbt b/src/main/resources/ponder/crushing_wheel.nbt new file mode 100644 index 000000000..67be32a30 Binary files /dev/null and b/src/main/resources/ponder/crushing_wheel.nbt differ diff --git a/src/main/resources/ponder/depot.nbt b/src/main/resources/ponder/depot.nbt new file mode 100644 index 000000000..cb1824d1b Binary files /dev/null and b/src/main/resources/ponder/depot.nbt differ diff --git a/src/main/resources/ponder/empty_blaze_burner.nbt b/src/main/resources/ponder/empty_blaze_burner.nbt new file mode 100644 index 000000000..b134772cd Binary files /dev/null and b/src/main/resources/ponder/empty_blaze_burner.nbt differ diff --git a/src/main/resources/ponder/gauges.nbt b/src/main/resources/ponder/gauges.nbt new file mode 100644 index 000000000..67246ab4f Binary files /dev/null and b/src/main/resources/ponder/gauges.nbt differ diff --git a/src/main/resources/ponder/mechanical_arm/filter.nbt b/src/main/resources/ponder/mechanical_arm/filter.nbt new file mode 100644 index 000000000..f7e859d44 Binary files /dev/null and b/src/main/resources/ponder/mechanical_arm/filter.nbt differ diff --git a/src/main/resources/ponder/mechanical_arm/modes.nbt b/src/main/resources/ponder/mechanical_arm/modes.nbt new file mode 100644 index 000000000..d7226abc0 Binary files /dev/null and b/src/main/resources/ponder/mechanical_arm/modes.nbt differ diff --git a/src/main/resources/ponder/mechanical_arm/redstone.nbt b/src/main/resources/ponder/mechanical_arm/redstone.nbt new file mode 100644 index 000000000..3c80e9c82 Binary files /dev/null and b/src/main/resources/ponder/mechanical_arm/redstone.nbt differ diff --git a/src/main/resources/ponder/mechanical_arm/setup.nbt b/src/main/resources/ponder/mechanical_arm/setup.nbt new file mode 100644 index 000000000..4c935edb0 Binary files /dev/null and b/src/main/resources/ponder/mechanical_arm/setup.nbt differ diff --git a/src/main/resources/ponder/mechanical_crafter/connect.nbt b/src/main/resources/ponder/mechanical_crafter/connect.nbt new file mode 100644 index 000000000..27dac0c32 Binary files /dev/null and b/src/main/resources/ponder/mechanical_crafter/connect.nbt differ diff --git a/src/main/resources/ponder/mechanical_crafter/covers.nbt b/src/main/resources/ponder/mechanical_crafter/covers.nbt new file mode 100644 index 000000000..0860f7010 Binary files /dev/null and b/src/main/resources/ponder/mechanical_crafter/covers.nbt differ diff --git a/src/main/resources/ponder/mechanical_crafter/setup.nbt b/src/main/resources/ponder/mechanical_crafter/setup.nbt new file mode 100644 index 000000000..5b744378f Binary files /dev/null and b/src/main/resources/ponder/mechanical_crafter/setup.nbt differ diff --git a/src/main/resources/ponder/mechanical_mixer/mixing.nbt b/src/main/resources/ponder/mechanical_mixer/mixing.nbt new file mode 100644 index 000000000..21114955b Binary files /dev/null and b/src/main/resources/ponder/mechanical_mixer/mixing.nbt differ diff --git a/src/main/resources/ponder/mechanical_press/compacting.nbt b/src/main/resources/ponder/mechanical_press/compacting.nbt new file mode 100644 index 000000000..a5eb8661a Binary files /dev/null and b/src/main/resources/ponder/mechanical_press/compacting.nbt differ diff --git a/src/main/resources/ponder/mechanical_press/pressing.nbt b/src/main/resources/ponder/mechanical_press/pressing.nbt new file mode 100644 index 000000000..649276a51 Binary files /dev/null and b/src/main/resources/ponder/mechanical_press/pressing.nbt differ diff --git a/src/main/resources/ponder/millstone.nbt b/src/main/resources/ponder/millstone.nbt new file mode 100644 index 000000000..81dc45037 Binary files /dev/null and b/src/main/resources/ponder/millstone.nbt differ diff --git a/src/main/resources/ponder/sail.nbt b/src/main/resources/ponder/sail.nbt new file mode 100644 index 000000000..9b325ae4d Binary files /dev/null and b/src/main/resources/ponder/sail.nbt differ