diff --git a/build.gradle b/build.gradle index b8cf8d5e0..7477d5da9 100644 --- a/build.gradle +++ b/build.gradle @@ -3,9 +3,11 @@ buildscript { maven { url = 'https://files.minecraftforge.net/maven' } jcenter() mavenCentral() + maven { url='https://dist.creeper.host/Sponge/maven' } } dependencies { classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true + classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT' } } plugins { @@ -35,6 +37,9 @@ minecraft { runs { client { workingDirectory project.file('run') + // property 'mixin.env.disableRefMap', 'true' + arg '-mixin.config=create.mixins.json' +// jvmArgs '-XX:+UnlockCommercialFeatures' property 'forge.logging.console.level', 'info' property 'fml.earlyprogresswindow', 'false' mods { @@ -46,6 +51,8 @@ minecraft { server { workingDirectory project.file('run/server') + // property 'mixin.env.disableRefMap', 'true' + arg '-mixin.config=create.mixins.json' property 'forge.logging.console.level', 'info' mods { create { @@ -98,6 +105,9 @@ repositories { name = "tterrag maven" url = "https://maven.tterrag.com/" } + maven { + url = "https://www.cursemaven.com" + } } configurations { @@ -116,9 +126,13 @@ dependencies { // at runtime, use the full JEI jar runtimeOnly fg.deobf("mezz.jei:jei-${minecraft_version}:${jei_version}") + // implementation fg.deobf("curse.maven:druidcraft-340991:3101903") + // i'll leave this here commented for easier testing //runtimeOnly fg.deobf("vazkii.arl:AutoRegLib:1.4-35.69") //runtimeOnly fg.deobf("vazkii.quark:Quark:r2.0-212.984") + + annotationProcessor 'org.spongepowered:mixin:0.8:processor' } jar { @@ -131,7 +145,8 @@ jar { "Implementation-Title": project.name, "Implementation-Version": "${version}", "Implementation-Vendor" :"simibubi", - "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + "MixinConfigs": "create.mixins.json" ]) } } @@ -200,3 +215,9 @@ curseforge { } } } + +apply plugin: 'org.spongepowered.mixin' + +mixin { + add sourceSets.main, "create.refmap.json" +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 025cae5ea..d70b89e89 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.daemon=false # mod version info mod_version=0.3.1 minecraft_version=1.15.2 -forge_version=31.2.31 +forge_version=31.2.47 # dependency versions registrate_version=1.0.0-rc.17 diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index e0d2e9685..208ff9692 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -401,18 +401,19 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json e3f618c5b622d21880de858678d1802cbf65e615 assets/create/lang/en_ud.json -1c2c42b885b5d2b23f452d1550fb6c3a3a7ab952 assets/create/lang/en_us.json -90fb5c8d2b384d93c3bbc2693103be18a0ff3dc7 assets/create/lang/unfinished/de_de.json -3789e356240833be498849723cde53f12553c889 assets/create/lang/unfinished/es_mx.json -89aa38cb8250cd56dff4ae00d1491aea7e8aea36 assets/create/lang/unfinished/fr_fr.json -61e46061b0e9487f381c32a6c1004aacdb0be2b1 assets/create/lang/unfinished/it_it.json -70d3beec87b4e461b02b38feec572fcf92ffad35 assets/create/lang/unfinished/ja_jp.json -d77cefebb91bce27fc098d4e5a81a39c5b3f10de assets/create/lang/unfinished/ko_kr.json -6f7f629f4e8597c39f1cb259359e451255b31864 assets/create/lang/unfinished/nl_nl.json -0fd66b2ff7124cff646f32cebcd679d5e16ed805 assets/create/lang/unfinished/pt_br.json -5cf5aae29b48a7066c98dfbb130f58dcca7be5f6 assets/create/lang/unfinished/ru_ru.json -d1afca478f7ceaa739220873cfdff4f2caa3b3fd assets/create/lang/unfinished/zh_cn.json -ee8599a8bf1c4fac02dc9501de5d08f58b19f395 assets/create/lang/unfinished/zh_tw.json +880014dda429e6e2f21e227398d861e4da5e90c6 assets/create/lang/en_us.json +c07a94266b5ccde4d9e35467943cc512fe4b5896 assets/create/lang/unfinished/de_de.json +e5a0e1b67981159c16eb4563736f85310c77f979 assets/create/lang/unfinished/es_es.json +4c492fcb95abe9242c3149ba2b08451ba078c223 assets/create/lang/unfinished/es_mx.json +a9ea43cba7ebf87860d165839c98986b8da17f8e assets/create/lang/unfinished/fr_fr.json +cc4fe91e45becc807f49b7114d32d44812d0ec42 assets/create/lang/unfinished/it_it.json +287f5a8985786f1fe4a44a4ff4907902074aa725 assets/create/lang/unfinished/ja_jp.json +2125c67df82987c0bf66efb0b6c59da916362480 assets/create/lang/unfinished/ko_kr.json +9cfd8839a607ba5230a9716bcda3fae0fc9fd9fd assets/create/lang/unfinished/nl_nl.json +d972eac60bf24d8102c013667b3c76291912edb4 assets/create/lang/unfinished/pt_br.json +a552694a6a62274a33cdea255584c3ea3bbc25ef assets/create/lang/unfinished/ru_ru.json +d4ea1d09bb09cd8fdbf9a9c996ab66e8db290e92 assets/create/lang/unfinished/zh_cn.json +5b453190f3d422b4124b426fe61cc831b89fd2fa 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 @@ -1586,7 +1587,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear 9f9455ccb5fc9e3cbfce73862b46078346a522a5 assets/create/models/item/zinc_nugget.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json e76041b7ae829fdd7dc0524f6ca4d2f89fca51bb assets/create/sounds.json -cb9641eaf33211af46daf57241c76733cf371ed2 data/create/advancements/aesthetics.json +5d0cc4c0255dc241e61c173b31ddca70c88d08e4 data/create/advancements/aesthetics.json 187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json 0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json 356f4855a2a6c65be3fb51d7d1aabf2ca6034d42 data/create/advancements/arm_blaze_burner.json @@ -1616,18 +1617,18 @@ d1fbc14303c7327e9fc02e505e7e434591b7f785 data/create/advancements/crushing_wheel 77edd30e3d60b4d492662c673387910f66b5a276 data/create/advancements/dual_extendo_grip.json 04eaf829696d735244c0e4798dd3bdeb26e13a32 data/create/advancements/electron_tube.json b78fe4e539fef1b3419f2eb4d1db47cb4a201992 data/create/advancements/extendo_grip.json -4dbbf5f39441fdfe0561022ea7bbaa8e1f9733b7 data/create/advancements/fan.json -9e2369129a52ffb4c67907ca5e81e342766f7867 data/create/advancements/fan_lava.json -acef16596b7ae82aaf853142d69bcea7094b8173 data/create/advancements/fan_smoke.json -36f72396d1b4ac9a89f4a9139fa10ed659f5954a data/create/advancements/fan_water.json +b1699baaadaac7ebce642c09428519d156e21594 data/create/advancements/fan.json +5aa76cba3b40a1c234ffa84a89ecca630990fc0f data/create/advancements/fan_lava.json +716a9816558300a3652ed8d8d568517017813f5c data/create/advancements/fan_smoke.json +a61eb63d02604e88836519f89f74b252a640d485 data/create/advancements/fan_water.json 69e96e926a4d72e59cc6390c25f064166ddb62d2 data/create/advancements/fist_bump.json 99ee1bf5390b9a4f2a2419c78f259ff5d2ab9ae9 data/create/advancements/flywheel.json 489c58a0508a2a41cc0849dfb933eb5ac96ef364 data/create/advancements/glass_pipe.json 62f3610188f7dbd3900ab305edc2d06282705a38 data/create/advancements/goggles.json 10c8686da9cec2ae30c10f434836ac15a1b88666 data/create/advancements/hose_pulley.json -d44f4dcc6d0c51b4f347bc0c5c0d97dbb7af6523 data/create/advancements/infinite_chocolate.json -db31e7853f9f15ad35e14bfa9925f4eb527f0f01 data/create/advancements/infinite_lava.json -eb7e3aac431fd16cf643a51e8546c53d6510c81c data/create/advancements/infinite_water.json +9f642faf92b75a28c564e90be8448b9a4328af5e data/create/advancements/infinite_chocolate.json +a933fa5e7217e2ffe123ae035cfbc9210ba69fd5 data/create/advancements/infinite_lava.json +a8ab0e4ffba358d23f9efaa9f51245b6d490a8be data/create/advancements/infinite_water.json 9beb622c79e9f5ce2397c22222cac0faf272f388 data/create/advancements/integrated_circuit.json 316bed3d8985d0a371200967d7edd2936f1b9f94 data/create/advancements/integrated_circuit_eob.json a80eea863bfdc7777b8bade39a81655b2f99e02f data/create/advancements/item_drain.json @@ -1638,7 +1639,7 @@ a80eea863bfdc7777b8bade39a81655b2f99e02f data/create/advancements/item_drain.jso 218568a4e416c5fa559c55a5c92aa4e93f88b837 data/create/advancements/mechanical_drill.json 6dc84ad2f0512495fe3f01f99d3c547849351e33 data/create/advancements/mechanical_saw.json 3bc549c06dc6d9568f92e1abc9654c9b4c33f035 data/create/advancements/millstone.json -704c7fc0ed357b1a116ffdc0b6c64fe64e337a5a data/create/advancements/mixer.json +238ac410eb4de16a82ae05cc16fef80e55a4b61b data/create/advancements/mixer.json 325d4cef263ce301b143ee0498fb15afdb2c125b data/create/advancements/musical_arm.json c9c4060ed207226b69fada2d61e01a97d7077eae data/create/advancements/nixie_tube.json 9329cb210a954c0de1dcf517e7dff1ece77c19c0 data/create/advancements/overstress_flywheel.json diff --git a/src/generated/resources/assets/create/blockstates/radial_chassis.json b/src/generated/resources/assets/create/blockstates/radial_chassis.json index 8bd829ffc..2e2d16cf1 100644 --- a/src/generated/resources/assets/create/blockstates/radial_chassis.json +++ b/src/generated/resources/assets/create/blockstates/radial_chassis.json @@ -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", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 9ea4a76c2..002bcd0e1 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -684,6 +684,7 @@ "create.recipe.mechanical_crafting": "Mechanical Crafting", "create.recipe.automatic_shaped": "Automated Shaped Crafting", "create.recipe.block_cutting": "Block Cutting", + "create.recipe.wood_cutting": "Wood Cutting", "create.recipe.blockzapper_upgrade": "Handheld Blockzapper", "create.recipe.sandpaper_polishing": "Sandpaper Polishing", "create.recipe.mystery_conversion": "Mysterious Conversion", @@ -844,13 +845,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "Move to upper lane at %1$s%%", "create.gui.sequenced_gearshift.title": "Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "Instruction", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "Turn", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distance", - "create.gui.sequenced_gearshift.instruction.wait": "Wait", - "create.gui.sequenced_gearshift.instruction.wait.duration": "Duration", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "End", "create.gui.sequenced_gearshift.instruction.end": "End", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "Await", "create.gui.sequenced_gearshift.speed": "Speed, Direction", "create.gui.sequenced_gearshift.speed.forward": "Input speed, Forwards", "create.gui.sequenced_gearshift.speed.forward_fast": "Double speed, Forwards", 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 845da707f..e8f533dd4 100644 --- a/src/generated/resources/assets/create/lang/unfinished/de_de.json +++ b/src/generated/resources/assets/create/lang/unfinished/de_de.json @@ -1,10 +1,10 @@ { - "_": "Missing Localizations: 1124", + "_": "Missing Localizations: 994", "_": "->------------------------] Game Elements [------------------------<-", - "block.create.acacia_window": "Akazienfenster", - "block.create.acacia_window_pane": "Akazienfensterscheibe", + "block.create.acacia_window": "Akazienholzfenster", + "block.create.acacia_window_pane": "Akazienholzfensterscheibe", "block.create.adjustable_chain_gearshift": "Verstellbares Kettengetriebe", "block.create.adjustable_crate": "Verstellbare Kiste", "block.create.adjustable_pulse_repeater": "Verstellbarer Pulsverstärker", @@ -26,8 +26,8 @@ "block.create.andesite_tunnel": "Andesittunnel", "block.create.basin": "Behälter", "block.create.belt": "Mechanischer Riemen", - "block.create.birch_window": "UNLOCALIZED: Birch Window", - "block.create.birch_window_pane": "UNLOCALIZED: Birch Window Pane", + "block.create.birch_window": "Birkenholzfenster", + "block.create.birch_window_pane": "Birkenholzfensterscheibe", "block.create.black_sail": "Schwarzes Segel", "block.create.black_seat": "Schwarzer Sitz", "block.create.black_valve_handle": "Schwarzer Ventilgriff", @@ -56,7 +56,7 @@ "block.create.clockwork_bearing": "Uhrwerk-Lager", "block.create.clutch": "Kupplung", "block.create.cogwheel": "Zahnrad", - "block.create.content_observer": "Inhalts Beobachter", + "block.create.content_observer": "Inhaltsbeobachter", "block.create.controller_rail": "Steureungsschiene", "block.create.copper_block": "Kupfer Block", "block.create.copper_casing": "Kupferrahmen", @@ -117,128 +117,128 @@ "block.create.fancy_dark_scoria_bricks_slab": "Schicke dunkle Schlackenziegelstufe", "block.create.fancy_dark_scoria_bricks_stairs": "Schicke dunkle Schlackenziegeltreppe", "block.create.fancy_dark_scoria_bricks_wall": "Schicke dunkle Schlackenziegelmauer", - "block.create.fancy_diorite_bricks": "UNLOCALIZED: Fancy Diorite Bricks", - "block.create.fancy_diorite_bricks_slab": "UNLOCALIZED: Fancy Diorite Bricks Slab", - "block.create.fancy_diorite_bricks_stairs": "UNLOCALIZED: Fancy Diorite Bricks Stairs", - "block.create.fancy_diorite_bricks_wall": "UNLOCALIZED: Fancy Diorite Bricks Wall", - "block.create.fancy_dolomite_bricks": "UNLOCALIZED: Fancy Dolomite Bricks", - "block.create.fancy_dolomite_bricks_slab": "UNLOCALIZED: Fancy Dolomite Bricks Slab", - "block.create.fancy_dolomite_bricks_stairs": "UNLOCALIZED: Fancy Dolomite Bricks Stairs", - "block.create.fancy_dolomite_bricks_wall": "UNLOCALIZED: Fancy Dolomite Bricks Wall", - "block.create.fancy_gabbro_bricks": "UNLOCALIZED: Fancy Gabbro Bricks", - "block.create.fancy_gabbro_bricks_slab": "UNLOCALIZED: Fancy Gabbro Bricks Slab", - "block.create.fancy_gabbro_bricks_stairs": "UNLOCALIZED: Fancy Gabbro Bricks Stairs", - "block.create.fancy_gabbro_bricks_wall": "UNLOCALIZED: Fancy Gabbro Bricks Wall", - "block.create.fancy_granite_bricks": "UNLOCALIZED: Fancy Granite Bricks", - "block.create.fancy_granite_bricks_slab": "UNLOCALIZED: Fancy Granite Bricks Slab", - "block.create.fancy_granite_bricks_stairs": "UNLOCALIZED: Fancy Granite Bricks Stairs", - "block.create.fancy_granite_bricks_wall": "UNLOCALIZED: Fancy Granite Bricks Wall", - "block.create.fancy_limestone_bricks": "UNLOCALIZED: Fancy Limestone Bricks", - "block.create.fancy_limestone_bricks_slab": "UNLOCALIZED: Fancy Limestone Bricks Slab", - "block.create.fancy_limestone_bricks_stairs": "UNLOCALIZED: Fancy Limestone Bricks Stairs", - "block.create.fancy_limestone_bricks_wall": "UNLOCALIZED: Fancy Limestone Bricks Wall", - "block.create.fancy_scoria_bricks": "UNLOCALIZED: Fancy Scoria Bricks", - "block.create.fancy_scoria_bricks_slab": "UNLOCALIZED: Fancy Scoria Bricks Slab", - "block.create.fancy_scoria_bricks_stairs": "UNLOCALIZED: Fancy Scoria Bricks Stairs", - "block.create.fancy_scoria_bricks_wall": "UNLOCALIZED: Fancy Scoria Bricks Wall", - "block.create.fancy_weathered_limestone_bricks": "UNLOCALIZED: Fancy Weathered Limestone Bricks", - "block.create.fancy_weathered_limestone_bricks_slab": "UNLOCALIZED: Fancy Weathered Limestone Bricks Slab", - "block.create.fancy_weathered_limestone_bricks_stairs": "UNLOCALIZED: Fancy Weathered Limestone Bricks Stairs", - "block.create.fancy_weathered_limestone_bricks_wall": "UNLOCALIZED: Fancy Weathered Limestone Bricks Wall", - "block.create.fluid_pipe": "Wasserrohr", - "block.create.fluid_tank": "Wassertank", + "block.create.fancy_diorite_bricks": "Schöne Dioritziegel", + "block.create.fancy_diorite_bricks_slab": "Schöne Dioritziegelstufe", + "block.create.fancy_diorite_bricks_stairs": "Schöne Dioritziegeltreppe", + "block.create.fancy_diorite_bricks_wall": "Schöne Dioritziegelmauer", + "block.create.fancy_dolomite_bricks": "Schöne Dolomitziegel", + "block.create.fancy_dolomite_bricks_slab": "Schöne Dolomitziegelstufe", + "block.create.fancy_dolomite_bricks_stairs": "Schöne Dolomitziegeltreppe", + "block.create.fancy_dolomite_bricks_wall": "Schöne Dolomitziegelmauer", + "block.create.fancy_gabbro_bricks": "Schöne Gabelsteinziegel", + "block.create.fancy_gabbro_bricks_slab": "Schöne Gabelsteinziegelstufe", + "block.create.fancy_gabbro_bricks_stairs": "Schöne Gabelsteinziegeltreppe", + "block.create.fancy_gabbro_bricks_wall": "Schöne Gabelsteinziegelmauer", + "block.create.fancy_granite_bricks": "Schöne Granitziegel", + "block.create.fancy_granite_bricks_slab": "Schöne Granitziegelstufe", + "block.create.fancy_granite_bricks_stairs": "Schöne Granitziegeltreppe", + "block.create.fancy_granite_bricks_wall": "Schöne Granitziegelmauer", + "block.create.fancy_limestone_bricks": "Schöne Kalksteinziegel", + "block.create.fancy_limestone_bricks_slab": "Schöne Kalksteinziegelstufe", + "block.create.fancy_limestone_bricks_stairs": "Schöne Kalksteinziegeltreppe", + "block.create.fancy_limestone_bricks_wall": "Schöne Kalksteinziegelmauer", + "block.create.fancy_scoria_bricks": "Schöne Schlackenziegel", + "block.create.fancy_scoria_bricks_slab": "Schöne Schlackenziegelstufe", + "block.create.fancy_scoria_bricks_stairs": "Schöne Schlackenziegeltreppe", + "block.create.fancy_scoria_bricks_wall": "Schöne Schlackenziegelmauer", + "block.create.fancy_weathered_limestone_bricks": "Schöne Verwitterte Kalksteinziegel", + "block.create.fancy_weathered_limestone_bricks_slab": "Schöne Verwitterte Kalksteinziegelstufe", + "block.create.fancy_weathered_limestone_bricks_stairs": "Schöne Verwitterte Kalksteinziegeltreppe", + "block.create.fancy_weathered_limestone_bricks_wall": "Schöne Verwitterte Kalksteinziegelmauer", + "block.create.fluid_pipe": "Flüssigkeitsrohr", + "block.create.fluid_tank": "Flüssigkeitstank", "block.create.fluid_valve": "Flüssigkeitsventil", "block.create.flywheel": "Schwungrad", "block.create.framed_glass": "Gerahmtes Glas", "block.create.framed_glass_pane": "Gerahmte Glasscheibe", - "block.create.furnace_engine": "UNLOCALIZED: Furnace Engine", - "block.create.gabbro": "Gabbro", - "block.create.gabbro_bricks": "Gabbroziegel", - "block.create.gabbro_bricks_slab": "Gabbroziegelstufe", - "block.create.gabbro_bricks_stairs": "Gabbroziegeltreppe", - "block.create.gabbro_bricks_wall": "Gabbroziegelmauer", - "block.create.gabbro_cobblestone": "UNLOCALIZED: Gabbro Cobblestone", - "block.create.gabbro_cobblestone_slab": "UNLOCALIZED: Gabbro Cobblestone Slab", - "block.create.gabbro_cobblestone_stairs": "UNLOCALIZED: Gabbro Cobblestone Stairs", - "block.create.gabbro_cobblestone_wall": "UNLOCALIZED: Gabbro Cobblestone Wall", - "block.create.gabbro_pillar": "UNLOCALIZED: Gabbro Pillar", + "block.create.furnace_engine": "Ofenmotor", + "block.create.gabbro": "Gabelstein", + "block.create.gabbro_bricks": "Gabelsteinziegel", + "block.create.gabbro_bricks_slab": "Gabelsteinziegelstufe", + "block.create.gabbro_bricks_stairs": "Gabelsteinziegeltreppe", + "block.create.gabbro_bricks_wall": "Gabelsteinziegelmauer", + "block.create.gabbro_cobblestone": "Gabelsteinbruchstein", + "block.create.gabbro_cobblestone_slab": "Gabelsteinbruchstein", + "block.create.gabbro_cobblestone_stairs": "Gabelsteinbruchstein", + "block.create.gabbro_cobblestone_wall": "Gabelsteinbruchstein", + "block.create.gabbro_pillar": "Gabelsteinsäule", "block.create.gantry_pinion": "UNLOCALIZED: Gantry Pinion", "block.create.gantry_shaft": "UNLOCALIZED: Gantry Shaft", "block.create.gearbox": "Getriebe", "block.create.gearshift": "Gangschaltung", "block.create.glass_fluid_pipe": "Glaswasserrohr", "block.create.granite_bricks": "Granitziegel", - "block.create.granite_bricks_slab": "UNLOCALIZED: Granite Bricks Slab", - "block.create.granite_bricks_stairs": "UNLOCALIZED: Granite Bricks Stairs", - "block.create.granite_bricks_wall": "UNLOCALIZED: Granite Bricks Wall", - "block.create.granite_cobblestone": "UNLOCALIZED: Granite Cobblestone", - "block.create.granite_cobblestone_slab": "UNLOCALIZED: Granite Cobblestone Slab", - "block.create.granite_cobblestone_stairs": "UNLOCALIZED: Granite Cobblestone Stairs", - "block.create.granite_cobblestone_wall": "UNLOCALIZED: Granite Cobblestone Wall", - "block.create.granite_pillar": "UNLOCALIZED: Granite Pillar", - "block.create.gray_sail": "UNLOCALIZED: Gray Sail", - "block.create.gray_seat": "UNLOCALIZED: Gray Seat", - "block.create.gray_valve_handle": "UNLOCALIZED: Gray Valve Handle", - "block.create.green_sail": "UNLOCALIZED: Green Sail", - "block.create.green_seat": "UNLOCALIZED: Green Seat", - "block.create.green_valve_handle": "UNLOCALIZED: Green Valve Handle", - "block.create.hand_crank": "UNLOCALIZED: Hand Crank", - "block.create.honey": "UNLOCALIZED: Honey", - "block.create.horizontal_framed_glass": "UNLOCALIZED: Horizontal Framed Glass", - "block.create.horizontal_framed_glass_pane": "UNLOCALIZED: Horizontal Framed Glass Pane", - "block.create.hose_pulley": "UNLOCALIZED: Hose Pulley", - "block.create.item_drain": "UNLOCALIZED: Item Drain", - "block.create.jungle_window": "UNLOCALIZED: Jungle Window", - "block.create.jungle_window_pane": "UNLOCALIZED: Jungle Window Pane", + "block.create.granite_bricks_slab": "Granitziegelstufe", + "block.create.granite_bricks_stairs": "Granitziegeltreppe", + "block.create.granite_bricks_wall": "Granitziegelmauer", + "block.create.granite_cobblestone": "Granitbruchstein", + "block.create.granite_cobblestone_slab": "Granitbruchsteinstufe", + "block.create.granite_cobblestone_stairs": "Granitbruchtreppe", + "block.create.granite_cobblestone_wall": "Granitbruchsteinmauer", + "block.create.granite_pillar": "Granitsäule", + "block.create.gray_sail": "Graues Segel", + "block.create.gray_seat": "Grauer Sitz", + "block.create.gray_valve_handle": "Grauer Ventilgriff", + "block.create.green_sail": "Grünes Segel", + "block.create.green_seat": "Grüner Sitz", + "block.create.green_valve_handle": "Grüner Ventilgriff", + "block.create.hand_crank": "Handkurbel", + "block.create.honey": "Honig", + "block.create.horizontal_framed_glass": "Horizontal Gerahmes Glas", + "block.create.horizontal_framed_glass_pane": "Horizontal Gerahmte Glasscheibe", + "block.create.hose_pulley": "Umlenkrolle", + "block.create.item_drain": "Abfluss", + "block.create.jungle_window": "Tropenholzfenster", + "block.create.jungle_window_pane": "Tropenholzfensterscheib", "block.create.large_cogwheel": "Großes Zahnrad", - "block.create.layered_andesite": "UNLOCALIZED: Layered Andesite", - "block.create.layered_dark_scoria": "UNLOCALIZED: Layered Dark Scoria", - "block.create.layered_diorite": "UNLOCALIZED: Layered Diorite", - "block.create.layered_dolomite": "UNLOCALIZED: Layered Dolomite", - "block.create.layered_gabbro": "UNLOCALIZED: Layered Gabbro", - "block.create.layered_granite": "UNLOCALIZED: Layered Granite", - "block.create.layered_limestone": "UNLOCALIZED: Layered Limestone", - "block.create.layered_scoria": "UNLOCALIZED: Layered Scoria", - "block.create.layered_weathered_limestone": "UNLOCALIZED: Layered Weathered Limestone", - "block.create.light_blue_sail": "UNLOCALIZED: Light Blue Sail", - "block.create.light_blue_seat": "UNLOCALIZED: Light Blue Seat", - "block.create.light_blue_valve_handle": "UNLOCALIZED: Light Blue Valve Handle", - "block.create.light_gray_sail": "UNLOCALIZED: Light Gray Sail", - "block.create.light_gray_seat": "UNLOCALIZED: Light Gray Seat", - "block.create.light_gray_valve_handle": "UNLOCALIZED: Light Gray Valve Handle", - "block.create.lime_sail": "UNLOCALIZED: Lime Sail", - "block.create.lime_seat": "UNLOCALIZED: Lime Seat", - "block.create.lime_valve_handle": "UNLOCALIZED: Lime Valve Handle", + "block.create.layered_andesite": "Geschichteter Andesit", + "block.create.layered_dark_scoria": "Geschichtete Dunkle Schlacke", + "block.create.layered_diorite": "Geschichteter Diorit", + "block.create.layered_dolomite": "Geschichteter Dolomit", + "block.create.layered_gabbro": "Geschichteter Gabelstein", + "block.create.layered_granite": "Geschichteter Granit", + "block.create.layered_limestone": "Geschichteter Kalkstein", + "block.create.layered_scoria": "Geschichtete Schlacke", + "block.create.layered_weathered_limestone": "Geschichteter Verwitterter Kalkstein", + "block.create.light_blue_sail": "Hellblaues Segel", + "block.create.light_blue_seat": "Hellblauer Sitz", + "block.create.light_blue_valve_handle": "Hellblauer Ventilgriff", + "block.create.light_gray_sail": "Hellgraues Segel", + "block.create.light_gray_seat": "Hellgrauer Sitz", + "block.create.light_gray_valve_handle": "Hellgrauer Ventilgriff", + "block.create.lime_sail": "Hellgrünes Segel", + "block.create.lime_seat": "Hellgrüner Sitz", + "block.create.lime_valve_handle": "Hellgrüner Ventilgriff", "block.create.limesand": "Kalksand", "block.create.limestone": "Kalkstein", "block.create.limestone_bricks": "Kalksteinziegel", "block.create.limestone_bricks_slab": "Kalksteinziegelstufe", "block.create.limestone_bricks_stairs": "Kalksteinziegeltreppe", "block.create.limestone_bricks_wall": "Kalksteinziegelmauer", - "block.create.limestone_cobblestone": "UNLOCALIZED: Limestone Cobblestone", - "block.create.limestone_cobblestone_slab": "UNLOCALIZED: Limestone Cobblestone Slab", - "block.create.limestone_cobblestone_stairs": "UNLOCALIZED: Limestone Cobblestone Stairs", - "block.create.limestone_cobblestone_wall": "UNLOCALIZED: Limestone Cobblestone Wall", + "block.create.limestone_cobblestone": "Kalkbruchstein", + "block.create.limestone_cobblestone_slab": "Kalkbruchsteinstufe", + "block.create.limestone_cobblestone_stairs": "Kalkbruchsteintreppe", + "block.create.limestone_cobblestone_wall": "Kalkbruchsteinmauer", "block.create.limestone_pillar": "Kalksteinsäule", "block.create.linear_chassis": "Schubgerüst", - "block.create.lit_blaze_burner": "UNLOCALIZED: Lit Blaze Burner", - "block.create.magenta_sail": "UNLOCALIZED: Magenta Sail", - "block.create.magenta_seat": "UNLOCALIZED: Magenta Seat", - "block.create.magenta_valve_handle": "UNLOCALIZED: Magenta Valve Handle", - "block.create.mechanical_arm": "UNLOCALIZED: Mechanical Arm", + "block.create.lit_blaze_burner": "Aktiver Lohenbrenner", + "block.create.magenta_sail": "Magenta Segel", + "block.create.magenta_seat": "Magenta Sitz", + "block.create.magenta_valve_handle": "Magenta Ventilgriff", + "block.create.mechanical_arm": "Mechanischer Arm", "block.create.mechanical_bearing": "Mechanisches Lager", - "block.create.mechanical_crafter": "UNLOCALIZED: Mechanical Crafter", + "block.create.mechanical_crafter": "Mechanische Handwerkseinheit", "block.create.mechanical_drill": "Mechanischer Bohrer", "block.create.mechanical_harvester": "Mechanische Erntemaschine", - "block.create.mechanical_mixer": "UNLOCALIZED: Mechanical Mixer", + "block.create.mechanical_mixer": "Mechanischer Mixer", "block.create.mechanical_piston": "Mechanischer Kolben", "block.create.mechanical_piston_head": "Mechanisches Kolbenende", - "block.create.mechanical_plough": "UNLOCALIZED: Mechanical Plough", + "block.create.mechanical_plough": "Mechanischer Pflug", "block.create.mechanical_press": "Mechanische Presse", - "block.create.mechanical_pump": "UNLOCALIZED: Mechanical Pump", - "block.create.mechanical_saw": "UNLOCALIZED: Mechanical Saw", - "block.create.metal_bracket": "UNLOCALIZED: Metal Bracket", - "block.create.millstone": "UNLOCALIZED: Millstone", + "block.create.mechanical_pump": "Mechanische Pumpe", + "block.create.mechanical_saw": "Mechanische Säge", + "block.create.metal_bracket": "Metallhalterung", + "block.create.millstone": "Mahlstein", "block.create.minecart_anchor": "UNLOCALIZED: Minecart Anchor", "block.create.mossy_andesite": "UNLOCALIZED: Mossy Andesite", "block.create.mossy_dark_scoria": "UNLOCALIZED: Mossy Dark Scoria", @@ -305,9 +305,9 @@ "block.create.paved_weathered_limestone_slab": "UNLOCALIZED: Paved Weathered Limestone Slab", "block.create.paved_weathered_limestone_stairs": "UNLOCALIZED: Paved Weathered Limestone Stairs", "block.create.paved_weathered_limestone_wall": "UNLOCALIZED: Paved Weathered Limestone Wall", - "block.create.pink_sail": "UNLOCALIZED: Pink Sail", - "block.create.pink_seat": "UNLOCALIZED: Pink Seat", - "block.create.pink_valve_handle": "UNLOCALIZED: Pink Valve Handle", + "block.create.pink_sail": "Rosa Segel", + "block.create.pink_seat": "Rosa Sitz", + "block.create.pink_valve_handle": "Rosa Ventilgriff", "block.create.piston_extension_pole": "Kolben-Pleuelverlängerung", "block.create.polished_dark_scoria": "UNLOCALIZED: Polished Dark Scoria", "block.create.polished_dark_scoria_slab": "UNLOCALIZED: Polished Dark Scoria Slab", @@ -317,7 +317,7 @@ "block.create.polished_dolomite_slab": "UNLOCALIZED: Polished Dolomite Slab", "block.create.polished_dolomite_stairs": "UNLOCALIZED: Polished Dolomite Stairs", "block.create.polished_dolomite_wall": "UNLOCALIZED: Polished Dolomite Wall", - "block.create.polished_gabbro": "Polierter Gabbro", + "block.create.polished_gabbro": "Polierter Gabelstein", "block.create.polished_gabbro_slab": "UNLOCALIZED: Polished Gabbro Slab", "block.create.polished_gabbro_stairs": "UNLOCALIZED: Polished Gabbro Stairs", "block.create.polished_gabbro_wall": "UNLOCALIZED: Polished Gabbro Wall", @@ -325,7 +325,7 @@ "block.create.polished_limestone_slab": "Polierte Kalksteinstufe", "block.create.polished_limestone_stairs": "UNLOCALIZED: Polished Limestone Stairs", "block.create.polished_limestone_wall": "UNLOCALIZED: Polished Limestone Wall", - "block.create.polished_scoria": "UNLOCALIZED: Polished Scoria", + "block.create.polished_scoria": "Polierte Schlacke", "block.create.polished_scoria_slab": "UNLOCALIZED: Polished Scoria Slab", "block.create.polished_scoria_stairs": "UNLOCALIZED: Polished Scoria Stairs", "block.create.polished_scoria_wall": "UNLOCALIZED: Polished Scoria Wall", @@ -412,13 +412,13 @@ "entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption", "entity.create.super_glue": "UNLOCALIZED: Super Glue", - "fluid.create.milk": "UNLOCALIZED: Milk", - "fluid.create.potion": "UNLOCALIZED: Potion", - "fluid.create.tea": "UNLOCALIZED: Builder's Tea", + "fluid.create.milk": "Milch", + "fluid.create.potion": "Trank", + "fluid.create.tea": "Bauherrentee", "item.create.andesite_alloy": "UNLOCALIZED: Andesite Alloy", "item.create.attribute_filter": "UNLOCALIZED: Attribute Filter", - "item.create.bar_of_chocolate": "UNLOCALIZED: Bar of Chocolate", + "item.create.bar_of_chocolate": "Schokoladetafel", "item.create.belt_connector": "Mechanischer Riemen", "item.create.blaze_cake": "UNLOCALIZED: Blaze Cake", "item.create.blaze_cake_base": "UNLOCALIZED: Blaze Cake Base", @@ -449,7 +449,7 @@ "item.create.crushed_tin_ore": "UNLOCALIZED: Crushed Tin Ore", "item.create.crushed_uranium_ore": "UNLOCALIZED: Crushed Uranium Ore", "item.create.crushed_zinc_ore": "UNLOCALIZED: Crushed Zinc Ore", - "item.create.deforester": "UNLOCALIZED: Deforester", + "item.create.deforester": "Entforster", "item.create.dough": "Teig", "item.create.electron_tube": "UNLOCALIZED: Electron Tube", "item.create.empty_blaze_burner": "UNLOCALIZED: Empty Blaze Burner", @@ -460,8 +460,8 @@ "item.create.goggles": "UNLOCALIZED: Engineer's Goggles", "item.create.golden_sheet": "UNLOCALIZED: Golden Sheet", "item.create.handheld_blockzapper": "Blockpistole", - "item.create.handheld_worldshaper": "UNLOCALIZED: Handheld Worldshaper", - "item.create.honey_bucket": "UNLOCALIZED: Honey Bucket", + "item.create.handheld_worldshaper": "Geländeformer", + "item.create.honey_bucket": "Honigeimer", "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", "item.create.iron_sheet": "Eisenblech", "item.create.lapis_sheet": "UNLOCALIZED: Lapis Sheet", @@ -470,18 +470,18 @@ "item.create.polished_rose_quartz": "UNLOCALIZED: Polished Rose Quartz", "item.create.powdered_obsidian": "UNLOCALIZED: Powdered Obsidian", "item.create.propeller": "Propeller", - "item.create.red_sand_paper": "UNLOCALIZED: Red Sand Paper", + "item.create.red_sand_paper": "Rotes Schmirgelpapier", "item.create.refined_radiance": "UNLOCALIZED: Refined Radiance", "item.create.rose_quartz": "Rosenquarz", - "item.create.sand_paper": "UNLOCALIZED: Sand Paper", + "item.create.sand_paper": "Schmirgelpapier", "item.create.schematic": "Bauplan", "item.create.schematic_and_quill": "Bauplan und Feder", "item.create.shadow_steel": "UNLOCALIZED: Shadow Steel", - "item.create.super_glue": "UNLOCALIZED: Super Glue", + "item.create.super_glue": "Superkleber", "item.create.tree_fertilizer": "Baumdünger", "item.create.vertical_gearbox": "UNLOCALIZED: Vertical Gearbox", "item.create.wand_of_symmetry": "Symmetriestab", - "item.create.wheat_flour": "UNLOCALIZED: Wheat Flour", + "item.create.wheat_flour": "Weizenmehl", "item.create.whisk": "UNLOCALIZED: Whisk", "item.create.wrench": "Schraubenschlüssel", "item.create.zinc_ingot": "Zinkbarren", @@ -654,21 +654,21 @@ "_": "->------------------------] UI & Messages [------------------------<-", - "itemGroup.create.base": "UNLOCALIZED: Create", - "itemGroup.create.palettes": "UNLOCALIZED: Create Palettes", + "itemGroup.create.base": "Create", + "itemGroup.create.palettes": "Create Paletten", "death.attack.create.crush": "%1$s stolperte in ein Mahlwerk", "death.attack.create.fan_fire": "%1$s hat heiße Luft eingeatmet", "death.attack.create.fan_lava": "%1$s wurde von Lava verweht", "death.attack.create.mechanical_drill": "%1$s wurde von einem Bohrer durchlöchert", - "death.attack.create.mechanical_saw": "UNLOCALIZED: %1$s got cut in half by a Mechanical Saw", - "death.attack.create.cuckoo_clock_explosion": "UNLOCALIZED: %1$s was blown up by tampered cuckoo clock", + "death.attack.create.mechanical_saw": "%1$s wurde zersägt", + "death.attack.create.cuckoo_clock_explosion": "%1$s wurde durch eine falsche Kuckucksuhr gesprengt", - "create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer", + "create.block.deployer.damage_source_name": "einem Finger", "create.block.cart_assembler.invalid": "UNLOCALIZED: Place your Cart Assembler on a rail block", - "create.recipe.crushing": "Mahlen", - "create.recipe.milling": "UNLOCALIZED: Milling", + "create.recipe.crushing": "Mahlen (Mahlwerk)", + "create.recipe.milling": "Mahlen (Mahlstein)", "create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing", "create.recipe.fan_washing.fan": "UNLOCALIZED: Fan behind Flowing Water", "create.recipe.fan_smoking": "UNLOCALIZED: Bulk Smoking", @@ -676,24 +676,25 @@ "create.recipe.fan_blasting": "UNLOCALIZED: Bulk Blasting", "create.recipe.fan_blasting.fan": "UNLOCALIZED: Fan behind Lava", "create.recipe.pressing": "Mechanische Presse", - "create.recipe.mixing": "UNLOCALIZED: Mixing", + "create.recipe.mixing": "Mixen", "create.recipe.automatic_shapeless": "UNLOCALIZED: Automated Shapeless Crafting", "create.recipe.automatic_brewing": "UNLOCALIZED: Automated Brewing", "create.recipe.packing": "UNLOCALIZED: Compacting", "create.recipe.automatic_packing": "UNLOCALIZED: Automated Packing", - "create.recipe.sawing": "UNLOCALIZED: Sawing", + "create.recipe.sawing": "Sägen", "create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting", "create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting", "create.recipe.block_cutting": "UNLOCALIZED: Block Cutting", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "Blockpistole", - "create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing", + "create.recipe.sandpaper_polishing": "Schleifen", "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", "create.recipe.spout_filling": "UNLOCALIZED: Filling by Spout", "create.recipe.draining": "UNLOCALIZED: Item Draining", "create.recipe.processing.chance": "Chance: %1$s%%", - "create.recipe.heat_requirement.none": "UNLOCALIZED: No Heating Required", - "create.recipe.heat_requirement.heated": "UNLOCALIZED: Heated", - "create.recipe.heat_requirement.superheated": "UNLOCALIZED: Super-Heated", + "create.recipe.heat_requirement.none": "Keine Hitze benötigt", + "create.recipe.heat_requirement.heated": "Wenig Hitze benötigt", + "create.recipe.heat_requirement.superheated": "Viel Hitze benötigt", "create.generic.range": "Reichweite", "create.generic.radius": "Radius", @@ -705,12 +706,12 @@ "create.generic.unit.ticks": "Ticks", "create.generic.unit.seconds": "Sekunden", "create.generic.unit.minutes": "Minuten", - "create.generic.unit.rpm": "UNLOCALIZED: RPM", - "create.generic.unit.stress": "UNLOCALIZED: su", - "create.generic.unit.degrees": "UNLOCALIZED: °", - "create.generic.unit.millibuckets": "UNLOCALIZED: %1$smB", - "create.generic.clockwise": "UNLOCALIZED: Clockwise", - "create.generic.counter_clockwise": "UNLOCALIZED: Counter-Clockwise", + "create.generic.unit.rpm": "RPM", + "create.generic.unit.stress": "su", + "create.generic.unit.degrees": "°", + "create.generic.unit.millibuckets": "%1$smB", + "create.generic.clockwise": "Uhrzeigersinn", + "create.generic.counter_clockwise": "Gegen-Uhrzeigersinn", "create.action.scroll": "Wechseln", "create.action.confirm": "Bestätigen", @@ -782,7 +783,7 @@ "create.blockzapper.component.retriever": "Empfänger", "create.blockzapper.component.scope": "Fernrohr", "create.blockzapper.componentTier.none": "Nichts", - "create.blockzapper.componentTier.brass": "UNLOCALIZED: Brass", + "create.blockzapper.componentTier.brass": "Messing", "create.blockzapper.componentTier.chromatic": "UNLOCALIZED: Chromatic", "create.blockzapper.leftClickToSet": "Linksklick auf einen Block zum Auswählen", "create.blockzapper.empty": "Keine Blöcke übrig!", @@ -811,8 +812,8 @@ "create.contraptions.clockwork.hour_first_24": "UNLOCALIZED: 24-Hour hand first", "create.logistics.filter": "Filter", - "create.logistics.recipe_filter": "UNLOCALIZED: Recipe Filter", - "create.logistics.fluid_filter": "UNLOCALIZED: Fluid Filter", + "create.logistics.recipe_filter": "Rezeptfilter", + "create.logistics.fluid_filter": "Flüssigkeitsfilter", "create.logistics.firstFrequency": "Freq. #1", "create.logistics.secondFrequency": "Freq. #2", "create.logistics.filter.apply": "UNLOCALIZED: Applied filter to %1$s.", @@ -837,7 +838,7 @@ "create.gui.stressometer.no_rotation": "UNLOCALIZED: No Rotation", "create.gui.contraptions.not_fast_enough": "UNLOCALIZED: It appears that this %1$s is _not_ rotating with _enough_ _speed_.", "create.gui.contraptions.network_overstressed": "UNLOCALIZED: It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.", - "create.gui.adjustable_crate.title": "adjustable_crate", + "create.gui.adjustable_crate.title": "UNLOCALIZED: Adjustable Crate", "create.gui.adjustable_crate.storageSpace": "Lagerraum", "create.gui.stockpile_switch.title": "Vorratssensor", "create.gui.stockpile_switch.invert_signal": "UNLOCALIZED: Invert Signal", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "UNLOCALIZED: Move to upper lane at %1$s%%", "create.gui.sequenced_gearshift.title": "UNLOCALIZED: Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "UNLOCALIZED: Instruction", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "UNLOCALIZED: Turn", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "UNLOCALIZED: Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "UNLOCALIZED: Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "UNLOCALIZED: Distance", - "create.gui.sequenced_gearshift.instruction.wait": "UNLOCALIZED: Wait", - "create.gui.sequenced_gearshift.instruction.wait.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "UNLOCALIZED: End", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "UNLOCALIZED: Speed, Direction", "create.gui.sequenced_gearshift.speed.forward": "UNLOCALIZED: Input speed, Forwards", "create.gui.sequenced_gearshift.speed.forward_fast": "UNLOCALIZED: Double speed, Forwards", @@ -863,7 +870,7 @@ "create.schematicAndQuill.secondPos": "Zweite Position festgelegt.", "create.schematicAndQuill.noTarget": "Halte [Strg] zur Auswahl von Luft.", "create.schematicAndQuill.abort": "Auswahl zurückgesetzt.", - "create.schematicAndQuill.title": "UNLOCALIZED: Schematic Name:", + "create.schematicAndQuill.title": "Bauplanname:", "create.schematicAndQuill.convert": "UNLOCALIZED: Save and Deploy Immediately", "create.schematicAndQuill.fallbackName": "Mein Bauplan", "create.schematicAndQuill.saved": "Gespeichert als %1$s", @@ -1781,8 +1788,8 @@ "item.create.crafter_slot_cover.tooltip": "UNLOCALIZED: SLOT COVER", "item.create.crafter_slot_cover.tooltip.summary": "UNLOCALIZED: Used to mark a _Mechanical Crafter_ as an empty slot in a recipe. Crafters do not necessarily have to form a full square grid. This is useful when there are recipes where _ingredients are diagonal_ to each other.", - "create.tooltip.wip": "UNLOCALIZED: WIP", - "create.tooltip.workInProgress": "UNLOCALIZED: Work in progress!", + "create.tooltip.wip": "WIP", + "create.tooltip.workInProgress": "Work in progress!", "create.tooltip.randomWipDescription0": "UNLOCALIZED: Please keep this item away from children.", "create.tooltip.randomWipDescription1": "UNLOCALIZED: A baby panda dies every time you use this item. Every. Time.", "create.tooltip.randomWipDescription2": "UNLOCALIZED: Use at your own risk.", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" diff --git a/src/generated/resources/assets/create/lang/unfinished/es_es.json b/src/generated/resources/assets/create/lang/unfinished/es_es.json new file mode 100644 index 000000000..86d845459 --- /dev/null +++ b/src/generated/resources/assets/create/lang/unfinished/es_es.json @@ -0,0 +1,1805 @@ +{ + "_": "Missing Localizations: 11", + + "_": "->------------------------] Game Elements [------------------------<-", + + "block.create.acacia_window": "Ventana de acacia", + "block.create.acacia_window_pane": "Panel de ventana de acacia", + "block.create.adjustable_chain_gearshift": "Cadena de transmisión ajustable", + "block.create.adjustable_crate": "Caja ajustable", + "block.create.adjustable_pulse_repeater": "Repetidor de pulso ajustable", + "block.create.adjustable_repeater": "Repetidor ajustable", + "block.create.analog_lever": "Palanca analógica", + "block.create.andesite_belt_funnel": "Embudo de cinta de andesita", + "block.create.andesite_bricks": "Ladrillos de andesita", + "block.create.andesite_bricks_slab": "Losa de ladrillos de andesita", + "block.create.andesite_bricks_stairs": "Escaleras de ladrillos de andesita", + "block.create.andesite_bricks_wall": "Pared de ladrillos de andesita", + "block.create.andesite_casing": "Revestidor de andesita", + "block.create.andesite_cobblestone": "Adoquín de andesita", + "block.create.andesite_cobblestone_slab": "Losa de adoquín de andesita", + "block.create.andesite_cobblestone_stairs": "Escaleras de adoquines de andesita", + "block.create.andesite_cobblestone_wall": "Muro de adoquines de andesita", + "block.create.andesite_encased_shaft": "Eje revestido de andesita", + "block.create.andesite_funnel": "Embudo de andesita", + "block.create.andesite_pillar": "Poste de andesita", + "block.create.andesite_tunnel": "Túnel de Andesita", + "block.create.basin": "Cuenca", + "block.create.belt": "Cinta", + "block.create.birch_window": "Ventana de abedul", + "block.create.birch_window_pane": "Panel de ventana de abedul", + "block.create.black_sail": "Vela negra", + "block.create.black_seat": "Asiento negro", + "block.create.black_valve_handle": "Asa de válvula negra", + "block.create.blaze_burner": "Quemador de Blaze", + "block.create.blue_sail": "Vela azul", + "block.create.blue_seat": "Asiento azul", + "block.create.blue_valve_handle": "Asa de válvula azul", + "block.create.brass_belt_funnel": "Embudo de cinta de latón", + "block.create.brass_block": "Bloque de latón", + "block.create.brass_casing": "Revestidor de latón", + "block.create.brass_encased_shaft": "Eje revestido de latón", + "block.create.brass_funnel": "Embudo de latón", + "block.create.brass_tunnel": "Túnel de latón", + "block.create.brown_sail": "Vela marrón", + "block.create.brown_seat": "Asiento marrón", + "block.create.brown_valve_handle": "Asa de válvula marrón", + "block.create.cart_assembler": "Ensamblador de vagonetas", + "block.create.chiseled_dark_scoria": "Escoria oscura cincelada", + "block.create.chiseled_dolomite": "Dolomita cincelada", + "block.create.chiseled_gabbro": "Gabro cincelado", + "block.create.chiseled_limestone": "Caliza cincelada", + "block.create.chiseled_scoria": "Escoria cincelada", + "block.create.chiseled_weathered_limestone": "Piedra caliza erosionada cincelada", + "block.create.chocolate": "Chocolate", + "block.create.chute": "Ducto", + "block.create.clockwork_bearing": "Rodamiento de reloj", + "block.create.clutch": "Embrague", + "block.create.cogwheel": "Rueda dentada", + "block.create.content_observer": "Observador de contenidos", + "block.create.controller_rail": "Raíl de control", + "block.create.copper_block": "Bloque de cobre", + "block.create.copper_casing": "Revestidor de caliza", + "block.create.copper_ore": "Mineral de cobre", + "block.create.copper_shingles": "Bloque de tejas de cobre", + "block.create.copper_tiles": "Bloque de baldosas de cobre", + "block.create.copper_valve_handle": "Asa de válvula de cobre", + "block.create.creative_crate": "Caja creativa", + "block.create.creative_fluid_tank": "Tanque de fluidos creativo", + "block.create.creative_motor": "Motor creativo", + "block.create.crushing_wheel": "Rueda trituradora", + "block.create.crushing_wheel_controller": "Controlador de Rueda trituradora", + "block.create.cuckoo_clock": "Reloj Cucú", + "block.create.cyan_sail": "Vela cian", + "block.create.cyan_seat": "Asiento cian", + "block.create.cyan_valve_handle": "Asa de válvula cian", + "block.create.dark_oak_window": "Ventana de roble oscuro", + "block.create.dark_oak_window_pane": "Panel de ventana de roble oscuro", + "block.create.dark_scoria": "Escoria oscura", + "block.create.dark_scoria_bricks": "Ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_stairs": "Escaleras de ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura", + "block.create.dark_scoria_cobblestone": "Adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_slab": "Losa de adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_stairs": "Escaleras de adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_wall": "Pared de adoquines de escoria oscura", + "block.create.dark_scoria_pillar": "Pilar de escoria oscura", + "block.create.deployer": "Desplegador", + "block.create.depot": "Depósito", + "block.create.diorite_bricks": "Ladrillos de diorita", + "block.create.diorite_bricks_slab": "Losa de ladrillos de diorita", + "block.create.diorite_bricks_stairs": "Escaleras de ladrillos de diorita", + "block.create.diorite_bricks_wall": "Pared de ladrillos de diorita", + "block.create.diorite_cobblestone": "Adoquín de diorita", + "block.create.diorite_cobblestone_slab": "Losa de adoquínes de diorita", + "block.create.diorite_cobblestone_stairs": "Escaleras de adoquines de diorita", + "block.create.diorite_cobblestone_wall": "Pared de adoquines de diorita", + "block.create.diorite_pillar": "Pilar de diorita", + "block.create.dolomite": "Dolomita", + "block.create.dolomite_bricks": "Ladrillos de dolomita", + "block.create.dolomite_bricks_slab": "Losa de ladrillos de dolomita", + "block.create.dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita", + "block.create.dolomite_bricks_wall": "Pared de ladrillos de dolomita", + "block.create.dolomite_cobblestone": "Adoquín de dolomita", + "block.create.dolomite_cobblestone_slab": "Losa de adoquín de dolomita", + "block.create.dolomite_cobblestone_stairs": "Escaleras de adoquines de dolomita", + "block.create.dolomite_cobblestone_wall": "Pared de adoquines de dolomita", + "block.create.dolomite_pillar": "Pilar de dolomita", + "block.create.encased_chain_drive": "Cadena de transmisión revestida", + "block.create.encased_fan": "Ventilador revestido", + "block.create.encased_fluid_pipe": "Tubería de fluidos de cobre revestida", + "block.create.fancy_andesite_bricks": "Ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_slab": "Ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_stairs": "Escaleras de ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_wall": "Pared de ladrillos de andesita elegantes", + "block.create.fancy_dark_scoria_bricks": "Ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_stairs": "Escalera de ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura elegantes", + "block.create.fancy_diorite_bricks": "Ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_slab": "Losa de ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_stairs": "Escaleras de ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_wall": "Pared de ladrillos de diorita elegantes", + "block.create.fancy_dolomite_bricks": "Ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_slab": "Losa de ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_wall": "Pared de ladrillos de dolomita elegantes", + "block.create.fancy_gabbro_bricks": "Ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_slab": "Losa de ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_stairs": "Escaleras de ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_wall": "Pared de ladrillos de gabro elegantes", + "block.create.fancy_granite_bricks": "Ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_slab": "Losa de ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_stairs": "Escaleras de ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_wall": "Pared de ladrillos de granito elegantes", + "block.create.fancy_limestone_bricks": "Ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_slab": "Losa de ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_wall": "Pared de ladrillos de piedra caliza elegantes", + "block.create.fancy_scoria_bricks": "Ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_slab": "Losa de ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_stairs": "Escaleras de ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_wall": "Pared de ladrillos de escoria elegantes", + "block.create.fancy_weathered_limestone_bricks": "Ladrillos de piedra de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_slab": "Losa de ladrillos de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_stairs": "Escaleras de ladrillos de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_wall": "Pared de ladrillos de caliza erosionada elegantes", + "block.create.fluid_pipe": "Tubería de fluidos de cobre", + "block.create.fluid_tank": "Depósito de fluidos", + "block.create.fluid_valve": "Válvula de fluidos", + "block.create.flywheel": "Rueda de inercia", + "block.create.framed_glass": "Cristal enmarcado", + "block.create.framed_glass_pane": "Panel de cristal enmarcado", + "block.create.furnace_engine": "Motor de horno", + "block.create.gabbro": "Gabro", + "block.create.gabbro_bricks": "Ladrillos de gabro", + "block.create.gabbro_bricks_slab": "Losa de ladrillos de gabro", + "block.create.gabbro_bricks_stairs": "Escaleras de ladrillos de gabro", + "block.create.gabbro_bricks_wall": "Pared de ladrillos de gabro", + "block.create.gabbro_cobblestone": "Adoquín de gabro", + "block.create.gabbro_cobblestone_slab": "Losa de adoquínes de gabro", + "block.create.gabbro_cobblestone_stairs": "Escaleras de adoquínes de gabro", + "block.create.gabbro_cobblestone_wall": "Pared de adoquínes de gabro", + "block.create.gabbro_pillar": "Pilar de gabro", + "block.create.gantry_pinion": "Piñón de grúa", + "block.create.gantry_shaft": "Eje de grúa", + "block.create.gearbox": "Caja de transmisión", + "block.create.gearshift": "Caja de cambios", + "block.create.glass_fluid_pipe": "Tubo de cristal para fluidos", + "block.create.granite_bricks": "Ladrillos de granito", + "block.create.granite_bricks_slab": "Losa de ladrillos de granito", + "block.create.granite_bricks_stairs": "Escaleras de ladrillos de granito", + "block.create.granite_bricks_wall": "Pared de ladrillos de granito", + "block.create.granite_cobblestone": "Adoquín de granito", + "block.create.granite_cobblestone_slab": "Losa de adoquínes de granito", + "block.create.granite_cobblestone_stairs": "Escaleras de adoquínes de granito", + "block.create.granite_cobblestone_wall": "Pared de adoquínes de granito", + "block.create.granite_pillar": "Pilar de granito", + "block.create.gray_sail": "Vela gris", + "block.create.gray_seat": "Asiento gris", + "block.create.gray_valve_handle": "Asa de válvula gris", + "block.create.green_sail": "Vela verde", + "block.create.green_seat": "Asiento verde", + "block.create.green_valve_handle": "Asa de válvula verde", + "block.create.hand_crank": "Manivela", + "block.create.honey": "Miel", + "block.create.horizontal_framed_glass": "Cristal con marco horizontal", + "block.create.horizontal_framed_glass_pane": "Panel de cristal con marco horizontal", + "block.create.hose_pulley": "Polea de manguera", + "block.create.item_drain": "Drenador de elementos", + "block.create.jungle_window": "Ventana de jungla", + "block.create.jungle_window_pane": "Panel de ventana de jungla", + "block.create.large_cogwheel": "Rueda dentada grande", + "block.create.layered_andesite": "Andesita estratificada", + "block.create.layered_dark_scoria": "Escoria oscura estratificada", + "block.create.layered_diorite": "Diorita estratificada", + "block.create.layered_dolomite": "Dolomita estratificada", + "block.create.layered_gabbro": "Gabro estratificado", + "block.create.layered_granite": "Granito estratificado", + "block.create.layered_limestone": "Piedra caliza estratificada", + "block.create.layered_scoria": "Escoria estratificada", + "block.create.layered_weathered_limestone": "Caliza erosionada estratificada", + "block.create.light_blue_sail": "Vela azul claro", + "block.create.light_blue_seat": "Asiento azul claro", + "block.create.light_blue_valve_handle": "Asa de válvula azul claro", + "block.create.light_gray_sail": "Vela gris claro", + "block.create.light_gray_seat": "Asiento gris claro", + "block.create.light_gray_valve_handle": "Asa de válvula gris claro", + "block.create.lime_sail": "Vela lima", + "block.create.lime_seat": "Asiento lima", + "block.create.lime_valve_handle": "Asa de válvula lima", + "block.create.limesand": "Arena caliza", + "block.create.limestone": "Piedra caliza", + "block.create.limestone_bricks": "Ladrillos de piedra caliza", + "block.create.limestone_bricks_slab": "Losa de ladrillos de piedra caliza", + "block.create.limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza", + "block.create.limestone_bricks_wall": "Pared de ladrillos de piedra caliza", + "block.create.limestone_cobblestone": "Adoquínes de piedra caliza", + "block.create.limestone_cobblestone_slab": "Losa de adoquines de piedra caliza", + "block.create.limestone_cobblestone_stairs": "Escaleras de adoquines de piedra caliza", + "block.create.limestone_cobblestone_wall": "Pared de adoquines de piedra caliza", + "block.create.limestone_pillar": "Pilar de piedra caliza", + "block.create.linear_chassis": "Chasis lineal", + "block.create.lit_blaze_burner": "Quemador de Blaze encendido", + "block.create.magenta_sail": "Vela magenta", + "block.create.magenta_seat": "Asiento magenta", + "block.create.magenta_valve_handle": "Asa de válvula magenta", + "block.create.mechanical_arm": "Brazo mecánico", + "block.create.mechanical_bearing": "Rodamiento mecánico", + "block.create.mechanical_crafter": "Autoensamblador mecánico", + "block.create.mechanical_drill": "Taladro mecánico", + "block.create.mechanical_harvester": "Cosechadora mecánica", + "block.create.mechanical_mixer": "Mezcladora mecánica", + "block.create.mechanical_piston": "Pistón mecánico", + "block.create.mechanical_piston_head": "Cabezal de pistón mecánico", + "block.create.mechanical_plough": "Arado mecánico", + "block.create.mechanical_press": "Prensa mecánica", + "block.create.mechanical_pump": "Bomba mecánica", + "block.create.mechanical_saw": "Sierra mecánica", + "block.create.metal_bracket": "Soporte de metal para ejes", + "block.create.millstone": "Piedra de molino", + "block.create.minecart_anchor": "Ancla de vagonetas", + "block.create.mossy_andesite": "Andesita musgosa", + "block.create.mossy_dark_scoria": "Escoria oscura musgosa", + "block.create.mossy_diorite": "Diorita musgosa", + "block.create.mossy_dolomite": "Dolomita musgosa", + "block.create.mossy_gabbro": "Gabro musgoso", + "block.create.mossy_granite": "Granito musgoso", + "block.create.mossy_limestone": "Caliza musgosa", + "block.create.mossy_scoria": "Escoria musgosa", + "block.create.mossy_weathered_limestone": "Caliza erosionada musgosa", + "block.create.mysterious_cuckoo_clock": "Reloj cucú", + "block.create.natural_scoria": "Escoria natural", + "block.create.nixie_tube": "Tubo Nixie", + "block.create.nozzle": "Boquilla", + "block.create.oak_window": "Ventana de roble", + "block.create.oak_window_pane": "Panel de ventana de roble", + "block.create.orange_sail": "Vela naranja", + "block.create.orange_seat": "Asiento naranja", + "block.create.orange_valve_handle": "Asa de válvula naranja", + "block.create.ornate_iron_window": "Ventana de hierro ornamentada", + "block.create.ornate_iron_window_pane": "Panel de ventana de hierro ornamentada", + "block.create.overgrown_andesite": "Andesita sobredimensionada", + "block.create.overgrown_dark_scoria": "Escoria oscura sobredimensionada", + "block.create.overgrown_diorite": "Diorita sobredimensionada", + "block.create.overgrown_dolomite": "Dolomita sobredimensionada", + "block.create.overgrown_gabbro": "Gabro sobredimensionado", + "block.create.overgrown_granite": "Granito sobredimensionado", + "block.create.overgrown_limestone": "Caliza sobredimensionada", + "block.create.overgrown_scoria": "Escoria sobredimensionada", + "block.create.overgrown_weathered_limestone": "Caliza erosionada sobredimensionada", + "block.create.paved_andesite": "Andesita pavimentada", + "block.create.paved_andesite_slab": "Losa de andesita pavimentada", + "block.create.paved_andesite_stairs": "Escaleras de andesita pavimentada", + "block.create.paved_andesite_wall": "Pared de andesita pavimentada", + "block.create.paved_dark_scoria": "Escoria oscura pavimentada", + "block.create.paved_dark_scoria_slab": "Losa de escoria oscura pavimentada", + "block.create.paved_dark_scoria_stairs": "Escaleras de escoria oscura pavimentada", + "block.create.paved_dark_scoria_wall": "Pared de escoria oscura pavimentad", + "block.create.paved_diorite": "Diorita pavimentada", + "block.create.paved_diorite_slab": "Losa de diorita pavimentada", + "block.create.paved_diorite_stairs": "Escaleras de diorita pavimentada", + "block.create.paved_diorite_wall": "Pared de diorita pavimentad", + "block.create.paved_dolomite": "Dolomita pavimentada", + "block.create.paved_dolomite_slab": "Losa de dolomita pavimentada", + "block.create.paved_dolomite_stairs": "Escaleras de dolomita pavimentada", + "block.create.paved_dolomite_wall": "Pared de dolomita pavimentada", + "block.create.paved_gabbro": "Gabro pavimentado", + "block.create.paved_gabbro_slab": "Losa de gabro pavimentado", + "block.create.paved_gabbro_stairs": "Escaleras de gabro pavimentado", + "block.create.paved_gabbro_wall": "Pared de gabro pavimentado", + "block.create.paved_granite": "Granito pavimentado", + "block.create.paved_granite_slab": "Losa de granito pavimentado", + "block.create.paved_granite_stairs": "Escaleras de granito pavimentado", + "block.create.paved_granite_wall": "Pared de granito pavimentado", + "block.create.paved_limestone": "Piedra caliza pavimentada", + "block.create.paved_limestone_slab": "Losa de piedra caliza pavimentada", + "block.create.paved_limestone_stairs": "Escaleras de piedra caliza pavimentada", + "block.create.paved_limestone_wall": "Pared de piedra caliza pavimentada", + "block.create.paved_scoria": "Escoria pavimentada", + "block.create.paved_scoria_slab": "Losa de escoria pavimentada", + "block.create.paved_scoria_stairs": "Escaleras de escoria pavimentada", + "block.create.paved_scoria_wall": "Pared de escoria pavimentada", + "block.create.paved_weathered_limestone": "Piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_slab": "Losa de piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_wall": "Pared de piedra caliza erosionada pavimentada", + "block.create.pink_sail": "Vela rosa", + "block.create.pink_seat": "Asiento rosa", + "block.create.pink_valve_handle": "Asa de válvula rosa", + "block.create.piston_extension_pole": "Pértiga de extensión de pistón", + "block.create.polished_dark_scoria": "Escoria oscura pulida", + "block.create.polished_dark_scoria_slab": "Losa de escoria oscura pulida", + "block.create.polished_dark_scoria_stairs": "Escaleras de escoria oscura pulida", + "block.create.polished_dark_scoria_wall": "Pared de escoria oscura pulida", + "block.create.polished_dolomite": "Dolomita pulida", + "block.create.polished_dolomite_slab": "Losa de dolomita pulida", + "block.create.polished_dolomite_stairs": "Escaleras de dolomita pulidas", + "block.create.polished_dolomite_wall": "Pared de dolomita pulida", + "block.create.polished_gabbro": "Gabro pulido", + "block.create.polished_gabbro_slab": "Losa de gabro pulido", + "block.create.polished_gabbro_stairs": "Escaleras de gabro pulido", + "block.create.polished_gabbro_wall": "Pared de gabro pulido", + "block.create.polished_limestone": "Piedra caliza pulida", + "block.create.polished_limestone_slab": "Losa de piedra caliza pulida", + "block.create.polished_limestone_stairs": "Escaleras de piedra caliza pulidas", + "block.create.polished_limestone_wall": "Pared de piedra caliza pulida", + "block.create.polished_scoria": "Escoria pulida", + "block.create.polished_scoria_slab": "Losa de escoria pulida", + "block.create.polished_scoria_stairs": "Escaleras de losa pulida", + "block.create.polished_scoria_wall": "Pared de escoria pulida", + "block.create.polished_weathered_limestone": "Piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_slab": "Losa de piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_wall": "Pared de piedra caliza erosionada pulida", + "block.create.portable_fluid_interface": "Interfaz de fluidos portátil", + "block.create.portable_storage_interface": "Interfaz de almacenamiento portátil", + "block.create.powered_latch": "Palanca motorizada", + "block.create.powered_toggle_latch": "Palanca de cierre motorizada", + "block.create.pulley_magnet": "Imán de la polea", + "block.create.pulse_repeater": "Repetidor de pulsos de Redstone", + "block.create.purple_sail": "Vela morada", + "block.create.purple_seat": "Asiento morado", + "block.create.purple_valve_handle": "Asa de válvula morada", + "block.create.radial_chassis": "Chasis radial", + "block.create.red_sail": "Vela roja", + "block.create.red_seat": "Asiento rojo", + "block.create.red_valve_handle": "Asa de válvula roja", + "block.create.redstone_contact": "Contacto de Redstone", + "block.create.redstone_link": "Enlace de Redstone", + "block.create.refined_radiance_casing": "Revestidor de radiante", + "block.create.reinforced_rail": "Raíl reforzado", + "block.create.rope": "Soga", + "block.create.rope_pulley": "Polea de cuerda", + "block.create.rotation_speed_controller": "Controlador de velocidad de rotación", + "block.create.sail_frame": "Marco de vela", + "block.create.schematic_table": "Tabla de esquemas", + "block.create.schematicannon": "Schematicannon", + "block.create.scoria": "Escoria", + "block.create.scoria_bricks": "Ladrillos de escoria", + "block.create.scoria_bricks_slab": "Losa de ladrillos de escoria", + "block.create.scoria_bricks_stairs": "Escaleras de ladrillos de escoria", + "block.create.scoria_bricks_wall": "Pared de ladrillos de escoria", + "block.create.scoria_cobblestone": "Adoquín de escoria", + "block.create.scoria_cobblestone_slab": "Losa de adoquínes de escoria", + "block.create.scoria_cobblestone_stairs": "Escaleras de adoquines de escoria", + "block.create.scoria_cobblestone_wall": "Pared de adoquines de escoria", + "block.create.scoria_pillar": "Pilar de escoria", + "block.create.secondary_linear_chassis": "Chasis lineal secundario", + "block.create.sequenced_gearshift": "Palanca de cambios secuencial", + "block.create.shadow_steel_casing": "Revestidor sombrío", + "block.create.shaft": "Eje", + "block.create.smart_chute": "Ducto inteligente", + "block.create.smart_fluid_pipe": "Tubería de fluidos inteligente", + "block.create.speedometer": "Velocímetro", + "block.create.spout": "Surtidor", + "block.create.spruce_window": "Ventana de abeto", + "block.create.spruce_window_pane": "Panel de ventana de abeto", + "block.create.sticky_mechanical_piston": "Pistón mecánico pegajoso", + "block.create.stockpile_switch": "Interruptor de acopio", + "block.create.stressometer": "Estresómetro", + "block.create.tiled_glass": "Vidrio esmaltado", + "block.create.tiled_glass_pane": "Panel de vidrio esmaltado", + "block.create.turntable": "Plataforma giratoria mecánica", + "block.create.vertical_framed_glass": "Vidrio esmaltado vertical", + "block.create.vertical_framed_glass_pane": "Panel de vidrio esmaltado vertical", + "block.create.water_wheel": "Rueda hidráulica mecánica", + "block.create.weathered_limestone": "Piedra caliza erosionada", + "block.create.weathered_limestone_bricks": "Ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_slab": "Losa de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_wall": "Pared de ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone": "Adoquín de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_slab": "Losa de adoquín de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_stairs": "Escaleras de adoquín de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_wall": "Pared de adoquínes de piedra caliza erosionada", + "block.create.weathered_limestone_pillar": "Pilar de piedra caliza erosionada", + "block.create.white_sail": "Vela blanca", + "block.create.white_seat": "Asiento blanco", + "block.create.white_valve_handle": "Asa de válvula blanco", + "block.create.windmill_bearing": "Rodamiento del molino de viento", + "block.create.wooden_bracket": "Soporte de madera para ejes", + "block.create.yellow_sail": "Vela amarilla", + "block.create.yellow_seat": "Asiento amarillo", + "block.create.yellow_valve_handle": "Asa de válvula amarillo", + "block.create.zinc_block": "Bloque de zinc", + "block.create.zinc_ore": "Mineral de zinc", + + "entity.create.contraption": "Artilugio", + "entity.create.gantry_contraption": "Artilugio de grúa", + "entity.create.seat": "Asiento", + "entity.create.stationary_contraption": "Artilugio estacionario", + "entity.create.super_glue": "Super Pegamento", + + "fluid.create.milk": "Leche", + "fluid.create.potion": "Poción", + "fluid.create.tea": "Té del Constructor", + + "item.create.andesite_alloy": "Aleación de andesita", + "item.create.attribute_filter": "Filtro de atributos", + "item.create.bar_of_chocolate": "Barra de chocolate", + "item.create.belt_connector": "Correa", + "item.create.blaze_cake": "Pastel de Blaze", + "item.create.blaze_cake_base": "Base de Pastel de Blaze", + "item.create.brass_hand": "Mano de latón", + "item.create.brass_ingot": "Lingote de latón", + "item.create.brass_nugget": "Pepita de latón", + "item.create.brass_sheet": "Lámina de latón", + "item.create.builders_tea": "Té del Constructor", + "item.create.chest_minecart_contraption": "Artilugio de vagoneta con cofre", + "item.create.chocolate_bucket": "Cubo de chocolate", + "item.create.chromatic_compound": "Compuesto cromático", + "item.create.cinder_flour": "Harina de ceniza", + "item.create.copper_ingot": "Lingote de cobre", + "item.create.copper_nugget": "Pepita de cobre", + "item.create.copper_sheet": "Lámina de cobre", + "item.create.crafter_slot_cover": "Tapa de ranura del Autoensamblador mecánico", + "item.create.crushed_aluminum_ore": "Mineral de aluminio molido", + "item.create.crushed_brass": "Latón molido", + "item.create.crushed_copper_ore": "Mineral de cobre molido", + "item.create.crushed_gold_ore": "Mineral de oro molido", + "item.create.crushed_iron_ore": "Mineral de hierro molido", + "item.create.crushed_lead_ore": "Mineral de plomo molido", + "item.create.crushed_nickel_ore": "Mineral de níquel molido", + "item.create.crushed_osmium_ore": "Mineral de osmio molido", + "item.create.crushed_platinum_ore": "Mineral de platino molido", + "item.create.crushed_quicksilver_ore": "Mineral de mercurio molido", + "item.create.crushed_silver_ore": "Mineral de plata molido", + "item.create.crushed_tin_ore": "Mineral de estaño molido", + "item.create.crushed_uranium_ore": "Mineral de uranio molido", + "item.create.crushed_zinc_ore": "Mineral de zinc molido", + "item.create.deforester": "Deforestador", + "item.create.dough": "Masilla", + "item.create.electron_tube": "Tubo de electrones", + "item.create.empty_blaze_burner": "Quemador de Blaze vacío", + "item.create.empty_schematic": "Esquema vacío", + "item.create.extendo_grip": "Agarre extendido", + "item.create.filter": "Filtro", + "item.create.furnace_minecart_contraption": "Artilugio de vagoneta de horno", + "item.create.goggles": "Gafas del Ingeniero", + "item.create.golden_sheet": "Lámina de oro", + "item.create.handheld_blockzapper": "Blockzapper", + "item.create.handheld_worldshaper": "Worldshaper", + "item.create.honey_bucket": "Cubo de miel", + "item.create.integrated_circuit": "Chip de circuito integrado", + "item.create.iron_sheet": "Lámina de hierro", + "item.create.lapis_sheet": "Lámina de lapislázuli", + "item.create.minecart_contraption": "Artilugio de vagoneta", + "item.create.minecart_coupling": "Acoplamiento de vagoneta", + "item.create.polished_rose_quartz": "Cuarzo rosado pulido", + "item.create.powdered_obsidian": "Obsidiana en polvo", + "item.create.propeller": "Hélice", + "item.create.red_sand_paper": "Papel de lija rojo", + "item.create.refined_radiance": "Resplandor refinado", + "item.create.rose_quartz": "Cuarzo rosado", + "item.create.sand_paper": "Papel de lija", + "item.create.schematic": "Esquema", + "item.create.schematic_and_quill": "Esquema y Pluma", + "item.create.shadow_steel": "Acero sombrío", + "item.create.super_glue": "Super Pegamento", + "item.create.tree_fertilizer": "Fertilizador de árboles", + "item.create.vertical_gearbox": "Caja de transmisión vertical", + "item.create.wand_of_symmetry": "Varita de simetría", + "item.create.wheat_flour": "Harina de trigo", + "item.create.whisk": "Batidora", + "item.create.wrench": "Llave inglesa", + "item.create.zinc_ingot": "Lingote de zinc", + "item.create.zinc_nugget": "Pepita de zinc", + + + "_": "->------------------------] Advancements [------------------------<-", + + "advancement.create.root": "Bienvenido a Create", + "advancement.create.root.desc": "¡Es hora de empezar a construir increíbles Artilugios!", + "advancement.create.andesite_alloy": "Aliteraciones en abundancia", + "advancement.create.andesite_alloy.desc": "Los materiales de Create tienen nombres extraños, la aleación de andesita es uno de ellos.", + "advancement.create.its_alive": "Está Vivo!", + "advancement.create.its_alive.desc": "Vea cómo gira su primer componente cinético.", + "advancement.create.shifting_gears": "Cambiando de marcha", + "advancement.create.shifting_gears.desc": "Conecta una rueda dentada grande a una pequeña, lo que te permitirá cambiar la velocidad de tu artilugio.", + "advancement.create.overstressed": "Sobrecargado", + "advancement.create.overstressed.desc": "Experimenta los límites del estrés.", + "advancement.create.belt": "Paseo de algas", + "advancement.create.belt.desc": "Conectar dos ejes con una correa.", + "advancement.create.tunnel": "Cúbrete!", + "advancement.create.tunnel.desc": "Embellece tu correa con un Túnel.", + "advancement.create.splitter_tunnel": "Divide y vencerás", + "advancement.create.splitter_tunnel.desc": "Crear un divisor con un grupo de túneles de latón.", + "advancement.create.chute": "Caída en picado", + "advancement.create.chute.desc": "Coloque un ducto, la contrapartida vertical de la correa.", + "advancement.create.upward_chute": "Abducción aérea", + "advancement.create.upward_chute.desc": "Observe cómo un objeto lanzado vuela hacia un paracaídas impulsado por un ventilador.", + "advancement.create.belt_funnel": "Colgantes con forma de embudo", + "advancement.create.belt_funnel.desc": "Coloca un embudo lateral encima de una cinta o depósito para crear un tipo especial.", + "advancement.create.belt_funnel_kiss": "Los loros y las aletas", + "advancement.create.belt_funnel_kiss.desc": "Haz besar dos embudos montados con una cinta.", + "advancement.create.fan": "Maestro mecánico del aire", + "advancement.create.fan.desc": "Monta la corriente de aire proporcionada por un ventilador revestido.", + "advancement.create.fan_lava": "Calentador geotérmico", + "advancement.create.fan_lava.desc": "Quedar atrapado en una corriente de aire que funde las cosas.", + "advancement.create.fan_water": "Lavado de la ropa", + "advancement.create.fan_water.desc": "Quedar atrapado en una corriente de aire que lava las cosas.", + "advancement.create.fan_smoke": "Fuelle mecánico", + "advancement.create.fan_smoke.desc": "Quedar atrapado en una corriente de aire que humea los artículos.", + "advancement.create.wrench": "Configurar convenientemente", + "advancement.create.wrench.desc": "Crea una llave inglesa para ayudarte a construir tus artilugios.", + "advancement.create.goggles": "Stress-O-Vision", + "advancement.create.goggles.desc": "Crea unas Gafas del Ingeniero para ayudarte a obtener más información cinética de los componentes.", + "advancement.create.speedometer": "Pero, ¿con qué rapidez exactamente??", + "advancement.create.speedometer.desc": "Coloca y alimenta un Velocímetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.stressometer": "Pero, ¿cuán estresado exactamente??", + "advancement.create.stressometer.desc": "Coloca y alimenta un Estresómetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.aesthetics": "Boom, Estética!", + "advancement.create.aesthetics.desc": "Colocar los soportes en un eje, tubo y rueda dentada.", + "advancement.create.reinforced": "Boom, Reforzado!", + "advancement.create.reinforced.desc": "Utilizar bloques de revestimiento en un eje, un tubo y una correa.", + "advancement.create.water_wheel": "Aprovechar la hidráulica", + "advancement.create.water_wheel.desc": "Coloca una Rueda hidráulica e intenta hacerla girar.", + "advancement.create.chocolate_wheel": "Potencia de buen gusto", + "advancement.create.chocolate_wheel.desc": "Hacer funcionar una rueda de agua con chocolate fundido.", + "advancement.create.lava_wheel": "Rueda de Magma", + "advancement.create.lava_wheel.desc": "Esto no debió haber funcionado.", + "advancement.create.cuckoo": "¿Es el momento?", + "advancement.create.cuckoo.desc": "Presenciar cómo un Reloj de cucú anuncia la hora de acostarse.", + "advancement.create.millstone": "Triturador de bolsillo", + "advancement.create.millstone.desc": "Colocar y alimentar una Piedra de molino.", + "advancement.create.windmill": "Una suave brisa", + "advancement.create.windmill.desc": "Montar un molino de viento.", + "advancement.create.maxed_windmill": "Una fuerte brisa", + "advancement.create.maxed_windmill.desc": "Montar un molino de viento de máxima intensidad.", + "advancement.create.andesite_casing": "La edad de la andesita", + "advancement.create.andesite_casing.desc": "Utiliza un poco de aleación de andesita y madera para crear un revestimiento básico.", + "advancement.create.mechanical_drill": "Interruptores fijos", + "advancement.create.mechanical_drill.desc": "Colocar y alimentar un taladro mecánico.", + "advancement.create.press": "¡La prensa se pone en marcha!", + "advancement.create.press.desc": "Activa una prensa mecánica y utilízala para crear algunas láminas.", + "advancement.create.polished_rose_quartz": "Diamantes rosas", + "advancement.create.polished_rose_quartz.desc": "Utiliza un trozo de papel de lija para pulir el cuarzo rosa hasta que se vuelva transparente.", + "advancement.create.electron_tube": "Beep Boop", + "advancement.create.electron_tube.desc": "Haz algunos Tubos de Electrones, útiles en la fabricación de maquinaria menos primitiva.", + "advancement.create.mechanical_saw": "Picado estacionario", + "advancement.create.mechanical_saw.desc": "Colocar y alimentar una sierra mecánica.", + "advancement.create.basin": "Funcionamiento de la cuenca", + "advancement.create.basin.desc": "Coloca una Cuenca e intenta arrojar objetos en ella.", + "advancement.create.mixer": "Mezcla de colores", + "advancement.create.mixer.desc": "Coloque una batidora mecánica sobre el lavabo, enciéndala y empiece a mezclar algunos ingredientes.", + "advancement.create.blaze_burner": "Una chimenea viva", + "advancement.create.blaze_burner.desc": "Obtener un Quemador de Blaze.", + "advancement.create.compact": "Compactación automática", + "advancement.create.compact.desc": "Utiliza una prensa y una palangana para compactar algunos elementos.", + "advancement.create.brass": "Aleaciones reales", + "advancement.create.brass.desc": "Utiliza Cobre molido y Zinc molido para crear algo de latón.", + "advancement.create.brass_casing": "La Edad de Latón", + "advancement.create.brass_casing.desc": "Utiliza el latón recién obtenido y algo de madera para crear un revestimiento más avanzado.", + "advancement.create.copper_casing": "La Edad de Cobre", + "advancement.create.copper_casing.desc": "Utiliza algunas láminas de cobre y madera para crear algunos revestimientos de cobre.", + "advancement.create.spout": "Sploosh", + "advancement.create.spout.desc": "Observar el llenado de un elemento fluido usando una boquilla.", + "advancement.create.spout_potion": "Cervecera global", + "advancement.create.spout_potion.desc": "Mira cómo un pico llena una botella con líquido de poción.", + "advancement.create.chocolate": "Un mundo de imaginación", + "advancement.create.chocolate.desc": "Obtener un cubo de chocolate fundido.", + "advancement.create.item_drain": "Drenaje de la ropa", + "advancement.create.item_drain.desc": "Ver cómo se vacía un elemento fluido mediante una drenadora de elementos.", + "advancement.create.chained_item_drain": "Déjalo rodar!", + "advancement.create.chained_item_drain.desc": "Observa cómo un objeto rueda por varios drenadores de elementos encadenados.", + "advancement.create.glass_pipe": "Espía del flujo", + "advancement.create.glass_pipe.desc": "Observe cómo se propaga el fluido a través de una tubería de fluidos con ventanas. Las tuberías de fluido rectas se convierten en ventanas cuando se utiliza una llave en ellas.", + "advancement.create.pipe_collision": "No cruzar nunca los arroyos", + "advancement.create.pipe_collision.desc": "Vea cómo se unen dos fluidos en su red de tuberías.", + "advancement.create.pipe_spill": "¡Hay una fuga!", + "advancement.create.pipe_spill.desc": "Observe cómo un extremo abierto de una tubería toma o deposita fluidos en el mundo.", + "advancement.create.hose_pulley": "Vertidos industriales", + "advancement.create.hose_pulley.desc": "Bajar una polea de manguera y ver cómo se vacía o se llena un cuerpo de líquido.", + "advancement.create.infinite_water": "Drenando el océano", + "advancement.create.infinite_water.desc": "Bombea de una masa de agua lo suficientemente grande como para ser considerada infinita.", + "advancement.create.infinite_lava": "Drenaje del núcleo de los planetas", + "advancement.create.infinite_lava.desc": "Bombea de una masa de lava lo suficientemente grande como para ser considerada infinita.", + "advancement.create.infinite_chocolate": "Ahogándose en la imaginación", + "advancement.create.infinite_chocolate.desc": "Bombea desde una masa de chocolate fundido lo suficientemente grande como para ser considerado infinito.", + "advancement.create.crafter": "Montaje automatizado", + "advancement.create.crafter.desc": "Coloca y alimenta algunos autoensambladores.", + "advancement.create.clockwork_bearing": "Artilugio a la hora", + "advancement.create.clockwork_bearing.desc": "Ensamblar una estructura montada sobre un rodamiento de relojería.", + "advancement.create.nixie_tube": "Signos de estilo", + "advancement.create.nixie_tube.desc": "Obtener y colocar un par de Tubos Nixie.", + "advancement.create.deployer": "Picar, colocar y atacar", + "advancement.create.deployer.desc": "Coloca y potencia un Desplegador, el reflejo perfecto de ti mismo.", + "advancement.create.speed_controller": "Los ingenieros lo odian!", + "advancement.create.speed_controller.desc": "Coloque un regulador de velocidad de rotación, el dispositivo definitivo para cambiar de marcha.", + "advancement.create.flywheel": "El corazón de la fábrica", + "advancement.create.flywheel.desc": "Conectar con éxito un motor a la rueda de inercia.", + "advancement.create.overstress_flywheel": "Altos niveles de estrés", + "advancement.create.overstress_flywheel.desc": "Sobrecargar un Motor de Horno.", + "advancement.create.integrated_circuit": "Cálculos complejos", + "advancement.create.integrated_circuit.desc": "Ensamblar un chip de circuito integrado.", + "advancement.create.mechanical_arm": "Manos ocupadas!", + "advancement.create.mechanical_arm.desc": "Crea un brazo mecánico, selecciona las entradas y salidas, colócalo en el suelo y dale energía; luego observa cómo hace todo el trabajo por ti.", + "advancement.create.musical_arm": "Tócame la melodía!", + "advancement.create.musical_arm.desc": "Vea cómo un brazo mecánico maneja su Jukebox.", + "advancement.create.arm_many_targets": "Organize-o-Tron", + "advancement.create.arm_many_targets.desc": "Programar un brazo mecánico con diez o más posiciones de salida.", + "advancement.create.arm_blaze_burner": "Combust-o-Tron", + "advancement.create.arm_blaze_burner.desc": "Instruya un brazo mecánico para alimentar su Quemador de Blaze.", + "advancement.create.fist_bump": "¡Pégale, hermano!", + "advancement.create.fist_bump.desc": "Hacer que dos Desplegadores se den un puñetazo.", + "advancement.create.crushing_wheel": "Un par de gigantes", + "advancement.create.crushing_wheel.desc": "Crea algunas Ruedas de trituración para descomponer más materiales de forma más eficaz.", + "advancement.create.blaze_cake": "Fiebre del azúcar", + "advancement.create.blaze_cake.desc": "Hornea en tu Quemador de Blaze un pastel especial.", + "advancement.create.chromatic_compound": "Minerales bipolares", + "advancement.create.chromatic_compound.desc": "Crea una Barra de Compuesto Cromático.", + "advancement.create.shadow_steel": "Retorno del vacío", + "advancement.create.shadow_steel.desc": "Crea Acero Sombrío, una barra de metal de la nada.", + "advancement.create.refined_radiance": "Brillante e inspirador", + "advancement.create.refined_radiance.desc": "Crea un Resplandor refinado, una poderosa sustancia cromática.", + "advancement.create.chromatic_age": "La edad cromática", + "advancement.create.chromatic_age.desc": "Crear bloques de revestimiento de la luz y la oscuridad.", + "advancement.create.zapper": "Construir con estilo", + "advancement.create.zapper.desc": "Construye un Blockzapper. Una pistola láser radiante que te ayuda a construir.", + "advancement.create.upgraded_zapper": "Radiante sobrecarga", + "advancement.create.upgraded_zapper.desc": "Crear y activar un Blockzapper totalmente mejorado.", + "advancement.create.wand_of_symmetry": "Espejos radiantes", + "advancement.create.wand_of_symmetry.desc": "Crear un bastón de simetría.", + "advancement.create.deforester": "Picado radiante", + "advancement.create.deforester.desc": "Crea un Deforestador y despídete del bosque local.", + "advancement.create.extendo_grip": "Boioioing!", + "advancement.create.extendo_grip.desc": "Hazte con un Agarre extentido.", + "advancement.create.dual_extendo_grip": "La última edad del boing", + "advancement.create.dual_extendo_grip.desc": "Doble Empuñadura extendida para un alcance sobrehumano.", + "advancement.create.eob": "Fin de la beta", + "advancement.create.eob.desc": "Espere más contenido aquí en el futuro. <3", + + + "_": "->------------------------] UI & Messages [------------------------<-", + + "itemGroup.create.base": "Create", + "itemGroup.create.palettes": "Paletas", + + "death.attack.create.crush": "%1$s se procesó por las Ruedas de trituración", + "death.attack.create.fan_fire": "%1$s murió quemado por el aire caliente", + "death.attack.create.fan_lava": "%1$s murió quemado por un abanico de lava", + "death.attack.create.mechanical_drill": "%1$s fue empalado por un taladro mecánico", + "death.attack.create.mechanical_saw": "%1$s fue cortado por la mitad por una sierra mecánica", + "death.attack.create.cuckoo_clock_explosion": "%1$s fue volado por los aires por un reloj cucú manipulado", + + "create.block.deployer.damage_source_name": "un Desplegador rebelde", + "create.block.cart_assembler.invalid": "Coloque su Ensamblador de vagonetas en un bloque de Raíles", + + "create.recipe.crushing": "Trituración", + "create.recipe.milling": "Fresado", + "create.recipe.fan_washing": "Lavado a granel", + "create.recipe.fan_washing.fan": "Ventilador detrás del agua fluyente", + "create.recipe.fan_smoking": "Ahumador a granel", + "create.recipe.fan_smoking.fan": "Ventilador detrás del fuego", + "create.recipe.fan_blasting": "Voladuras a granel", + "create.recipe.fan_blasting.fan": "Ventilador detrás de la lava", + "create.recipe.pressing": "Prensando", + "create.recipe.mixing": "Mezclando", + "create.recipe.automatic_shapeless": "Elaboración automatizada de productos sin forma", + "create.recipe.automatic_brewing": "Elaboración de cerveza automatizada", + "create.recipe.packing": "Compactando", + "create.recipe.automatic_packing": "Embalaje automatizado", + "create.recipe.sawing": "Aserrando", + "create.recipe.mechanical_crafting": "Elaboración mecánica", + "create.recipe.automatic_shaped": "Elaboración automatizada de productos con forma", + "create.recipe.block_cutting": "Corte de bloques", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", + "create.recipe.blockzapper_upgrade": "Blockzapper", + "create.recipe.sandpaper_polishing": "Pulido con papel de lija", + "create.recipe.mystery_conversion": "Conversión misteriosa", + "create.recipe.spout_filling": "Llenar por el pico", + "create.recipe.draining": "Drenador de elementos", + "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.heat_requirement.none": "No es necesario calentar", + "create.recipe.heat_requirement.heated": "Calentado", + "create.recipe.heat_requirement.superheated": "Súper-Calentado", + + "create.generic.range": "Rango", + "create.generic.radius": "Radio", + "create.generic.width": "Ancho", + "create.generic.height": "Alto", + "create.generic.length": "Largo", + "create.generic.speed": "Velocidad", + "create.generic.delay": "Retraso", + "create.generic.unit.ticks": "Ticks", + "create.generic.unit.seconds": "Segundos", + "create.generic.unit.minutes": "Minutos", + "create.generic.unit.rpm": "RPM", + "create.generic.unit.stress": "su", + "create.generic.unit.degrees": "°", + "create.generic.unit.millibuckets": "%1$smB", + "create.generic.clockwise": "En el sentido de las agujas del reloj", + "create.generic.counter_clockwise": "En sentido contrario a las agujas del reloj", + + "create.action.scroll": "Desplazar", + "create.action.confirm": "Confirmar", + "create.action.abort": "Abortar", + "create.action.saveToFile": "Guardar", + "create.action.discard": "Descartar", + + "create.keyinfo.toolmenu": "Menú de la Herramienta de Enfoque", + "create.keyinfo.scrollup": "Simular usar la rueda del ratón hacia arriba (en el mundo)", + "create.keyinfo.scrolldown": "Simular usar la rueda del ratón hacia abajo (en el mundo)", + + "create.gui.scrollInput.defaultTitle": "Seleccione una opción:", + "create.gui.scrollInput.scrollToModify": "Usa la rueda del ratón para Modificar", + "create.gui.scrollInput.scrollToAdjustAmount": "Usa la rueda del ratón para ajustar la cantidad", + "create.gui.scrollInput.scrollToSelect": "Usa la rueda del ratón para Seleccionar", + "create.gui.scrollInput.shiftScrollsFaster": "Shift para usar la rueda del ratón más rápido", + "create.gui.toolmenu.focusKey": "Mantenga [%1$s] para enfocar", + "create.gui.toolmenu.cycle": "[RUEDA DEL RATÓN] para el ciclo", + "create.gui.symmetryWand.mirrorType": "Espejado", + "create.gui.symmetryWand.orientation": "Orientación", + + "create.symmetry.mirror.plane": "Plano de espejo", + "create.symmetry.mirror.doublePlane": "Rectangular", + "create.symmetry.mirror.triplePlane": "Octogonal", + + "create.orientation.orthogonal": "Ortogonal", + "create.orientation.diagonal": "Diagonal", + "create.orientation.horizontal": "Horizontal", + "create.orientation.alongZ": "A lo largo de Z", + "create.orientation.alongX": "A lo largo de X", + + "create.gui.blockzapper.title": "Blockzapper", + "create.gui.blockzapper.replaceMode": "Modo de sustitución", + "create.gui.blockzapper.searchDiagonal": "Seguir las diagonales", + "create.gui.blockzapper.searchFuzzy": "Ignorar los bordes del material", + "create.gui.blockzapper.range": "Alcance del margen de maniobra", + "create.gui.blockzapper.needsUpgradedAmplifier": "Requiere un amplificador mejorado", + "create.gui.blockzapper.patternSection": "Patrón", + "create.gui.blockzapper.pattern.solid": "Sólido", + "create.gui.blockzapper.pattern.checkered": "Tablero de ajedrez", + "create.gui.blockzapper.pattern.inversecheckered": "Tablero de ajedrez invertido", + "create.gui.blockzapper.pattern.chance25": "25% Roll", + "create.gui.blockzapper.pattern.chance50": "50% Roll", + "create.gui.blockzapper.pattern.chance75": "75% Roll", + "create.gui.terrainzapper.title": "Worldshaper", + "create.gui.terrainzapper.placement": "Colocación", + "create.gui.terrainzapper.placement.merged": "Fusionado", + "create.gui.terrainzapper.placement.attached": "Adjuntado", + "create.gui.terrainzapper.placement.inserted": "Insertado", + "create.gui.terrainzapper.brush": "Pincel", + "create.gui.terrainzapper.brush.cuboid": "Cuboide", + "create.gui.terrainzapper.brush.sphere": "Esfera", + "create.gui.terrainzapper.brush.cylinder": "Cilindro", + "create.gui.terrainzapper.tool": "Herramienta", + "create.gui.terrainzapper.tool.fill": "Llenar", + "create.gui.terrainzapper.tool.place": "Sitio", + "create.gui.terrainzapper.tool.replace": "Sustituir", + "create.gui.terrainzapper.tool.clear": "Borrar", + "create.gui.terrainzapper.tool.overlay": "Superposición", + "create.gui.terrainzapper.tool.flatten": "Aplanar", + + "create.terrainzapper.shiftRightClickToSet": "Shift+Clic con el botón derecho para seleccionar una forma", + + "create.blockzapper.usingBlock": "Utilizando: %1$s", + "create.blockzapper.componentUpgrades": "Mejoras de componentes:", + "create.blockzapper.component.body": "Cuerpo", + "create.blockzapper.component.amplifier": "Amplificador", + "create.blockzapper.component.accelerator": "Acelerador", + "create.blockzapper.component.retriever": "Recuperador", + "create.blockzapper.component.scope": "Mira telescópica", + "create.blockzapper.componentTier.none": "Ninguno", + "create.blockzapper.componentTier.brass": "Latón", + "create.blockzapper.componentTier.chromatic": "Cromático", + "create.blockzapper.leftClickToSet": "Clic izquierdo en un bloque para establecer el material", + "create.blockzapper.empty": "Sin bloques!", + + "create.minecart_coupling.two_couplings_max": "Las vagonetas no pueden tener más de dos enganches cada una", + "create.minecart_coupling.unloaded": "Algunas partes de su tren parecen estar en chunks no cargados", + "create.minecart_coupling.no_loops": "Los acoplamientos no pueden formar un bucle", + "create.minecart_coupling.removed": "Se han retirado todos los acoplamientos de la vagoneta", + "create.minecart_coupling.too_far": "Las vagonetas están demasiado separadas", + + "create.contraptions.movement_mode": "Modo de movimiento", + "create.contraptions.movement_mode.move_place": "Colocar siempre al detenerse", + "create.contraptions.movement_mode.move_place_returned": "Colocar sólo en la posición inicial", + "create.contraptions.movement_mode.move_never_place": "Colocar sólo cuando se destruye el ancla", + "create.contraptions.movement_mode.rotate_place": "Colocar siempre al detenerse", + "create.contraptions.movement_mode.rotate_place_returned": "Colocar sólo cerca del ángulo inicial", + "create.contraptions.movement_mode.rotate_never_place": "Colocar sólo cuando se destruye el ancla", + "create.contraptions.cart_movement_mode": "Modo de movimiento de la vagoneta", + "create.contraptions.cart_movement_mode.rotate": "Siempre de cara al movimiento", + "create.contraptions.cart_movement_mode.rotate_paused": "Pausar a los actores mientras giran", + "create.contraptions.cart_movement_mode.rotation_locked": "Bloquear rotación", + "create.contraptions.windmill.rotation_direction": "Dirección de rotación", + "create.contraptions.clockwork.clock_hands": "Manecillas de reloj", + "create.contraptions.clockwork.hour_first": "La manecilla de las horas primero", + "create.contraptions.clockwork.minute_first": "La manecilla de los minutos primero", + "create.contraptions.clockwork.hour_first_24": "La manecilla del día primero", + + "create.logistics.filter": "Filtro", + "create.logistics.recipe_filter": "Filtro de recetas", + "create.logistics.fluid_filter": "Filtro de fluidos", + "create.logistics.firstFrequency": "Freq. #1", + "create.logistics.secondFrequency": "Freq. #2", + "create.logistics.filter.apply": "Filtro aplicado a %1$s.", + "create.logistics.filter.apply_click_again": "Filtro aplicado a %1$s, haga clic de nuevo para copiar la cantidad.", + "create.logistics.filter.apply_count": "Aplicado recuento de extracciones al filtro.", + + "create.gui.goggles.generator_stats": "Estadísticas del generador:", + "create.gui.goggles.kinetic_stats": "Estadísticas cinéticas:", + "create.gui.goggles.at_current_speed": "con la velocidad actual", + "create.gui.goggles.pole_length": "Longitud del poste:", + "create.gui.assembly.exception": "Este artilugio no se pudo montar:", + "create.gui.assembly.exception.unmovableBlock": "Bloque inamovible (%4$s) en [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "El bloque en [%1$s %2$s %3$s] no estaba en un chunk cargado", + "create.gui.assembly.exception.structureTooLarge": "Hay demasiados bloques incluídos en el artilugio.\nEl máximo configurado es: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "Hay demasiadas Pértigas de extensión conectadas a este Pistón.\nEl máximo configurado es: %1$s", + "create.gui.assembly.exception.noPistonPoles": "Faltan pértigas de extensión para el Pistón", + "create.gui.gauge.info_header": "Información sobre el medidor:", + "create.gui.speedometer.title": "Velocidad de rotación", + "create.gui.stressometer.title": "Estrés de la red", + "create.gui.stressometer.capacity": "Capacidad restante", + "create.gui.stressometer.overstressed": "Sobrecargado", + "create.gui.stressometer.no_rotation": "Sin rotación", + "create.gui.contraptions.not_fast_enough": "Parece que este %1$s no está girando con _suficiente_ velocidad_.", + "create.gui.contraptions.network_overstressed": "Parece que este artilugio está _sobrecargado_. Añade más fuentes o _desacelera_ los componentes con un _impacto_ de alto estrés.", + "create.gui.adjustable_crate.title": "Caja ajustable", + "create.gui.adjustable_crate.storageSpace": "Espacio de almacenamiento", + "create.gui.stockpile_switch.title": "Interruptor de acopio", + "create.gui.stockpile_switch.invert_signal": "Invertir señal", + "create.gui.stockpile_switch.move_to_lower_at": "Pasar al carril inferior en %1$s%%", + "create.gui.stockpile_switch.move_to_upper_at": "Pasar al carril superior en %1$s%%", + "create.gui.sequenced_gearshift.title": "Cambio de marchas secuenciado", + "create.gui.sequenced_gearshift.instruction": "Instrucción", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", + "create.gui.sequenced_gearshift.instruction.turn_angle": "Giro", + "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Ángulo", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", + "create.gui.sequenced_gearshift.instruction.turn_distance": "Pistón", + "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distancia", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", + "create.gui.sequenced_gearshift.instruction.end": "Fin", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", + "create.gui.sequenced_gearshift.speed": "Velocidad, Dirección", + "create.gui.sequenced_gearshift.speed.forward": "Velocidad de entrada, hacia adelante", + "create.gui.sequenced_gearshift.speed.forward_fast": "Doble velocidad, hacia adelante", + "create.gui.sequenced_gearshift.speed.back": "Velocidad de entrada, Invertida", + "create.gui.sequenced_gearshift.speed.back_fast": "Doble velocidad, Invertida", + + "create.schematicAndQuill.dimensions": "Tamaño del esquema: %1$sx%2$sx%3$s", + "create.schematicAndQuill.firstPos": "Primera posición fijada.", + "create.schematicAndQuill.secondPos": "Segunda posición fijada.", + "create.schematicAndQuill.noTarget": "Mantenga [Ctrl] para seleccionar los bloques del aire.", + "create.schematicAndQuill.abort": "Selección eliminada.", + "create.schematicAndQuill.title": "Nombre del esquema:", + "create.schematicAndQuill.convert": "Guardar y desplegar inmediatamente", + "create.schematicAndQuill.fallbackName": "Mi esquema", + "create.schematicAndQuill.saved": "Guardado como %1$s", + + "create.schematic.invalid": "[!] Elemento no válido - Utilice la tabla de esquemas en su lugar", + "create.schematic.position": "Posición", + "create.schematic.rotation": "Rotación", + "create.schematic.rotation.none": "Ninguno", + "create.schematic.rotation.cw90": "En el sentido de las agujas del reloj 90", + "create.schematic.rotation.cw180": "En el sentido de las agujas del reloj 180", + "create.schematic.rotation.cw270": "En el sentido de las agujas del reloj 270", + "create.schematic.mirror": "Espejado", + "create.schematic.mirror.none": "Ninguno", + "create.schematic.mirror.frontBack": "Delante-detrás", + "create.schematic.mirror.leftRight": "Izquierda-Derecha", + "create.schematic.tool.deploy": "Despliegue", + "create.schematic.tool.move": "Mover XZ", + "create.schematic.tool.movey": "Mover Y", + "create.schematic.tool.rotate": "Rotar", + "create.schematic.tool.print": "Imprimir", + "create.schematic.tool.flip": "Voltear", + "create.schematic.tool.deploy.description.0": "Mueve la estructura a un lugar.", + "create.schematic.tool.deploy.description.1": "Haga clic con el botón derecho del ratón en el suelo para colocar.", + "create.schematic.tool.deploy.description.2": "Mantenga [Ctrl] para seleccionar a una distancia fija.", + "create.schematic.tool.deploy.description.3": "[Ctrl]-Rueda del ratón para cambiar la distancia.", + "create.schematic.tool.move.description.0": "Desplaza el esquema horizontalmente.", + "create.schematic.tool.move.description.1": "Apunta al Esquema y [CTRL]-Rueda del ratón para ponerlo.", + "create.schematic.tool.move.description.2": "", + "create.schematic.tool.move.description.3": "", + "create.schematic.tool.movey.description.0": "Desplaza el esquema verticalmente..", + "create.schematic.tool.movey.description.1": "[CTRL]-Rueda del ratón para moverlo hacia arriba/abajo.", + "create.schematic.tool.movey.description.2": "", + "create.schematic.tool.movey.description.3": "", + "create.schematic.tool.rotate.description.0": "Gira el esquema alrededor de su centro.", + "create.schematic.tool.rotate.description.1": "[CTRL]-Rueda del ratón para girar 90 grados.", + "create.schematic.tool.rotate.description.2": "", + "create.schematic.tool.rotate.description.3": "", + "create.schematic.tool.print.description.0": "Sitúa instantáneamente la estructura en el mundo.", + "create.schematic.tool.print.description.1": "[Clic derecho] para confirmar la colocación en el lugar actual.", + "create.schematic.tool.print.description.2": "Esta herramienta es sólo para el Modo Creativo.", + "create.schematic.tool.print.description.3": "", + "create.schematic.tool.flip.description.0": "Voltea el Esquema a lo largo de la cara que seleccione.", + "create.schematic.tool.flip.description.1": "Apunta al esquema y [CTRL]-Rueda del ratón para voltearlo.", + "create.schematic.tool.flip.description.2": "", + "create.schematic.tool.flip.description.3": "", + + "create.schematics.synchronizing": "Sincronizando...", + "create.schematics.uploadTooLarge": "Tu esquema excede las limitaciones especificadas por el servidor.", + "create.schematics.maxAllowedSize": "El tamaño máximo permitido del archivo del esquema es:", + + "create.gui.schematicTable.refresh": "Refrescar archivos", + "create.gui.schematicTable.open_folder": "Abrir carpeta", + "create.gui.schematicTable.title": "Tabla de esquemas", + "create.gui.schematicTable.availableSchematics": "Esquemas disponibles", + "create.gui.schematicTable.noSchematics": "No hay esquemas guardados", + "create.gui.schematicTable.uploading": "Subiendo...", + "create.gui.schematicTable.finished": "Subida finalizada!", + "create.gui.schematicannon.title": "Schematicannon", + "create.gui.schematicannon.listPrinter": "Lista de control de la impresora", + "create.gui.schematicannon.gunpowderLevel": "Pólvora %1$s%%", + "create.gui.schematicannon.shotsRemaining": "Disparos restantes: %1$s", + "create.gui.schematicannon.shotsRemainingWithBackup": "Con respaldo: %1$s", + "create.gui.schematicannon.optionEnabled": "Actualmente habilitado", + "create.gui.schematicannon.optionDisabled": "Actualmente deshabilitado", + "create.gui.schematicannon.showOptions": "Mostrar la configuración de la impresora", + "create.gui.schematicannon.option.dontReplaceSolid": "No sustituír los bloques sólidos", + "create.gui.schematicannon.option.replaceWithSolid": "Sustituir sólido por sólido", + "create.gui.schematicannon.option.replaceWithAny": "Sustituir sólido por cualquiera", + "create.gui.schematicannon.option.replaceWithEmpty": "Sustituir sólido por vacío", + "create.gui.schematicannon.option.skipMissing": "Omitir los bloques que faltan", + "create.gui.schematicannon.option.skipTileEntities": "Proteger a las entidades", + "create.gui.schematicannon.slot.gunpowder": "Añade pólvora para alimentar el cañón", + "create.gui.schematicannon.slot.listPrinter": "Coloque los libros aquí para imprimir una lista de comprobación para su esquema", + "create.gui.schematicannon.slot.schematic": "Añada su esquema aquí. Asegúrese de que se despliega en un lugar específico.", + "create.gui.schematicannon.option.skipMissing.description": "Si el cañón no encuentra un bloque necesario para su colocación, continuará en la siguiente ubicación.", + "create.gui.schematicannon.option.skipTileEntities.description": "El cañón evitará reemplazar los bloques que contienen datos, como los Cofres.", + "create.gui.schematicannon.option.dontReplaceSolid.description": "El cañón nunca sustituirá ningún bloque sólido en su zona de trabajo, sólo los no sólidos y el aire.", + "create.gui.schematicannon.option.replaceWithSolid.description": "El cañón sólo reemplazará los bloques sólidos en su área de trabajo si el esquema contiene un bloque sólido en la ubicación.", + "create.gui.schematicannon.option.replaceWithAny.description": "El cañón reemplazará los bloques sólidos en su área de trabajo si el esquema contiene algún bloque en la ubicación.", + "create.gui.schematicannon.option.replaceWithEmpty.description": "El cañón eliminará todos los bloques de su zona de trabajo, incluidos los sustituidos por Aire.", + + "create.schematicannon.status.idle": "Inactivo", + "create.schematicannon.status.ready": "Listo", + "create.schematicannon.status.running": "Funcionando", + "create.schematicannon.status.finished": "Finished", + "create.schematicannon.status.paused": "Pausado", + "create.schematicannon.status.stopped": "Detenido", + "create.schematicannon.status.noGunpowder": "Sin pólvora", + "create.schematicannon.status.targetNotLoaded": "El objetivo no está cargado", + "create.schematicannon.status.targetOutsideRange": "Objetivo demasiado lejano", + "create.schematicannon.status.searching": "Buscando", + "create.schematicannon.status.skipping": "Omitiendo", + "create.schematicannon.status.missingBlock": "Elementos perdidos:", + "create.schematicannon.status.placing": "Colocando", + "create.schematicannon.status.clearing": "Limpiando bloques", + "create.schematicannon.status.schematicInvalid": "Esquema inválido", + "create.schematicannon.status.schematicNotPlaced": "Esquema no desplegado", + "create.schematicannon.status.schematicExpired": "Archivo de esquemas caducado", + + "create.materialChecklist": "Lista de control del material", + "create.materialChecklist.blocksNotLoaded": "* Descargo de Responsabilidad *\n\nLa lista de materiales puede ser inexacta debido a que no se han cargado los chunks pertinentes.", + + "create.gui.filter.deny_list": "Lista de denegados", + "create.gui.filter.deny_list.description": "Los elementos pasan si NO coinciden con ninguno de los anteriores. Una lista de denegación vacía acepta todo.", + "create.gui.filter.allow_list": "Lista de permitidos", + "create.gui.filter.allow_list.description": "Los elementos pasan si coinciden con alguno de los anteriores. Una lista de permitidos vacía rechaza todo.", + "create.gui.filter.respect_data": "Respetar datos", + "create.gui.filter.respect_data.description": "Los objetos sólo coinciden si su durabilidad, encantos y otros atributos también coinciden.", + "create.gui.filter.ignore_data": "Ignorar datos", + "create.gui.filter.ignore_data.description": "Los artículos coinciden independientemente de sus atributos.", + + "create.item_attributes.placeable": "se puede colocar", + "create.item_attributes.placeable.inverted": "no se puede colocar", + "create.item_attributes.consumable": "se puede comer", + "create.item_attributes.consumable.inverted": "no se puede comer", + "create.item_attributes.smeltable": "se puede fundir", + "create.item_attributes.smeltable.inverted": "no se puede fundir", + "create.item_attributes.washable": "se puede lavar", + "create.item_attributes.washable.inverted": "no se puede lavar", + "create.item_attributes.smokable": "puede ser ahumado", + "create.item_attributes.smokable.inverted": "no puede ser ahumado", + "create.item_attributes.crushable": "puede ser molido", + "create.item_attributes.crushable.inverted": "no puede ser molido", + "create.item_attributes.blastable": "es fundible en el alto horno", + "create.item_attributes.blastable.inverted": "no es fundible en el alto horno", + "create.item_attributes.enchanted": "está encantado", + "create.item_attributes.enchanted.inverted": "no está encantado", + "create.item_attributes.damaged": "está dañado", + "create.item_attributes.damaged.inverted": "no está dañado", + "create.item_attributes.badly_damaged": "está muy dañado", + "create.item_attributes.badly_damaged.inverted": "no está muy dañado", + "create.item_attributes.not_stackable": "no se puede apilar", + "create.item_attributes.not_stackable.inverted": "se puede apilar", + "create.item_attributes.equipable": "se puede equipar", + "create.item_attributes.equipable.inverted": "no se puede equipar", + "create.item_attributes.furnace_fuel": "es combustible para hornos", + "create.item_attributes.furnace_fuel.inverted": "no es combustible para hornos", + "create.item_attributes.in_tag": "está etiquetado %1$s", + "create.item_attributes.in_tag.inverted": "no está etiquetado %1$s", + "create.item_attributes.in_item_group": "está en el grupo '%1$s'", + "create.item_attributes.in_item_group.inverted": "no está en el grupo '%1$s'", + "create.item_attributes.added_by": "fue añadido por %1$s", + "create.item_attributes.added_by.inverted": "no fue añadida por %1$s", + "create.item_attributes.has_enchant": "está encantado con %1$s", + "create.item_attributes.has_enchant.inverted": "no está encantado con %1$s", + "create.item_attributes.has_fluid": "contiene %1$s", + "create.item_attributes.has_fluid.inverted": "no contiene %1$s", + "create.item_attributes.has_name": "tiene el nombre personalizado %1$s", + "create.item_attributes.has_name.inverted": "no tiene el nombre personalizado %1$s", + "create.item_attributes.book_author": "es obra de %1$s", + "create.item_attributes.book_author.inverted": "no es es obra de %1$s", + "create.item_attributes.book_copy_original": "es un original", + "create.item_attributes.book_copy_original.inverted": "no es un original", + "create.item_attributes.book_copy_first": "es una copia de primera generación", + "create.item_attributes.book_copy_first.inverted": "no es una copia de primera generación", + "create.item_attributes.book_copy_second": "es una copia de segunda generación", + "create.item_attributes.book_copy_second.inverted": "no es una copia de segunda generación", + "create.item_attributes.book_copy_tattered": "es un desordenado desastre", + "create.item_attributes.book_copy_tattered.inverted": "no es un desordenado desastre", + "create.item_attributes.astralsorcery_crystal": "tiene el atributo de cristal %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "no tiene atributo de cristal %1$s", + "create.item_attributes.astralsorcery_constellation": "está en sintonía con %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "no está en sintonía con %1$s", + "create.item_attributes.astralsorcery_perk_gem": "tiene el atributo ventaja %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "no tiene el atributo ventaja %1$s", + "create.item_attributes.astralsorcery_amulet": "mejora %1$s", + "create.item_attributes.astralsorcery_amulet.inverted": "no mejora %1$s", + + "create.gui.attribute_filter.no_selected_attributes": "No hay atributos seleccionados", + "create.gui.attribute_filter.selected_attributes": "Atributos seleccionados:", + "create.gui.attribute_filter.add_attribute": "Añadir atributo a la lista", + "create.gui.attribute_filter.add_inverted_attribute": "Añadir atributo invertido a la Lista", + "create.gui.attribute_filter.allow_list_disjunctive": "Lista de permitidos (Cualquiera)", + "create.gui.attribute_filter.allow_list_disjunctive.description": "Los elementos pasan si tienen alguno de los atributos seleccionados", + "create.gui.attribute_filter.allow_list_conjunctive": "Lista de permitidos (Todos)", + "create.gui.attribute_filter.allow_list_conjunctive.description": "Los elementos pasan sólo si tienen TODOS los atributos seleccionados", + "create.gui.attribute_filter.deny_list": "Lista de denegados", + "create.gui.attribute_filter.deny_list.description": "Los elementos pasan si NO tienen ninguno de los atributos seleccionados", + "create.gui.attribute_filter.add_reference_item": "Añadir elemento de referencia", + + "create.tooltip.holdKey": "Mantener [%1$s]", + "create.tooltip.holdKeyOrKey": "Mantener [%1$s] o [%2$s]", + "create.tooltip.keyShift": "Shift", + "create.tooltip.keyCtrl": "Ctrl", + "create.tooltip.speedRequirement": "Requisitos de velocidad: %1$s", + "create.tooltip.speedRequirement.none": "Ninguno", + "create.tooltip.speedRequirement.medium": "Moderado", + "create.tooltip.speedRequirement.high": "Rápido", + "create.tooltip.stressImpact": "Impacto de estrés: %1$s", + "create.tooltip.stressImpact.low": "Bajo", + "create.tooltip.stressImpact.medium": "Moderado", + "create.tooltip.stressImpact.high": "Alto", + "create.tooltip.stressImpact.overstressed": "Sobrecargado", + "create.tooltip.capacityProvided": "Capacidad de estrés: %1$s", + "create.tooltip.capacityProvided.low": "Pequeña", + "create.tooltip.capacityProvided.medium": "Media", + "create.tooltip.capacityProvided.high": "Grande", + "create.tooltip.capacityProvided.asGenerator": "(Como generador)", + "create.tooltip.generationSpeed": "Genera en %1$s %2$s", + "create.tooltip.analogStrength": "Fuerza analógica: %1$s/15", + + "create.mechanical_arm.extract_from": "Extraer elementos de %1$s", + "create.mechanical_arm.deposit_to": "Depositar elementos en %1$s", + "create.mechanical_arm.summary": "El brazo mecánico tiene %1$s entrada(s) y %2$s salida(s)", + "create.mechanical_arm.points_outside_range": "%1$s punto(s) de interacción seleccionado(s) eliminado(s) debido a las limitaciones de rango", + + "create.logistics.when_multiple_outputs_available": "Cuando hay múltiples salidas disponibles", + + "create.mechanical_arm.selection_mode.round_robin": "Round Robin", + "create.mechanical_arm.selection_mode.forced_round_robin": "Round Robin forzado", + "create.mechanical_arm.selection_mode.prefer_first": "Preferir el primer objetivo", + + "create.tunnel.selection_mode.split": "División", + "create.tunnel.selection_mode.forced_split": "División forzada", + "create.tunnel.selection_mode.round_robin": "Round Robin", + "create.tunnel.selection_mode.forced_round_robin": "Round Robin forzado", + "create.tunnel.selection_mode.prefer_nearest": "Preferir el más cercano", + "create.tunnel.selection_mode.randomize": "Aleatorizar", + "create.tunnel.selection_mode.synchronize": "Sincronizar entradas", + + "create.tooltip.chute.header": "Información del ducto", + "create.tooltip.chute.items_move_down": "Los elementos se mueven hacia abajo", + "create.tooltip.chute.items_move_up": "Los elementos se mueven hacia arriba", + "create.tooltip.chute.no_fans_attached": "No hay ventiladores adjuntos", + "create.tooltip.chute.fans_push_up": "Los ventiladores empujan desde abajo", + "create.tooltip.chute.fans_push_down": "Los ventiladores empujan desde arriba", + "create.tooltip.chute.fans_pull_up": "Los ventiladores tiran desde arriba", + "create.tooltip.chute.fans_pull_down": "Los ventiladores tiran desde abajo", + "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + + "create.hint.hose_pulley.title": "Suministro sin fondo", + "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita", + "create.hint.mechanical_arm_no_targets.title": "No hay objetivos", + "create.hint.mechanical_arm_no_targets": "Parece que a este _brazo mecánico_ no se le ha asignado ningún _objetivo._ Selecciona correas, depósitos, embudos y otros bloques haciendo _clic derecho_ sobre ellos mientras _sostienes_ el _brazo mecánico_ en tu _mano_.", + "create.hint.horizontal_funnel.title": "Embudos horizontales", + "create.hint.horizontal_funnel": "No puede transferir entre inventarios _directamente_. Intenta pasar una _correa_ o un _depósito_ por debajo de tu embudo para extraer artículos de los inventarios", + "create.hint.upward_funnel.title": "Embudos hacia arriba", + "create.hint.upward_funnel": "sólo pueden transferir objetos insertados por _brazos_, y _ductos_ impulsados por ventilador, o elementos _lanzados_ hacia ellos. Intenta construir algunos _ductos_ si quieres mover tus objetos _verticalmente_", + "create.hint.empty_bearing.title": "Rodamiento de reloj", + "create.hint.empty_bearing": "_Haz clic con el botón derecho del ratón_ en el rodamiento con la _mano vacía_ para _adherir_ la estructura que acabas de construir delante de él", + "create.hint.full_deployer.title": "Desbordamiento de elementos del desplegador", + "create.hint.full_deployer": "Parece que este _Desplegador_ contiene _elementos_ en exceso que necesitan ser _extraídos._ Usa un _tolva,_embudo_ u otro medio para liberarlo de su desbordamiento.", + + "create.gui.config.overlay1": "Hola :)", + "create.gui.config.overlay2": "Esta es una muestra de la superposición", + "create.gui.config.overlay3": "Haga clic o arrastre con el ratón", + "create.gui.config.overlay4": "para mover esta vista previa", + "create.gui.config.overlay5": "Pulsar ESC para salir de esta pantalla", + "create.gui.config.overlay6": "y guardar la nueva posición", + "create.gui.config.overlay7": "Ejecute /create overlay reset", + "create.gui.config.overlay8": "para restablecer la posición por defecto", + + "create.command.killTPSCommand": "killtps", + "create.command.killTPSCommand.status.slowed_by.0": "[Crear]: El tick del servidor está actualmente ralentizado en %s ms :o", + "create.command.killTPSCommand.status.slowed_by.1": "[Crear]: El tick del servidor está ralentizado en %s ms ahora >:)", + "create.command.killTPSCommand.status.slowed_by.2": "[Create]: El tick del servidor ha vuelto a su velocidad normal :D", + "create.command.killTPSCommand.status.usage.0": "[Create]: usar /killtps stop para que el servidor vuelva a la velocidad normal", + "create.command.killTPSCommand.status.usage.1": "[Create]: usar /killtps start para ralentizar artificialmente el tick del servidor", + "create.command.killTPSCommand.argument.tickTime": "tickTime", + + "create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon", + "create.subtitle.schematicannon_finish": "Acabados de Schematicannon", + "create.subtitle.slime_added": "Slime aplastado", + "create.subtitle.mechanical_press_activation": "La Prensa Mecánica se activa", + "create.subtitle.mechanical_press_item_break": "Clanks de metal", + "create.subtitle.blockzapper_place": "Los bloques se colocan en su sitio", + "create.subtitle.blockzapper_confirm": "Ding afirmativo", + "create.subtitle.blockzapper_deny": "Boop declinante", + "create.subtitle.block_funnel_eat": "CHOMPS del embudo", + "create.subtitle.blaze_munch": "Blaze mastica felizmente", + + + "_": "->------------------------] Item Descriptions [------------------------<-", + + "item.create.example_item.tooltip": "EJEMPLO DE ITEM (sólo un marcador de que este tooltip existe)", + "item.create.example_item.tooltip.summary": "Una breve descripción del elemento. Los puntajes bajos resaltan un término", + "item.create.example_item.tooltip.condition1": "Cuando este", + "item.create.example_item.tooltip.behaviour1": "Entonces este elemento hace esto. (los comportamientos se muestran en el turno)", + "item.create.example_item.tooltip.condition2": "Y cuando esto", + "item.create.example_item.tooltip.behaviour2": "Puedes añadir tantos comportamientos como quieras", + "item.create.example_item.tooltip.control1": "Cuando se pulsa Ctrl", + "item.create.example_item.tooltip.action1": "Se muestran estos controles", + + "block.create.andesite_encased_shaft.tooltip": "EJE REVESTIDO DE ANDESITA", + "block.create.andesite_encased_shaft.tooltip.summary": "Elemento _sólo para el modo creativo_. Reviste los _ejes_ en el mundo usando _revestimiento de andesita_. Los bloques de revestimiento _no se consumirán_.", + + "block.create.brass_encased_shaft.tooltip": "EJE REVESTIDO DE LATÓN", + "block.create.brass_encased_shaft.tooltip.summary": "Elemento _sólo para el modo creativo_. Reviste los _ejes_ en el mundo usando _revestimiento de latón_. Los bloques de revestimiento _no se consumirán_.", + + "block.create.wooden_bracket.tooltip": "SOPORTE DE MADERA PARA EJES", + "block.create.wooden_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un refuerzo acogedor y de madera.", + + "block.create.metal_bracket.tooltip": "SOPORTE DE METAL PARA EJES", + "block.create.metal_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un poco de refuerzo industrial robusto.", + + "block.create.andesite_casing.tooltip": "REVESTIDOR DE ANDESITA", + "block.create.andesite_casing.tooltip.summary": "Máquina de revestimiento simple con una variedad de usos. Seguro para la decoración. Puede utilizarse para _encastrar ejes_ y _correas._", + + "block.create.andesite_funnel.tooltip": "EMBUDO DE ANDESITA", + "block.create.andesite_funnel.tooltip.summary": "Un componente de transferencia de elementos en general, que hace la transición de éstos entre los medios de transporte. Se puede controlar con una _señal de Redstone_.", + "block.create.andesite_funnel.tooltip.condition1": "Comportamiento general", + "block.create.andesite_funnel.tooltip.behaviour1": "La cara _abierta_ _recogerá los objetos molidos_ en el espacio del bloque que tiene delante y los _insertará_ en cualquier contenedor del lado opuesto del embudo", + "block.create.andesite_funnel.tooltip.condition2": "Cuando se montan en correas, depósitos y similares", + "block.create.andesite_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ los elementos en el componente montado, desde o hacia el inventario _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, puede invertirse utilizando una Llave.", + "block.create.andesite_funnel.tooltip.condition3": "Cuando se encuentra verticalmente entre dos inventarios", + "block.create.andesite_funnel.tooltip.behaviour3": "Transferirá los artículos hacia abajo, como una tolva sin búfer.", + + "block.create.andesite_tunnel.tooltip": "TÚNEL DE ANDESITA", + "block.create.andesite_tunnel.tooltip.summary": "¡Una cubierta protectora para sus _correas_!. El _Túnel de Andesita_ puede separar un elemento de una pila cuando se coloca otra correa o depósito al lado de la correa principal.", + "block.create.andesite_tunnel.tooltip.control1": "Click derecho con la Llave Inglesa en el lateral", + "block.create.andesite_tunnel.tooltip.action1": "_Ajusta las persianas de las ventanas_ si el túnel tiene una ventana en esa cara.", + + "block.create.brass_funnel.tooltip": "EMBUDO DE LATÓN", + "block.create.brass_funnel.tooltip.summary": "Un componente de transferencia de elementos en general, que hace la transición de éstos entre los medios de transporte. Se puede controlar con una _señal de Redstone_. Viene con un práctico _filtro_.", + "block.create.brass_funnel.tooltip.condition1": "Comportamiento General", + "block.create.brass_funnel.tooltip.behaviour1": "La cara _abierta_ _recogerá los objetos molidos_ en el espacio del bloque que tiene delante y los _insertará_ en cualquier contenedor del lado opuesto del embudo.", + "block.create.brass_funnel.tooltip.condition2": "Cuando se montan en correas, depósitos y similares", + "block.create.brass_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ los elementos en el componente montado, desde o hacia el inventario _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, puede invertirse utilizando una Llave Inglesa.", + "block.create.brass_funnel.tooltip.condition3": "Cuando se encuentra verticalmente entre dos inventarios", + "block.create.brass_funnel.tooltip.behaviour3": "Transfiere los artículos hacia abajo, como una tolva sin búfer.", + + "block.create.brass_tunnel.tooltip": "TÚNEL DE LATÓN", + "block.create.brass_tunnel.tooltip.summary": "Una cubierta protectora elegante para sus _correas_. Los _Túneles de latón_ también vienen con una serie de opciones de _Filtración_ y _División_ para sus artículos.", + "block.create.brass_tunnel.tooltip.condition1": "Cuando se colocan uno al lado del otro", + "block.create.brass_tunnel.tooltip.behaviour1": "Los túneles de latón se conectan entre sí y permiten redirigir el contenido de una correa a otra.", + "block.create.brass_tunnel.tooltip.condition2": "Filtrado", + "block.create.brass_tunnel.tooltip.behaviour2": "Los _Túneles de latón_ vienen con filtros tanto para la _Entrada_ como para la _Salida_. Si un _Elemento_ no está permitido desde la salida filtrada de un _Túnel_ será transferido a la salida de un _Túnel_ conectado.", + "block.create.brass_tunnel.tooltip.condition3": "Dividiendo", + "block.create.brass_tunnel.tooltip.behaviour3": "Los _Túneles de latón_ pueden ser configurados para cambiar el método en el que los _Elementos_ son ordenados en los _Túneles_ conectados.", + "block.create.brass_tunnel.tooltip.control1": "Cuando haces click derecho con una Llave Inglesa", + "block.create.brass_tunnel.tooltip.action1": "_Ajusta las persianas de las ventanas_ si el túnel tiene una ventana en esa cara.", + "block.create.brass_tunnel.tooltip.control2": "Usa la rueda del ratón con la Llave Inglesa en la parte superior", + "block.create.brass_tunnel.tooltip.action2": "Cambiar el método de división de los _Túneles_ conectados.", + + "block.create.copper_casing.tooltip": "REVESTIDOR DE COBRE", + "block.create.copper_casing.tooltip.summary": "Robusta máquina de revestimientos con una gran variedad de usos. Seguro para la decoración.", + "block.create.copper_casing.tooltip.condition1": "Cuando se utiliza en una tubería de fluidos", + "block.create.copper_casing.tooltip.behaviour1": "_Reviste_ la _Tubería de fluidos_ con _Revestimiento de cobre_. Las tuberías de fluidos revestidas _bloquean sus conexiones_ en su lugar, dejando de reaccionar a los cambios en las tuberías vecinas.", + + "block.create.encased_fluid_pipe.tooltip": "TUBO DE FLUIDOS REVESTIDO", + "block.create.encased_fluid_pipe.tooltip.summary": "Un tubo de fluidos revestido con cobre.", + + "block.create.copper_valve_handle.tooltip": "ASA DE VÁLVULA DE COBRE", + "block.create.copper_valve_handle.tooltip.summary": "Una precisa _fuente_ de _fuerza de rotación_ que requiere la interacción de los jugadores. ¡Ten cuidado de no agotarte!", + "block.create.copper_valve_handle.tooltip.condition1": "Cuando se utiliza", + "block.create.copper_valve_handle.tooltip.behaviour1": "Proporciona _Fuerza de rotación_ a un artilugio acoplado. _Shift_ para _invertir_ la rotación.", + + "block.create.seat.tooltip": "ASIENTO", + "block.create.seat.tooltip.summary": "¡Siéntate y disfruta del viaje! Anclará a un jugador en un _contrafuerte_ en movimiento. También es ideal para los muebles estáticos. Viene en una variedad de colores.", + "block.create.seat.tooltip.condition1": "Click derecho en el asiento", + "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _Asiento_. Pulsa shift izquierdo para dejar el _Asiento_.", + + "block.create.chute.tooltip": "DUCTO", + "block.create.chute.tooltip.summary": "_Recoge_ y _Transporta_ elementos en vertical o en diagonal. Puede tanto coger como colocar objetos en _contenedores de objetos_. También puede interactuar con los ductos desde el lateral utilizando _tolvas_ o _embudos montados_.", + "block.create.chute.tooltip.condition1": "Cuando se alimenta con un ventilador", + "block.create.chute.tooltip.behaviour1": "Los ductos accionados por ventilador pueden transportar _elementos_ hacia arriba, y aspirar _elementos_ de los _depósitos_ y de las _correas_.", + + "block.create.depot.tooltip": "DEPÓSITO", + "block.create.depot.tooltip.summary": "Un lugar práctico para colocar sus _elementos_. Proporciona un punto de interacción para varias máquinas", + "block.create.depot.tooltip.condition1": "Click derecho en el depósito", + "block.create.depot.tooltip.behaviour1": "Coloca o toma un _Elemento_ del _Depósito_. Los _Bloques_ y los _Artilugios_ que interactúan con una _Correa_ también funcionan en un _Depósito_.", + + "item.create.blaze_cake.tooltip": "PASTEL DE BLAZE", + "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para sus esforzados _Quemadores de blaze_. Los pone en marcha!.", + + "item.create.empty_blaze_burner.tooltip": "QUEMADOR DE BLAZE VACÍO", + "item.create.empty_blaze_burner.tooltip.summary": "Un pequeño hogar de hierro para tus amigos fogosos. Estoy seguro de que podrías darles un buen uso.", + "item.create.empty_blaze_burner.tooltip.condition1": "Cuando se utiliza en un Blaze o en un generador de Blaze", + "item.create.empty_blaze_burner.tooltip.behaviour1": "_Captura_ un Blaze en el elemento", + + "block.create.fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS DE COBRE", + "block.create.fluid_pipe.tooltip.summary": "Se utiliza para mover _fluidos_. Necesita una _bomba mecánica_ para que el _fluido_ se mueva.", + "block.create.fluid_pipe.tooltip.condition1": "Transferencia de fluidos", + "block.create.fluid_pipe.tooltip.behaviour1": "Puede conectarse a _contenedores de fluidos_ como _depósitos_ o _cuencas_. Los extremos expuestos de los _tubos_ también pueden drenar o colocar bloques de fluido. ¡Cuidado con las fugas!", + "block.create.fluid_pipe.tooltip.control1": "Cuando haces clic derecho con una Llave Inglesa", + "block.create.fluid_pipe.tooltip.action1": "Coloca una ventana en la tubería si está disponible", + + "block.create.hose_pulley.tooltip": "POLEA DE MANGUERA", + "block.create.hose_pulley.tooltip.summary": "Se utiliza para _colocar_ o _drenar_ grandes _cuerpos fluidos_ en el mundo", + "block.create.hose_pulley.tooltip.condition1": "Cuando se alimenta por cinética", + "block.create.hose_pulley.tooltip.behaviour1": "_Sube_ o _baja_ la manguera, la ubicación de la manguera determina hasta qué _altura de extracción_ o _llenado_ actuará.", + "block.create.hose_pulley.tooltip.condition2": "Cuando los fluidos se extraen de la polea", + "block.create.hose_pulley.tooltip.behaviour2": "Comienza a _tomar bloques de fluidos_ del cuerpo al que se bajó el extremo de la manguera. Los cuerpos muy _grandes_ de fluidos se _considerarán infinitos_.", + "block.create.hose_pulley.tooltip.condition3": "Cuando los fluidos son empujados a la polea", + "block.create.hose_pulley.tooltip.behaviour3": "Comienza a _llenar de fluido_ el mundo hasta la _altura_ de los extremos de la _manguera_", + + "block.create.fluid_tank.tooltip": "TANQUE DE FLUIDOS", + "block.create.fluid_tank.tooltip.summary": "Almacena todos tus _líquidos_ favoritos. Escala en anchura y altura.", + "block.create.fluid_tank.tooltip.condition1": "Cuando se hace click derecho con la Llave Inglesa", + "block.create.fluid_tank.tooltip.behaviour1": "Cambia la ventana opcional", + + "block.create.creative_fluid_tank.tooltip": "TANQUE DE FLUIDOS CREATIVO", + "block.create.creative_fluid_tank.tooltip.summary": "Este _Tanque de Fluidos_ permite la replicación infinita de cualquier Fluido. Escala en anchura y altura.", + "block.create.creative_fluid_tank.tooltip.condition1": "Cuando hay fluido en el tanque", + "block.create.creative_fluid_tank.tooltip.behaviour1": "Todo lo que se _extraiga_ de este tanque proporcionará un _suministro ilimitado_ del fluido especificado. Los fluidos _insertados_ en este tanque serán _evitados._", + "block.create.creative_fluid_tank.tooltip.condition2": "Cuando se hace clic derecho con una Llave Inglesa", + "block.create.creative_fluid_tank.tooltip.behaviour2": "Cambia la ventana opcional", + + "block.create.fluid_valve.tooltip": "VALVULA DE FLUIDOS", + "block.create.fluid_valve.tooltip.summary": "Detiene el flujo de un fluido por una tubería", + "block.create.fluid_valve.tooltip.condition1": "Flujo controlable", + "block.create.fluid_valve.tooltip.behaviour1": "La _fuerza de rotación_ aplicada obligará a la _válvula_ a cerrarse, cesando el flujo de _fluidos_. Invierta la dirección de la _fuerza de rotación_ para volver a abrir la válvula", + + "block.create.mechanical_pump.tooltip": "BOMBA MECÁNICA", + "block.create.mechanical_pump.tooltip.summary": "Toma la _fuerza de rotación_ y la utiliza para mover el _fluido_ a lo largo de un _tubo_. Tiene un rango máximo de efecto en ambas direcciones. (16 bloques por defecto)", + "block.create.mechanical_pump.tooltip.condition1": "Flujo de fluido", + "block.create.mechanical_pump.tooltip.behaviour1": "La _fuerza de rotación_ aplicada crea una presión que obliga al _fluido_ a pasar por la red de _tuberías_. Invierte la dirección de la _fuerza de rotación_ para cambiar la dirección en la que fluye el _fluido_", + "block.create.mechanical_pump.tooltip.control1": "Pulsando con el botón derecho del ratón con la Llave Inglesa", + "block.create.mechanical_pump.tooltip.action1": "Invierte la dirección de la _bomba_, cambiando la dirección por defecto del flujo", + + "block.create.smart_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS INTELIGENTE", + "block.create.smart_fluid_pipe.tooltip.summary": "Una _tubería de fluidos_ con un filtro. Puede especificar qué _fluidos_ pasan por ella", + "block.create.smart_fluid_pipe.tooltip.condition1": "Cuando se introducen fluidos en ella", + "block.create.smart_fluid_pipe.tooltip.behaviour1": "Las tuberías inteligentes que reciban fluidos que no coincidan con su filtro bloquearán el flujo", + "block.create.smart_fluid_pipe.tooltip.condition2": "Cuando es adyacente a un contenedor de fluido", + "block.create.smart_fluid_pipe.tooltip.behaviour2": "Las tuberías inteligentes que _inicien_ un _flujo_ desde cualquier contenedor sólo extraerán fluidos que _coincidan_ con su _filtro._", + + "block.create.spout.tooltip": "SURTIDOR", + "block.create.spout.tooltip.summary": "Un inyector para rellenar tus elementos de _fluidos._", + "block.create.spout.tooltip.condition1": "Transferencia de fluidos", + "block.create.spout.tooltip.behaviour1": "Cuando se coloca un _contenedor de fluidos_ como un _cubo_ o una _botella_ debajo, el caño intentará rellenarlo con su propio _fluido_ almacenado", + "block.create.spout.tooltip.condition2": "Automatización de fluidos", + "block.create.spout.tooltip.behaviour2": "El caño colocado encima de una _correa_ o _depósito_ reaccionará automáticamente con un contenedor de fluidos_ que pase por debajo", + + "block.create.item_drain.tooltip": "DRENADOR DE ELEMENTOS", + "block.create.item_drain.tooltip.summary": "Un depósito rallado para vaciar tus _artículos fluidos._", + "block.create.item_drain.tooltip.condition1": "Transferencia de fluidos", + "block.create.item_drain.tooltip.behaviour1": "Cuando un _contenedor de fluidos_, como un _cubo_ o una _botella_, se inserta desde el lateral, el desagüe intentará vaciarlo en su propio _contenedor de fluidos_. El artículo será entonces expulsado por el lado opuesto", + + "block.create.mechanical_arm.tooltip": "BRAZO MECÁNICO", + "block.create.mechanical_arm.tooltip.summary": "Artilugio avanzado para reubicar _elementos_", + "block.create.mechanical_arm.tooltip.condition1": "Transferencia de elementos", + "block.create.mechanical_arm.tooltip.behaviour1": "Puede tomar o colocar objetos en cualquier _inventario_ accesible_, como _Correas_, _Depósitos_, _Embudos_ y _Autoensambladores_", + "block.create.mechanical_arm.tooltip.control1": "Mientras está en la mano", + "block.create.mechanical_arm.tooltip.action1": "Haz clic con el botón derecho en un _objeto accesible del inventario_ para establecerlo como _fuente_ para el _brazo mecánico_. Haz clic con el botón derecho del ratón dos veces para establecerlo como _destino_", + "block.create.mechanical_arm.tooltip.control2": "Usa la rueda del ratón con la Llave Inglesa", + "block.create.mechanical_arm.tooltip.action2": "Establece el comportamiento de orden de los _items_ emitidos por el _brazo mecánico_", + + "item.create.wand_of_symmetry.tooltip": "VARITA DE SIMETRÍA", + "item.create.wand_of_symmetry.tooltip.summary": "Refleja perfectamente la colocación de bloques en los planos configurados", + "item.create.wand_of_symmetry.tooltip.condition1": "Mientras está en el inventario rápido", + "item.create.wand_of_symmetry.tooltip.behaviour1": "Permanece activo", + "item.create.wand_of_symmetry.tooltip.control1": "Click derecho en el suelo", + "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _Mueve_ el Espejo", + "item.create.wand_of_symmetry.tooltip.control2": "Click derecho en el aire", + "item.create.wand_of_symmetry.tooltip.action2": "_Quita_ el Espejo activo", + "item.create.wand_of_symmetry.tooltip.control3": "Click derecho mientras se agacha", + "item.create.wand_of_symmetry.tooltip.action3": "Abre la _Interfaz de Configuración_", + + "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", + "item.create.handheld_blockzapper.tooltip.summary": "Novedoso artefacto para colocar o intercambiar bloques a distancia", + "item.create.handheld_blockzapper.tooltip.control1": "Click izquierdo en un bloque", + "item.create.handheld_blockzapper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", + "item.create.handheld_blockzapper.tooltip.control2": "Click derecho en un bloque", + "item.create.handheld_blockzapper.tooltip.action2": "_Coloca_ o _Reemplaza_ el bloque objetivo", + "item.create.handheld_blockzapper.tooltip.control3": "Click derecho mientras se agacha", + "item.create.handheld_blockzapper.tooltip.action3": "Abre la _Interfaz de Configuración_", + + "item.create.handheld_worldshaper.tooltip": "WORLDSHAPER", + "item.create.handheld_worldshaper.tooltip.summary": "Práctica herramienta para crear _paisajes_ y _características del terreno_", + "item.create.handheld_worldshaper.tooltip.control1": "Click izquierdo en un bloque", + "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", + "item.create.handheld_worldshaper.tooltip.control2": "Click derecho en un bloque", + "item.create.handheld_worldshaper.tooltip.action2": "Aplica el _pincel_ y la _herramienta_ actualmente seleccionadas en el lugar deseado.", + "item.create.handheld_worldshaper.tooltip.control3": "Click derecho mientras se agacha", + "item.create.handheld_worldshaper.tooltip.action3": "Abre la _Interfaz de Configuración_", + + "item.create.tree_fertilizer.tooltip": "FERTILIZANTE PARA ÁRBOLES", + "item.create.tree_fertilizer.tooltip.summary": "Una potente combinación de minerales adecuada para acelerar el crecimiento de los tipos de árboles más comunes", + "item.create.tree_fertilizer.tooltip.condition1": "Cuando se utiliza en un árbol joven", + "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles _independientemente_ de sus condiciones de _espacio_", + + "item.create.deforester.tooltip": "DEFORESTADOR", + "item.create.deforester.tooltip.summary": "Un hacha _radiante_ capaz de talar árboles en una fracción de segundo", + + "item.create.extendo_grip.tooltip": "AGARRE EXTENDIDO", + "item.create.extendo_grip.tooltip.summary": "¡Boioioing! Aumenta enormemente la _distancia de alcance_ del portador", + "item.create.extendo_grip.tooltip.condition1": "Cuando está fuera de la mano", + "item.create.extendo_grip.tooltip.behaviour1": "Aumenta la _distancia de alcance_ de los objetos usados en la _mano principal_", + + "item.create.filter.tooltip": "FILTRO", + "item.create.filter.tooltip.summary": "Controla las salidas_ y _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de elementos_ o varios _filtros anidados_", + "item.create.filter.tooltip.condition1": "Cuando está en la ranura del filtro", + "item.create.filter.tooltip.behaviour1": "Controla_ el flujo del elemento según su _configuración_", + "item.create.filter.tooltip.condition2": "Cuando se hace clic derecho", + "item.create.filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + + "item.create.attribute_filter.tooltip": "FILTRO DE ATRIBUTOS", + "item.create.attribute_filter.tooltip.summary": "Controla las salidas_ y las _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de _atributos_ y _categorías_ de artículos", + "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura del filtro", + "item.create.attribute_filter.tooltip.behaviour1": "Controla el flujo del elemento según su _configuración_", + "item.create.attribute_filter.tooltip.condition2": "Cuando se hace clic derecho", + "item.create.attribute_filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + + "item.create.empty_schematic.tooltip": "ESQUEMA VACÍO", + "item.create.empty_schematic.tooltip.summary": "Se utiliza como ingrediente de las recetas y para escribir en la _tabla de esquemas_", + + "item.create.schematic.tooltip": "ESQUEMA", + "item.create.schematic.tooltip.summary": "Contiene una estructura para ser posicionada y colocada en el mundo. Posiciona el holograma como se desee y utiliza un _Esquematicannon_ para construirlo", + "item.create.schematic.tooltip.condition1": "Cuando se mantiene", + "item.create.schematic.tooltip.behaviour1": "Se puede posicionar utilizando las herramientas en pantalla", + "item.create.schematic.tooltip.control1": "Click derecho mientras se agacha", + "item.create.schematic.tooltip.action1": "Abre una _Interfaz_ para introducir las _Coordenadas_ exactas", + + "item.create.schematic_and_quill.tooltip": "ESQUEMA Y PLUMA", + "item.create.schematic_and_quill.tooltip.summary": "Se utiliza para guardar una estructura de tu mundo en un archivo .nbt", + "item.create.schematic_and_quill.tooltip.condition1": "Paso 1", + "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos puntos de esquina usando click derecho", + "item.create.schematic_and_quill.tooltip.condition2": "Paso 2", + "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl-Rueda del ratón_ en las caras para ajustar el tamaño. Click derecho de nuevo para guardar", + "item.create.schematic_and_quill.tooltip.control1": "Click derecho", + "item.create.schematic_and_quill.tooltip.action1": "Seleccionar un punto de esquina / confirmar guardar", + "item.create.schematic_and_quill.tooltip.control2": "Al mantener Ctrl", + "item.create.schematic_and_quill.tooltip.action2": "Seleccionar puntos en _medio del aire_. Rueda del ratón para ajustar la distancia", + "item.create.schematic_and_quill.tooltip.control3": "Click derecho mientras se agacha", + "item.create.schematic_and_quill.tooltip.action3": "Reinicia_ y elimina la selección", + + "block.create.schematicannon.tooltip": "ESQUEMATICAÑÓN", + "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _Esquema_ desplegado en el Mundo. Utiliza elementos de los inventarios adyacentes y _Pólvora_ como combustible.", + "block.create.schematicannon.tooltip.control1": "Cuando se hace clic derecho", + "block.create.schematicannon.tooltip.action1": "Abre la _Interfaz_ de configuración", + + "block.create.schematic_table.tooltip": "TABLA DE ESQUEMAS", + "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _esquema vacío_", + "block.create.schematic_table.tooltip.condition1": "Cuando se da un esquema vacío", + "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de la carpeta de esquemas", + + "block.create.shaft.tooltip": "EJE", + "block.create.shaft.tooltip.summary": "_Retransmite la rotación_ en línea recta", + + "block.create.cogwheel.tooltip": "RUEDA DENTADA", + "block.create.cogwheel.tooltip.summary": "_Retransmite la rotación_ en línea recta, y a las _ruedas dentadas_ adyacentes", + + "block.create.large_cogwheel.tooltip": "RUEDA DENTADA GRANDE", + "block.create.large_cogwheel.tooltip.summary": "Una versión más grande de la _Rueda dentada_, que permite _cambiar_ la _Velocidad de Rotación_ cuando se conecta a su contraparte más pequeña", + + "block.create.encased_shaft.tooltip": "EJE REVESTIDO", + "block.create.encased_shaft.tooltip.summary": "_Retransmite la rotación_ en línea recta. Adecuado para propagar la Rotación a través de Muros", + + "block.create.gearbox.tooltip": "CAJA DE TRANSMISIÓN", + "block.create.gearbox.tooltip.summary": "_Retransmite la rotación_ en _cuatro direcciones_. Invierte las conexiones rectas", + + "block.create.gearshift.tooltip": "CAJA DE CAMBIOS", + "block.create.gearshift.tooltip.summary": "Un control para alternar la dirección de rotación de los ejes conectados", + "block.create.gearshift.tooltip.condition1": "Cuando se alimenta", + "block.create.gearshift.tooltip.behaviour1": "_Invierte_ la rotación de salida", + + "block.create.clutch.tooltip": "UNLOCALIZED: CLUTCH", + "block.create.clutch.tooltip.summary": "Un control para conectar/desconectar la rotación de los ejes conectados", + "block.create.clutch.tooltip.condition1": "Cuando se acciona", + "block.create.clutch.tooltip.behaviour1": "_Detiene_ el transporte de la rotación al otro lado", + + "block.create.encased_chain_drive.tooltip": "CADENA DE TRANSMISIÓN REVESTIDA", + "block.create.encased_chain_drive.tooltip.summary": "_Retransmite la rotación_ en línea recta y a las cadenas de transmisión adyacentes. Las cadenas de transmisión se conectan en un grupo cuando se colocan junto a otra en cualquier cara sin eje. Su orientación no tiene que coincidir", + "block.create.encased_chain_drive.tooltip.condition1": "Cuando se conecta", + "block.create.encased_chain_drive.tooltip.behaviour1": "Los bloques conectados transmitirán la _velocidad de rotación_ y la dirección de este componente", + + "block.create.adjustable_chain_gearshift.tooltip": "CADENA DE TRANSMISIÓN AJUSTABLE", + "block.create.adjustable_chain_gearshift.tooltip.summary": "_Retransmite el giro_ en línea recta y a las _cadenas adyacentes_. El Redstone analógo proporcionada a este bloque controlará qué tamaño de rueda motriz se acopla a las cadenas de transmisión adyacentes", + "block.create.adjustable_chain_gearshift.tooltip.condition1": "Control de Redstone", + "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "_Sin señal_, los accionamientos de cadena adyacentes transmitirán la _misma velocidad._ Con una señal de _fuerza completa_, los accionamientos de cadena adyacentes transmitirán exactamente _el doble de su velocidad._ Cualquier cosa entre medias dará resultados entre 1-2x su velocidad", + + "item.create.belt_connector.tooltip": "CORREA", + "item.create.belt_connector.tooltip.summary": "Conecta dos o más _ejes_ con una _Correa_. Los ejes conectados tendrán exactamente la misma velocidad y dirección de rotación. La correa puede actuar como _Transportador_ para _Estados_ y _Entidades_", + "item.create.belt_connector.tooltip.control1": "Click derecho en el eje", + "item.create.belt_connector.tooltip.action1": "Selecciona el eje como una polea de la correa. Los dos ejes seleccionados tienen que estar _alineados_ ya sea _Verticalmente_, _Horizontalmente_ o _Diagonalmente_ hacia la dirección de la correa", + "item.create.belt_connector.tooltip.control2": "Click derecho mientras te agachas", + "item.create.belt_connector.tooltip.action2": "_Reinicia_ la primera posición seleccionada para la correa", + + "item.create.goggles.tooltip": "GAFAS DEL INGENIERO", + "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar tu visión con útil información _cinética_", + "item.create.goggles.tooltip.condition1": "Cuando se llevan puestas", + "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores de color_ correspondientes al _Nivel de velocidad_ de un componente cinético colocado, así como el _Impacto de estrés_ y la _Capacidad_ de los componentes individuales.", + "item.create.goggles.tooltip.condition2": "Al mirar el medidor", + "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre _Velocidad_ o _Estrés_ de la red a la que está conectado el medidor", + + "item.create.wrench.tooltip": "LLAVE INGLESA", + "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artilugios cinéticos. Se puede utilizar para _Rotar_, _Desmantelar_ y para _Configurar_ componentes", + "item.create.wrench.tooltip.control1": "Click con el botón derecho en un bloque cinético", + "item.create.wrench.tooltip.action1": "_Rota los componentes_ hacia o desde la cara con la que ha interactuado", + "item.create.wrench.tooltip.control2": "Click derecho mientras te agachas", + "item.create.wrench.tooltip.action2": "Desmonta los componentes cinéticos_ y los devuelve a _tu inventario_", + + "block.create.creative_motor.tooltip": "MOTOR CREATIVO", + "block.create.creative_motor.tooltip.summary": "Una fuente configurable de _Fuerza Rotativa_", + + "block.create.water_wheel.tooltip": "RUEDA HIDRÁULICA MECÁNICA", + "block.create.water_wheel.tooltip.summary": "Proporciona _Fuerza de rotación_ tomada de las _Corrientes de agua_ adyacentes", + + "block.create.encased_fan.tooltip": "VENTILADOR REVESTIDO", + "block.create.encased_fan.tooltip.summary": "Convierte la _fuerza de rotación_ en _corrientes de aire_ y viceversa. Tiene una gran variedad de usos", + "block.create.encased_fan.tooltip.condition1": "Cuando es alimentado por Redstone", + "block.create.encased_fan.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a partir de cualquier _fuente de calor_ inmediatamente inferior. El ventilador debe estar orientado hacia abajo", + "block.create.encased_fan.tooltip.condition2": "Cuando es impulsado por la cinética", + "block.create.encased_fan.tooltip.behaviour2": "_Empuja_ o _Tira_ de Entidades, dependiendo de la velocidad de Rotación entrante", + "block.create.encased_fan.tooltip.condition3": "Al soplar a través de bloques especiales", + "block.create.encased_fan.tooltip.behaviour3": "Se emiten partículas de _Líquidos_ y _Fuego_ en el flujo de aire. Esto puede utilizarse para _procesar objetos_", + + "block.create.nozzle.tooltip": "BOQUILLA", + "block.create.nozzle.tooltip.summary": "Se acopla a la parte delantera de un _ventilador revestido_ para distribuir su efecto sobre las entidades en _todas las direcciones_", + + "block.create.hand_crank.tooltip": "MANIVELA", + "block.create.hand_crank.tooltip.summary": "Una sencilla _fuente_ de _fuerza de rotación_ que requiere la interacción de los jugadores. Ten cuidado de no agotarte!", + "block.create.hand_crank.tooltip.condition1": "Cuando se usa", + "block.create.hand_crank.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a un artilugio acoplado. _Se puede revertir_ la rotación", + + "block.create.cuckoo_clock.tooltip": "RELOJ DE CUCO", + "block.create.cuckoo_clock.tooltip.summary": "Fina artesanía para _decorar_ un espacio y _contar el tiempo_", + "block.create.cuckoo_clock.tooltip.condition1": "Cuando es alimentado por cinética", + "block.create.cuckoo_clock.tooltip.behaviour1": "Muestra la _hora actual_ y toca una melodía dos veces al día. Se activa_ una vez al _mediodía_ y al anochecer, en cuanto _los jugadores pueden dormir_", + + "block.create.turntable.tooltip": "PLATAFORMA GIRATORIA", + "block.create.turntable.tooltip.summary": "Convierte la _fuerza de rotación_ en un refinado mareo", + + "block.create.millstone.tooltip": "PIEDRA DEL MOLINO", + "block.create.millstone.tooltip.summary": "Un componente cinético adecuado para _moler_ materiales insertados. Puede ser alimentado por una rueda dentada adyacente o conectándose al eje de la parte inferior. Los resultados tienen que ser extraídos del componente", + "block.create.millstone.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.millstone.tooltip.behaviour1": "Comienza a aplicar _recetas de fresado_ a cualquier elemento insertado desde el lateral o la parte superior del bloque", + "block.create.millstone.tooltip.condition2": "Cuando se hace clic derecho", + "block.create.millstone.tooltip.behaviour2": "Recoge las salidas manualmente", + + "block.create.crushing_wheel.tooltip": "RUEDA DE TRITURACIÓN", + "block.create.crushing_wheel.tooltip.summary": "Grandes ruedas giratorias que _rompen_ cualquier cosa", + "block.create.crushing_wheel.tooltip.condition1": "Cuando se une a otra rueda trituradora", + "block.create.crushing_wheel.tooltip.behaviour1": "Forma una máquina trituradora para procesar una variedad de cosas. Los dientes de las ruedas tienen que conectarse y moverse con la _misma velocidad_ en _direcciones opuestas_", + + "block.create.mechanical_press.tooltip": "PRENSA MECÁNICA", + "block.create.mechanical_press.tooltip.summary": "Un pistón de fuerza para comprimir los objetos que tiene debajo. Requiere una _fuerza de rotación_ constante", + "block.create.mechanical_press.tooltip.condition1": "Cuando es impulsado por Redstone", + "block.create.mechanical_press.tooltip.behaviour1": "Comienza a _comprimir_ los objetos que caen debajo", + "block.create.mechanical_press.tooltip.condition2": "Cuando está por encima de una correa", + "block.create.mechanical_press.tooltip.behaviour2": "Comprime _automáticamente_ los elementos de derivación en la correa", + "block.create.mechanical_press.tooltip.condition3": "Cuando está por encima de la Cuenca", + "block.create.mechanical_press.tooltip.behaviour3": "Comienza a _compactar artículos_ en la cuenca siempre que estén presentes todos los ingredientes necesarios", + + "block.create.basin.tooltip": "CUENCA", + "block.create.basin.tooltip.summary": "Un práctico _contenedor de elementos_ utilizado en el procesamiento con la _Mezcladora mecánica_ y la _Prensa mecánica_. Soporta _Comparadores de Redstone_. Viene con un práctico filtro que especifica qué elementos deben crearse en esta cuenca", + "block.create.basin.tooltip.condition1": "Salida automática", + "block.create.basin.tooltip.behaviour1": "Cuando los _inventarios abiertos_ como cintas, otras cuencas, depósitos, desagües de fluidos y otros están _bajo un lado_ de una cuenca, recibirán automáticamente cualquier _salida de artículos/fluidos_ creada en la cuenca. Esto es útil para la automatización", + + "block.create.blaze_burner.tooltip": "QUEMADOR DE BLAZE", + "block.create.blaze_burner.tooltip.summary": "Un bloque donde se aloja un blaze domado para calentar una cuenca", + "block.create.blaze_burner.tooltip.condition1": "Cuando se coloca debajo de una cuenca", + "block.create.blaze_burner.tooltip.behaviour1": "Proporciona _calor_ a las recetas de la cuenca", + "block.create.blaze_burner.tooltip.condition2": "Cuando se utiliza el combustible en el Quemador de Blaze", + "block.create.blaze_burner.tooltip.behaviour2": "Aumenta el tiempo de combustión restante en el tiempo de combustión del horno del elemento utilizado. Consume el objeto. Utiliza _Torta de Blaze_ para altas temperaturas", + + "block.create.reinforced_rail.tooltip": "RAÍL REFORZADO", + "block.create.reinforced_rail.tooltip.summary": "Raíl estabilizado con madera, _no necesita soportes_", + + "block.create.mechanical_mixer.tooltip": "MEZCLADOR MECÁNICO", + "block.create.mechanical_mixer.tooltip.summary": "Un batidor cinético que proporciona recetas de elaboración automatizada de múltiples ingredientes. Requiere una _fuerza de rotación_ constante y una _cuenca_ colocada debajo (con un espacio intermedio)", + "block.create.mechanical_mixer.tooltip.condition1": "Cuando está por encima de la Cuenca", + "block.create.mechanical_mixer.tooltip.behaviour1": "Comienza a mezclar los elementos en la cuenca siempre que estén presentes todos los ingredientes necesarios. Para evitar recetas no deseadas, utilice la ranura del filtro de la cuenca o reduzca la fuerza de rotación hasta que se hayan añadido todos los ingredientes deseados", + + "block.create.mechanical_crafter.tooltip": "AUTOENSAMBLADOR MECÁNICO", + "block.create.mechanical_crafter.tooltip.summary": "Un ensamblador cinético para _automatizar_ cualquier receta de _crafteo_ con forma. Coloca _múltiples en una cuadrícula_ correspondiente a tu receta, y _organiza sus correas_ para crear un _flujo_ que salga de la cuadrícula en uno de los Autoensambladores", + "block.create.mechanical_crafter.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.mechanical_crafter.tooltip.behaviour1": "_Empieza el proceso de creación_ en cuanto _todos los crafters_ de la parrilla hayan recibido un objeto_", + "block.create.mechanical_crafter.tooltip.condition2": "Con pulso de Redstone", + "block.create.mechanical_crafter.tooltip.behaviour2": "_Fuerza_ el inicio del proceso de _creación_ con todos los _artículos_ dados actualmente en la parrilla", + "block.create.mechanical_crafter.tooltip.control1": "Cuando se arranca por delante", + "block.create.mechanical_crafter.tooltip.action1": "_Circula la dirección_ hacia la que un autoensamblador individual _mueve sus objetos_. Para formar una cuadrícula de trabajo, _organiza las correas en un flujo_ que mueva todos los objetos hacia un autoensamblador final. El autoensamblador final debe _apuntar hacia fuera_ de la rejilla", + "block.create.mechanical_crafter.tooltip.control2": "Cuando se arranca hacia atrás", + "block.create.mechanical_crafter.tooltip.action2": "Conecta_ el _inventario de entrada_ de los autoensambladores adyacentes. Usa esto para _combinar ranuras_ en la cuadrícula de trabajo y _guardar el la entrada de trabajo_", + + "block.create.furnace_engine.tooltip": "MOTOR DEL HORNO", + "block.create.furnace_engine.tooltip.summary": "Una poderosa fuente de _fuerza de rotación/torque_ que requiere un _horno en funcionamiento_ para funcionar", + "block.create.furnace_engine.tooltip.condition1": "Cuando se conecta a un horno encendido", + "block.create.furnace_engine.tooltip.behaviour1": "_Empieza a alimentar_ un _Horno_ colocado delante de él (a 1m de distancia). Utiliza un Alto Horno para obtener mayores velocidades", + + "block.create.flywheel.tooltip": "RUEDA DE INERCIA", + "block.create.flywheel.tooltip.summary": "Una gran rueda metálica para _conducir y estabilizar_ la fuerza generada por un _motor conectado_. Las ruedas de inercia se conectan a los motores si están a _1m de distancia_ y en un _ángulo de 90º_ entre ellos", + "block.create.flywheel.tooltip.condition1": "Cuando está unida a un motor en marcha", + "block.create.flywheel.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a un artilugio conectado en función de la fuerza y la velocidad del generador", + + "block.create.portable_storage_interface.tooltip": "INTERFAZ DE ALMACENAMIENTO PORTÁTIL", + "block.create.portable_storage_interface.tooltip.summary": "Un punto de intercambio portátil para _mover elementos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", + "block.create.portable_storage_interface.tooltip.condition1": "Mientras se mueve", + "block.create.portable_storage_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátil_ estacionarias para transferir elementos hacia o desde el artilugio. Los componentes que se inserten o extraigan de la _interfaz estacionaria_ interactuarán con los inventarios del artilugio _directamente._ La estructura se detendrá brevemente mientras se intercambian los elementos.", + "block.create.portable_storage_interface.tooltip.condition2": "Cuando es alimentado por Redstone", + "block.create.portable_storage_interface.tooltip.behaviour2": "Desactiva_ cualquier conexión activa inmediatamente", + + "block.create.portable_fluid_interface.tooltip": "INTERFAZ DE FLUIDO PORTÁTIL", + "block.create.portable_fluid_interface.tooltip.summary": "Punto de intercambio portátil para _mover fluidos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", + "block.create.portable_fluid_interface.tooltip.condition1": "Mientras se mueve", + "block.create.portable_fluid_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátiles_ estacionarias para transferir fluidos hacia o desde el artilugio. Las tuberías que se inserten en la _interfaz estacionaria_ o se extraigan de ella interactuarán con los depósitos del artilugio _directamente._ La estructura se paralizará brevemente mientras se intercambian fluidos.", + "block.create.portable_fluid_interface.tooltip.condition2": "Cuando se alimenta con Redstone", + "block.create.portable_fluid_interface.tooltip.behaviour2": "_Desconecta_ cualquier conexión activa inmediatamente", + + "block.create.rotation_speed_controller.tooltip": "CONTROLADOR DE VELOCIDAD DE ROTACIÓN", + "block.create.rotation_speed_controller.tooltip.summary": "Un _relé_ configurable_ capaz de acelerar o ralentizar el componente de destino a cualquier velocidad deseada", + "block.create.rotation_speed_controller.tooltip.condition1": "Cuando se adjunta a una rueda dentada grande", + "block.create.rotation_speed_controller.tooltip.behaviour1": "Transmite la fuerza de rotación entrante a la rueda, intentando _igualar_ la _velocidad_ a la que está configurada. La _rueda mecánica_ tiene que estar _adherida en la parte superior_ del controlador", + + "block.create.mechanical_piston.tooltip": "PISTÓN MECÁNICO", + "block.create.mechanical_piston.tooltip.summary": "Una versión más avanzada del _Pistón_. Utiliza la _Fuerza de rotación_ para mover con precisión las estructuras que tiene delante. las pértigas de extensión del pistón_ en la parte trasera definen el _alcance_ de este dispositivo. Sin las extensiones, el pistón no se moverá. Utiliza _Chasis_ o _Bloques de Slime_ para mover más de una línea de bloques", + "block.create.mechanical_piston.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.mechanical_piston.tooltip.behaviour1": "Comienza a mover la estructura adjunta. La velocidad y la dirección se correlacionan con la velocidad de rotación entrante", + + "block.create.piston_extension_pole.tooltip": "PÉRTIGA DE EXTENSIÓN", + "block.create.piston_extension_pole.tooltip.summary": "Amplía la gama de _Pistones mecánicos_", + "block.create.piston_extension_pole.tooltip.condition1": "Cuando se acopla a un pistón mecánico", + "block.create.piston_extension_pole.tooltip.behaviour1": "Extiende el alcance de un pistón en 1 bloque", + + "block.create.mechanical_bearing.tooltip": "RODAMIENTO MECÁNICO", + "block.create.mechanical_bearing.tooltip.summary": "Se utiliza para girar _estructuras más grandes_ con fuerza de rotación", + "block.create.mechanical_bearing.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.mechanical_bearing.tooltip.behaviour1": "Inicia la rotación de los bloques adjuntos. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque", + + "block.create.windmill_bearing.tooltip": "RODAMIENTO DEL MOLINO DE VIENTO", + "block.create.windmill_bearing.tooltip.summary": "Se utiliza para aprovechar la _fuerza de rotación_ del viento. Coloca tu propio diseño y mira cómo gira!", + "block.create.windmill_bearing.tooltip.condition1": "Al hacer clic con el botón derecho", + "block.create.windmill_bearing.tooltip.behaviour1": "Comienza a proporcionar _Fuerza de rotación_ generada por la rotación de su estructura adjunta. La estructura tiene que incluir bloques de vela o lana adecuados. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque.", + + "block.create.sail_frame.tooltip": "MARCO DE VELA", + "block.create.sail_frame.tooltip.summary": "Un útil bloque de construcción y fuente de energía cinética cuando forma parte de una estructura montada sobre un _Rodamiento de molino_", + + "block.create.white_sail.tooltip": "VELA BLANCA", + "block.create.white_sail.tooltip.summary": "Un útil bloque de construcción y fuente de energía cinética cuando forma parte de una estructura montada en un _Rodamiento de molino_. Viene en una variedad de colores", + "block.create.white_sail.tooltip.condition1": "Cuando se hace clic con el botón derecho del ratón con tinte", + "block.create.white_sail.tooltip.behaviour1": "Cambia el color de la vela", + + "block.create.clockwork_bearing.tooltip": "RODAMIENTO DE RELOJ", + "block.create.clockwork_bearing.tooltip.summary": "Una versión avanzada del _rodamiento mecánico_ para hacer girar hasta dos _manecillas de reloj_ según la _hora actual_ en el _juego_", + "block.create.clockwork_bearing.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.clockwork_bearing.tooltip.behaviour1": "Comienza a girar la estructura adjunta hacia la _hora actual_. Si existe una segunda estructura independiente delante de la primera, servirá de _manecilla de las horas_", + + "block.create.sequenced_gearshift.tooltip": "CAMBIO DE MARCHAS SECUENCIADO", + "block.create.sequenced_gearshift.tooltip.summary": "Un _componente de utilidad programable_, que puede cambiar su _rendimiento rotacional_ según hasta _5 instrucciones consecutivas._ Utilízalo para alimentar Rodamientos Mecánicos, Pistones o Poleas con más control sobre la sincronización y la velocidad. Puede ser menos preciso a velocidades más altas", + "block.create.sequenced_gearshift.tooltip.condition1": "Cuando es impulsado por Redstone", + "block.create.sequenced_gearshift.tooltip.behaviour1": "_Ejecuta_ las instrucciones programadas en función de la velocidad de entrada", + "block.create.sequenced_gearshift.tooltip.condition2": "Cuando se hace clic derecho", + "block.create.sequenced_gearshift.tooltip.behaviour2": "Abre la _interfaz de configuración._", + + "block.create.cart_assembler.tooltip": "ENSAMBLADOR DE VAGONETAS", + "block.create.cart_assembler.tooltip.summary": "Cuando se coloca en un _Raíl_, puede _ensamblar_ y _desensamblar_ estructuras móviles en las vagonetas que pasan. Consulta [Ctrl] para conocer el comportamiento específico del tipo de raíl", + "block.create.cart_assembler.tooltip.condition1": "Artilugio de vagoneta simple", + "block.create.cart_assembler.tooltip.behaviour1": "Con un _miembro único_, las estructuras se anclarán y girarán en _una sola vagoneta_. Utilice una _Llave Inglesa_ para especificar el _comportamiento de rotación_ deseado", + "block.create.cart_assembler.tooltip.condition2": "Artilugio de vagonetas", + "block.create.cart_assembler.tooltip.behaviour2": "Dos ensambladores de vagonetas _conectadas por_ una _estructura_, una vez que ambos contengan una vagoneta, las conectará con un artilugio montado _entre los dos_. La estructura se comportará de forma similar a un _acoplador de vagonetas_", + "block.create.cart_assembler.tooltip.control1": "Cuando se coloca sobre un Rail", + "block.create.cart_assembler.tooltip.action1": "_Se monta_ en las vagonetas que pasan _cuando está alimentado_, _se desmonta_ en caso contrario", + "block.create.cart_assembler.tooltip.control2": "Cuando se coloca sobre un raíl energizado", + "block.create.cart_assembler.tooltip.action2": "Monta y _acelera_ las vagonetas _cuando está alimentado_, desmonta y _sostiene_ en caso contrario", + "block.create.cart_assembler.tooltip.control3": "Cuando se coloca sobre el raíl detector", + "block.create.cart_assembler.tooltip.action3": "_Monta vagonetas sin montar_, _desmonta vagonetas montadas_", + "block.create.cart_assembler.tooltip.control4": "Cuando se coloca sobre el raíl activador", + "block.create.cart_assembler.tooltip.action4": "Desmonta_ vagonetas cuando se activa", + + "block.create.rope_pulley.tooltip": "POLEA DE CUERDA", + "block.create.rope_pulley.tooltip.summary": "Mueve verticalmente los _bloques_ y _estructuras_ adjuntos. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque", + "block.create.rope_pulley.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.rope_pulley.tooltip.behaviour1": "Comienza a mover la estructura adjunta. La velocidad y la dirección se correlacionan con la velocidad de rotación entrante", + + "block.create.linear_chassis.tooltip": "CHASIS LINEAL", + "block.create.linear_chassis.tooltip.summary": "Bloque base configurable que conecta estructuras para el movimiento", + "block.create.linear_chassis.tooltip.condition1": "Cuando se mueve", + "block.create.linear_chassis.tooltip.behaviour1": "_Mueve_ todos los _Chasis adjuntos_ con la misma orientación, y una columna de Bloques dentro de su rango. Los bloques sólo serán arrastrados si la cara del chasis es _Pegajosa_ (Ver [Ctrl])", + "block.create.linear_chassis.tooltip.condition2": "Con Llave Inglesa", + "block.create.linear_chassis.tooltip.behaviour2": "Configura el _rango_ para este bloque de chasis. Mantenga pulsada la tecla CTRL para modificar también el rango de todos los bloques de chasis adjuntos", + "block.create.linear_chassis.tooltip.control1": "Cuando se hace clic derecho con slime", + "block.create.linear_chassis.tooltip.action1": "Hace que la cara sobre la que se ha hecho clic sea _pegajosa_. Cuando se mueva, el chasis _tirará_ de los bloques adjuntos, independientemente de la dirección del movimiento", + + "block.create.secondary_linear_chassis.tooltip": "CHASIS LINEAL SECUNDARIO", + "block.create.secondary_linear_chassis.tooltip.summary": "Un segundo tipo de _Chasis lineal_ que no se conecta al otro", + + "block.create.radial_chassis.tooltip": "UNLOCALIZED: ROTATION CHASSIS", + "block.create.radial_chassis.tooltip.summary": "Bloque base configurable que conecta estructuras para el movimiento", + "block.create.radial_chassis.tooltip.condition1": "Cuando se mueve", + "block.create.radial_chassis.tooltip.behaviour1": "_Mueve_ todos los _Chasis_ adjuntos en una columna, y un cilindro de bloques a su alrededor. Los bloques que lo rodean sólo se mueven cuando están dentro del rango y están adheridos a un lado pegajoso (Ver [Ctrl]).", + "block.create.radial_chassis.tooltip.condition2": "Con Llave Inglesa", + "block.create.radial_chassis.tooltip.behaviour2": "Configura el _rango_ para este bloque de chasis. Mantenga pulsada la tecla CTRL para modificar también el rango de todos los bloques de chasis adjuntos", + "block.create.radial_chassis.tooltip.control1": "Cuando se hace clic derecho con slime", + "block.create.radial_chassis.tooltip.action1": "Hace que la cara sobre la que se ha hecho clic sea _pegajosa_. Cuando el chasis se mueve, todos los bloques designados unidos a la cara pegajosa se mueven con él", + + "block.create.mechanical_drill.tooltip": "TALADRO MECÁNICO", + "block.create.mechanical_drill.tooltip.summary": "Un dispositivo mecánico adecuado para _romper bloques_. Se puede mover con _pistones mecánicos_, _rodamientos_ u otros controladores", + "block.create.mechanical_drill.tooltip.condition1": "Cuando se mueve con cinética", + "block.create.mechanical_drill.tooltip.behaviour1": "Actúa como un rompebloques _estacionario_. También _hace daño a las entidades_ en su área efectiva", + "block.create.mechanical_drill.tooltip.condition2": "Mientras se mueve", + "block.create.mechanical_drill.tooltip.behaviour2": "Rompe los bloques con los que colisiona el taladro", + + "block.create.mechanical_harvester.tooltip": "COSECHADORA MECÁNICA", + "block.create.mechanical_harvester.tooltip.summary": "Una cosechadora mecánica adecuada para la automatización de cultivos a mediana escala. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros controladores", + "block.create.mechanical_harvester.tooltip.condition1": "Mientras se mueve", + "block.create.mechanical_harvester.tooltip.behaviour1": "_Corta_ todos los _cultivos maduros_ con los que la cuchilla colisiona y los restablece a su estado de crecimiento inicial", + + "block.create.mechanical_plough.tooltip": "ARADO MECÁNICO", + "block.create.mechanical_plough.tooltip.summary": "Un arado mecánico tiene varios usos. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros mandos", + "block.create.mechanical_plough.tooltip.condition1": "Mientras se mueve", + "block.create.mechanical_plough.tooltip.behaviour1": "_Rompe bloques_ con los que _no se puede colisionar_, como antorchas, raíles o capas de nieve. _Aplica_ su _movimiento_ a las _entidades_ sin dañarlas. _Labra bloques de tierra_ como si se usara una azada en ellos", + + "block.create.mechanical_saw.tooltip": "SIERRA MECÁNICA", + "block.create.mechanical_saw.tooltip.summary": "Adecuada para _cortar árboles_ de forma eficaz y para _cortar bloques_ en sus homólogos carpinteros. Se puede mover mediante _pistones mecánicos_ o _rodamientos_", + "block.create.mechanical_saw.tooltip.condition1": "Cuando está orientado hacia arriba", + "block.create.mechanical_saw.tooltip.behaviour1": "Aplica las recetas _Serrar_ y _Estallar_ a los objetos que se dejan caer o se introducen en ella. Cuando hay varias salidas posibles, las recorre a menos que se asigne un _filtro_", + "block.create.mechanical_saw.tooltip.condition2": "Cuando se orienta horizontalmente", + "block.create.mechanical_saw.tooltip.behaviour2": "Rompe los troncos_ que tiene delante. Si el tronco soportaba un árbol por sí mismo, el _árbol se derrumbará_ lejos de la sierra", + "block.create.mechanical_saw.tooltip.condition3": "Mientras se mueve", + "block.create.mechanical_saw.tooltip.behaviour3": "_Corta_ todos los _Árboles_ con los que colisiona la sierra", + + "block.create.stockpile_switch.tooltip": "INTERRUPTOR DE ACOPIO", + "block.create.stockpile_switch.tooltip.summary": "Activa una señal de Redstone en función de la cantidad de _Artículos almacenados_ en el Contenedor adjunto. Viene con un práctico filtro. A diferencia de un _Comparador,_ el _Interruptor de acopio_ permite la configuración de _Umbrales,_ a partir de los cuales se invierten las señales", + "block.create.stockpile_switch.tooltip.condition1": "Cuando haces click derecho", + "block.create.stockpile_switch.tooltip.behaviour1": "Abre la _Interfaz de Configuración_", + + "block.create.content_observer.tooltip": "OBSERVADOR DE CONTENIDO", + "block.create.content_observer.tooltip.summary": "_Detecta artículos_ dentro de _contenedores_ y _transportadores_ que coinciden con un _filtro_ configurado. Mientras el _inventario_, la _cinta_ o la _canaleta_ observados contengan_ un artículo que coincida, este componente emitirá una _señal de Redstone_. Cuando un _túnel observado transfiere_ un artículo coincidente, este componente emitirá un _Pulso de Redstone_", + + "block.create.redstone_link.tooltip": "ENLACE DE REDSTONE", + "block.create.redstone_link.tooltip.summary": "Puntos finales para conexiones _Inalámbricas Redstone_. Se pueden asignar _frecuencias_ utilizando cualquier elemento. El alcance de la señal es limitado, aunque razonablemente lejano", + "block.create.redstone_link.tooltip.condition1": "Cuando se alimenta", + "block.create.redstone_link.tooltip.behaviour1": "Recibir enlaces de la misma _Frecuencia_ producirá una señal de Redstone", + "block.create.redstone_link.tooltip.control1": "Cuando se hace Clic derecho con un ítem", + "block.create.redstone_link.tooltip.action1": "Establece la _Frecuencia_ a ese elemento. Se pueden utilizar un total de _dos elementos diferentes_ en combinación para definir una Frecuencia", + "block.create.redstone_link.tooltip.control2": "Cuando se hace clic derecho mientras se agacha", + "block.create.redstone_link.tooltip.action2": "Cambia entre el modo _Receptor_ y _Transmisor_", + + "block.create.nixie_tube.tooltip": "TUBO NIXIE", + "block.create.nixie_tube.tooltip.summary": "Un elegante _visualizador_ de _números y texto_ potenciados por Redstone", + "block.create.nixie_tube.tooltip.condition1": "Cuando se alimenta", + "block.create.nixie_tube.tooltip.behaviour1": "Muestra el valor actual de la _Fuerza de la señal Redstone_", + "block.create.nixie_tube.tooltip.condition2": "Con etiqueta de nombre", + "block.create.nixie_tube.tooltip.behaviour2": "Mostrar el _contenido_ de su _etiqueta de nombre_ con varios tubos nixie _ordenados_ en una _línea_", + + "block.create.redstone_contact.tooltip": "CONTACTO DE REDSTONE", + "block.create.redstone_contact.tooltip.summary": "Solo emite energía de Redstone por parejas. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros controladores", + "block.create.redstone_contact.tooltip.condition1": "Cuando se enfrenta a otro Contacto", + "block.create.redstone_contact.tooltip.behaviour1": "Proporciona una _señal de Redstone_", + "block.create.redstone_contact.tooltip.condition2": "Mientras se mueve", + "block.create.redstone_contact.tooltip.behaviour2": "Activa todos los contactos estacionarios que pasa", + + "block.create.adjustable_crate.tooltip": "CAJA AJUSTABLE", + "block.create.adjustable_crate.tooltip.summary": "Este _Contenedor de Artículos_ permite el control manual de su capacidad. Puede contener hasta _16 pilas_ de cualquier objeto. Soporta _Comparadores de Redstone_", + "block.create.adjustable_crate.tooltip.control1": "Cuando haces click derecho", + "block.create.adjustable_crate.tooltip.action1": "Abre la _Interfaz_", + + "block.create.creative_crate.tooltip": "CAJA CREATIVA", + "block.create.creative_crate.tooltip.summary": "Este _Contenedor de Almacenamiento_ permite la replicación infinita de cualquier elemento. Colócalo junto a un _Schematicannon_ para eliminar cualquier requisito de material", + "block.create.creative_crate.tooltip.condition1": "Cuando el artículo está en la ranura del filtro", + "block.create.creative_crate.tooltip.behaviour1": "Todo lo que se _extraiga_ de este contenedor proporcionará un _suministro ilimitado_ del elemento especificado. Los elementos _insertados_ en esta caja serán _evitados._", + + "block.create.deployer.tooltip": "DESPLEGADOR", + "block.create.deployer.tooltip.summary": "_Lanza_, _Usa_ y _Activa_. Esta máquina intentará _imitar_ a un _jugador_ en la medida de lo posible. Puede _tomar_ y _depositar objetos_ en su propio _inventario_. Los objetos guardados deben ser _insertados_ y _extraídos_ del bloque directamente", + "block.create.deployer.tooltip.condition1": "Cuando se alimenta de cinética", + "block.create.deployer.tooltip.behaviour1": "Extiende su brazo y se _activa_ en el espacio del bloque _2m por delante_ de sí mismo", + "block.create.deployer.tooltip.condition2": "Click derecho con la Llave Inglesa", + "block.create.deployer.tooltip.behaviour2": "Activa el modo puñetazo. En el _modo puñetazo_, el Desplegador intentará usar su objeto para _romper bloques_ o _herir entidades_", + "block.create.deployer.tooltip.condition3": "Cuando se asigna el filtro", + "block.create.deployer.tooltip.behaviour3": "El desplegador no se activará a menos que el elemento retenido _coincida_ con el _filtro._ Los elementos que no coincidan no podrán ser insertados; los elementos retenidos que coincidan con el filtro no podrán ser extraídos.", + + "block.create.brass_casing.tooltip": "REVESTIDOR DE LATÓN", + "block.create.brass_casing.tooltip.summary": "Resistente máquina revestidora con una gran variedad de usos. Segura para la decoración. Se puede utilizar para _revestir ejes_ y _correas._", + + "block.create.pulse_repeater.tooltip": "REPETIDOR DE PULSOS DE REDSTONE", + "block.create.pulse_repeater.tooltip.summary": "Un circuito sencillo para cortar las señales de Redstone que pasan a una longitud de _1 tick_", + + "block.create.adjustable_repeater.tooltip": "REPETIDOR AJUSTABLE", + "block.create.adjustable_repeater.tooltip.summary": "Un avanzado _repetidor de Redstone_ con un _retraso configurable_ de hasta 30 minutos", + + "block.create.adjustable_pulse_repeater.tooltip": "REPETIDOR DE PULSO AJUSTABLE", + "block.create.adjustable_pulse_repeater.tooltip.summary": "Un _repetidor de pulsos_ con un _retardo configurable_ de hasta 30 minutos", + + "block.create.analog_lever.tooltip": "PALANCA ANALÓGICA", + "block.create.analog_lever.tooltip.summary": "Una palanca con un control más _preciso_ sobre su fuerza de _señal_ emitida", + + "block.create.powered_toggle_latch.tooltip": "PALANCA MECANIZADA", + "block.create.powered_toggle_latch.tooltip.summary": "Una palanca que puede ser accionada por un _Pulso de Redstone_", + + "block.create.powered_latch.tooltip": "PALANCA DE CIERRE MECANIZADA", + "block.create.powered_latch.tooltip.summary": "Una palanca que puede ser controlada por _señales de Redstone_. Una señal en la _trasera la habilita_, una señal desde el _lado la reinicia_", + + "block.create.controller_rail.tooltip": "RAÍL DE CONTROL", + "block.create.controller_rail.tooltip.summary": "Un _raíl energizado unidireccional_ capaz de _controlar con precisión_ la _velocidad de movimiento_ de una vagoneta", + "block.create.controller_rail.tooltip.condition1": "Cuando es impulsado por Redstone", + "block.create.controller_rail.tooltip.behaviour1": "_Acelera_ o _Desacelera_ pasando _vagonetas_ correspondientes a la _fuerza de la señal_. Propaga la energía de Redstone a los Raíles de control adyacentes. Al alimentar dos Raíles de control con diferentes intensidades, los carriles entre ellos interpolarán su señal", + + "block.create.speedometer.tooltip": "VELOCÍMETRO", + "block.create.speedometer.tooltip.summary": "Mide y muestra la _velocidad de rotación_ de los componentes cinéticos acoplados. Es compatible con _comparadores de Redstone_", + "block.create.speedometer.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.speedometer.tooltip.behaviour1": "Indica un color correspondiente al nivel de velocidad. El _Verde_ indica Lento, el _Azul_ Moderado y el _Púrpura_ Rápido. Algunos componentes mecánicos requieren un nivel de velocidad suficiente para funcionar correctamente", + + "block.create.stressometer.tooltip": "ESTRESÓMETRO", + "block.create.stressometer.tooltip.summary": "Mide y muestra el _estrés global_ de la red cinética adjunta. Es compatible con _comparadores de Redstone_", + "block.create.stressometer.tooltip.condition1": "Cuando se alimenta con cinética", + "block.create.stressometer.tooltip.behaviour1": "Indica un color correspondiente al nivel de estrés. Las redes demasiado estresadas dejarán de moverse. El estrés puede aliviarse añadiendo más _fuentes de rotación_ a la red", + + "item.create.sand_paper.tooltip": "PAPEL DE LIJA", + "item.create.sand_paper.tooltip.summary": "Un papel rugoso que se puede utilizar para _pulir materiales_. Se puede aplicar automáticamente con el Desplegador", + "item.create.sand_paper.tooltip.condition1": "Cuando se usa", + "item.create.sand_paper.tooltip.behaviour1": "Aplica el pulido a los objetos sostenidos en la _mano libre_ o tirados en el _suelo_ cuando se _miran_", + + "item.create.super_glue.tooltip": "SÚPER PEGAMENTO", + "item.create.super_glue.tooltip.summary": "Pega un bloque a otro y serán inseparables para siempre", + "item.create.super_glue.tooltip.condition1": "Cuando se usa", + "item.create.super_glue.tooltip.behaviour1": "Hace que la cara _clicada_ de un bloque sea _pegajosa_. Los bloques unidos a caras pegajosas serán _arrastrados_ cuando se muevan por _pistones mecánicos_, _rodamientos_ y otros controladores", + "item.create.super_glue.tooltip.condition2": "Cuando se sostiene en la mano", + "item.create.super_glue.tooltip.behaviour2": "_Adjunta automáticamente_ los bloques colocados desde la mano principal al _lado_ contra el que fueron _colocados._", + + "item.create.builders_tea.tooltip": "TÉ DEL CONSTRUCTOR", + "item.create.builders_tea.tooltip.summary": "La bebida perfecta para empezar el día- _Motivante_ y _Saturante._", + + "item.create.refined_radiance.tooltip": "RESPLANDOR REFINADO", + "item.create.refined_radiance.tooltip.summary": "Material cromático forjado a partir de _luz absorbida_", + + "item.create.shadow_steel.tooltip": "ACERO SOMBRÍO", + "item.create.shadow_steel.tooltip.summary": "Un material cromático forjado _en el vacío_", + + "item.create.minecart_coupling.tooltip": "ENSAMBLADOR DE VAGONETAS", + "item.create.minecart_coupling.tooltip.summary": "_Encadena_ todas tus _Vagonetas_ o _Artilugios de vagoneta_ para formar un majestuoso Tren", + "item.create.minecart_coupling.tooltip.condition1": "Cuando se utiliza en Vagonetas", + "item.create.minecart_coupling.tooltip.behaviour1": "_Acopla_ dos Vagonetas, intentando mantenerlas a una _distancia constante_ mientras se mueven", + + "item.create.crafter_slot_cover.tooltip": "TAPA DE RANURA DEL AUTOENSAMBLADOR", + "item.create.crafter_slot_cover.tooltip.summary": "Se utiliza para marcar a un _Autoensamblador_ una ranura vacía en una receta. Los autoensambladores no tienen que formar necesariamente una cuadrícula completa. Esto es útil cuando hay recetas en las que los _ingredientes están en diagonal_ entre sí", + + "create.tooltip.wip": "WIP", + "create.tooltip.workInProgress": "¡Trabajo en curso!", + "create.tooltip.randomWipDescription0": "Por favor, mantenga este artículo fuera del alcance de los niños", + "create.tooltip.randomWipDescription1": "Un bebé panda muere cada vez que usas este objeto. Cada vez. Cada vez", + "create.tooltip.randomWipDescription2": "Úsalo bajo tu propio riesgo", + "create.tooltip.randomWipDescription3": "Este no es el objeto que buscas, *mueve los dedos* por favor, dispérsate", + "create.tooltip.randomWipDescription4": "Este objeto se autodestruirá en 10 segundos. 10, 9, 8...", + "create.tooltip.randomWipDescription5": "Créeme, es inútil", + "create.tooltip.randomWipDescription6": "Al utilizar este elemento, aceptas nuestra exención de responsabilidad y estás de acuerdo con sus términos", + "create.tooltip.randomWipDescription7": "Este quizás no es para ti. ¿Qué tal ese?", + "create.tooltip.randomWipDescription8": "Úsalo y arrepiéntete de tu decisión inmediatamente", + + "_": "Thank you for translating Create!" + +} \ No newline at end of file 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 9946947f4..1b52d7196 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: 915", + "_": "Missing Localizations: 924", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting", "create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting", "create.recipe.block_cutting": "UNLOCALIZED: Block Cutting", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "UNLOCALIZED: Handheld Blockzapper", "create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing", "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "UNLOCALIZED: Move to upper lane at %1$s%%", "create.gui.sequenced_gearshift.title": "UNLOCALIZED: Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "UNLOCALIZED: Instruction", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "UNLOCALIZED: Turn", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "UNLOCALIZED: Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "UNLOCALIZED: Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "UNLOCALIZED: Distance", - "create.gui.sequenced_gearshift.instruction.wait": "UNLOCALIZED: Wait", - "create.gui.sequenced_gearshift.instruction.wait.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "UNLOCALIZED: End", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "UNLOCALIZED: Speed, Direction", "create.gui.sequenced_gearshift.speed.forward": "UNLOCALIZED: Input speed, Forwards", "create.gui.sequenced_gearshift.speed.forward_fast": "UNLOCALIZED: Double speed, Forwards", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 cdeab2100..6b3650342 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,5 @@ { - "_": "Missing Localizations: 695", + "_": "Missing Localizations: 706", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "Fabrication mécanique", "create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting", "create.recipe.block_cutting": "Coupe de bloc", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "Blockzappeur portable", "create.recipe.sandpaper_polishing": "Polissage au papier de verre", "create.recipe.mystery_conversion": "Métamorphose chromatique", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "Bouger sur la ligne de haut à %1$s%%", "create.gui.sequenced_gearshift.title": "Décaleur de rotation séquencé", "create.gui.sequenced_gearshift.instruction": "Instructions", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "Tourner", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distance", - "create.gui.sequenced_gearshift.instruction.wait": "Attente", - "create.gui.sequenced_gearshift.instruction.wait.duration": "Durée", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "Fin", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "Vitesse, direction", "create.gui.sequenced_gearshift.speed.forward": "Vitesse d'entrée, normal", "create.gui.sequenced_gearshift.speed.forward_fast": "Vitesse double, normal", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 5169c7260..0f7271a5a 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,5 @@ { - "_": "Missing Localizations: 32", + "_": "Missing Localizations: 41", "_": "->------------------------] Game Elements [------------------------<-", @@ -162,8 +162,8 @@ "block.create.gabbro_cobblestone_stairs": "Scalini di pietrisco di gabbro", "block.create.gabbro_cobblestone_wall": "Muretto di pietrisco di gabbro", "block.create.gabbro_pillar": "Pilastro di gabbro", - "block.create.gantry_pinion": "UNLOCALIZED: Gantry Pinion", - "block.create.gantry_shaft": "UNLOCALIZED: Gantry Shaft", + "block.create.gantry_pinion": "Pignone a portale", + "block.create.gantry_shaft": "Albero a portale", "block.create.gearbox": "Riduttore", "block.create.gearshift": "Cambio", "block.create.glass_fluid_pipe": "Tubo per fluidi con vetrata", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "Costruzione meccanica", "create.recipe.automatic_shaped": "Costruzione con forma automatizzata", "create.recipe.block_cutting": "Taglio di blocchi", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "Zapper di blocchi portatile", "create.recipe.sandpaper_polishing": "Levigamento da carta vetrata", "create.recipe.mystery_conversion": "Metamorfosi cromatica", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "Muovi su al %1$s%%", "create.gui.sequenced_gearshift.title": "Cambio sequenziale", "create.gui.sequenced_gearshift.instruction": "Istruzione", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "Gira", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angolo", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "Pistone", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distanza", - "create.gui.sequenced_gearshift.instruction.wait": "Aspetta", - "create.gui.sequenced_gearshift.instruction.wait.duration": "Durata", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "Fine", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "Velocità, direzione", "create.gui.sequenced_gearshift.speed.forward": "Velocità di ingresso, avanti", "create.gui.sequenced_gearshift.speed.forward_fast": "Doppia velocità, avanti", @@ -1373,7 +1380,7 @@ "item.create.schematic_and_quill.tooltip.condition1": "Passo 1", "item.create.schematic_and_quill.tooltip.behaviour1": "Seleziona due punti d'angolo usando il clic destro.", "item.create.schematic_and_quill.tooltip.condition2": "Passo 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "Premi _Ctrl_ e _scorri_ sui volti per regolare le dimensioni. Clic destro di nuovo per salvare.", + "item.create.schematic_and_quill.tooltip.behaviour2": "Premi _Ctrl_ e _scorri_ sulle facciate per regolare le dimensioni. Clic destro di nuovo per salvare.", "item.create.schematic_and_quill.tooltip.control1": "Clic-Destro", "item.create.schematic_and_quill.tooltip.action1": "Seleziona un punto d'angolo / conferma il salvataggio.", "item.create.schematic_and_quill.tooltip.control2": "Ctrl premuto", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 0d1de356a..de73897c0 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,5 @@ { - "_": "Missing Localizations: 41", + "_": "Missing Localizations: 48", "_": "->------------------------] Game Elements [------------------------<-", @@ -149,8 +149,8 @@ "block.create.fluid_tank": "液体タンク", "block.create.fluid_valve": "液体バルブ", "block.create.flywheel": "勢車", - "block.create.framed_glass": "大きなガラス窓", - "block.create.framed_glass_pane": "大きなガラス窓板", + "block.create.framed_glass": "ガラス窓", + "block.create.framed_glass_pane": "ガラス窓板", "block.create.furnace_engine": "かまどエンジン", "block.create.gabbro": "斑れい岩", "block.create.gabbro_bricks": "斑れい岩レンガ", @@ -162,8 +162,8 @@ "block.create.gabbro_cobblestone_stairs": "斑れい岩の丸石の階段", "block.create.gabbro_cobblestone_wall": "斑れい岩の丸石の壁", "block.create.gabbro_pillar": "斑れい岩の柱", - "block.create.gantry_pinion": "UNLOCALIZED: Gantry Pinion", - "block.create.gantry_shaft": "UNLOCALIZED: Gantry Shaft", + "block.create.gantry_pinion": "ガントリーピニオン", + "block.create.gantry_shaft": "ガントリーシャフト", "block.create.gearbox": "ギアボックス", "block.create.gearshift": "ギアシフト", "block.create.glass_fluid_pipe": "ガラスの液体パイプ", @@ -372,13 +372,13 @@ "block.create.shaft": "シャフト", "block.create.smart_chute": "スマートシュート", "block.create.smart_fluid_pipe": "スマート液体パイプ", - "block.create.speedometer": "スピードメーター", + "block.create.speedometer": "速度メーター", "block.create.spout": "アイテム注液口", "block.create.spruce_window": "マツの窓", "block.create.spruce_window_pane": "マツの窓パネル", "block.create.sticky_mechanical_piston": "粘着メカニカルピストン", "block.create.stockpile_switch": "在庫スイッチ", - "block.create.stressometer": "ストレスメーター", + "block.create.stressometer": "応力メーター", "block.create.tiled_glass": "タイルガラス", "block.create.tiled_glass_pane": "タイルガラス板", "block.create.turntable": "ターンテーブル", @@ -407,7 +407,7 @@ "block.create.zinc_ore": "亜鉛鉱石", "entity.create.contraption": "からくり", - "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.gantry_contraption": "ガントリーからくり", "entity.create.seat": "シート", "entity.create.stationary_contraption": "付設からくり", "entity.create.super_glue": "接着剤", @@ -527,9 +527,9 @@ "advancement.create.goggles": "応力をこの目で", "advancement.create.goggles.desc": "機械からより多くの情報を手に入れるために、エンジニアのゴーグルを作る", "advancement.create.speedometer": "正確な速度は?", - "advancement.create.speedometer.desc": "動作中のスピードメーターをゴーグルで見て、正確な値を読み取る", + "advancement.create.speedometer.desc": "動作中の速度メーターをゴーグルで見て、正確な値を読み取る", "advancement.create.stressometer": "正確な応力は?", - "advancement.create.stressometer.desc": "動作中のストレスメーターをゴーグルを通して見て、正確な値を読み取る", + "advancement.create.stressometer.desc": "動作中の応力メーターをゴーグルを通して見て、正確な値を読み取る", "advancement.create.aesthetics": "装飾ブーム!", "advancement.create.aesthetics.desc": "シャフト、パイプ、歯車に腕木や腕金を取り付ける", "advancement.create.reinforced": "補強ブーム!", @@ -591,7 +591,7 @@ "advancement.create.pipe_spill": "漏れてる!", "advancement.create.pipe_spill.desc": "パイプの端を露出させて液体が吹き出しているところを見る", "advancement.create.hose_pulley": "工業排水", - "advancement.create.hose_pulley.desc": "ホースプーリーを下げて、液体の排出や吸引を見る", + "advancement.create.hose_pulley.desc": "ホースプーリーを下げて、液体の放出や吸引を見る", "advancement.create.infinite_water": "海の水ぜんぶ抜く大作戦", "advancement.create.infinite_water.desc": "無限と言えるほどの大量の水を吸引する", "advancement.create.infinite_lava": "星の核ぜんぶ抜く大作戦", @@ -602,7 +602,7 @@ "advancement.create.crafter.desc": "メカニカルクラフターを設置して、回転力を与える", "advancement.create.clockwork_bearing": "時計仕掛け", "advancement.create.clockwork_bearing.desc": "時計仕掛けのベアリングの上に構造物を組み立てる", - "advancement.create.nixie_tube": "派手な看板", + "advancement.create.nixie_tube": "イカした看板", "advancement.create.nixie_tube.desc": "ニキシー管を手に入れて、設置する", "advancement.create.deployer": "突く、置く、殴る!", "advancement.create.deployer.desc": "自分の手と全く同じ動きをするデプロイヤーを設置して、稼働させる", @@ -610,7 +610,7 @@ "advancement.create.speed_controller.desc": "究極の伝動機、回転速度コントローラーを設置する", "advancement.create.flywheel": "工場の心臓部", "advancement.create.flywheel.desc": "かまどエンジンを勢車に繋ぐ", - "advancement.create.overstress_flywheel": "高レベル応力", + "advancement.create.overstress_flywheel": "ハイレベル応力", "advancement.create.overstress_flywheel.desc": "かまどエンジンに超過応力をかける", "advancement.create.integrated_circuit": "複素数の計算", "advancement.create.integrated_circuit.desc": "集積回路を組み立てる", @@ -680,11 +680,12 @@ "create.recipe.automatic_shapeless": "自動不定形クラフト", "create.recipe.automatic_brewing": "自動醸造", "create.recipe.packing": "圧縮", - "create.recipe.automatic_packing": "自動包装", + "create.recipe.automatic_packing": "自動圧縮クラフト", "create.recipe.sawing": "製材", "create.recipe.mechanical_crafting": "メカニカルクラフト", "create.recipe.automatic_shaped": "自動定形クラフト", "create.recipe.block_cutting": "自動石切", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "携帯型ブロックザッパー", "create.recipe.sandpaper_polishing": "紙やすりでの研磨", "create.recipe.mystery_conversion": "色彩変態", @@ -836,7 +837,7 @@ "create.gui.stressometer.overstressed": "超過応力", "create.gui.stressometer.no_rotation": "回転なし", "create.gui.contraptions.not_fast_enough": "この %1$s は_十分な_回転を_していない_ようです。", - "create.gui.contraptions.network_overstressed": "この仕掛けは_超過応力_のようです。さらに原動機を追加するか、_応力_の影響が大きい機械のスピードを_下げて_ください。", + "create.gui.contraptions.network_overstressed": "この仕掛けは_超過応力_のようです。さらに原動機を追加するか、_応力_の影響が大きい機械の速度を_下げて_ください。", "create.gui.adjustable_crate.title": "可変クレート", "create.gui.adjustable_crate.storageSpace": "収納スペース", "create.gui.stockpile_switch.title": "在庫スイッチ", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "動作の上限は%1$s%%", "create.gui.sequenced_gearshift.title": "シーケンスギアシフト", "create.gui.sequenced_gearshift.instruction": "命令", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "回転", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "角度", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "ピストン", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "距離", - "create.gui.sequenced_gearshift.instruction.wait": "待機", - "create.gui.sequenced_gearshift.instruction.wait.duration": "期間", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "終了", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "速度, 方向", "create.gui.sequenced_gearshift.speed.forward": "入力速度, 正転", "create.gui.sequenced_gearshift.speed.forward_fast": "倍速, 正転", @@ -967,9 +974,9 @@ "create.materialChecklist.blocksNotLoaded": "*免責事項*\n\n素材チェックリストは関連するチャンクがロードされていないため、不正確な場合があります。", "create.gui.filter.deny_list": "ブラックリスト", - "create.gui.filter.deny_list.description": "上記のいずれにも一致しない場合、アイテムは通り抜けます。 空のブラックリストはすべてを受け入れます。", + "create.gui.filter.deny_list.description": "上記のいずれにも一致しない場合、アイテムは通り抜けます。空のブラックリストはすべてを受け入れます。", "create.gui.filter.allow_list": "ホワイトリスト", - "create.gui.filter.allow_list.description": "上記のいずれかに一致した場合、アイテムは通り抜けます。 空のホワイトリストはすべてを拒否します。", + "create.gui.filter.allow_list.description": "上記のいずれかに一致した場合、アイテムは通り抜けます。空のホワイトリストはすべてを拒否します。", "create.gui.filter.respect_data": "データを重視", "create.gui.filter.respect_data.description": "アイテムは、耐久性、エンチャント、その他の属性も一致する場合にのみ一致します。", "create.gui.filter.ignore_data": "データを無視", @@ -1036,7 +1043,7 @@ "create.gui.attribute_filter.selected_attributes": "選択された属性:", "create.gui.attribute_filter.add_attribute": "属性をリストに追加する", "create.gui.attribute_filter.add_inverted_attribute": "反属性をリストに追加する", - "create.gui.attribute_filter.allow_list_disjunctive": "ホワイトリスト(どれか)", + "create.gui.attribute_filter.allow_list_disjunctive": "ホワイトリスト(いずれか)", "create.gui.attribute_filter.allow_list_disjunctive.description": "選択した属性のいずれかを持っている場合、アイテムは通り抜けます。", "create.gui.attribute_filter.allow_list_conjunctive": "ホワイトリスト(全て)", "create.gui.attribute_filter.allow_list_conjunctive.description": "選択した属性をすべてを持っている場合、アイテムは通り抜けます。", @@ -1052,12 +1059,12 @@ "create.tooltip.speedRequirement.none": "無し", "create.tooltip.speedRequirement.medium": "中速", "create.tooltip.speedRequirement.high": "高速", - "create.tooltip.stressImpact": "応力への影響: %1$s", + "create.tooltip.stressImpact": "応力の影響: %1$s", "create.tooltip.stressImpact.low": "低", "create.tooltip.stressImpact.medium": "中", "create.tooltip.stressImpact.high": "高", "create.tooltip.stressImpact.overstressed": "超過応力", - "create.tooltip.capacityProvided": "応力許容量: %1$s", + "create.tooltip.capacityProvided": "応力の容量: %1$s", "create.tooltip.capacityProvided.low": "小", "create.tooltip.capacityProvided.medium": "中", "create.tooltip.capacityProvided.high": "大", @@ -1125,7 +1132,7 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", - "create.subtitle.schematicannon_finish": "概略図砲が完了する", + "create.subtitle.schematicannon_finish": "概略図砲が作業を終える", "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", "create.subtitle.mechanical_press_activation": "メカニカルプレスが作動する", "create.subtitle.mechanical_press_item_break": "金属がガチャンと鳴る", @@ -1186,11 +1193,11 @@ "block.create.brass_funnel.tooltip.behaviour3": "下向きホッパーのように、_アイテム_を_下方向_に_移動_させます。", "block.create.brass_tunnel.tooltip": "真鍮トンネル", - "block.create.brass_tunnel.tooltip.summary": "派手な_メカニカルベルト_の保護カバー!_真鍮トンネル_にはアイテムの_フィルター機能_や、_分割機能_の設定項目も多数用意されています。", + "block.create.brass_tunnel.tooltip.summary": "オシャレな_メカニカルベルト_の保護カバー!_真鍮トンネル_にはアイテムの_フィルター機能_や、_分割機能_の設定項目も多数用意されています。", "block.create.brass_tunnel.tooltip.condition1": "並べて設置したとき", "block.create.brass_tunnel.tooltip.behaviour1": "_真鍮トンネル_は相互に接続し、ある_メカニカルベルト_のアイテムを別の_メカニカルベルト_に送ったりできるようにします。", "block.create.brass_tunnel.tooltip.condition2": "フィルター機能", - "block.create.brass_tunnel.tooltip.behaviour2": "_真鍮トンネル_は_搬入_と_搬出_、両方のフィルターを搭載しています。 _トンネル_のフィルター付き出力から_アイテム_が出てくることが許可されていない場合、並べて設置された_トンネル_の出力に送られます。", + "block.create.brass_tunnel.tooltip.behaviour2": "_真鍮トンネル_は_搬入_と_搬出_、両方のフィルターを搭載しています。_トンネル_のフィルター付き出力から_アイテム_が出てくることが許可されていない場合、並べて設置された_トンネル_の出力に送られます。", "block.create.brass_tunnel.tooltip.condition3": "分割機能", "block.create.brass_tunnel.tooltip.behaviour3": "_真鍮トンネル_は、_アイテム_が接続された_メカニカルベルト_に分類して並べる方法を変更するように設定できます。", "block.create.brass_tunnel.tooltip.control1": "側面をレンチで右クリックしたとき。", @@ -1244,14 +1251,14 @@ "block.create.hose_pulley.tooltip": "ホースプーリー", "block.create.hose_pulley.tooltip.summary": "ワールドの大量の_液体_を_吸引_したり、_放出_したりするのに使います。", "block.create.hose_pulley.tooltip.condition1": "回転したとき", - "block.create.hose_pulley.tooltip.behaviour1": "ホースを_上げ下げ_して、どの程度の_高さ_まで_吸引_や_排出_を行うか決めます。", + "block.create.hose_pulley.tooltip.behaviour1": "ホースを_上げ下げ_して、どの程度の_高さ_まで_吸引_や_放出_を行うか決めます。", "block.create.hose_pulley.tooltip.condition2": "プーリーから液体が吸い込まれたとき", "block.create.hose_pulley.tooltip.behaviour2": "ホースの端がおろされた本体から_液体_ブロックを_吸引_し始めます。非常に_大量_の液体は_無限_と_みなされます_。", "block.create.hose_pulley.tooltip.condition3": "液体がプーリーに押しこまれたとき", "block.create.hose_pulley.tooltip.behaviour3": "ホースの端の_高さ_まで、_液体_の_放出_を始めます。", "block.create.fluid_tank.tooltip": "液体タンク", - "block.create.fluid_tank.tooltip.summary": "あなたのお気に入りの_液体_をすべて_貯蔵_します。縦横に並べて大きさを調整できます。", + "block.create.fluid_tank.tooltip.summary": "あなたのお気に入りのあらゆる_液体_を_貯蔵_できます。縦横に並べて大きさを調整できます。", "block.create.fluid_tank.tooltip.condition1": "レンチで右クリックしたとき", "block.create.fluid_tank.tooltip.behaviour1": "窓の設定を変更します。", @@ -1290,7 +1297,7 @@ "block.create.item_drain.tooltip": "アイテム排液口", "block.create.item_drain.tooltip.summary": "_液体アイテム_を空にする格子付きデポ。", - "block.create.item_drain.tooltip.condition1": "液体排液 ", + "block.create.item_drain.tooltip.condition1": "液体排液", "block.create.item_drain.tooltip.behaviour1": "_バケツ_や_ボトル_などの_液体入り容器_を横から搬入すると、アイテム排液口はその_液体入り容器_に空にしようとします。その後、アイテムは反対側に排出されます。", "block.create.mechanical_arm.tooltip": "メカニカルアーム", @@ -1316,7 +1323,7 @@ "item.create.handheld_blockzapper.tooltip": "携帯ブロックザッパー", "item.create.handheld_blockzapper.tooltip.summary": "離れた場所にブロックを設置または交換する新しいガジェット。", "item.create.handheld_blockzapper.tooltip.control1": "ブロックを左クリックしたとき", - "item.create.handheld_blockzapper.tooltip.action1": "UNLOCALIZED: Sets blocks placed by the tool to the targeted block.", + "item.create.handheld_blockzapper.tooltip.action1": "ターゲットのブロックをこのツールに設定します。", "item.create.handheld_blockzapper.tooltip.control2": "ブロックを右クリックしたとき", "item.create.handheld_blockzapper.tooltip.action2": "ターゲットブロックを_配置_または_置換_します。", "item.create.handheld_blockzapper.tooltip.control3": "スニークしながら右クリックしたとき。", @@ -1362,7 +1369,7 @@ "item.create.empty_schematic.tooltip.summary": "レシピの材料、および_概略図テーブル_での書き込みに使用されます。", "item.create.schematic.tooltip": "概略図", - "item.create.schematic.tooltip.summary": "ワールドに設置できる構造物を保持します。 ホログラムを必要に応じて配置し、_概略図砲_を使用して建築します。", + "item.create.schematic.tooltip.summary": "ワールドに設置できる構造物を保持します。ホログラムを必要に応じて配置し、_概略図砲_を使用して建築します。", "item.create.schematic.tooltip.condition1": "持ったとき", "item.create.schematic.tooltip.behaviour1": "画面上のツールを使用して配置できます。", "item.create.schematic.tooltip.control1": "スニークしながら右クリックしたとき", @@ -1373,11 +1380,11 @@ "item.create.schematic_and_quill.tooltip.condition1": "ステップ1", "item.create.schematic_and_quill.tooltip.behaviour1": "右クリックして2つのコーナーポイントを選択します。", "item.create.schematic_and_quill.tooltip.condition2": "ステップ2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrlキーを押しながらスクロール_して、サイズを調整します。 もう一度右クリックして保存します。", + "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrlキーを押しながらスクロール_して、サイズを調整します。もう一度右クリックして保存します。", "item.create.schematic_and_quill.tooltip.control1": "右クリックしたとき", "item.create.schematic_and_quill.tooltip.action1": "コーナーポイントを選択/保存を確認します。", "item.create.schematic_and_quill.tooltip.control2": "Ctrlを長押してるとき", - "item.create.schematic_and_quill.tooltip.action2": "_空中_でポイントを選択します。 _スクロール_して距離を調整します。", + "item.create.schematic_and_quill.tooltip.action2": "_空中_でポイントを選択します。_スクロール_して距離を調整します。", "item.create.schematic_and_quill.tooltip.control3": "スニークしながら右クリックしたとき", "item.create.schematic_and_quill.tooltip.action3": "選択を_リセット_して削除します。", @@ -1397,11 +1404,11 @@ "block.create.cogwheel.tooltip": "歯車", "block.create.cogwheel.tooltip.summary": "_回転_を直線で、または隣接する_歯車_に_伝達_します。", - "block.create.large_cogwheel.tooltip": "大型歯車", + "block.create.large_cogwheel.tooltip": "大きな歯車", "block.create.large_cogwheel.tooltip.summary": "小さな歯車に接続したときに_回転速度_を_変更_できる歯車の大型バージョン。", "block.create.encased_shaft.tooltip": "ケース入りシャフト", - "block.create.encased_shaft.tooltip.summary": "_回転_を直線で_伝達_します。 壁を通過する回転の伝達に適しています。", + "block.create.encased_shaft.tooltip.summary": "_回転_を直線で_伝達_します。壁を通過する回転の伝達に適しています。", "block.create.gearbox.tooltip": "ギアボックス", "block.create.gearbox.tooltip.summary": "接続された_4方向_の_回転_方向を逆にして_伝達_します。", @@ -1427,9 +1434,9 @@ "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "レッドストーン信号を受けて_いない_ときは、隣接するチェーンドライブと_同じ速度_で回転を伝達します。_レッドストーン信号強度が最大_のときは隣接するチェーンドライブは_その2倍_の速度で伝達します。その間にあるものは1-2倍の速度で伝達されます。", "item.create.belt_connector.tooltip": "メカニカルベルト", - "item.create.belt_connector.tooltip.summary": "2本以上の_シャフト_を_メカニカルベルト_で接続します。接続されたシャフトは全く同じ速度と方向で回転します。 メカニカルベルトは_アイテム_と_エンティティ_を_運搬_するベルトコンベアとして使えます。", + "item.create.belt_connector.tooltip.summary": "2本以上の_シャフト_を_メカニカルベルト_で接続します。接続されたシャフトは全く同じ速度と方向で回転します。メカニカルベルトは_アイテム_と_エンティティ_を_運搬_するベルトコンベアとして使えます。", "item.create.belt_connector.tooltip.control1": "シャフトを右クリックしたとき", - "item.create.belt_connector.tooltip.action1": "ベルトの片端のシャフトを選択します。 選択する2つのシャフトは_ベルトの方向_に向かって_縦_、_横_、または_斜め_に_並べる_必要があります。", + "item.create.belt_connector.tooltip.action1": "ベルトの片端のシャフトを選択します。選択する2つのシャフトは_ベルトの方向_に向かって_縦_、_横_、または_斜め_に_並べる_必要があります。", "item.create.belt_connector.tooltip.control2": "スニークしながら右クリックしたとき", "item.create.belt_connector.tooltip.action2": "ベルトの最初に選択した位置を_リセット_します。", @@ -1441,7 +1448,7 @@ "item.create.goggles.tooltip.behaviour2": "計器が接続されているネットワークの_速度_または_応力_に関する詳細情報を表示します。", "item.create.wrench.tooltip": "レンチ", - "item.create.wrench.tooltip.summary": "動的からくりに取り組むための便利なツール。 コンポーネントの_回転_、_解体_、_設定_に使用できます。", + "item.create.wrench.tooltip.summary": "動的からくりに取り組むための便利なツール。コンポーネントの_回転_、_解体_、_設定_に使用できます。", "item.create.wrench.tooltip.control1": "機械を右クリックしたとき", "item.create.wrench.tooltip.action1": "操作した面に向かって、または面から離れるように機械を_回転_させます。", "item.create.wrench.tooltip.control2": "スニークしながら右クリックしたとき", @@ -1456,7 +1463,7 @@ "block.create.encased_fan.tooltip": "ケース入りファン", "block.create.encased_fan.tooltip.summary": "_回転力_を_気流_に変換し往復させます。色んな使い方があります。", "block.create.encased_fan.tooltip.condition1": "レッドストーン信号を受けたとき", - "block.create.encased_fan.tooltip.behaviour1": "真下の_熱源_から_回転力_を供給します。 ファンは下向きにする必要があります。", + "block.create.encased_fan.tooltip.behaviour1": "真下の_熱源_から_回転力_を供給します。ファンは下向きにする必要があります。", "block.create.encased_fan.tooltip.condition2": "回転したとき", "block.create.encased_fan.tooltip.behaviour2": "回転速度に応じてエンティティを_押し_たり、_吸い戻し_たりします。", "block.create.encased_fan.tooltip.condition3": "特別なブロックを吹き抜けるとき", @@ -1468,18 +1475,18 @@ "block.create.hand_crank.tooltip": "ハンドクランク", "block.create.hand_crank.tooltip.summary": "プレイヤーの相互作用を必要とする_シンプル_な_原動機_。", "block.create.hand_crank.tooltip.condition1": "使っているとき", - "block.create.hand_crank.tooltip.behaviour1": "接続したに_回転力_を供給します。 _スニークで回転を逆_にできます。", + "block.create.hand_crank.tooltip.behaviour1": "接続したに_回転力_を供給します。_スニークで回転を逆_にできます。", "block.create.cuckoo_clock.tooltip": "鳩時計", "block.create.cuckoo_clock.tooltip.summary": "空間を_彩り_、_時間を刻む_素晴らしい細工。", "block.create.cuckoo_clock.tooltip.condition1": "回転したとき", - "block.create.cuckoo_clock.tooltip.behaviour1": "_現在の時刻_を表示し、1日に2回曲を再生します。 、_正午_と夕暮れにプレイヤーが_眠れるようになるとすぐ_に_アクティブ_になります。", + "block.create.cuckoo_clock.tooltip.behaviour1": "_現在の時刻_を表示し、1日に2回曲を再生します。、_正午_と夕暮れにプレイヤーが_眠れるようになるとすぐ_に_アクティブ_になります。", "block.create.turntable.tooltip": "ターンテーブル", "block.create.turntable.tooltip.summary": "_回転力_を洗練された乗り物酔いに変えます。", "block.create.millstone.tooltip": "石臼", - "block.create.millstone.tooltip.summary": "搬入された_材料_の_研削_に適した機械。 隣接する歯車によって、または下部のシャフトに接続することによって、回転力を供給できます。 完成品は機械から搬出する必要があります。", + "block.create.millstone.tooltip.summary": "搬入された_材料_の_研削_に適した機械。隣接する歯車によって、または下部のシャフトに接続することによって、回転力を供給できます。完成品は機械から搬出する必要があります。", "block.create.millstone.tooltip.condition1": "回転したとき", "block.create.millstone.tooltip.behaviour1": "ブロックの側面または上面から搬入されたアイテムを_粉砕_を開始します。", "block.create.millstone.tooltip.condition2": "右クリックしたとき", @@ -1488,10 +1495,10 @@ "block.create.crushing_wheel.tooltip": "破砕ホイール", "block.create.crushing_wheel.tooltip.summary": "何かを_破砕_する大きな回転させられるホイール。", "block.create.crushing_wheel.tooltip.condition1": "他の破砕ホイールに取り付けたとき", - "block.create.crushing_wheel.tooltip.behaviour1": "様々な物を処理する破砕機を形成します。 ホイールの歯は、_同じ速度_で_反対方向_に回る必要があります。", + "block.create.crushing_wheel.tooltip.behaviour1": "様々な物を処理する破砕機を形成します。ホイールの歯は、_同じ速度_で_反対方向_に回る必要があります。", "block.create.mechanical_press.tooltip": "メカニカルプレス", - "block.create.mechanical_press.tooltip.summary": "その下のアイテムを圧縮する強力なピストン。 一定の_回転力_が必要です。", + "block.create.mechanical_press.tooltip.summary": "その下のアイテムを圧縮する強力なピストン。一定の_回転力_が必要です。", "block.create.mechanical_press.tooltip.condition1": "レッドストーン信号を受けたとき", "block.create.mechanical_press.tooltip.behaviour1": "その下にドロップされたアイテムの圧縮を_開始_します。", "block.create.mechanical_press.tooltip.condition2": "メカニカルベルトの上にあるとき", @@ -1526,9 +1533,9 @@ "block.create.mechanical_crafter.tooltip.condition2": "レッドストーンパルスがオンの時", "block.create.mechanical_crafter.tooltip.behaviour2": "現在与えられているすべての_アイテム_を使って、_強制的_に_クラフト_を開始します。", "block.create.mechanical_crafter.tooltip.control1": "正面をレンチで使ったとき", - "block.create.mechanical_crafter.tooltip.action1": "_個々のクラフターが_アイテムを移動_させる_方向_を循環させます。 クラフトグリッドを形成するには、すべてのアイテムを最後のクラフターに向かって_移動させる流れ_を作るように_ベルト_を設置する必要があります。最後のクラフターはグリッドから_離れる_方向を指す必要があります。", + "block.create.mechanical_crafter.tooltip.action1": "_個々のクラフターが_アイテムを移動_させる_方向_を循環させます。クラフトグリッドを形成するには、すべてのアイテムを最後のクラフターに向かって_移動させる流れ_を作るように_ベルト_を設置する必要があります。最後のクラフターはグリッドから_離れる_方向を指す必要があります。", "block.create.mechanical_crafter.tooltip.control2": "背面をレンチで使ったとき", - "block.create.mechanical_crafter.tooltip.action2": "隣接するクラフターの_搬入インベントリ_を_接続_します。 これを使用してクラフトグリッドの_スロットを_結合_し、_搬入作業_を_簡略化_できます。", + "block.create.mechanical_crafter.tooltip.action2": "隣接するクラフターの_搬入インベントリ_を_接続_します。これを使用してクラフトグリッドの_スロットを_結合_し、_搬入作業_を_簡略化_できます。", "block.create.furnace_engine.tooltip": "かまどエンジン", "block.create.furnace_engine.tooltip.summary": "_稼動しているかまど_で動く強力な_原動機_。", @@ -1555,14 +1562,14 @@ "block.create.portable_fluid_interface.tooltip.behaviour2": "アクティブな接続を即座に_切断_します。", "block.create.rotation_speed_controller.tooltip": "回転速度コントローラー", - "block.create.rotation_speed_controller.tooltip.summary": "回転を任意の速度にスピードアップまたはスローダウンさせることができる_設定_可能な_伝達機_。", + "block.create.rotation_speed_controller.tooltip.summary": "回転を任意の速度に上げたり下げたりさせることができる_設定_可能な_伝達機_。", "block.create.rotation_speed_controller.tooltip.condition1": "大きな歯車を取り付けたとき", "block.create.rotation_speed_controller.tooltip.behaviour1": "入ってくる回転力を歯車に伝達して、目標とする_速度_に_合わせ_ようとします。_歯車_はコントローラの_上_に_取り付ける_必要があります。", "block.create.mechanical_piston.tooltip": "メカニカルピストン", "block.create.mechanical_piston.tooltip.summary": "ピストンのさらに進化したバージョン。回転力を利用して前にある構造物を正確に移動させます。後部にあるピストン延長ポールは、このの稼働範囲を決めます。延長ポールがないと、ピストンは動きません。_シャーシ_や_スライムボール_、_接着剤_を使用して、1列以上のブロックを移動させることができます。", "block.create.mechanical_piston.tooltip.condition1": "回転したとき", - "block.create.mechanical_piston.tooltip.behaviour1": "取り付けられた構造物の移動を開始します。 速度と方向は、入力される回転速度と相関します。", + "block.create.mechanical_piston.tooltip.behaviour1": "取り付けられた構造物の移動を開始します。速度と方向は、入力される回転速度と相関します。", "block.create.piston_extension_pole.tooltip": "ピストン延長ポール", "block.create.piston_extension_pole.tooltip.summary": "メカニカルピストンの範囲を拡張します。", @@ -1590,7 +1597,7 @@ "block.create.clockwork_bearing.tooltip": "時計仕掛けのベアリング", "block.create.clockwork_bearing.tooltip.summary": "現在の_ゲーム内時間_に応じて最大2つの_時計の針_を回転させる、_メカニカルベアリング_の進化版。", "block.create.clockwork_bearing.tooltip.condition1": "回転したとき", - "block.create.clockwork_bearing.tooltip.behaviour1": "現在の時間に向かって取り付けた構造物の回転を開始します。 2番目の構造物が存在する場合、それは分針として機能します。", + "block.create.clockwork_bearing.tooltip.behaviour1": "現在の時間に向かって取り付けた構造物の回転を開始します。2番目の構造物が存在する場合、それは分針として機能します。", "block.create.sequenced_gearshift.tooltip": "シーケンスギアシフト", "block.create.sequenced_gearshift.tooltip.summary": "_プログラミング_できる_便利_な伝達機械。最大_5つ_の_連続_した_命令_に従って_回転処理_を変更することができます。高速になると精度が悪くなる可能性があります。", @@ -1617,7 +1624,7 @@ "block.create.rope_pulley.tooltip": "ローププーリー", "block.create.rope_pulley.tooltip.summary": "_取り付けられたブロック_や_構造物_を_垂直_方向に移動させます。_シャーシ_、_スライムボール_、_接着剤_を使用して、1つ以上のブロックを移動させることもできます。", "block.create.rope_pulley.tooltip.condition1": "回転したとき", - "block.create.rope_pulley.tooltip.behaviour1": "取り付けた構造物の移動を開始します。 速度と方向は、回転速度に相関します。", + "block.create.rope_pulley.tooltip.behaviour1": "取り付けた構造物の移動を開始します。速度と方向は、回転速度に相関します。", "block.create.linear_chassis.tooltip": "線形シャーシ", "block.create.linear_chassis.tooltip.summary": "移動用の構造物を接続する設定可能な土台ブロック。", @@ -1636,19 +1643,19 @@ "block.create.radial_chassis.tooltip.condition1": "動かしたとき", "block.create.radial_chassis.tooltip.behaviour1": "柱状に_接続_したすべての_シャーシ_と、周囲のブロックを_移動_させます。周囲のブロックは、範囲内にあり、かつ粘着面に面している場合にのみ_引っ張られ_ます([Ctrl]を参照)。", "block.create.radial_chassis.tooltip.condition2": "レンチを持ったとき", - "block.create.radial_chassis.tooltip.behaviour2": "このシャーシブロックの有効_範囲_を設定します。 Ctrlキーを押したままにすると、接続されているすべてのシャーシブロックの範囲も同時に変更できます。", + "block.create.radial_chassis.tooltip.behaviour2": "このシャーシブロックの有効_範囲_を設定します。Ctrlキーを押したままにすると、接続されているすべてのシャーシブロックの範囲も同時に変更できます。", "block.create.radial_chassis.tooltip.control1": "スライムボールで右クリックしたとき", - "block.create.radial_chassis.tooltip.action1": "クリックした面を_粘着面_にします。 シャーシが移動すると、粘着面に接続されているすべての指定のブロックも一緒に移動します。", + "block.create.radial_chassis.tooltip.action1": "クリックした面を_粘着面_にします。シャーシが移動すると、粘着面に接続されているすべての指定のブロックも一緒に移動します。", "block.create.mechanical_drill.tooltip": "メカニカルドリル", - "block.create.mechanical_drill.tooltip.summary": "_ブロックを壊す_のに適した作業機。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.mechanical_drill.tooltip.summary": "_ブロックを壊す_のに適した作業機。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.mechanical_drill.tooltip.condition1": "回転したとき", - "block.create.mechanical_drill.tooltip.behaviour1": "_固定式_のブロック破壊機として機能します。 また、有効範囲の_エンティティを傷つけます_。", + "block.create.mechanical_drill.tooltip.behaviour1": "_固定式_のブロック破壊機として機能します。また、有効範囲の_エンティティを傷つけます_。", "block.create.mechanical_drill.tooltip.condition2": "動かしたとき", "block.create.mechanical_drill.tooltip.behaviour2": "ドリルが衝突するブロックを壊します。", "block.create.mechanical_harvester.tooltip": "メカニカルハーベスター", - "block.create.mechanical_harvester.tooltip.summary": "中規模の作物の自動化に適した機械式植物カッター。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.mechanical_harvester.tooltip.summary": "中規模の作物の自動化に適した機械式植物カッター。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.mechanical_harvester.tooltip.condition1": "動かしたとき", "block.create.mechanical_harvester.tooltip.behaviour1": "ブレードが衝突する_すべての成熟した作物を収穫_し、それらを初期の成長状態にリセットします。", @@ -1658,9 +1665,9 @@ "block.create.mechanical_plough.tooltip.behaviour1": "松明や雪など、当たり判定がないブロックを壊します。エンティティを傷付けることはありません。また、クワを使うように土を耕します。", "block.create.mechanical_saw.tooltip": "メカニカルノコギリ", - "block.create.mechanical_saw.tooltip.summary": "_木_を効率的に_切り倒したり_、_ブロック_を_加工_したりするのに適しています。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.mechanical_saw.tooltip.summary": "_木_を効率的に_切り倒したり_、_ブロック_を_加工_したりするのに適しています。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.mechanical_saw.tooltip.condition1": "上向きのとき", - "block.create.mechanical_saw.tooltip.behaviour1": "そこにドロップまたは搬入されたアイテムに_製材_および石工レシピを適用します。 複数の出力が可能な場合、フィルターが割り当てられていない限り、出力が循環します。", + "block.create.mechanical_saw.tooltip.behaviour1": "そこにドロップまたは搬入されたアイテムに_製材_および石工レシピを適用します。複数の出力が可能な場合、フィルターが割り当てられていない限り、出力が循環します。", "block.create.mechanical_saw.tooltip.condition2": "横向きの場合", "block.create.mechanical_saw.tooltip.behaviour2": "その前の_原木_を_切り倒す_。その原木が木を支えていた場合、_木_は_崩壊_します。", "block.create.mechanical_saw.tooltip.condition3": "動かしたとき", @@ -1675,30 +1682,30 @@ "block.create.content_observer.tooltip.summary": "設定された_フィルター_に一致する_コンテナ_や_メカニカルベルト_内の_アイテム_を検出します。観察している_インベントリ_、_ベルト_、または_シュート_に一致するアイテムが含まれている場合、このは_レッドストーン信号_を発します。観察された_ファンネル_が一致するアイテムを_輸送_すると、このコンポーネントは_レッドストーンパルス_を発します。", "block.create.redstone_link.tooltip": "レッドストーンリンク", - "block.create.redstone_link.tooltip.summary": "_ワイヤレスレッドストーン_接続の終点。 任意のアイテムを使用して_周波数_を割り当てることができます。 通信距離は限られていますが、かなり離れても通信することができます。", + "block.create.redstone_link.tooltip.summary": "_ワイヤレスレッドストーン_接続の終点。任意のアイテムを使用して_周波数_を割り当てることができます。通信距離は限られていますが、かなり離れても通信することができます。", "block.create.redstone_link.tooltip.condition1": "信号を受信したとき", "block.create.redstone_link.tooltip.behaviour1": "同じ周波数のリンクから信号を受信すると、レッドストーン信号を出力します。", "block.create.redstone_link.tooltip.control1": "アイテムで右クリックしたとき", - "block.create.redstone_link.tooltip.action1": "_周波数_をそのアイテムに設定します。 周波数を定義するために、_合計2つの異なるアイテム_を組み合わせて使えます。", + "block.create.redstone_link.tooltip.action1": "_周波数_をそのアイテムに設定します。周波数を定義するために、_合計2つの異なるアイテム_を組み合わせて使えます。", "block.create.redstone_link.tooltip.control2": "スニークしながら右クリックしたとき", "block.create.redstone_link.tooltip.action2": "_受信_モードと_送信_モードを切り替えます。", "block.create.nixie_tube.tooltip": "ニキシー管", - "block.create.nixie_tube.tooltip.summary": "派手にレッドストーン強度と文字を表示します。", + "block.create.nixie_tube.tooltip.summary": "オシャレにレッドストーン強度と文字を表示します。", "block.create.nixie_tube.tooltip.condition1": "レッドストーン信号を受けたとき", "block.create.nixie_tube.tooltip.behaviour1": "現在のレッドストーンの_信号強度_を表示します。", "block.create.nixie_tube.tooltip.condition2": "名札を使ったとき", "block.create.nixie_tube.tooltip.behaviour2": "_名札_の_内容_を複数のニキシー管を並べて表示します。", "block.create.redstone_contact.tooltip": "レッドストーンコンタクト", - "block.create.redstone_contact.tooltip.summary": "レッドストーン信号をペアで出力します。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.redstone_contact.tooltip.summary": "レッドストーン信号をペアで出力します。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.redstone_contact.tooltip.condition1": "他のコンタクトと向かい合ったとき", "block.create.redstone_contact.tooltip.behaviour1": "レッドストーン信号を出力します。", "block.create.redstone_contact.tooltip.condition2": "動かしたとき", "block.create.redstone_contact.tooltip.behaviour2": "通過するすべての固定したレッドストーンコンタクトに反応します。", "block.create.adjustable_crate.tooltip": "可変クレート", - "block.create.adjustable_crate.tooltip.summary": "この_収納ブロック_は、容量を手動で制御できます。任意のアイテムを_16スタック_まで収納できます。 _レッドストーンコンパレーター_に対応しています。", + "block.create.adjustable_crate.tooltip.summary": "この_収納ブロック_は、容量を手動で制御できます。任意のアイテムを_16スタック_まで収納できます。_レッドストーンコンパレーター_に対応しています。", "block.create.adjustable_crate.tooltip.control1": "右クリックしたとき", "block.create.adjustable_crate.tooltip.action1": "_インターフェース_を開きます。", @@ -1708,7 +1715,7 @@ "block.create.creative_crate.tooltip.behaviour1": "このクレートから何かを_搬出_すると、指定されたアイテムが_無限_に_搬出_されます。このクレートに_搬入_されたアイテムは_消滅_します。", "block.create.deployer.tooltip": "デプロイヤー", - "block.create.deployer.tooltip.summary": "_殴る_、_使う_、_起動する_。この機械は、_プレイヤー_をできるだけ_真似_しようとします。_アイテムを自分のインベントリに入れたり_、_預けたり_できます。 持っているアイテムはブロックから直接搬入・搬出する必要があります。", + "block.create.deployer.tooltip.summary": "_殴る_、_使う_、_起動する_。この機械は、_プレイヤー_をできるだけ_真似_しようとします。_アイテムを自分のインベントリに入れたり_、_預けたり_できます。持っているアイテムはブロックから直接搬入・搬出する必要があります。", "block.create.deployer.tooltip.condition1": "回転したとき", "block.create.deployer.tooltip.behaviour1": "腕を機械の2m先まで伸ばし、アイテムを_発動_する。", "block.create.deployer.tooltip.condition2": "レンチで右クリックしたとき", @@ -1717,7 +1724,7 @@ "block.create.deployer.tooltip.behaviour3": "合わないアイテムは搬入できません。逆に合うアイテムは搬出できません。", "block.create.brass_casing.tooltip": "真ちゅうのケーシング", - "block.create.brass_casing.tooltip.summary": "さまざまな用途に使用できる頑丈な機械ケーシング。 装飾にも安心してお使いいただけます。", + "block.create.brass_casing.tooltip.summary": "さまざまな用途に使用できる頑丈な機械ケーシング。装飾にも安心してお使いいただけます。", "block.create.pulse_repeater.tooltip": "パルスリピーター", "block.create.pulse_repeater.tooltip.summary": "通過するレッドストーン信号を_1ティック_の長さにカットする簡単な回路。", @@ -1735,22 +1742,22 @@ "block.create.powered_toggle_latch.tooltip.summary": "レッドストーンパルスによって切替できるレバー。", "block.create.powered_latch.tooltip": "パワードラッチ", - "block.create.powered_latch.tooltip.summary": "_レッドストーン信号_で制御できるレバー。 _背面のレッドストーン信号_でオンになり、_側面からのレッドストーン信号_でリセットされます。", + "block.create.powered_latch.tooltip.summary": "_レッドストーン信号_で制御できるレバー。_背面のレッドストーン信号_でオンになり、_側面からのレッドストーン信号_でリセットされます。", "block.create.controller_rail.tooltip": "コントローラーレール", "block.create.controller_rail.tooltip.summary": "トロッコの_移動速度_を_細かく制御_できる一方通行の_パワード_レール", "block.create.controller_rail.tooltip.condition1": "レッドストーン信号を受けたとき", "block.create.controller_rail.tooltip.behaviour1": "通過する_トロッコ_を_信号の強度_に対応した速度に_加速_または_減速_します。また、隣接するコントローラレールにレッドストーン信号を伝達します。強度の異なる2つのコントローラレールにレッドストーン信号を供給すると、それらの間のレールはその信号の変化を補間します。", - "block.create.speedometer.tooltip": "スピードメーター", - "block.create.speedometer.tooltip.summary": "接続された機械の_回転速度_を測定して表示します。 _レッドストーンコンパレーター_に対応しています。", + "block.create.speedometer.tooltip": "速度メーター", + "block.create.speedometer.tooltip.summary": "接続された機械の_回転速度_を測定して表示します。_レッドストーンコンパレーター_に対応しています。", "block.create.speedometer.tooltip.condition1": "回転したとき", - "block.create.speedometer.tooltip.behaviour1": "速度レベルに対応する色を表示します。 _緑_は低速、_青_は中速、_紫_は高速を示します。 一部の機械は、稼働に十分なレベルの速度を必要とします。", + "block.create.speedometer.tooltip.behaviour1": "速度レベルに対応する色を表示します。_緑_は低速、_青_は中速、_紫_は高速を示します。一部の機械は、稼働に十分なレベルの速度を必要とします。", - "block.create.stressometer.tooltip": "ストレスメーター", - "block.create.stressometer.tooltip.summary": "接続された動力ネットワーク全体の応力を測定して表示します。 _レッドストーンコンパレーター_に対応しています。", + "block.create.stressometer.tooltip": "速度メーター", + "block.create.stressometer.tooltip.summary": "接続された動力ネットワーク全体の応力を測定して表示します。_レッドストーンコンパレーター_に対応しています。", "block.create.stressometer.tooltip.condition1": "回転したとき", - "block.create.stressometer.tooltip.behaviour1": "応力レベルに対応する色を表示します。 _過度に応力がかかった(超過応力)ネットワーク_の機械は全て停止します。応力は動力ネットワークに_原動機_を追加することで緩和することができます。", + "block.create.stressometer.tooltip.behaviour1": "応力レベルに対応する色を表示します。_過度に応力がかかった(超過応力)ネットワーク_の機械は全て停止します。応力は動力ネットワークに_原動機_を追加することで緩和することができます。", "item.create.sand_paper.tooltip": "紙やすり", "item.create.sand_paper.tooltip.summary": "_素材_を_磨く_のに使える荒い紙。デプロイヤーに自動的で磨かせることもできます。", @@ -1768,7 +1775,7 @@ "item.create.builders_tea.tooltip.summary": "_やる気_がみなぎる、一日の始まりに最適な飲み物。", "item.create.refined_radiance.tooltip": "洗練された輝き", - "item.create.refined_radiance.tooltip.summary": "_吸収した光_から鍛造した色彩素材。", + "item.create.refined_radiance.tooltip.summary": "_吸収した輝き_から鍛造した色彩素材。", "item.create.shadow_steel.tooltip": "シャドウスチール", "item.create.shadow_steel.tooltip.summary": "_奈落の虚無_から鍛造した色彩素材。", @@ -1779,7 +1786,7 @@ "item.create.minecart_coupling.tooltip.behaviour1": "2台のトロッコを連結します。それらは移動中に一定の距離を保とうします。", "item.create.crafter_slot_cover.tooltip": "スロットカバー", - "item.create.crafter_slot_cover.tooltip.summary": "取り付けた_メカニカルクラフター_をレシピの空のスロットとして示します。 クラフターは必ずしも正方形である必要はありません。 これは、_同じアイテムが離れた場所にある_レシピに便利です。", + "item.create.crafter_slot_cover.tooltip.summary": "取り付けた_メカニカルクラフター_をレシピの空のスロットとして示します。クラフターは必ずしも正方形である必要はありません。これは、_同じアイテムが離れた場所にある_レシピに便利です。", "create.tooltip.wip": "WIP", "create.tooltip.workInProgress": "作業中です!", @@ -1787,10 +1794,10 @@ "create.tooltip.randomWipDescription1": "赤ちゃんパンダは、このアイテムを使用するたびに死にます。そう、いつでもね。", "create.tooltip.randomWipDescription2": "自己責任。", "create.tooltip.randomWipDescription3": "これはあなたが探しているアイテムではありません。*人差し指を振って*ちっちっちっ、解散!", - "create.tooltip.randomWipDescription4": "このアイテムは10秒で自爆します。 10、9、8 ...", + "create.tooltip.randomWipDescription4": "このアイテムは10秒で自爆します。10、9、8 ...", "create.tooltip.randomWipDescription5": "私を信じて、それは無駄だ。", "create.tooltip.randomWipDescription6": "このアイテムを使用することにより、お客様はここに免責事項に同意し、その条件に同意するものとします。", - "create.tooltip.randomWipDescription7": "これは君に向いていないかもしれない。 あれはどう??", + "create.tooltip.randomWipDescription7": "これは君に向いていないかもしれない。あれはどう??", "create.tooltip.randomWipDescription8": "それを使ったことをすぐ後悔する。", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 33c304adf..cc4731bfb 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,5 @@ { - "_": "Missing Localizations: 84", + "_": "Missing Localizations: 95", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "기계 조합", "create.recipe.automatic_shaped": "유형 자동 조합", "create.recipe.block_cutting": "블 절단", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "휴대용 블록발사기 업그레이드", "create.recipe.sandpaper_polishing": "사포질", "create.recipe.mystery_conversion": "?", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "최소 신호 유지 비율:%1$s%%", "create.gui.sequenced_gearshift.title": "순서 기어쉬프트", "create.gui.sequenced_gearshift.instruction": "설명", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "회전", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "각도", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "피스톤", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "거리", - "create.gui.sequenced_gearshift.instruction.wait": "정지", - "create.gui.sequenced_gearshift.instruction.wait.duration": "지속시간", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "마침", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "속도, 방향", "create.gui.sequenced_gearshift.speed.forward": "입력된 속도, 그대로 회전", "create.gui.sequenced_gearshift.speed.forward_fast": "입력된 속도의 2배, 그대로 회전", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 f09b09a1d..3afae9153 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,5 @@ { - "_": "Missing Localizations: 1184", + "_": "Missing Localizations: 1193", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting", "create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting", "create.recipe.block_cutting": "Blok Zagen", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "Blokzapper", "create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing", "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "UNLOCALIZED: Move to upper lane at %1$s%%", "create.gui.sequenced_gearshift.title": "UNLOCALIZED: Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "UNLOCALIZED: Instruction", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "UNLOCALIZED: Turn", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "UNLOCALIZED: Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "UNLOCALIZED: Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "UNLOCALIZED: Distance", - "create.gui.sequenced_gearshift.instruction.wait": "UNLOCALIZED: Wait", - "create.gui.sequenced_gearshift.instruction.wait.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "UNLOCALIZED: End", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "UNLOCALIZED: Speed, Direction", "create.gui.sequenced_gearshift.speed.forward": "UNLOCALIZED: Input speed, Forwards", "create.gui.sequenced_gearshift.speed.forward_fast": "UNLOCALIZED: Double speed, Forwards", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 5e937709f..9ba011116 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,5 @@ { - "_": "Missing Localizations: 1250", + "_": "Missing Localizations: 1259", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "UNLOCALIZED: Mechanical Crafting", "create.recipe.automatic_shaped": "UNLOCALIZED: Automated Shaped Crafting", "create.recipe.block_cutting": "UNLOCALIZED: Block Cutting", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "Blockzapper Portátil", "create.recipe.sandpaper_polishing": "UNLOCALIZED: Sandpaper Polishing", "create.recipe.mystery_conversion": "UNLOCALIZED: Mysterious Conversion", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "UNLOCALIZED: Move to upper lane at %1$s%%", "create.gui.sequenced_gearshift.title": "UNLOCALIZED: Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "UNLOCALIZED: Instruction", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "UNLOCALIZED: Turn", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "UNLOCALIZED: Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "UNLOCALIZED: Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "UNLOCALIZED: Distance", - "create.gui.sequenced_gearshift.instruction.wait": "UNLOCALIZED: Wait", - "create.gui.sequenced_gearshift.instruction.wait.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "UNLOCALIZED: End", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "UNLOCALIZED: Speed, Direction", "create.gui.sequenced_gearshift.speed.forward": "UNLOCALIZED: Input speed, Forwards", "create.gui.sequenced_gearshift.speed.forward_fast": "UNLOCALIZED: Double speed, Forwards", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 82bb3ce9f..3c7745036 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: 34", + "_": "Missing Localizations: 45", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "Механическое создание", "create.recipe.automatic_shaped": "Автоматическая форменная сборка", "create.recipe.block_cutting": "Резка блока", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "Ручная блоковая пушка", "create.recipe.sandpaper_polishing": "Полировка наждачной бумагой", "create.recipe.mystery_conversion": "Хроматический метаморфоз", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "Двигаться к верхней линии при %1$s%%", "create.gui.sequenced_gearshift.title": "Последовательное переключение передач", "create.gui.sequenced_gearshift.instruction": "Инструкция", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "Повернуть", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Угол", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "Поршень", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Расстояние", - "create.gui.sequenced_gearshift.instruction.wait": "Перерыв", - "create.gui.sequenced_gearshift.instruction.wait.duration": "Продолжительность", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "Конец", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "Скорость, Направление", "create.gui.sequenced_gearshift.speed.forward": "Скорость ввода, вперед", "create.gui.sequenced_gearshift.speed.forward_fast": "Двойная скорость, вперед", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 3ea36f056..73a434dea 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: 32", + "_": "Missing Localizations: 43", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "自动合成", "create.recipe.automatic_shaped": "自动合成", "create.recipe.block_cutting": "方块切割", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "手持式方块放置器", "create.recipe.sandpaper_polishing": "砂纸打磨", "create.recipe.mystery_conversion": "神秘转化", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "移至上线%1$s%%", "create.gui.sequenced_gearshift.title": "可编程齿轮箱", "create.gui.sequenced_gearshift.instruction": "指令", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "旋转", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "角度", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "驱动活塞", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "距离", - "create.gui.sequenced_gearshift.instruction.wait": "等待", - "create.gui.sequenced_gearshift.instruction.wait.duration": "间隔", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "停止", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "速度,速度方向", "create.gui.sequenced_gearshift.speed.forward": "一倍速,正向", "create.gui.sequenced_gearshift.speed.forward_fast": "两倍速,正向", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" 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 03543e9a6..b5d3185c0 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: 37", + "_": "Missing Localizations: 48", "_": "->------------------------] Game Elements [------------------------<-", @@ -685,6 +685,7 @@ "create.recipe.mechanical_crafting": "自動合成", "create.recipe.automatic_shaped": "自動合成", "create.recipe.block_cutting": "方塊切割", + "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", "create.recipe.blockzapper_upgrade": "方塊放置器", "create.recipe.sandpaper_polishing": "砂紙打磨", "create.recipe.mystery_conversion": "神秘轉化", @@ -845,13 +846,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "移至上線%1$s%%", "create.gui.sequenced_gearshift.title": "可程式化齒輪箱", "create.gui.sequenced_gearshift.instruction": "指令", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "旋轉", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "角度", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "驅動活塞", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "距離", - "create.gui.sequenced_gearshift.instruction.wait": "等待", - "create.gui.sequenced_gearshift.instruction.wait.duration": "間隔", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", "create.gui.sequenced_gearshift.instruction.end": "停止", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", "create.gui.sequenced_gearshift.speed": "速度,速度方向", "create.gui.sequenced_gearshift.speed.forward": "一倍速,正向", "create.gui.sequenced_gearshift.speed.forward_fast": "兩倍速,正向", @@ -1818,6 +1825,8 @@ "create.ponder.brass_hand.scene_4.incoming": "UNLOCALIZED: Incoming...", "create.ponder.brass_hand.scene_4.title": "UNLOCALIZED: Debug Scene 5: Emitting particles", "create.ponder.brass_hand.scene_5.title": "UNLOCALIZED: Debug Scene 6: Basic player interaction", + "create.ponder.brass_hand.scene_6.birbs_interesting": "UNLOCALIZED: More birbs = More interesting", + "create.ponder.brass_hand.scene_6.poi": "UNLOCALIZED: Point of Interest", "create.ponder.brass_hand.scene_6.title": "UNLOCALIZED: Debug Scene 7: Birbs", "_": "Thank you for translating Create!" diff --git a/src/generated/resources/data/create/advancements/aesthetics.json b/src/generated/resources/data/create/advancements/aesthetics.json index 722bd2ec7..d723cbe38 100644 --- a/src/generated/resources/data/create/advancements/aesthetics.json +++ b/src/generated/resources/data/create/advancements/aesthetics.json @@ -17,13 +17,29 @@ }, "criteria": { "0": { - "trigger": "create:bracket_shaft" + "trigger": "create:bracket_apply", + "conditions": { + "accepted_entries": [ + "create:shaft" + ] + } }, "1": { - "trigger": "create:bracket_cog" + "trigger": "create:bracket_apply", + "conditions": { + "accepted_entries": [ + "create:cogwheel", + "create:large_cogwheel" + ] + } }, "2": { - "trigger": "create:bracket_pipe" + "trigger": "create:bracket_apply", + "conditions": { + "accepted_entries": [ + "create:fluid_pipe" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/fan.json b/src/generated/resources/data/create/advancements/fan.json index fd00498a5..bafda450d 100644 --- a/src/generated/resources/data/create/advancements/fan.json +++ b/src/generated/resources/data/create/advancements/fan.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:fan" + "trigger": "create:fan_processing", + "conditions": { + "accepted_entries": [ + "NONE" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/fan_lava.json b/src/generated/resources/data/create/advancements/fan_lava.json index 1b15d56b6..6e6362c0a 100644 --- a/src/generated/resources/data/create/advancements/fan_lava.json +++ b/src/generated/resources/data/create/advancements/fan_lava.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:fan_lava" + "trigger": "create:fan_processing", + "conditions": { + "accepted_entries": [ + "BLASTING" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/fan_smoke.json b/src/generated/resources/data/create/advancements/fan_smoke.json index 51cd3cdc1..017a1b6f7 100644 --- a/src/generated/resources/data/create/advancements/fan_smoke.json +++ b/src/generated/resources/data/create/advancements/fan_smoke.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:fan_smoke" + "trigger": "create:fan_processing", + "conditions": { + "accepted_entries": [ + "SMOKING" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/fan_water.json b/src/generated/resources/data/create/advancements/fan_water.json index a70ae1092..3e7368f4b 100644 --- a/src/generated/resources/data/create/advancements/fan_water.json +++ b/src/generated/resources/data/create/advancements/fan_water.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:fan_water" + "trigger": "create:fan_processing", + "conditions": { + "accepted_entries": [ + "SPLASHING" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/infinite_chocolate.json b/src/generated/resources/data/create/advancements/infinite_chocolate.json index de6e78ad2..5715963c3 100644 --- a/src/generated/resources/data/create/advancements/infinite_chocolate.json +++ b/src/generated/resources/data/create/advancements/infinite_chocolate.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:infinite_chocolate" + "trigger": "create:infinite_fluid", + "conditions": { + "accepted_entries": [ + "create:chocolate" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/infinite_lava.json b/src/generated/resources/data/create/advancements/infinite_lava.json index 732fbfd39..5d634ef94 100644 --- a/src/generated/resources/data/create/advancements/infinite_lava.json +++ b/src/generated/resources/data/create/advancements/infinite_lava.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:infinite_lava" + "trigger": "create:infinite_fluid", + "conditions": { + "accepted_entries": [ + "minecraft:lava" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/infinite_water.json b/src/generated/resources/data/create/advancements/infinite_water.json index 1fc7be3c0..27b8c7a64 100644 --- a/src/generated/resources/data/create/advancements/infinite_water.json +++ b/src/generated/resources/data/create/advancements/infinite_water.json @@ -17,7 +17,12 @@ }, "criteria": { "0": { - "trigger": "create:infinite_water" + "trigger": "create:infinite_fluid", + "conditions": { + "accepted_entries": [ + "minecraft:water" + ] + } } }, "requirements": [ diff --git a/src/generated/resources/data/create/advancements/mixer.json b/src/generated/resources/data/create/advancements/mixer.json index 5988c6b10..b67d6b70d 100644 --- a/src/generated/resources/data/create/advancements/mixer.json +++ b/src/generated/resources/data/create/advancements/mixer.json @@ -23,12 +23,6 @@ } }, "1": { - "trigger": "create:kinetic_block", - "conditions": { - "block": "create:mechanical_mixer" - } - }, - "2": { "trigger": "create:mixer" } }, @@ -38,9 +32,6 @@ ], [ "1" - ], - [ - "2" ] ] } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index f0b558da7..52641d2a9 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -7,15 +7,21 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Supplier; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; +import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour.AttachmentTypes; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.contraptions.relays.belt.BeltData; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.model.IBakedModel; @@ -223,4 +229,30 @@ public class AllBlockPartials { return CreateClient.bufferCache.renderDirectionalPartial(this, referenceState, facing, ms); } + public InstancedModel renderOnRotating(InstancedTileRenderer ctx, BlockState referenceState) { + return ctx.getMaterial(KineticRenderMaterials.ROTATING).getModel(this, referenceState); + } + + public InstancedModel renderOnBelt(InstancedTileRenderer ctx, BlockState referenceState) { + return ctx.getMaterial(KineticRenderMaterials.BELTS).getModel(this, referenceState); + } + + public InstancedModel renderOnDirectionalSouthRotating(InstancedTileRenderer dispatcher, BlockState referenceState) { + Direction facing = referenceState.get(FACING); + return renderOnDirectionalSouthRotating(dispatcher, referenceState, facing); + } + + public InstancedModel renderOnDirectionalSouthRotating(InstancedTileRenderer dispatcher, BlockState referenceState, Direction facing) { + Supplier ms = () -> { + MatrixStack stack = new MatrixStack(); + MatrixStacker.of(stack) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .unCentre(); + return stack; + }; + return dispatcher.getMaterial(KineticRenderMaterials.ROTATING).getModel(this, referenceState, facing, ms); + } + } diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 3446861fb..1c89a813d 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -408,10 +408,10 @@ public class AllBlocks { REGISTRATE.block("crushing_wheel_controller", CrushingWheelControllerBlock::new) .initialProperties(() -> Blocks.AIR) .blockstate((c, p) -> p.getVariantBuilder(c.get()) - .forAllStates(state -> ConfiguredModel.builder() + .forAllStatesExcept(state -> ConfiguredModel.builder() .modelFile(p.models() .getExistingFile(p.mcLoc("block/air"))) - .build())) + .build(), CrushingWheelControllerBlock.FACING)) .register(); public static final BlockEntry MECHANICAL_PRESS = diff --git a/src/main/java/com/simibubi/create/AllColorHandlers.java b/src/main/java/com/simibubi/create/AllColorHandlers.java index f6c0fe245..9aa7ce8cc 100644 --- a/src/main/java/com/simibubi/create/AllColorHandlers.java +++ b/src/main/java/com/simibubi/create/AllColorHandlers.java @@ -1,7 +1,11 @@ package com.simibubi.create; +import java.util.HashMap; +import java.util.Map; + import com.simibubi.create.foundation.block.IBlockVertexColor; import com.simibubi.create.foundation.block.render.ColoredVertexModel; + import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.RedstoneWireBlock; @@ -18,9 +22,6 @@ import net.minecraft.world.GrassColors; import net.minecraft.world.ILightReader; import net.minecraft.world.biome.BiomeColors; -import java.util.HashMap; -import java.util.Map; - public class AllColorHandlers { private final Map coloredVertexBlocks = new HashMap<>(); diff --git a/src/main/java/com/simibubi/create/AllEntityTypes.java b/src/main/java/com/simibubi/create/AllEntityTypes.java index 061e0507d..d811fba0e 100644 --- a/src/main/java/com/simibubi/create/AllEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllEntityTypes.java @@ -2,12 +2,11 @@ package com.simibubi.create; import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRenderer; import com.simibubi.create.foundation.utility.Lang; @@ -62,11 +61,11 @@ public class AllEntityTypes { @OnlyIn(value = Dist.CLIENT) public static void registerRenderers() { RenderingRegistry.registerEntityRenderingHandler(CONTROLLED_CONTRAPTION.get(), - ControlledContraptionEntityRenderer::new); + ContraptionEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler(ORIENTED_CONTRAPTION.get(), OrientedContraptionEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler(GANTRY_CONTRAPTION.get(), - GantryContraptionEntityRenderer::new); + ContraptionEntityRenderer::new); RenderingRegistry.registerEntityRenderingHandler(SUPER_GLUE.get(), SuperGlueRenderer::new); RenderingRegistry.registerEntityRenderingHandler(SEAT.get(), SeatEntity.Render::new); } diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 85d8cd1f9..292e50d91 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -284,6 +284,7 @@ public class AllItems { .register(); } + @SuppressWarnings("unused") private static ItemEntry hiddenIngredient(String name) { return REGISTRATE.item(name, HiddenIngredientItem::new) .register(); diff --git a/src/main/java/com/simibubi/create/AllShapes.java b/src/main/java/com/simibubi/create/AllShapes.java index ad49e3edb..44322d22c 100644 --- a/src/main/java/com/simibubi/create/AllShapes.java +++ b/src/main/java/com/simibubi/create/AllShapes.java @@ -107,7 +107,10 @@ public class AllShapes { .forHorizontal(Direction.SOUTH), 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) + .forDirectional(Direction.UP), + CRUSHING_WHEEL_CONTROLLER_COLLISION = shape(0, 0, 0, 16, 13, 16) + .forDirectional(Direction.DOWN) + ; @@ -145,7 +148,8 @@ public class AllShapes { 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, 22, 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(), diff --git a/src/main/java/com/simibubi/create/AllSpriteShifts.java b/src/main/java/com/simibubi/create/AllSpriteShifts.java index e358b069c..9aafdc586 100644 --- a/src/main/java/com/simibubi/create/AllSpriteShifts.java +++ b/src/main/java/com/simibubi/create/AllSpriteShifts.java @@ -51,9 +51,9 @@ public class AllSpriteShifts { FLUID_TANK = getCT(CTType.CROSS, "fluid_tank"), CREATIVE_FLUID_TANK = getCT(CTType.CROSS, "creative_fluid_tank"); - public static final SpriteShiftEntry BELT = SpriteShifter.get("block/belt", "block/belt_animated"), - BELT_OFFSET = SpriteShifter.get("block/belt_offset", "block/belt_animated"), - BELT_DIAGONAL = SpriteShifter.get("block/belt_diagonal", "block/belt_diagonal_animated"), + public static final SpriteShiftEntry BELT = SpriteShifter.get("block/belt", "block/belt_scroll"), + BELT_OFFSET = SpriteShifter.get("block/belt_offset", "block/belt_scroll"), + BELT_DIAGONAL = SpriteShifter.get("block/belt_diagonal", "block/belt_diagonal_scroll"), ANDESIDE_BELT_CASING = SpriteShifter.get("block/brass_casing_belt", "block/andesite_casing_belt"), CRAFTER_THINGIES = SpriteShifter.get("block/crafter_thingies", "block/crafter_thingies"); @@ -92,9 +92,9 @@ public class AllSpriteShifts { for (DyeColor color : DyeColor.values()) { String id = color.getName(); - DYED_BELTS.put(color, SpriteShifter.get("block/belt", "block/belt/" + id)); - DYED_OFFSET_BELTS.put(color, SpriteShifter.get("block/belt_offset", "block/belt/" + id)); - DYED_DIAGONAL_BELTS.put(color, SpriteShifter.get("block/belt_diagonal", "block/belt/" + id + "_diagonal")); + DYED_BELTS.put(color, SpriteShifter.get("block/belt", "block/belt/" + id + "_scroll")); + DYED_OFFSET_BELTS.put(color, SpriteShifter.get("block/belt_offset", "block/belt/" + id + "_scroll")); + DYED_DIAGONAL_BELTS.put(color, SpriteShifter.get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll")); } } diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 9cf3b8fb2..1abb73271 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -1,6 +1,12 @@ package com.simibubi.create; +import com.simibubi.create.content.contraptions.base.BackHalfShaftInstance; +import com.simibubi.create.content.contraptions.base.HalfShaftInstance; +import com.simibubi.create.content.contraptions.base.HorizontalHalfShaftInstance; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.content.contraptions.base.ShaftlessCogInstance; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.content.contraptions.components.actors.DrillInstance; import com.simibubi.create.content.contraptions.components.actors.DrillRenderer; import com.simibubi.create.content.contraptions.components.actors.DrillTileEntity; import com.simibubi.create.content.contraptions.components.actors.HarvesterRenderer; @@ -10,6 +16,7 @@ import com.simibubi.create.content.contraptions.components.actors.PortableItemIn import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceRenderer; import com.simibubi.create.content.contraptions.components.clock.CuckooClockRenderer; import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity; +import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterInstance; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterRenderer; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; import com.simibubi.create.content.contraptions.components.crank.HandCrankRenderer; @@ -20,11 +27,14 @@ import com.simibubi.create.content.contraptions.components.deployer.DeployerRend import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity; import com.simibubi.create.content.contraptions.components.fan.EncasedFanRenderer; import com.simibubi.create.content.contraptions.components.fan.EncasedFanTileEntity; +import com.simibubi.create.content.contraptions.components.fan.FanInstance; import com.simibubi.create.content.contraptions.components.fan.NozzleTileEntity; +import com.simibubi.create.content.contraptions.components.flywheel.FlyWheelInstance; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelRenderer; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity; import com.simibubi.create.content.contraptions.components.flywheel.engine.EngineRenderer; import com.simibubi.create.content.contraptions.components.flywheel.engine.FurnaceEngineTileEntity; +import com.simibubi.create.content.contraptions.components.millstone.MillStoneCogInstance; import com.simibubi.create.content.contraptions.components.millstone.MillstoneRenderer; import com.simibubi.create.content.contraptions.components.millstone.MillstoneTileEntity; import com.simibubi.create.content.contraptions.components.mixer.MechanicalMixerRenderer; @@ -33,6 +43,7 @@ import com.simibubi.create.content.contraptions.components.motor.CreativeMotorRe import com.simibubi.create.content.contraptions.components.motor.CreativeMotorTileEntity; import com.simibubi.create.content.contraptions.components.press.MechanicalPressRenderer; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.content.contraptions.components.saw.SawInstance; import com.simibubi.create.content.contraptions.components.saw.SawRenderer; import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingRenderer; @@ -49,6 +60,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pul import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; import com.simibubi.create.content.contraptions.components.turntable.TurntableTileEntity; import com.simibubi.create.content.contraptions.components.waterwheel.WaterWheelTileEntity; +import com.simibubi.create.content.contraptions.fluids.PumpCogInstance; import com.simibubi.create.content.contraptions.fluids.PumpRenderer; import com.simibubi.create.content.contraptions.fluids.PumpTileEntity; import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyRenderer; @@ -74,6 +86,7 @@ import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileE import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerRenderer; import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerTileEntity; import com.simibubi.create.content.contraptions.relays.advanced.sequencer.SequencedGearshiftTileEntity; +import com.simibubi.create.content.contraptions.relays.belt.BeltInstance; import com.simibubi.create.content.contraptions.relays.belt.BeltRenderer; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.contraptions.relays.elementary.SimpleKineticTileEntity; @@ -81,10 +94,13 @@ import com.simibubi.create.content.contraptions.relays.encased.AdjustablePulleyT import com.simibubi.create.content.contraptions.relays.encased.ClutchTileEntity; import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftRenderer; import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftTileEntity; +import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; +import com.simibubi.create.content.contraptions.relays.encased.SplitShaftInstance; import com.simibubi.create.content.contraptions.relays.encased.SplitShaftRenderer; import com.simibubi.create.content.contraptions.relays.gauge.GaugeRenderer; import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; import com.simibubi.create.content.contraptions.relays.gauge.StressGaugeTileEntity; +import com.simibubi.create.content.contraptions.relays.gearbox.GearboxInstance; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxRenderer; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxTileEntity; import com.simibubi.create.content.contraptions.relays.gearbox.GearshiftTileEntity; @@ -104,6 +120,7 @@ import com.simibubi.create.content.logistics.block.funnel.FunnelRenderer; import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateTileEntity; import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTileEntity; +import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInstance; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmRenderer; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity; import com.simibubi.create.content.logistics.block.redstone.AnalogLeverRenderer; @@ -138,36 +155,42 @@ public class AllTileEntities { .tileEntity("simple_kinetic", SimpleKineticTileEntity::new) .validBlocks(AllBlocks.SHAFT, AllBlocks.COGWHEEL, AllBlocks.LARGE_COGWHEEL) .renderer(() -> KineticTileEntityRenderer::new) + .onRegister(SingleRotatingInstance::register) .register(); public static final TileEntityEntry MOTOR = Create.registrate() .tileEntity("motor", CreativeMotorTileEntity::new) .validBlocks(AllBlocks.CREATIVE_MOTOR) .renderer(() -> CreativeMotorRenderer::new) + .onRegister(HalfShaftInstance::register) .register(); public static final TileEntityEntry GEARBOX = Create.registrate() .tileEntity("gearbox", GearboxTileEntity::new) .validBlocks(AllBlocks.GEARBOX) .renderer(() -> GearboxRenderer::new) + .onRegister(GearboxInstance::register) .register(); public static final TileEntityEntry ENCASED_SHAFT = Create.registrate() .tileEntity("encased_shaft", EncasedShaftTileEntity::new) .validBlocks(AllBlocks.ANDESITE_ENCASED_SHAFT, AllBlocks.BRASS_ENCASED_SHAFT, AllBlocks.ENCASED_CHAIN_DRIVE) .renderer(() -> EncasedShaftRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry ADJUSTABLE_PULLEY = Create.registrate() .tileEntity("adjustable_pulley", AdjustablePulleyTileEntity::new) .validBlocks(AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) .renderer(() -> EncasedShaftRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry ENCASED_FAN = Create.registrate() .tileEntity("encased_fan", EncasedFanTileEntity::new) .validBlocks(AllBlocks.ENCASED_FAN) .renderer(() -> EncasedFanRenderer::new) + .onRegister(FanInstance::register) .register(); public static final TileEntityEntry NOZZLE = Create.registrate() @@ -180,18 +203,21 @@ public class AllTileEntities { .tileEntity("clutch", ClutchTileEntity::new) .validBlocks(AllBlocks.CLUTCH) .renderer(() -> SplitShaftRenderer::new) + .onRegister(SplitShaftInstance::register) .register(); public static final TileEntityEntry GEARSHIFT = Create.registrate() .tileEntity("gearshift", GearshiftTileEntity::new) .validBlocks(AllBlocks.GEARSHIFT) .renderer(() -> SplitShaftRenderer::new) + .onRegister(SplitShaftInstance::register) .register(); public static final TileEntityEntry TURNTABLE = Create.registrate() .tileEntity("turntable", TurntableTileEntity::new) .validBlocks(AllBlocks.TURNTABLE) .renderer(() -> KineticTileEntityRenderer::new) + .onRegister(SingleRotatingInstance::register) .register(); public static final TileEntityEntry HAND_CRANK = Create.registrate() @@ -199,30 +225,35 @@ public class AllTileEntities { .validBlocks(AllBlocks.HAND_CRANK, AllBlocks.COPPER_VALVE_HANDLE) .validBlocks(AllBlocks.DYED_VALVE_HANDLES) .renderer(() -> HandCrankRenderer::new) + .onRegister(SingleRotatingInstance::register) .register(); public static final TileEntityEntry CUCKOO_CLOCK = Create.registrate() .tileEntity("cuckoo_clock", CuckooClockTileEntity::new) .validBlocks(AllBlocks.CUCKOO_CLOCK, AllBlocks.MYSTERIOUS_CUCKOO_CLOCK) .renderer(() -> CuckooClockRenderer::new) + .onRegister(HorizontalHalfShaftInstance::register) .register(); public static final TileEntityEntry GANTRY_SHAFT = Create.registrate() .tileEntity("gantry_shaft", GantryShaftTileEntity::new) .validBlocks(AllBlocks.GANTRY_SHAFT) .renderer(() -> KineticTileEntityRenderer::new) + .onRegister(SingleRotatingInstance::register) .register(); public static final TileEntityEntry GANTRY_PINION = Create.registrate() .tileEntity("gantry_pinion", GantryPinionTileEntity::new) .validBlocks(AllBlocks.GANTRY_PINION) .renderer(() -> GantryPinionRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry MECHANICAL_PUMP = Create.registrate() .tileEntity("mechanical_pump", PumpTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_PUMP) .renderer(() -> PumpRenderer::new) + .onRegister(PumpCogInstance::register) .register(); public static final TileEntityEntry SMART_FLUID_PIPE = Create.registrate() @@ -251,6 +282,7 @@ public class AllTileEntities { .tileEntity("fluid_valve", FluidValveTileEntity::new) .validBlocks(AllBlocks.FLUID_VALVE) .renderer(() -> FluidValveRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry FLUID_TANK = Create.registrate() @@ -269,6 +301,7 @@ public class AllTileEntities { .tileEntity("hose_pulley", HosePulleyTileEntity::new) .validBlocks(AllBlocks.HOSE_PULLEY) .renderer(() -> HosePulleyRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry SPOUT = Create.registrate() @@ -287,6 +320,7 @@ public class AllTileEntities { .tileEntity("belt", BeltTileEntity::new) .validBlocks(AllBlocks.BELT) .renderer(() -> BeltRenderer::new) + .onRegister(BeltInstance::register) .register(); public static final TileEntityEntry CHUTE = Create.registrate() @@ -317,36 +351,42 @@ public class AllTileEntities { .tileEntity("mechanical_arm", ArmTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_ARM) .renderer(() -> ArmRenderer::new) + .onRegister(ArmInstance::register) .register(); public static final TileEntityEntry MECHANICAL_PISTON = Create.registrate() .tileEntity("mechanical_piston", MechanicalPistonTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_PISTON, AllBlocks.STICKY_MECHANICAL_PISTON) .renderer(() -> MechanicalPistonRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry WINDMILL_BEARING = Create.registrate() .tileEntity("windmill_bearing", WindmillBearingTileEntity::new) .validBlocks(AllBlocks.WINDMILL_BEARING) .renderer(() -> BearingRenderer::new) + .onRegister(BackHalfShaftInstance::register) .register(); public static final TileEntityEntry MECHANICAL_BEARING = Create.registrate() .tileEntity("mechanical_bearing", MechanicalBearingTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_BEARING) .renderer(() -> BearingRenderer::new) + .onRegister(BackHalfShaftInstance::register) .register(); public static final TileEntityEntry CLOCKWORK_BEARING = Create.registrate() .tileEntity("clockwork_bearing", ClockworkBearingTileEntity::new) .validBlocks(AllBlocks.CLOCKWORK_BEARING) .renderer(() -> BearingRenderer::new) + .onRegister(BackHalfShaftInstance::register) .register(); public static final TileEntityEntry ROPE_PULLEY = Create.registrate() .tileEntity("rope_pulley", PulleyTileEntity::new) .validBlocks(AllBlocks.ROPE_PULLEY) .renderer(() -> PulleyRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry CHASSIS = Create.registrate() @@ -359,12 +399,14 @@ public class AllTileEntities { .tileEntity("drill", DrillTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_DRILL) .renderer(() -> DrillRenderer::new) + .onRegister(DrillInstance::register) .register(); public static final TileEntityEntry SAW = Create.registrate() .tileEntity("saw", SawTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_SAW) .renderer(() -> SawRenderer::new) + .onRegister(SawInstance::register) .register(); public static final TileEntityEntry HARVESTER = Create.registrate() @@ -390,6 +432,7 @@ public class AllTileEntities { .tileEntity("flywheel", FlywheelTileEntity::new) .validBlocks(AllBlocks.FLYWHEEL) .renderer(() -> FlywheelRenderer::new) + .onRegister(FlyWheelInstance::register) .register(); public static final TileEntityEntry FURNACE_ENGINE = Create.registrate() @@ -402,12 +445,14 @@ public class AllTileEntities { .tileEntity("millstone", MillstoneTileEntity::new) .validBlocks(AllBlocks.MILLSTONE) .renderer(() -> MillstoneRenderer::new) + .onRegister(MillStoneCogInstance::register) .register(); public static final TileEntityEntry CRUSHING_WHEEL = Create.registrate() .tileEntity("crushing_wheel", CrushingWheelTileEntity::new) .validBlocks(AllBlocks.CRUSHING_WHEEL) .renderer(() -> KineticTileEntityRenderer::new) + .onRegister(SingleRotatingInstance::register) .register(); public static final TileEntityEntry CRUSHING_WHEEL_CONTROLLER = @@ -421,24 +466,28 @@ public class AllTileEntities { .tileEntity("water_wheel", WaterWheelTileEntity::new) .validBlocks(AllBlocks.WATER_WHEEL) .renderer(() -> KineticTileEntityRenderer::new) + .onRegister(SingleRotatingInstance::register) .register(); public static final TileEntityEntry MECHANICAL_PRESS = Create.registrate() .tileEntity("mechanical_press", MechanicalPressTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_PRESS) .renderer(() -> MechanicalPressRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry MECHANICAL_MIXER = Create.registrate() .tileEntity("mechanical_mixer", MechanicalMixerTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_MIXER) .renderer(() -> MechanicalMixerRenderer::new) + .onRegister(ShaftlessCogInstance::register) .register(); public static final TileEntityEntry DEPLOYER = Create.registrate() .tileEntity("deployer", DeployerTileEntity::new) .validBlocks(AllBlocks.DEPLOYER) .renderer(() -> DeployerRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry BASIN = Create.registrate() @@ -457,30 +506,35 @@ public class AllTileEntities { .tileEntity("mechanical_crafter", MechanicalCrafterTileEntity::new) .validBlocks(AllBlocks.MECHANICAL_CRAFTER) .renderer(() -> MechanicalCrafterRenderer::new) + .onRegister(MechanicalCrafterInstance::register) .register(); public static final TileEntityEntry SEQUENCED_GEARSHIFT = Create.registrate() .tileEntity("sequenced_gearshift", SequencedGearshiftTileEntity::new) .validBlocks(AllBlocks.SEQUENCED_GEARSHIFT) .renderer(() -> SplitShaftRenderer::new) + .onRegister(SplitShaftInstance::register) .register(); public static final TileEntityEntry ROTATION_SPEED_CONTROLLER = Create.registrate() .tileEntity("rotation_speed_controller", SpeedControllerTileEntity::new) .validBlocks(AllBlocks.ROTATION_SPEED_CONTROLLER) .renderer(() -> SpeedControllerRenderer::new) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry SPEEDOMETER = Create.registrate() .tileEntity("speedometer", SpeedGaugeTileEntity::new) .validBlocks(AllBlocks.SPEEDOMETER) .renderer(() -> GaugeRenderer::speed) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry STRESSOMETER = Create.registrate() .tileEntity("stressometer", StressGaugeTileEntity::new) .validBlocks(AllBlocks.STRESSOMETER) .renderer(() -> GaugeRenderer::stress) + .onRegister(ShaftInstance::register) .register(); public static final TileEntityEntry ANALOG_LEVER = Create.registrate() diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index af28f62f3..4a13fc88d 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -95,7 +95,7 @@ public class Create { AllConfigs.register(); random = new Random(); - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> CreateClient.addClientListeners(modEventBus)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.addClientListeners(modEventBus)); } public static void init(final FMLCommonSetupEvent event) { diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 4ff75d77b..482cf089b 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -6,7 +6,7 @@ import java.util.Map; import java.util.function.Function; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; import com.simibubi.create.content.schematics.ClientSchematicLoader; import com.simibubi.create.content.schematics.client.SchematicAndQuillHandler; @@ -18,7 +18,11 @@ import com.simibubi.create.foundation.item.CustomItemModels; import com.simibubi.create.foundation.item.CustomRenderedItems; import com.simibubi.create.foundation.ponder.content.PonderIndex; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; -import com.simibubi.create.foundation.utility.SuperByteBufferCache; +import com.simibubi.create.foundation.render.KineticRenderer; +import com.simibubi.create.foundation.render.SuperByteBufferCache; +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.OptifineHandler; +import com.simibubi.create.foundation.utility.ghost.GhostBlocks; import com.simibubi.create.foundation.utility.outliner.Outliner; import net.minecraft.block.Block; @@ -44,7 +48,9 @@ public class CreateClient { public static SchematicHandler schematicHandler; public static SchematicAndQuillHandler schematicAndQuillHandler; public static SuperByteBufferCache bufferCache; + public static KineticRenderer kineticRenderer; public static final Outliner outliner = new Outliner(); + public static GhostBlocks ghostBlocks; private static CustomBlockModels customBlockModels; private static CustomItemModels customItemModels; @@ -58,18 +64,25 @@ public class CreateClient { modEventBus.addListener(CreateClient::onModelRegistry); modEventBus.addListener(CreateClient::onTextureStitch); modEventBus.addListener(AllParticleTypes::registerFactories); + + Backend.init(); + OptifineHandler.init(); } public static void clientInit(FMLClientSetupEvent event) { + kineticRenderer = new KineticRenderer(); + schematicSender = new ClientSchematicLoader(); schematicHandler = new SchematicHandler(); schematicAndQuillHandler = new SchematicAndQuillHandler(); bufferCache = new SuperByteBufferCache(); bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); - bufferCache.registerCompartment(ContraptionRenderer.CONTRAPTION, 20); + bufferCache.registerCompartment(ContraptionRenderDispatcher.CONTRAPTION, 20); bufferCache.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20); + ghostBlocks = new GhostBlocks(); + AllKeys.register(); AllContainerTypes.registerScreenFactories(); //AllTileEntities.registerRenderers(); @@ -175,4 +188,9 @@ public class CreateClient { return casingConnectivity; } + public static void invalidateRenderers() { + CreateClient.bufferCache.invalidate(); + CreateClient.kineticRenderer.invalidate(); + ContraptionRenderDispatcher.invalidateAll(); + } } diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index 5cb215a61..de757db48 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -35,6 +35,7 @@ import com.simibubi.create.compat.jei.category.ProcessingViaFanCategory; import com.simibubi.create.compat.jei.category.SawingCategory; import com.simibubi.create.compat.jei.category.SpoutCategory; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity; +import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipeManager; import com.simibubi.create.content.contraptions.processing.BasinRecipe; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateScreen; @@ -54,6 +55,7 @@ import mezz.jei.api.registration.ISubtypeRegistration; import mezz.jei.api.runtime.IIngredientManager; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; import net.minecraft.item.crafting.ICraftingRecipe; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipeSerializer; @@ -61,8 +63,10 @@ import net.minecraft.item.crafting.IRecipeType; import net.minecraft.item.crafting.ShapedRecipe; import net.minecraft.util.IItemProvider; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.ModList; @JeiPlugin +@SuppressWarnings("unused") public class CreateJEI implements IModPlugin { private static final ResourceLocation ID = new ResourceLocation(Create.ID, "jei_plugin"); @@ -132,12 +136,18 @@ public class CreateJEI implements IModPlugin { .catalyst(AllBlocks.MECHANICAL_SAW::get) .build(), - blockCutting = register("block_cutting", BlockCuttingCategory::new) + blockCutting = register("block_cutting", () -> new BlockCuttingCategory(Items.STONE_BRICK_STAIRS)) .recipeList(() -> CondensedBlockCuttingRecipe.condenseRecipes(findRecipesByType(IRecipeType.STONECUTTING))) .catalyst(AllBlocks.MECHANICAL_SAW::get) .enableWhen(c -> c.allowStonecuttingOnSaw) .build(), + woodCutting = register("wood_cutting", () -> new BlockCuttingCategory(Items.OAK_STAIRS)) + .recipeList(() -> CondensedBlockCuttingRecipe.condenseRecipes(findRecipesByType(SawTileEntity.woodcuttingRecipeType.getValue()))) + .catalyst(AllBlocks.MECHANICAL_SAW::get) + .enableWhenBool(c -> c.allowWoodcuttingOnSaw.get() && ModList.get().isLoaded("druidcraft")) + .build(), + packing = register("packing", PackingCategory::standard).recipes(AllRecipeTypes.COMPACTING) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .catalyst(AllBlocks.BASIN::get) @@ -293,8 +303,12 @@ public class CreateJEI implements IModPlugin { CategoryBuilder enableWhen(Function configValue) { this.pred = c -> configValue.apply(c) - .get() - .booleanValue(); + .get(); + return this; + } + + CategoryBuilder enableWhenBool(Function configValue) { + this.pred = configValue::apply; return this; } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java index 86806e554..2fd5373e6 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/BlockCuttingCategory.java @@ -14,8 +14,8 @@ import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.gui.IRecipeLayout; import mezz.jei.api.gui.ingredient.IGuiItemStackGroup; import mezz.jei.api.ingredients.IIngredients; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.Ingredient; import net.minecraft.item.crafting.StonecuttingRecipe; @@ -25,8 +25,8 @@ public class BlockCuttingCategory extends CreateRecipeCategory type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, BackHalfShaftInstance::new)); + } + + public BackHalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected Direction getShaftDirection() { + return tile.getBlockState().get(BlockStateProperties.FACING).getOpposite(); + } +} 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 new file mode 100644 index 000000000..6e70b9780 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java @@ -0,0 +1,33 @@ +package com.simibubi.create.content.contraptions.base; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class HalfShaftInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, HalfShaftInstance::new)); + } + + public HalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected InstancedModel getModel() { + Direction dir = getShaftDirection(); + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, dir); + } + + protected Direction getShaftDirection() { + return lastState.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 new file mode 100644 index 000000000..958305113 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.contraptions.base; + +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class HorizontalHalfShaftInstance extends HalfShaftInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, HorizontalHalfShaftInstance::new)); + } + + public HorizontalHalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected Direction getShaftDirection() { + return lastState.get(BlockStateProperties.HORIZONTAL_FACING).getOpposite(); + } +} 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 new file mode 100644 index 000000000..84d8a878a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java @@ -0,0 +1,116 @@ +package com.simibubi.create.content.contraptions.base; + +import java.nio.ByteBuffer; + +import com.simibubi.create.foundation.render.backend.instancing.InstanceData; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.utility.ColorHelper; + +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.util.math.BlockPos; + +public class KineticData> extends InstanceData { + 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; + + protected KineticData(InstancedModel owner) { + super(owner); + } + + public D setTileEntity(KineticTileEntity te) { + setPosition(te.getPos()); + if (te.hasSource()) { + setColor(te.network); + }else { + setColor(0xFF, 0xFF, 0x00); + } + return (D) this; + } + + public D setPosition(BlockPos pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + public D setPosition(Vector3f pos) { + return setPosition(pos.getX(), pos.getY(), pos.getZ()); + } + + public D 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 D setPosition(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + return (D) this; + } + + public D setBlockLight(int blockLight) { + this.blockLight = (byte) ((blockLight & 0xF) << 4); + return (D) this; + } + + public D setSkyLight(int skyLight) { + this.skyLight = (byte) ((skyLight & 0xF) << 4); + return (D) this; + } + + public D setColor(Long l) { + if (l != null) + return setColor(l.longValue()); + else + return setColor(0xFF, 0xFF, 0xFF); + } + + private D 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); + } + + 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) { + this.rotationalSpeed = rotationalSpeed; + return (D) this; + } + + public D setRotationOffset(float rotationOffset) { + this.rotationOffset = rotationOffset; + return (D) 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); + } +} 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 new file mode 100644 index 000000000..49223a3cb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticRenderMaterials.java @@ -0,0 +1,13 @@ +package com.simibubi.create.content.contraptions.base; + +import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData; +import com.simibubi.create.content.contraptions.relays.belt.BeltData; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.MaterialType; + +public class KineticRenderMaterials { + public static final MaterialType> ROTATING = new MaterialType<>(); + public static final MaterialType> BELTS = new MaterialType<>(); + + public static final MaterialType> ACTORS = new MaterialType<>(); +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java index 944d6a0f9..9ef0a28ff 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntity.java @@ -8,6 +8,7 @@ import java.util.List; import javax.annotation.Nullable; import com.simibubi.create.Create; +import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticNetwork; import com.simibubi.create.content.contraptions.RotationPropagator; import com.simibubi.create.content.contraptions.base.IRotate.SpeedLevel; @@ -17,6 +18,8 @@ import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.item.TooltipHelper; +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; import com.simibubi.create.foundation.utility.Lang; @@ -32,12 +35,16 @@ import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.AxisDirection; +import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; public abstract class KineticTileEntity extends SmartTileEntity - implements ITickableTileEntity, IHaveGoggleInformation, IHaveHoveringInformation { + implements ITickableTileEntity, IHaveGoggleInformation, IHaveHoveringInformation, IInstanceRendered { public @Nullable Long network; public @Nullable BlockPos source; @@ -166,10 +173,6 @@ public abstract class KineticTileEntity extends SmartTileEntity boolean directionSwap = !fromOrToZero && Math.signum(previousSpeed) != Math.signum(getSpeed()); if (fromOrToZero || directionSwap) flickerTally = getFlickerScore() + 5; - - if (fromOrToZero && previousSpeed == 0 && !world.isRemote) - AllTriggers.getPlayersInRange(world, pos, 4) - .forEach(p -> AllTriggers.KINETIC_BLOCK.trigger(p, getBlockState())); } @Override @@ -245,6 +248,9 @@ public abstract class KineticTileEntity extends SmartTileEntity if (clientPacket && overStressedBefore != overStressed && speed != 0) effects.triggerOverStressedEffect(); + + if (clientPacket) + FastRenderDispatcher.enqueueUpdate(this); } public float getGeneratedSpeed() { @@ -465,7 +471,7 @@ public abstract class KineticTileEntity extends SmartTileEntity /** * Specify ratio of transferred rotation from this kinetic component to a * specific other. - * + * * @param target other Kinetic TE to transfer to * @param stateFrom this TE's blockstate * @param stateTo other TE's blockstate @@ -486,7 +492,7 @@ public abstract class KineticTileEntity extends SmartTileEntity * Specify additional locations the rotation propagator should look for * potentially connected components. Neighbour list contains offset positions in * all 6 directions by default. - * + * * @param block * @param state * @param neighbours @@ -513,7 +519,7 @@ public abstract class KineticTileEntity extends SmartTileEntity * circumstance. Shaft and cogwheel connections are already handled by internal * logic. Does not have to be specified on both ends, it is assumed that this * relation is symmetrical. - * + * * @param other * @param state * @param otherState @@ -528,4 +534,42 @@ public abstract class KineticTileEntity extends SmartTileEntity return block.hasIntegratedCogwheel(world, pos, state); } + @Override + public void onLoad() { + super.onLoad(); + if (world != null && world.isRemote) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.add(this)); + } + + @Override + public void onChunkUnloaded() { + if (world != null && world.isRemote) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.kineticRenderer.remove(this)); + } + + @Override + public void requestModelDataUpdate() { + super.requestModelDataUpdate(); + if (!this.removed) { + FastRenderDispatcher.enqueueUpdate(this); + } + } + + @Override + public void onChunkLightUpdate() { + CreateClient.kineticRenderer.onLightUpdate(this); + } + + protected AxisAlignedBB cachedBoundingBox; + @OnlyIn(Dist.CLIENT) + public AxisAlignedBB getRenderBoundingBox() { + if (cachedBoundingBox == null) { + cachedBoundingBox = makeRenderBoundingBox(); + } + return cachedBoundingBox; + } + + protected AxisAlignedBB makeRenderBoundingBox() { + return super.getRenderBoundingBox(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java index 5eb1aea7a..cc27ee7f8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticTileEntityRenderer.java @@ -6,11 +6,12 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticDebugger; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; +import com.simibubi.create.foundation.render.Compartment; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -38,6 +39,8 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer extends TileEntityInstance { + + public KineticTileInstance(InstancedTileRenderer modelManager, T tile) { + super(modelManager, tile); + } + + protected final void updateRotation(InstanceKey key, Direction.Axis axis) { + key.modifyInstance(data -> { + data.setColor(tile.network) + .setRotationalSpeed(tile.getSpeed()) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(axis); + }); + } + + protected final Consumer setupFunc(float speed, Direction.Axis axis) { + return data -> { + data.setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)) + .setTileEntity(tile) + .setRotationalSpeed(speed) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(axis); + }; + } + + protected final void relight(KineticData data) { + data.setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + } + + protected float getRotationOffset(final Direction.Axis axis) { + float offset = CogWheelBlock.isLargeCog(lastState) ? 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) { + offset = 22.5f; + } + return offset; + } + + public static BlockState shaft(Direction.Axis axis) { + return AllBlocks.SHAFT.getDefaultState() + .with(ShaftBlock.AXIS, axis); + } + + public Direction.Axis getRotationAxis() { + return ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + } + + protected final RenderMaterial> rotatingMaterial() { + return modelManager.getMaterial(KineticRenderMaterials.ROTATING); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticVertexAttributes.java new file mode 100644 index 000000000..46f8740f4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticVertexAttributes.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.contraptions.base; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +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 { + INSTANCE_POSITION("aInstancePos", CommonAttributes.VEC3), + LIGHT("aLight", CommonAttributes.LIGHT), + NETWORK_COLOR("aNetworkTint", CommonAttributes.RGB), + SPEED("aSpeed", CommonAttributes.FLOAT), + OFFSET("aOffset", CommonAttributes.FLOAT), + ; + + private final String name; + private final VertexAttribSpec spec; + + KineticVertexAttributes(String name, VertexAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public VertexAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 1; + } + + @Override + public int getBufferIndex() { + return 1; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java index 2e86a897a..75c45893c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatedPillarKineticBlock.java @@ -27,7 +27,7 @@ public abstract class RotatedPillarKineticBlock extends KineticBlock { switch (rot) { case COUNTERCLOCKWISE_90: case CLOCKWISE_90: - switch ((Direction.Axis) state.get(AXIS)) { + switch (state.get(AXIS)) { case X: return state.with(AXIS, Direction.Axis.Z); case Z: 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 new file mode 100644 index 000000000..dcc5ca5f7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java @@ -0,0 +1,49 @@ +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.client.renderer.Vector3f; +import net.minecraft.util.Direction; + +public class RotatingData extends KineticData { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(KineticVertexAttributes.class) + .addAttributes(RotatingVertexAttributes.class) + .build(); + + private byte rotationAxisX; + private byte rotationAxisY; + private byte rotationAxisZ; + + protected RotatingData(InstancedModel owner) { + super(owner); + } + + public RotatingData setRotationAxis(Direction.Axis axis) { + Direction orientation = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis); + setRotationAxis(orientation.getUnitVector()); + return this; + } + + public RotatingData setRotationAxis(Vector3f axis) { + setRotationAxis(axis.getX(), axis.getY(), axis.getZ()); + return this; + } + + public RotatingData setRotationAxis(float rotationAxisX, float rotationAxisY, float rotationAxisZ) { + this.rotationAxisX = (byte) (rotationAxisX * 127); + this.rotationAxisY = (byte) (rotationAxisY * 127); + this.rotationAxisZ = (byte) (rotationAxisZ * 127); + return this; + } + + @Override + public void write(ByteBuffer buf) { + super.write(buf); + + putVec3(buf, rotationAxisX, rotationAxisY, 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/RotatingInstancedModel.java new file mode 100644 index 000000000..6f439ca42 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingInstancedModel.java @@ -0,0 +1,24 @@ +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 net.minecraft.client.renderer.BufferBuilder; + +public class RotatingInstancedModel extends InstancedModel { + public RotatingInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + super(renderer, buf); + } + + @Override + protected RotatingData newInstance() { + return new RotatingData(this); + } + + @Override + protected VertexFormat getInstanceFormat() { + return RotatingData.FORMAT; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingVertexAttributes.java new file mode 100644 index 000000000..677b18190 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingVertexAttributes.java @@ -0,0 +1,38 @@ +package com.simibubi.create.content.contraptions.base; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +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 { + AXIS("aAxis", CommonAttributes.NORMAL), + ; + + private final String name; + private final VertexAttribSpec spec; + + RotatingVertexAttributes(String name, VertexAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public VertexAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 1; + } + + @Override + public int getBufferIndex() { + return 1; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/ShaftlessCogInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/ShaftlessCogInstance.java new file mode 100644 index 000000000..ff96d5856 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/ShaftlessCogInstance.java @@ -0,0 +1,26 @@ +package com.simibubi.create.content.contraptions.base; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class ShaftlessCogInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, ShaftlessCogInstance::new)); + } + + public ShaftlessCogInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected InstancedModel getModel() { + return AllBlockPartials.SHAFTLESS_COGWHEEL.renderOnRotating(modelManager, tile.getBlockState()); + } +} 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 new file mode 100644 index 000000000..9008e2f44 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java @@ -0,0 +1,57 @@ +package com.simibubi.create.content.contraptions.base; + +import static com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer.KINETIC_TILE; + +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.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class SingleRotatingInstance extends KineticTileInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, SingleRotatingInstance::new)); + } + + protected InstanceKey rotatingModelKey; + + public SingleRotatingInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected void init() { + Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + rotatingModelKey = getModel().setupInstance(setupFunc(tile.getSpeed(), axis)); + } + + @Override + public void onUpdate() { + Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + updateRotation(rotatingModelKey, axis); + } + + @Override + public void updateLight() { + rotatingModelKey.modifyInstance(this::relight); + } + + @Override + public void remove() { + rotatingModelKey.delete(); + } + + protected BlockState getRenderedBlockState() { + return lastState; + } + + protected InstancedModel getModel() { + return rotatingMaterial().getModel(KINETIC_TILE, getRenderedBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java new file mode 100644 index 000000000..fdeae0d94 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java @@ -0,0 +1,43 @@ +package com.simibubi.create.content.contraptions.components.actors; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; +import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; + +public enum ActorVertexAttributes implements IVertexAttrib { + INSTANCE_POSITION("aInstancePos", CommonAttributes.VEC3), + LIGHT("aModelLight", CommonAttributes.LIGHT), + OFFSET("aOffset", CommonAttributes.FLOAT), + AXIS("aAxis", CommonAttributes.NORMAL), + INSTANCE_ROTATION("aInstanceRot", CommonAttributes.VEC3), + ROTATION_CENTER("aRotationCenter", CommonAttributes.NORMAL), + ; + + private final String name; + private final VertexAttribSpec spec; + + ActorVertexAttributes(String name, VertexAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public VertexAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 1; + } + + @Override + public int getBufferIndex() { + return 1; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java index cc14b1ffc..3bcaa5286 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/BellMovementBehaviour.java @@ -10,8 +10,8 @@ import net.minecraft.util.math.Vec3d; public class BellMovementBehaviour extends MovementBehaviour { @Override - public boolean hasSpecialMovementRenderer() { - return false; + public boolean renderAsNormalTileEntity() { + return true; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java index a1f1c148f..e27cffee5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/CampfireMovementBehaviour.java @@ -10,8 +10,8 @@ import net.minecraft.particles.ParticleTypes; public class CampfireMovementBehaviour extends MovementBehaviour { @Override - public boolean hasSpecialMovementRenderer() { - return false; + public boolean renderAsNormalTileEntity() { + return true; } @Override 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/ContraptionActorData.java new file mode 100644 index 000000000..56853e9d1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ContraptionActorData.java @@ -0,0 +1,106 @@ +package com.simibubi.create.content.contraptions.components.actors; + +import java.nio.ByteBuffer; + +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.client.renderer.Vector3f; +import net.minecraft.util.math.BlockPos; + +public class ContraptionActorData extends InstanceData { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(ActorVertexAttributes.class) + .build(); + + private float x; + private float y; + private float z; + private byte blockLight; + private byte skyLight; + private float rotationOffset; + private byte rotationAxisX; + private byte rotationAxisY; + private byte rotationAxisZ; + private float localRotationX; + private float localRotationY; + private float localRotationZ; + private byte rotationCenterX = 64; + private byte rotationCenterY = 64; + private byte rotationCenterZ = 64; + + protected ContraptionActorData(InstancedModel owner) { + super(owner); + } + + + public ContraptionActorData setPosition(BlockPos pos) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + return this; + } + + public ContraptionActorData setBlockLight(int blockLight) { + this.blockLight = (byte) ((blockLight & 0xF) << 4); + return this; + } + + public ContraptionActorData setSkyLight(int skyLight) { + this.skyLight = (byte) ((skyLight & 0xF) << 4); + return this; + } + + public ContraptionActorData setRotationOffset(float rotationOffset) { + this.rotationOffset = rotationOffset; + return this; + } + + public ContraptionActorData setRotationAxis(Vector3f axis) { + setRotationAxis(axis.getX(), axis.getY(), axis.getZ()); + return this; + } + + public ContraptionActorData 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) { + setRotationCenter(axis.getX(), axis.getY(), axis.getZ()); + return this; + } + + public ContraptionActorData 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(Vector3f axis) { + setLocalRotation(axis.getX(), axis.getY(), axis.getZ()); + return this; + } + + public ContraptionActorData setLocalRotation(float localRotationX, float localRotationY, float localRotationZ) { + this.localRotationX = localRotationX; + this.localRotationY = localRotationY; + this.localRotationZ = localRotationZ; + return this; + } + + @Override + public void write(ByteBuffer buf) { + putVec3(buf, x, y, z); + putVec2(buf, blockLight, skyLight); + put(buf, rotationOffset); + putVec3(buf, rotationAxisX, rotationAxisY, rotationAxisZ); + putVec3(buf, localRotationX, localRotationY, localRotationZ); + putVec3(buf, rotationCenterX, rotationCenterY, rotationCenterZ); + + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java new file mode 100644 index 000000000..6ff6d7832 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillInstance.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.contraptions.components.actors; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.base.RotatingData; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class DrillInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, DrillInstance::new)); } + + public DrillInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + public static void addInstanceForContraption(RenderedContraption contraption, MovementContext context) { + RenderMaterial> renderMaterial = contraption.getActorMaterial(); + + BlockState state = context.state; + InstancedModel model = renderMaterial.getModel(AllBlockPartials.DRILL_HEAD, state); + + model.setupInstance(data -> { + Direction facing = state.get(DrillBlock.FACING); + float eulerX = AngleHelper.verticalAngle(facing) + ((facing.getAxis() == Direction.Axis.Y) ? 180 : 0); + float eulerY = facing.getHorizontalAngle(); + data.setPosition(context.localPos) + .setBlockLight(contraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos)) + .setRotationOffset(0) + .setRotationAxis(0, 0, 1) + .setLocalRotation(eulerX, eulerY, 0); + }); + } + + @Override + protected InstancedModel getModel() { + return AllBlockPartials.DRILL_HEAD.renderOnDirectionalSouthRotating(modelManager, tile.getBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java index 62f8c319d..965d6c3c0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillMovementBehaviour.java @@ -2,6 +2,8 @@ package com.simibubi.create.content.contraptions.components.actors; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -31,7 +33,18 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @OnlyIn(value = Dist.CLIENT) public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) { - DrillRenderer.renderInContraption(context, ms, msLocal, buffer); + if (!FastRenderDispatcher.available()) + DrillRenderer.renderInContraption(context, ms, msLocal, buffer); + } + + @Override + public boolean hasSpecialInstancedRendering() { + return true; + } + + @Override + public void addInstance(RenderedContraption contraption, MovementContext context) { + DrillInstance.addInstanceForContraption(contraption, context); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java index 40945edf1..8a73c8ec7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillRenderer.java @@ -7,10 +7,10 @@ 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.components.structureMovement.MovementContext; +import com.simibubi.create.foundation.render.SuperByteBuffer; 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.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java index 38d5f55f8..ea53b2b2c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterMovementBehaviour.java @@ -7,6 +7,8 @@ import org.apache.commons.lang3.mutable.MutableBoolean; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -35,10 +37,21 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { .getOpposite()); } + @Override + public boolean hasSpecialInstancedRendering() { + return true; + } + + @Override + public void addInstance(RenderedContraption contraption, MovementContext context) { + HarvesterRenderer.addInstanceForContraption(contraption, context); + } + @Override public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { - HarvesterRenderer.renderInContraption(context, ms, msLocal, buffers); + if (!FastRenderDispatcher.available()) + HarvesterRenderer.renderInContraption(context, ms, msLocal, buffers); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java index 71ecfdbc6..f271549d9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterRenderer.java @@ -5,19 +5,25 @@ import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FAC 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.ContraptionRenderDispatcher; +import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Vector3f; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.LightType; public class HarvesterRenderer extends SafeTileEntityRenderer { @@ -34,6 +40,25 @@ public class HarvesterRenderer extends SafeTileEntityRenderer> renderMaterial = contraption.getActorMaterial(); + + BlockState state = context.state; + InstancedModel model = renderMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state); + + model.setupInstance(data -> { + Direction facing = state.get(HORIZONTAL_FACING); + float originOffset = 1 / 16f; + Vector3f rotOffset = new Vector3f(0.5f, -2 * originOffset + 0.5f, originOffset + 0.5f); + data.setPosition(context.localPos) + .setBlockLight(contraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos)) + .setRotationOffset(0) + .setRotationCenter(rotOffset) + .setRotationAxis(-1, 0, 0) + .setLocalRotation(0, facing.getHorizontalAngle(), 0); + }); + } + public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffers) { BlockState blockState = context.state; @@ -55,7 +80,7 @@ public class HarvesterRenderer extends SafeTileEntityRenderer oldcap = capability; capability = createEmptyHandler(); oldcap.invalidate(); + super.stopTransferring(); } private LazyOptional createEmptyHandler() { @@ -90,7 +91,7 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi @Override public FluidStack drain(FluidStack resource, FluidAction action) { - if (!isConnected()) + if (!canTransfer()) return FluidStack.EMPTY; FluidStack drain = wrapped.drain(resource, action); if (!drain.isEmpty() && action.execute()) @@ -100,7 +101,7 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi @Override public FluidStack drain(int maxDrain, FluidAction action) { - if (!isConnected()) + if (!canTransfer()) return FluidStack.EMPTY; FluidStack drain = wrapped.drain(maxDrain, action); if (!drain.isEmpty() && (action.execute() || drain.getAmount() == 1)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java index 1642a30ed..227c42dee 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableItemInterfaceTileEntity.java @@ -33,6 +33,7 @@ public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTil LazyOptional oldCap = capability; capability = LazyOptional.of(() -> new InterfaceItemHandler(new ItemStackHandler(0))); oldCap.invalidate(); + super.stopTransferring(); } @Override @@ -55,7 +56,7 @@ public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTil @Override public ItemStack extractItem(int slot, int amount, boolean simulate) { - if (!isConnected()) + if (!canTransfer()) return ItemStack.EMPTY; ItemStack extractItem = super.extractItem(slot, amount, simulate); if (!simulate && !extractItem.isEmpty()) @@ -65,7 +66,7 @@ public class PortableItemInterfaceTileEntity extends PortableStorageInterfaceTil @Override public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { - if (!isConnected()) + if (!canTransfer()) return stack; ItemStack insertItem = super.insertItem(slot, stack, simulate); if (!simulate && !insertItem.equals(stack, false)) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java index c45de1c3f..a67d0da54 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java @@ -7,13 +7,14 @@ import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; 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.SuperByteBuffer; import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -43,8 +44,7 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer sbb.light(msLocal.peek() - .getModel()) + .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) .renderInto(ms, vb), ms, msLocal); } - protected static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) { - String _workingPos_ = PortableStorageInterfaceMovement._workingPos_; - if (!context.contraption.stalled || !context.data.contains(_workingPos_)) - return null; - - BlockPos pos = NBTUtil.readBlockPos(context.data.getCompound(_workingPos_)); - TileEntity tileEntity = context.world.getTileEntity(pos); - if (!(tileEntity instanceof PortableStorageInterfaceTileEntity)) - return null; - - PortableStorageInterfaceTileEntity psi = (PortableStorageInterfaceTileEntity) tileEntity; - if (!psi.isTransferring()) - return null; - return psi; - } - private static void render(BlockState blockState, float progress, boolean lit, Consumer drawCallback, MatrixStack... matrixStacks) { for (MatrixStack ms : matrixStacks) @@ -109,6 +93,22 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer tileEntityTypeIn) { super(tileEntityTypeIn); @@ -32,11 +34,20 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity public void startTransferringTo(Contraption contraption, float distance) { this.distance = distance; + connectedEntity = contraption.entity; startConnecting(); notifyUpdate(); } - protected abstract void stopTransferring(); + protected void stopTransferring() { + connectedEntity = null; + } + + public boolean canTransfer() { + if (connectedEntity != null && !connectedEntity.isAlive()) + stopTransferring(); + return connectedEntity != null && isConnected(); + } protected abstract void invalidateCapability(); @@ -100,10 +111,14 @@ public abstract class PortableStorageInterfaceTileEntity extends SmartTileEntity return powered; } + protected AxisAlignedBB cachedBoundingBox; @Override @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().grow(2); + if (cachedBoundingBox == null) { + cachedBoundingBox = super.getRenderBoundingBox().grow(2); + } + return cachedBoundingBox; } public boolean isTransferring() { 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/RotatingActorModel.java new file mode 100644 index 000000000..8715c6f99 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/RotatingActorModel.java @@ -0,0 +1,23 @@ +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.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.client.renderer.BufferBuilder; + +public class RotatingActorModel extends InstancedModel { + public RotatingActorModel(InstancedTileRenderer renderer, BufferBuilder buf) { + super(renderer, buf); + } + + @Override + protected VertexFormat getInstanceFormat() { + return ContraptionActorData.FORMAT; + } + + @Override + protected ContraptionActorData newInstance() { + return new ContraptionActorData(this); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java index 6e8250e35..cdbd0e92e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockRenderer.java @@ -6,8 +6,8 @@ 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.components.clock.CuckooClockTileEntity.Animation; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java index dad7b19ce..791d82e8e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/clock/CuckooClockTileEntity.java @@ -95,9 +95,9 @@ public class CuckooClockTileEntity extends KineticTileEntity { moveHands(hours, minutes); if (animationType == Animation.NONE) { - if (AnimationTickHolder.ticks % 32 == 0) + if (AnimationTickHolder.getTicks() % 32 == 0) playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 2f); - else if (AnimationTickHolder.ticks % 16 == 0) + else if (AnimationTickHolder.getTicks() % 16 == 0) playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 1.5f); } else { @@ -172,4 +172,8 @@ public class CuckooClockTileEntity extends KineticTileEntity { world.playSound(vec.x, vec.y, vec.z, sound, SoundCategory.BLOCKS, volume, pitch, false); } + @Override + public boolean shouldRenderAsTE() { + return true; + } } 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 new file mode 100644 index 000000000..5313cdbef --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java @@ -0,0 +1,48 @@ +package com.simibubi.create.content.contraptions.components.crafter; + +import java.util.function.Supplier; + +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.RotatingData; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.utility.MatrixStacker; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class MechanicalCrafterInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, MechanicalCrafterInstance::new)); + } + + public MechanicalCrafterInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected InstancedModel getModel() { + Direction facing = lastState.get(MechanicalCrafterBlock.HORIZONTAL_FACING); + + Supplier ms = () -> { + MatrixStack stack = new MatrixStack(); + MatrixStacker stacker = MatrixStacker.of(stack).centre(); + + if (facing.getAxis() == Direction.Axis.X) + stacker.rotateZ(90); + else if (facing.getAxis() == Direction.Axis.Z) + stacker.rotateX(90); + + stacker.unCentre(); + return stack; + }; + return rotatingMaterial().getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, lastState, facing, ms); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java index 9de9abd72..a40e7d3aa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterRenderer.java @@ -9,11 +9,12 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity.Phase; import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; 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.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -25,7 +26,6 @@ import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.item.ItemStack; import net.minecraft.util.Direction; -import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -154,12 +154,13 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer 0) != (otherTe.getSpeed() > 0) - && te.getSpeed() != 0) { - float signum = Math.signum(te.getSpeed()) * (state.get(AXIS) == Axis.X ? -1 : 1); - controllerShouldBeValid = facing.getAxisDirection() - .getOffset() != signum; + && te.getSpeed() != 0) { + Axis wheelAxis = state.get(AXIS); + Axis sideAxis = side.getAxis(); + int controllerADO = Math.round(Math.signum(te.getSpeed())) * side.getAxisDirection().getOffset(); + Vec3d controllerDirVec = new Vec3d(wheelAxis == Axis.X ? 1 : 0 + , wheelAxis == Axis.Y ? 1 : 0 + , wheelAxis == Axis.Z ? 1 : 0) + .crossProduct(new Vec3d(sideAxis == Axis.X ? 1 : 0 + , sideAxis == Axis.Y ? 1 : 0 + , sideAxis == Axis.Z ? 1 : 0)); + + controllerNewDirection = Direction.getFacingFromVector(controllerDirVec.x * controllerADO + , controllerDirVec.y * controllerADO + , controllerDirVec.z * controllerADO); + + controllerShouldBeValid = true; } if (otherState.get(AXIS) != state.get(AXIS)) controllerShouldExist = false; @@ -111,18 +130,20 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE if (!controllerExists) { if (!world.getBlockState(controllerPos) - .getMaterial() - .isReplaceable()) + .getMaterial() + .isReplaceable()) return; world.setBlockState(controllerPos, AllBlocks.CRUSHING_WHEEL_CONTROLLER.getDefaultState() - .with(VALID, controllerShouldBeValid)); - } else if (controllerIsValid != controllerShouldBeValid) { + .with(VALID, controllerShouldBeValid) + .with(FACING, controllerNewDirection)); + } else if (controllerIsValid != controllerShouldBeValid || controllerOldDirection != controllerNewDirection) { world.setBlockState(controllerPos, world.getBlockState(controllerPos) - .with(VALID, controllerShouldBeValid)); + .with(VALID, controllerShouldBeValid) + .with(FACING, controllerNewDirection)); } ((CrushingWheelControllerBlock) AllBlocks.CRUSHING_WHEEL_CONTROLLER.get()) - .updateSpeed(world.getBlockState(controllerPos), world, controllerPos); + .updateSpeed(world.getBlockState(controllerPos), world, controllerPos); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java index d85549b7f..97ddd3101 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.crusher; import java.util.Random; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.foundation.block.ITE; @@ -11,6 +12,7 @@ import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.DirectionalBlock; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.entity.player.PlayerEntity; @@ -23,7 +25,7 @@ import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; -import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.shapes.ISelectionContext; @@ -34,7 +36,7 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; import net.minecraft.world.World; -public class CrushingWheelControllerBlock extends Block +public class CrushingWheelControllerBlock extends DirectionalBlock implements ITE { public CrushingWheelControllerBlock(Properties p_i48440_1_) { @@ -66,27 +68,40 @@ public class CrushingWheelControllerBlock extends Block @Override protected void fillStateContainer(Builder builder) { builder.add(VALID); + builder.add(FACING); super.fillStateContainer(builder); } public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { if (!state.get(VALID)) return; + + Direction facing = state.get(FACING); + Axis axis = facing.getAxis(); + + checkEntityForProcessing(worldIn, pos, entityIn); + withTileEntityDo(worldIn, pos, te -> { if (te.processingEntity == entityIn) - entityIn.setMotionMultiplier(state, new Vec3d(0.25D, (double) 0.05F, 0.25D)); + + entityIn.setMotionMultiplier(state, new Vec3d(axis == Axis.X ? (double) 0.05F : 0.25D + , axis == Axis.Y ? (double) 0.05F : 0.25D + , axis == Axis.Z ? (double) 0.05F : 0.25D)); }); } - @Override - public void onLanded(IBlockReader worldIn, Entity entityIn) { - super.onLanded(worldIn, entityIn); + public void checkEntityForProcessing(World worldIn, BlockPos pos, Entity entityIn){ try { - CrushingWheelControllerTileEntity te = getTileEntity(worldIn, entityIn.getPosition().down()); + CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); if (te.crushingspeed == 0) return; if (entityIn instanceof ItemEntity) ((ItemEntity) entityIn).setPickupDelay(10); + CompoundNBT data = entityIn.getPersistentData(); + if (data.contains("BypassCrushingWheel")) { + if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) + return; + } if (te.isOccupied()) return; boolean isPlayer = entityIn instanceof PlayerEntity; @@ -99,6 +114,12 @@ public class CrushingWheelControllerBlock extends Block } catch (TileEntityException e) {} } + @Override + public void onLanded(IBlockReader worldIn, Entity entityIn) { + super.onLanded(worldIn, entityIn); + //Moved to onEntityCollision to allow for omnidirectional input + } + @Override public void animateTick(BlockState stateIn, World worldIn, BlockPos pos, Random rand) { if (!stateIn.get(VALID)) @@ -128,7 +149,7 @@ public class CrushingWheelControllerBlock extends Block return; } - for (Direction d : Iterate.horizontalDirections) { + for (Direction d : Iterate.directions) { BlockState neighbour = world.getBlockState(pos.offset(d)); if (!AllBlocks.CRUSHING_WHEEL.has(neighbour)) continue; @@ -144,22 +165,19 @@ public class CrushingWheelControllerBlock extends Block @Override public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, - ISelectionContext context) { + ISelectionContext context) { if (!state.get(VALID)) - return VoxelShapes.fullCube(); + return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING)); Entity entity = context.getEntity(); if (entity != null) { - if (entity != null) { - CompoundNBT data = entity.getPersistentData(); - if (data.contains("BypassCrushingWheel")) { - if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) - return VoxelShapes.empty(); - } - } - if (new AxisAlignedBB(pos).contains(entity.getPositionVec())) - return VoxelShapes.empty(); + CompoundNBT data = entity.getPersistentData(); + if (data.contains("BypassCrushingWheel")) { + if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) + if (state.get(FACING) != Direction.UP) //Allow output items to land on top of the block rather than falling back through. + return VoxelShapes.empty(); + } try { CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); @@ -167,7 +185,7 @@ public class CrushingWheelControllerBlock extends Block return VoxelShapes.empty(); } catch (TileEntityException e) {} } - return VoxelShapes.fullCube(); + return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING)); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java index 2c1eb2f3b..2fb13c6c0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerTileEntity.java @@ -6,6 +6,8 @@ import java.util.Optional; import java.util.Random; import java.util.UUID; +import static com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock.FACING; + import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.processing.ProcessingInventory; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; @@ -16,6 +18,7 @@ import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.BlockItem; @@ -28,7 +31,9 @@ import net.minecraft.particles.ItemParticleData; import net.minecraft.particles.ParticleTypes; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraftforge.common.capabilities.Capability; @@ -63,7 +68,15 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { @Override public void addBehaviours(List behaviours) { - behaviours.add(new DirectBeltInputBehaviour(this)); + behaviours.add(new DirectBeltInputBehaviour(this).onlyInsertWhen(this::supportsDirectBeltInput)); + } + + private boolean supportsDirectBeltInput(Direction side) { + BlockState blockState = getBlockState(); + if (blockState == null) + return false; + Direction direction = blockState.get(CrushingWheelControllerBlock.FACING); + return direction == Direction.DOWN || direction == side; } @Override @@ -72,26 +85,37 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { if (searchForEntity) { searchForEntity = false; List search = world.getEntitiesInAABBexcluding(null, new AxisAlignedBB(getPos()), - e -> entityUUID.equals(e.getUniqueID())); + e -> entityUUID.equals(e.getUniqueID())); if (search.isEmpty()) clear(); else processingEntity = search.get(0); } + + if (!isOccupied()) return; if (crushingspeed == 0) return; float speed = crushingspeed * 4; - Vec3d outPos = VecHelper.getCenterOf(pos); + + Vec3d centerPos = VecHelper.getCenterOf(pos); + Direction facing = getBlockState().get(FACING); + int offset = facing.getAxisDirection().getOffset(); + Vec3d outSpeed = new Vec3d((facing.getAxis() == Axis.X ? 0.25D : 0.0D) * offset + , offset == 1 ? (facing.getAxis() == Axis.Y ? 0.5D : 0.0D) : 0.0D //Increased upwards speed so upwards crushing wheels shoot out the item properly. + , (facing.getAxis() == Axis.Z ? 0.25D : 0.0D) * offset); //No downwards speed, so downwards crushing wheels drop the items as before. + Vec3d outPos = centerPos.add((facing.getAxis() == Axis.X ? .55f * offset : 0f) + , (facing.getAxis() == Axis.Y ? .55f * offset : 0f) + , (facing.getAxis() == Axis.Z ? .55f * offset : 0f)); if (!hasEntity()) { float processingSpeed = - MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0) - .getCount()) : 1), .25f, 20); + MathHelper.clamp((speed) / (!inventory.appliedRecipe ? MathHelper.log2(inventory.getStackInSlot(0) + .getCount()) : 1), .25f, 20); inventory.remainingTime -= processingSpeed; spawnParticles(inventory.getStackInSlot(0)); @@ -105,27 +129,59 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { return; } - if (inventory.remainingTime <= 0) { - for (int slot = 0; slot < inventory.getSlots(); slot++) { - ItemStack stack = inventory.getStackInSlot(slot); - if (stack.isEmpty()) - continue; - ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack); - entityIn.setMotion(Vec3d.ZERO); - entityIn.getPersistentData() - .put("BypassCrushingWheel", NBTUtil.writeBlockPos(pos)); - world.addEntity(entityIn); - } - inventory.clear(); - world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); + if (inventory.remainingTime > 0) { return; } + inventory.remainingTime = 0; + + //Output Items + if (facing.getAxis().isHorizontal() || facing == Direction.DOWN) { + BlockPos nextPos = pos.add(facing.getAxis() == Axis.X ? 1f * offset : 0f + , (-1f) + , facing.getAxis() == Axis.Z ? 1f * offset : 0f); + DirectBeltInputBehaviour behaviour = TileEntityBehaviour.get(world, nextPos, DirectBeltInputBehaviour.TYPE); + if (behaviour != null) { + boolean changed = false; + if (!behaviour.canInsertFromSide(facing)) + return; + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemStack remainder = behaviour.handleInsertion(stack, facing, false); + if (remainder.equals(stack, false)) + continue; + inventory.setStackInSlot(slot, remainder); + changed = true; + } + if (changed) { + markDirty(); + sendData(); + } + return; + } + } + + //Eject Items + for (int slot = 0; slot < inventory.getSlots(); slot++) { + ItemStack stack = inventory.getStackInSlot(slot); + if (stack.isEmpty()) + continue; + ItemEntity entityIn = new ItemEntity(world, outPos.x, outPos.y, outPos.z, stack); + entityIn.setMotion(outSpeed); + entityIn.getPersistentData() + .put("BypassCrushingWheel", NBTUtil.writeBlockPos(pos)); + world.addEntity(entityIn); + } + inventory.clear(); + world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); + return; } if (!processingEntity.isAlive() || !processingEntity.getBoundingBox() - .intersects(new AxisAlignedBB(pos).grow(.5f))) { + .intersects(new AxisAlignedBB(pos).grow(.5f))) { clear(); return; } @@ -134,32 +190,49 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { double zMotion = ((pos.getZ() + .5f) - processingEntity.getZ()) / 2f; if (processingEntity.isSneaking()) xMotion = zMotion = 0; - - processingEntity.setMotion(new Vec3d(xMotion, Math.max(-speed / 4f, -.5f), zMotion)); + double movement = Math.max(-speed / 4f, -.5f) * -offset; + processingEntity.setMotion(new Vec3d(facing.getAxis() == Axis.X ? movement : xMotion + , facing.getAxis() == Axis.Y ? movement : 0f //Do not move entities upwards or downwards for horizontal crushers, + , facing.getAxis() == Axis.Z ? movement : zMotion)); //Or they'll only get their feet crushed. if (world.isRemote) return; if (!(processingEntity instanceof ItemEntity)) { processingEntity.attackEntityFrom(CrushingWheelTileEntity.damageSource, - AllConfigs.SERVER.kinetics.crushingDamage.get()); + AllConfigs.SERVER.kinetics.crushingDamage.get()); if (!processingEntity.isAlive()) { - processingEntity.setPosition(outPos.x, outPos.y - .75f, outPos.z); + processingEntity.setPosition(outPos.x + (facing.getAxis() == Axis.X ? .75f * offset : 0f) //This is supposed to move the mobs to the output location + , outPos.y + (facing.getAxis() == Axis.Y ? .75f * offset : 0f) //So the item drops end up on the other end + , outPos.z + (facing.getAxis() == Axis.Z ? .75f * offset : 0f)); //This, however, does not currently work consistently for non-downwards crushers. } return; } ItemEntity itemEntity = (ItemEntity) processingEntity; itemEntity.setPickupDelay(20); - if (processingEntity.getY() < pos.getY() + .25f) { - inventory.clear(); - inventory.setStackInSlot(0, itemEntity.getItem() - .copy()); - itemInserted(inventory.getStackInSlot(0)); - itemEntity.remove(); - world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); + if (facing.getAxis() == Axis.Y) { + if (processingEntity.getY() * -offset < (centerPos.y - .25f) * -offset) { + intakeItem(itemEntity); + } + } else if (facing.getAxis() == Axis.Z) { + if (processingEntity.getZ() * -offset < (centerPos.z - .25f) * -offset) { + intakeItem(itemEntity); + } + } else { + if (processingEntity.getX() * -offset < (centerPos.x - .25f) * -offset) { + intakeItem(itemEntity); + } } + } + private void intakeItem(ItemEntity itemEntity) { + inventory.clear(); + inventory.setStackInSlot(0, itemEntity.getItem() + .copy()); + itemInserted(inventory.getStackInSlot(0)); + itemEntity.remove(); + world.notifyBlockUpdate(pos, getBlockState(), getBlockState(), 2 | 16); } protected void spawnParticles(ItemStack stack) { @@ -169,14 +242,14 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { IParticleData particleData = null; if (stack.getItem() instanceof BlockItem) particleData = new BlockParticleData(ParticleTypes.BLOCK, ((BlockItem) stack.getItem()).getBlock() - .getDefaultState()); + .getDefaultState()); else particleData = new ItemParticleData(ParticleTypes.ITEM, stack); Random r = world.rand; for (int i = 0; i < 4; i++) world.addParticle(particleData, pos.getX() + r.nextFloat(), pos.getY() + r.nextFloat(), - pos.getZ() + r.nextFloat(), 0, 0, 0); + pos.getZ() + r.nextFloat(), 0, 0, 0); } private void applyRecipe() { @@ -185,11 +258,11 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { List list = new ArrayList<>(); if (recipe.isPresent()) { int rolls = inventory.getStackInSlot(0) - .getCount(); + .getCount(); inventory.clear(); for (int roll = 0; roll < rolls; roll++) { List rolledResults = recipe.get() - .rollResults(); + .rollResults(); for (int i = 0; i < rolledResults.size(); i++) { ItemStack stack = rolledResults.get(i); ItemHelper.addToList(stack, list); @@ -238,7 +311,7 @@ public class CrushingWheelControllerTileEntity extends SmartTileEntity { private void itemInserted(ItemStack stack) { Optional> recipe = findRecipe(); inventory.remainingTime = recipe.isPresent() ? recipe.get() - .getProcessingDuration() : 100; + .getProcessingDuration() : 100; inventory.appliedRecipe = false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java index d14531a6c..8d94992d5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelTileEntity.java @@ -36,7 +36,7 @@ public class CrushingWheelTileEntity extends KineticTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { + public AxisAlignedBB makeRenderBoundingBox() { return new AxisAlignedBB(pos).grow(1); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java index 8482b8529..ee30d715c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java @@ -11,12 +11,14 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.State; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.NBTHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -102,7 +104,9 @@ public class DeployerRenderer extends SafeTileEntityRenderer protected void renderComponents(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light); + if (!FastRenderDispatcher.available(te.getWorld())) { + KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light); + } BlockState blockState = te.getBlockState(); BlockPos pos = te.getPos(); @@ -178,8 +182,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer double distance = context.position.distanceTo(center); double nextDistance = context.position.add(context.motion) .distanceTo(center); - factor = .5f - MathHelper.clamp(MathHelper.lerp(Minecraft.getInstance() - .getRenderPartialTicks(), distance, nextDistance), 0, 1); + factor = .5f - MathHelper.clamp(MathHelper.lerp(AnimationTickHolder.getPartialTicks(), distance, nextDistance), 0, 1); } Vec3d offset = new Vec3d(blockState.get(FACING) @@ -189,9 +192,9 @@ public class DeployerRenderer extends SafeTileEntityRenderer .getModel(); for (MatrixStack m : matrixStacks) m.translate(offset.x, offset.y, offset.z); - pole.light(lighting) + pole.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) .renderInto(ms, builder); - hand.light(lighting) + hand.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) .renderInto(ms, builder); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java index 1aa3a0330..4af470f72 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerTileEntity.java @@ -346,8 +346,8 @@ public class DeployerTileEntity extends KineticTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().grow(3); + public AxisAlignedBB makeRenderBoundingBox() { + return super.makeRenderBoundingBox().grow(3); } @Override @@ -382,4 +382,8 @@ public class DeployerTileEntity extends KineticTileEntity { return true; } + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java index 8f499bce8..53c2eac1d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java @@ -114,9 +114,10 @@ public class AirCurrent { entityDistance -= .5f; InWorldProcessing.Type processingType = getSegmentAt((float) entityDistance); - if (processingType == null) { - if (entity instanceof ServerPlayerEntity) - AllTriggers.triggerFor(AllTriggers.FAN, (PlayerEntity) entity); + if (entity instanceof ServerPlayerEntity) + AllTriggers.triggerFor(AllTriggers.FAN_PROCESSING.constructTriggerFor(processingType), (PlayerEntity) entity); + + if (processingType == null || processingType == Type.NONE) { continue; } @@ -139,24 +140,18 @@ public class AirCurrent { entity.setFire(10); entity.attackEntityFrom(damageSourceLava, 4); } - if (entity instanceof ServerPlayerEntity) - AllTriggers.triggerFor(AllTriggers.FAN_LAVA, (PlayerEntity) entity); break; case SMOKING: if (!entity.isImmuneToFire()) { entity.setFire(2); entity.attackEntityFrom(damageSourceFire, 2); } - if (entity instanceof ServerPlayerEntity) - AllTriggers.triggerFor(AllTriggers.FAN_SMOKE, (PlayerEntity) entity); break; case SPLASHING: if (entity instanceof EndermanEntity || entity.getType() == EntityType.SNOW_GOLEM || entity.getType() == EntityType.BLAZE) { entity.attackEntityFrom(DamageSource.DROWN, 2); } - if (entity instanceof ServerPlayerEntity) - AllTriggers.triggerFor(AllTriggers.FAN_WATER, (PlayerEntity) entity); if (!entity.isBurning()) break; entity.extinguish(); @@ -193,7 +188,7 @@ public class AirCurrent { AirCurrentSegment currentSegment = new AirCurrentSegment(); segments.clear(); currentSegment.startOffset = 0; - InWorldProcessing.Type type = null; + InWorldProcessing.Type type = Type.NONE; int limit = (int) (maxDistance + .5f); int searchStart = pushing ? 0 : limit; @@ -203,7 +198,7 @@ public class AirCurrent { for (int i = searchStart; i * searchStep <= searchEnd * searchStep; i += searchStep) { BlockPos currentPos = start.offset(direction, i); InWorldProcessing.Type newType = InWorldProcessing.Type.byBlock(world, currentPos); - if (newType != null) + if (newType != Type.NONE) type = newType; if (currentSegment.type != type || currentSegment.startOffset == 0) { currentSegment.endOffset = i; @@ -341,7 +336,7 @@ public class AirCurrent { continue; return airCurrentSegment.type; } - return null; + return InWorldProcessing.Type.NONE; } public static class AirCurrentSegment { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java index 957ec69e7..5bf8b87d2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/EncasedFanRenderer.java @@ -7,8 +7,9 @@ import com.mojang.blaze3d.vertex.IVertexBuilder; 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.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -26,6 +27,8 @@ public class EncasedFanRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + if (FastRenderDispatcher.available(te.getWorld())) return; + Direction direction = te.getBlockState() .get(FACING); IVertexBuilder vb = buffer.getBuffer(RenderType.getCutoutMipped()); 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 new file mode 100644 index 000000000..c2fbf6d56 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java @@ -0,0 +1,118 @@ +package com.simibubi.create.content.contraptions.components.fan; + +import static net.minecraft.state.properties.BlockStateProperties.FACING; + +import com.simibubi.create.AllBlockPartials; +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.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class FanInstance extends KineticTileInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, FanInstance::new)); + } + + protected InstanceKey shaft; + protected InstanceKey fan; + + 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); + + InstancedModel shaftHalf = + AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, direction.getOpposite()); + InstancedModel fanInner = + AllBlockPartials.ENCASED_FAN_INNER.renderOnDirectionalSouthRotating(modelManager, lastState, direction.getOpposite()); + + shaft = shaftHalf.setupInstance(data -> { + BlockPos behind = pos.offset(direction.getOpposite()); + int blockLight = world.getLightLevel(LightType.BLOCK, behind); + int skyLight = world.getLightLevel(LightType.SKY, behind); + + data.setRotationalSpeed(tile.getSpeed()) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setTileEntity(tile) + .setBlockLight(blockLight) + .setSkyLight(skyLight); + }); + fan = fanInner.setupInstance(data -> { + BlockPos inFront = pos.offset(direction); + int blockLight = world.getLightLevel(LightType.BLOCK, inFront); + int skyLight = world.getLightLevel(LightType.SKY, inFront); + + data.setRotationalSpeed(getFanSpeed()) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setTileEntity(tile) + .setBlockLight(blockLight) + .setSkyLight(skyLight); + }); + } + + private float getFanSpeed() { + float speed = tile.getSpeed() * 5; + if (speed > 0) + speed = MathHelper.clamp(speed, 80, 64 * 20); + if (speed < 0) + speed = MathHelper.clamp(speed, -64 * 20, -80); + return speed; + } + + @Override + protected void onUpdate() { + Direction.Axis axis = lastState.get(FACING).getAxis(); + updateRotation(shaft, axis); + + fan.modifyInstance(data -> { + data.setColor(tile.network) + .setRotationalSpeed(getFanSpeed()) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()); + }); + } + + @Override + public void updateLight() { + final Direction direction = lastState.get(FACING); + + shaft.modifyInstance(data -> { + BlockPos behind = pos.offset(direction.getOpposite()); + int blockLight = world.getLightLevel(LightType.BLOCK, behind); + int skyLight = world.getLightLevel(LightType.SKY, behind); + data.setBlockLight(blockLight) + .setSkyLight(skyLight); + }); + fan.modifyInstance(data -> { + BlockPos inFront = pos.offset(direction); + int blockLight = world.getLightLevel(LightType.BLOCK, inFront); + int skyLight = world.getLightLevel(LightType.SKY, inFront); + data.setBlockLight(blockLight) + .setSkyLight(skyLight); + }); + } + + @Override + public void remove() { + shaft.delete(); + fan.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java index 2c0a842ce..8cffa1023 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleBlock.java @@ -1,8 +1,11 @@ package com.simibubi.create.content.contraptions.components.fan; +import javax.annotation.ParametersAreNonnullByDefault; + import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.ProperDirectionalBlock; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -18,8 +21,6 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -import javax.annotation.ParametersAreNonnullByDefault; - @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault public class NozzleBlock extends ProperDirectionalBlock { 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 new file mode 100644 index 000000000..f49c7dbef --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java @@ -0,0 +1,76 @@ +package com.simibubi.create.content.contraptions.components.flywheel; + +import java.util.function.Consumer; + +import com.simibubi.create.AllBlockPartials; +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.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.Rotation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class FlyWheelInstance extends KineticTileInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, FlyWheelInstance::new)); + } + + protected Direction facing; + + protected InstanceKey shaft; +// protected InstanceKey wheel; + + public FlyWheelInstance(InstancedTileRenderer modelManager, FlywheelTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected void init() { + facing = lastState.get(BlockStateProperties.HORIZONTAL_FACING); + + Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + Consumer setup = setupFunc(tile.getSpeed(), axis); + shaft = shaftModel().setupInstance(setup); +// wheel = wheelModel().setupInstance(setup); + } + + @Override + protected void onUpdate() { + Direction.Axis axis = ((IRotate) lastState.getBlock()).getRotationAxis(lastState); + updateRotation(shaft, axis); +// updateRotation(wheel, axis); + } + + @Override + public void updateLight() { + shaft.modifyInstance(this::relight); +// wheel.modifyInstance(this::relight); + } + + @Override + public void remove() { + shaft.delete(); + shaft = null; +// wheel.delete(); +// wheel = null; + } + + protected InstancedModel shaftModel() { + return AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, facing.getOpposite()); + } + + protected InstancedModel wheelModel() { + BlockState rotate = lastState.rotate(Rotation.CLOCKWISE_90); + return AllBlockPartials.FLYWHEEL.renderOnDirectionalSouthRotating(modelManager, rotate, rotate.get(BlockStateProperties.HORIZONTAL_FACING)); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java index 9632779d4..be3d3e108 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelRenderer.java @@ -8,8 +8,8 @@ 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.components.flywheel.FlywheelBlock.ConnectionState; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java index 05283aebd..67f4952b7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlywheelTileEntity.java @@ -48,8 +48,8 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().grow(2); + public AxisAlignedBB makeRenderBoundingBox() { + return super.makeRenderBoundingBox().grow(2); } @Override @@ -101,4 +101,8 @@ public class FlywheelTileEntity extends GeneratingKineticTileEntity { } } + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java index a0869af09..6a3988caa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineTileEntity.java @@ -14,6 +14,8 @@ import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class EngineTileEntity extends SmartTileEntity { @@ -34,9 +36,14 @@ public class EngineTileEntity extends SmartTileEntity { return true; } + protected AxisAlignedBB cachedBoundingBox; @Override + @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().grow(1.5f); + if (cachedBoundingBox == null) { + cachedBoundingBox = super.getRenderBoundingBox().grow(1.5f); + } + return cachedBoundingBox; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillStoneCogInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillStoneCogInstance.java new file mode 100644 index 000000000..329cc5e7b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillStoneCogInstance.java @@ -0,0 +1,28 @@ +package com.simibubi.create.content.contraptions.components.millstone; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.base.RotatingData; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class MillStoneCogInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, MillStoneCogInstance::new)); } + + public MillStoneCogInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected InstancedModel getModel() { + return AllBlockPartials.MILLSTONE_COG.renderOnRotating(modelManager, tile.getBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java index 2890f16d3..f9fa65b7b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneRenderer.java @@ -4,7 +4,7 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java index da84d012f..4220afa17 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MechanicalMixerRenderer.java @@ -5,8 +5,9 @@ import com.mojang.blaze3d.vertex.IVertexBuilder; 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.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -22,6 +23,11 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer { super(dispatcher); } + @Override + public boolean isGlobalRenderer(KineticTileEntity te) { + return true; + } + @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { @@ -31,8 +37,10 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer { IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState); - standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); + if (!FastRenderDispatcher.available(te.getWorld())) { + SuperByteBuffer superBuffer = AllBlockPartials.SHAFTLESS_COGWHEEL.renderOn(blockState); + standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); + } int packedLightmapCoords = WorldRenderer.getLightmapCoordinates(te.getWorld(), blockState, pos); float renderedHeadOffset = mixer.getRenderedHeadOffset(partialTicks); 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 b6037c0c7..6073f366e 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 @@ -80,7 +80,7 @@ public class MechanicalMixerTileEntity extends BasinOperatingTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { + public AxisAlignedBB makeRenderBoundingBox() { return new AxisAlignedBB(pos).expand(0, -1.5, 0); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java index 0993097d0..215cf1b57 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/motor/CreativeMotorRenderer.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.components.motor; 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.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java index 1a721bac8..18f2353a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/MechanicalPressRenderer.java @@ -4,7 +4,7 @@ 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.KineticTileEntityRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -19,6 +19,11 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer { super(dispatcher); } + @Override + public boolean isGlobalRenderer(KineticTileEntity te) { + return true; + } + @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { 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 ca52ae3a6..ddc48fb8b 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 @@ -102,7 +102,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { + public AxisAlignedBB makeRenderBoundingBox() { return new AxisAlignedBB(pos).expand(0, -1.5, 0) .expand(0, 1, 0); } 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 new file mode 100644 index 000000000..62060db98 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java @@ -0,0 +1,36 @@ +package com.simibubi.create.content.contraptions.components.saw; + +import static net.minecraft.state.properties.BlockStateProperties.FACING; + +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.base.RotatingData; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Rotation; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class SawInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, SawInstance::new)); + } + + public SawInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @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)); + else + return rotatingMaterial().getModel(KineticTileEntityRenderer.KINETIC_TILE, shaft(getRotationAxis())); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java index 6ab63b12f..d68105100 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawRenderer.java @@ -8,11 +8,13 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -42,6 +44,9 @@ public class SawRenderer extends SafeTileEntityRenderer { renderBlade(te, ms, buffer, light); renderItems(te, partialTicks, ms, buffer, light, overlay); FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); + + if (FastRenderDispatcher.available(te.getWorld())) return; + renderShaft(te, ms, buffer, light, overlay); } @@ -179,7 +184,7 @@ public class SawRenderer extends SafeTileEntityRenderer { superBuffer .light(msLocal.peek() - .getModel()) + .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); } 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 64a448598..8652591db 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 @@ -4,9 +4,9 @@ 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 com.google.common.base.Predicate; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity; import com.simibubi.create.content.contraptions.processing.ProcessingInventory; @@ -22,6 +22,7 @@ import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.recipe.RecipeConditions; import com.simibubi.create.foundation.utility.recipe.RecipeFinder; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BambooBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -45,21 +46,30 @@ import net.minecraft.particles.ParticleTypes; import net.minecraft.tags.BlockTags; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; +import net.minecraft.util.LazyValue; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; +import javax.annotation.ParametersAreNonnullByDefault; + + +@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 ProcessingInventory inventory; private int recipeIndex; - private LazyOptional invProvider = LazyOptional.empty(); + private final LazyOptional invProvider; private FilteringBehaviour filtering; public SawTileEntity(TileEntityType type) { @@ -251,7 +261,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { List results = new LinkedList(); if (recipe instanceof CuttingRecipe) results = ((CuttingRecipe) recipe).rollResults(); - else if (recipe instanceof StonecuttingRecipe) + else if (recipe instanceof StonecuttingRecipe || recipe.getType() == woodcuttingRecipeType.getValue()) results.add(recipe.getRecipeOutput() .copy()); @@ -266,10 +276,20 @@ 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()); - List> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, types); + + */ + + Predicate> types = RecipeConditions.isOfType( + AllRecipeTypes.CUTTING.getType(), + AllConfigs.SERVER.recipes.allowStonecuttingOnSaw.get() ? IRecipeType.STONECUTTING : null, + AllConfigs.SERVER.recipes.allowWoodcuttingOnSaw.get() ? woodcuttingRecipeType.getValue() : null + ); + + List> startedSearch = RecipeFinder.get(cuttingRecipesKey, world, types); return startedSearch.stream() .filter(RecipeConditions.outputMatchesFilter(filtering)) .filter(RecipeConditions.firstIngredientMatches(inventory.getStackInSlot(0))) @@ -393,4 +413,9 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { return false; } + @Override + public boolean shouldRenderAsTE() { + return true; + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java index c863f4372..acd2b1625 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntity.java @@ -10,6 +10,7 @@ import java.util.UUID; import org.apache.commons.lang3.mutable.MutableInt; import org.apache.commons.lang3.tuple.MutablePair; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; @@ -58,6 +59,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit protected Contraption contraption; protected boolean initialized; private boolean prevPosInvalid; + private boolean ticking; public AbstractContraptionEntity(EntityType entityTypeIn, World worldIn) { super(entityTypeIn, worldIn); @@ -245,6 +247,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit if (!world.isRemote) contraption.stalled = false; + ticking = true; for (MutablePair pair : contraption.getActors()) { MovementContext context = pair.right; BlockInfo blockInfo = pair.left; @@ -264,13 +267,25 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit continue; if (newPosVisited && !context.stall) { actor.visitNewPosition(context, gridPosition); + if (!isAlive()) + break; context.firstMovement = false; } - if (!oldMotion.equals(context.motion)) + if (!oldMotion.equals(context.motion)) { actor.onSpeedChanged(context, oldMotion, context.motion); + if (!isAlive()) + break; + } actor.tick(context); + if (!isAlive()) + break; contraption.stalled |= context.stall; } + if (!isAlive()) { + contraption.stop(world); + return; + } + ticking = false; for (Entity entity : getPassengers()) { if (!(entity instanceof OrientedContraptionEntity)) @@ -444,7 +459,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit @Override public void remove(boolean keepData) { if (!world.isRemote && !removed && contraption != null) { - contraption.stop(world); + if (!ticking) + contraption.stop(world); } super.remove(keepData); } @@ -597,6 +613,9 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit return false; } + @OnlyIn(Dist.CLIENT) + public abstract void doLocalTransforms(float partialTicks, MatrixStack[] matrixStacks); + public static class ContraptionRotationState { public static final ContraptionRotationState NONE = new ContraptionRotationState(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java index 0db500c6d..d4f38a469 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AssemblyException.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.simibubi.create.foundation.config.AllConfigs; + import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.math.BlockPos; @@ -8,6 +9,8 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TranslationTextComponent; public class AssemblyException extends Exception { + + private static final long serialVersionUID = 1L; public final ITextComponent component; private BlockPos position = null; 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 6fc93a511..3e363d2d3 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 @@ -1,5 +1,29 @@ package com.simibubi.create.content.contraptions.components.structureMovement; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.Queue; +import java.util.Set; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.stream.Collectors; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.tuple.MutablePair; +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.base.IRotate; @@ -28,19 +52,29 @@ import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBl import com.simibubi.create.content.logistics.block.redstone.RedstoneContactBlock; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.fluid.CombinedTankWrapper; +import com.simibubi.create.foundation.render.backend.light.EmptyLighter; import com.simibubi.create.foundation.utility.BlockFace; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; -import net.minecraft.block.*; + +import net.minecraft.block.AbstractButtonBlock; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.ChestBlock; +import net.minecraft.block.DoorBlock; +import net.minecraft.block.IWaterLoggable; +import net.minecraft.block.PressurePlateBlock; import net.minecraft.block.material.PushReaction; import net.minecraft.entity.Entity; import net.minecraft.fluid.Fluids; import net.minecraft.fluid.IFluidState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.state.properties.BlockStateProperties; @@ -55,9 +89,12 @@ import net.minecraft.util.Rotation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.palette.PaletteHashMap; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.Constants.BlockFlags; import net.minecraftforge.common.util.Constants.NBT; import net.minecraftforge.fluids.FluidStack; @@ -67,16 +104,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; import net.minecraftforge.fluids.capability.templates.FluidTank; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.wrapper.CombinedInvWrapper; -import org.apache.commons.lang3.tuple.MutablePair; -import org.apache.commons.lang3.tuple.Pair; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.function.BiConsumer; -import java.util.stream.Collectors; - -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; +import net.minecraftforge.registries.GameData; public abstract class Contraption { @@ -102,7 +130,8 @@ public abstract class Contraption { // Client public Map presentTileEntities; - public List renderedTileEntities; + public List maybeInstancedTileEntities; + public List specialRenderedTileEntities; public Contraption() { blocks = new HashMap<>(); @@ -115,7 +144,8 @@ public abstract class Contraption { glueToRemove = new ArrayList<>(); initialPassengers = new HashMap<>(); presentTileEntities = new HashMap<>(); - renderedTileEntities = new ArrayList<>(); + maybeInstancedTileEntities = new ArrayList<>(); + specialRenderedTileEntities = new ArrayList<>(); pendingSubContraptions = new ArrayList<>(); stabilizedSubContraptions = new HashMap<>(); } @@ -474,7 +504,6 @@ public abstract class Contraption { } private boolean moveMechanicalPiston(World world, BlockPos pos, Queue frontier, Set visited, BlockState state) throws AssemblyException { - int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get(); Direction direction = state.get(MechanicalPistonBlock.FACING); PistonState pistonState = state.get(MechanicalPistonBlock.STATE); if (pistonState == PistonState.MOVING) @@ -593,53 +622,18 @@ public abstract class Contraption { public void readNBT(World world, CompoundNBT nbt, boolean spawnData) { blocks.clear(); presentTileEntities.clear(); - renderedTileEntities.clear(); + specialRenderedTileEntities.clear(); - nbt.getList("Blocks", 10) - .forEach(c -> { - CompoundNBT comp = (CompoundNBT) c; - BlockInfo info = new BlockInfo(NBTUtil.readBlockPos(comp.getCompound("Pos")), - NBTUtil.readBlockState(comp.getCompound("Block")), - comp.contains("Data") ? comp.getCompound("Data") : null); - blocks.put(info.pos, info); - - if (world.isRemote) { - Block block = info.state.getBlock(); - CompoundNBT tag = info.nbt; - MovementBehaviour movementBehaviour = AllMovementBehaviours.of(block); - if (tag == null || (movementBehaviour != null && movementBehaviour.hasSpecialMovementRenderer())) - return; - - tag.putInt("x", info.pos.getX()); - tag.putInt("y", info.pos.getY()); - tag.putInt("z", info.pos.getZ()); - - TileEntity te = TileEntity.create(tag); - if (te == null) - return; - te.setLocation(new WrappedWorld(world) { - - @Override - public BlockState getBlockState(BlockPos pos) { - if (!pos.equals(te.getPos())) - return Blocks.AIR.getDefaultState(); - return info.state; - } - - }, te.getPos()); - if (te instanceof KineticTileEntity) - ((KineticTileEntity) te).setSpeed(0); - te.getBlockState(); - presentTileEntities.put(info.pos, te); - renderedTileEntities.add(te); - } - }); + INBT blocks = nbt.get("Blocks"); + //used to differentiate between the 'old' and the paletted serialization + boolean usePalettedDeserialization = blocks != null && blocks.getId() == 10 && ((CompoundNBT) blocks).contains("Palette"); + readBlocksCompound(blocks, world, usePalettedDeserialization); actors.clear(); nbt.getList("Actors", 10) .forEach(c -> { CompoundNBT comp = (CompoundNBT) c; - BlockInfo info = blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos"))); + BlockInfo info = this.blocks.get(NBTUtil.readBlockPos(comp.getCompound("Pos"))); MovementContext context = MovementContext.readNBT(world, info, comp, this); getActors().add(MutablePair.of(info, context)); }); @@ -704,15 +698,8 @@ public abstract class Contraption { public CompoundNBT writeNBT(boolean spawnPacket) { CompoundNBT nbt = new CompoundNBT(); nbt.putString("Type", getType().id); - ListNBT blocksNBT = new ListNBT(); - for (BlockInfo block : this.blocks.values()) { - CompoundNBT c = new CompoundNBT(); - c.put("Block", NBTUtil.writeBlockState(block.state)); - c.put("Pos", NBTUtil.writeBlockPos(block.pos)); - if (block.nbt != null) - c.put("Data", block.nbt); - blocksNBT.add(c); - } + + CompoundNBT blocksNBT = writeBlocksCompound(); ListNBT actorsNBT = new ListNBT(); for (MutablePair actor : getActors()) { @@ -789,6 +776,107 @@ public abstract class Contraption { return nbt; } + private CompoundNBT writeBlocksCompound() { + CompoundNBT compound = new CompoundNBT(); + PaletteHashMap palette = new PaletteHashMap<>(GameData.getBlockStateIDMap(), 16, (i, s) -> {throw new IllegalStateException("Palette Map index exceeded maximum");}, NBTUtil::readBlockState, NBTUtil::writeBlockState); + ListNBT blockList = new ListNBT(); + + for (BlockInfo block : this.blocks.values()) { + int id = palette.idFor(block.state); + CompoundNBT c = new CompoundNBT(); + c.putLong("Pos", block.pos.toLong()); + c.putInt("State", id); + if (block.nbt != null) + c.put("Data", block.nbt); + blockList.add(c); + } + + ListNBT paletteNBT = new ListNBT(); + palette.writePaletteToList(paletteNBT); + compound.put("Palette", paletteNBT); + compound.put("BlockList", blockList); + + return compound; + } + + private void readBlocksCompound(INBT compound, World world, boolean usePalettedDeserialization) { + PaletteHashMap palette = null; + ListNBT blockList; + if (usePalettedDeserialization) { + CompoundNBT c = ((CompoundNBT) compound); + palette = new PaletteHashMap<>(GameData.getBlockStateIDMap(), 16, (i, s) -> {throw new IllegalStateException("Palette Map index exceeded maximum");}, NBTUtil::readBlockState, NBTUtil::writeBlockState); + palette.read(c.getList("Palette", 10)); + + blockList = c.getList("BlockList", 10); + } else { + blockList = (ListNBT) compound; + } + + PaletteHashMap finalPalette = palette; + blockList.forEach(e -> { + CompoundNBT c = (CompoundNBT) e; + + BlockInfo info = usePalettedDeserialization ? readBlockInfo(c, finalPalette) : legacyReadBlockInfo(c); + + this.blocks.put(info.pos, info); + + if (world.isRemote) { + Block block = info.state.getBlock(); + CompoundNBT tag = info.nbt; + MovementBehaviour movementBehaviour = AllMovementBehaviours.of(block); + if (tag == null) + return; + + tag.putInt("x", info.pos.getX()); + tag.putInt("y", info.pos.getY()); + tag.putInt("z", info.pos.getZ()); + + TileEntity te = TileEntity.create(tag); + if (te == null) + return; + te.setLocation(new WrappedWorld(world) { + + @Override + public BlockState getBlockState(BlockPos pos) { + if (!pos.equals(te.getPos())) + return Blocks.AIR.getDefaultState(); + return info.state; + } + + }, te.getPos()); + if (te instanceof KineticTileEntity) + ((KineticTileEntity) te).setSpeed(0); + te.getBlockState(); + + if (movementBehaviour == null || !movementBehaviour.hasSpecialInstancedRendering()) + maybeInstancedTileEntities.add(te); + + if (movementBehaviour != null && !movementBehaviour.renderAsNormalTileEntity()) + return; + + presentTileEntities.put(info.pos, te); + specialRenderedTileEntities.add(te); + } + + }); + } + + private static BlockInfo readBlockInfo(CompoundNBT blockListEntry, PaletteHashMap palette) { + return new BlockInfo( + BlockPos.fromLong(blockListEntry.getLong("Pos")), + Objects.requireNonNull(palette.get(blockListEntry.getInt("State"))), + blockListEntry.contains("Data") ? blockListEntry.getCompound("Data") : null + ); + } + + private static BlockInfo legacyReadBlockInfo(CompoundNBT blockListEntry) { + return new BlockInfo( + NBTUtil.readBlockPos(blockListEntry.getCompound("Pos")), + NBTUtil.readBlockState(blockListEntry.getCompound("Block")), + blockListEntry.contains("Data") ? blockListEntry.getCompound("Data") : null + ); + } + public void removeBlocksFromWorld(World world, BlockPos offset) { storage.values() .forEach(MountedStorage::removeStorageFromWorld); @@ -915,7 +1003,6 @@ public abstract class Contraption { if (!shouldUpdateAfterMovement(block)) continue; BlockPos targetPos = transform.apply(block.pos); - BlockState state = world.getBlockState(targetPos); world.markAndNotifyBlock(targetPos, null, block.state, block.state, BlockFlags.IS_MOVING | BlockFlags.DEFAULT); } @@ -1049,4 +1136,9 @@ public abstract class Contraption { mountedFluidStorage.updateFluid(containedFluid); } + @OnlyIn(Dist.CLIENT) + public ContraptionLighter makeLighter() { + return new EmptyLighter(this); + } + } 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 4f8e5f812..f9922623a 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 @@ -311,7 +311,7 @@ public class ContraptionCollider { if (!entity.world.isRemote) return PlayerType.SERVER; MutableBoolean isClient = new MutableBoolean(false); - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> isClient.setValue(isClientPlayerEntity(entity))); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> isClient.setValue(isClientPlayerEntity(entity))); return isClient.booleanValue() ? PlayerType.CLIENT : PlayerType.REMOTE; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java index 20baaaa45..50b27b6ff 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionDisassemblyPacket.java @@ -33,7 +33,7 @@ public class ContraptionDisassemblyPacket extends SimplePacketBase { @Override public void handle(Supplier context) { context.get() - .enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, + .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleDisassemblyPacket(this))); context.get() .setPacketHandled(true); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java similarity index 58% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java rename to src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java index f6b9ad44d..b66008c4e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/AbstractContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java @@ -1,8 +1,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.utility.AnimationTickHolder; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.culling.ClippingHelperImpl; import net.minecraft.client.renderer.entity.EntityRenderer; @@ -10,29 +11,26 @@ import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; -public abstract class AbstractContraptionEntityRenderer extends EntityRenderer { +public class ContraptionEntityRenderer extends EntityRenderer { - protected AbstractContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { + public ContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { super(p_i46179_1_); } @Override - public ResourceLocation getEntityTexture(C p_110775_1_) { + public ResourceLocation getEntityTexture(C entity) { return null; } - protected abstract void transform(C contraptionEntity, float partialTicks, MatrixStack[] matrixStacks); - @Override - public boolean shouldRender(C entity, ClippingHelperImpl p_225626_2_, double p_225626_3_, double p_225626_5_, + public boolean shouldRender(C entity, ClippingHelperImpl clippingHelper, double p_225626_3_, double p_225626_5_, double p_225626_7_) { - if (!super.shouldRender(entity, p_225626_2_, p_225626_3_, p_225626_5_, p_225626_7_)) + if (entity.getContraption() == null) return false; if (!entity.isAlive()) return false; - if (entity.getContraption() == null) - return false; - return true; + + return super.shouldRender(entity, clippingHelper, p_225626_3_, p_225626_5_, p_225626_7_); } @Override @@ -41,21 +39,20 @@ public abstract class AbstractContraptionEntityRenderer { + protected final C contraption; + public final LightVolume lightVolume; + + protected GridAlignedBB bounds; + + protected boolean scheduleRebuild; + + protected ContraptionLighter(C contraption) { + this.contraption = contraption; + + bounds = getContraptionBounds(); + + lightVolume = new LightVolume(contraptionBoundsToVolume(bounds.copy())); + + 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; + } + + public void tick(RenderedContraption owner) { + if (scheduleRebuild) { + lightVolume.initialize(owner.contraption.entity.world); + scheduleRebuild = false; + } + } + + public abstract GridAlignedBB getContraptionBounds(); +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java deleted file mode 100644 index 7892307d8..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionRenderer.java +++ /dev/null @@ -1,157 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import java.util.List; -import java.util.Random; - -import org.apache.commons.lang3.tuple.Pair; -import org.lwjgl.opengl.GL11; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.SuperByteBufferCache; -import com.simibubi.create.foundation.utility.SuperByteBufferCache.Compartment; -import com.simibubi.create.foundation.utility.TileEntityRenderHelper; -import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; - -import net.minecraft.block.BlockRenderType; -import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; -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.Matrix4f; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.RenderTypeLookup; -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.world.LightType; -import net.minecraft.world.World; -import net.minecraft.world.gen.feature.template.Template.BlockInfo; -import net.minecraftforge.client.ForgeHooksClient; -import net.minecraftforge.client.model.data.EmptyModelData; - -public class ContraptionRenderer { - - public static final Compartment> CONTRAPTION = new Compartment<>(); - protected static PlacementSimulationWorld renderWorld; - - public static void render(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - renderTileEntities(world, c, ms, msLocal, buffer); - if (buffer instanceof IRenderTypeBuffer.Impl) - ((IRenderTypeBuffer.Impl) buffer).draw(); - renderStructure(world, c, ms, msLocal, buffer); - renderActors(world, c, ms, msLocal, buffer); - } - - protected static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - SuperByteBufferCache bufferCache = CreateClient.bufferCache; - List blockLayers = RenderType.getBlockLayers(); - - buffer.getBuffer(RenderType.getSolid()); - for (int i = 0; i < blockLayers.size(); i++) { - RenderType layer = blockLayers.get(i); - Pair key = Pair.of(c, i); - SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(c, layer)); - if (contraptionBuffer.isEmpty()) - continue; - Matrix4f model = msLocal.peek() - .getModel(); - contraptionBuffer.light(model) - .renderInto(ms, buffer.getBuffer(layer)); - } - } - - private static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - TileEntityRenderHelper.renderTileEntities(world, c.renderedTileEntities, ms, msLocal, buffer); - } - - private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { - if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world) - renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world); - - ForgeHooksClient.setRenderLayer(layer); - MatrixStack ms = new MatrixStack(); - BlockRendererDispatcher dispatcher = Minecraft.getInstance() - .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 (BlockInfo info : c.getBlocks() - .values()) - renderWorld.setBlockState(info.pos, info.state); - for (BlockInfo info : c.getBlocks() - .values()) { - BlockState state = info.state; - - if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) - continue; - if (!RenderTypeLookup.canRenderInLayer(state, layer)) - continue; - - IBakedModel originalModel = dispatcher.getModelForState(state); - 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); - ms.pop(); - } - - builder.finishDrawing(); - renderWorld.clear(); - return new SuperByteBuffer(builder); - } - - private static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; - for (Pair actor : c.getActors()) { - MovementContext context = actor.getRight(); - if (context == null) - continue; - if (context.world == null) - context.world = world; - BlockInfo blockInfo = actor.getLeft(); - for (MatrixStack m : matrixStacks) { - m.push(); - MatrixStacker.of(m) - .translate(blockInfo.pos); - } - - MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); - if (movementBehaviour != null) - movementBehaviour.renderInContraption(context, ms, msLocal, buffer); - - for (MatrixStack m : matrixStacks) - m.pop(); - } - } - - public static int getLight(World world, float lx, float ly, float lz) { - BlockPos.Mutable pos = new BlockPos.Mutable(); - float sky = 0, block = 0; - float offset = 1 / 8f; - - for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) - for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) - for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { - pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); - sky += world.getLightLevel(LightType.SKY, pos) / 8f; - block += world.getLightLevel(LightType.BLOCK, pos) / 8f; - } - - return ((int) sky) << 20 | ((int) block) << 4; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java index 1909dd3ca..9c9aac76f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionStallPacket.java @@ -42,7 +42,7 @@ public class ContraptionStallPacket extends SimplePacketBase { @Override public void handle(Supplier context) { context.get().enqueueWork( - () -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this))); + () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AbstractContraptionEntity.handleStallPacket(this))); context.get().setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java index 5ef894acb..9c78cf924 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntity.java @@ -2,8 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import static com.simibubi.create.foundation.utility.AngleHelper.angleLerp; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingContraption; +import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -219,4 +221,18 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { setPos(x, y, z); this.angle = angle; } + + @Override + @OnlyIn(Dist.CLIENT) + public void doLocalTransforms(float partialTicks, MatrixStack[] matrixStacks) { + float angle = getAngle(partialTicks); + Axis axis = getRotationAxis(); + + for (MatrixStack stack : matrixStacks) + MatrixStacker.of(stack) + .nudge(getEntityId()) + .centre() + .rotate(angle, axis) + .unCentre(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntityRenderer.java deleted file mode 100644 index 6567b0419..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ControlledContraptionEntityRenderer.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.utility.MatrixStacker; - -import net.minecraft.client.renderer.entity.EntityRendererManager; -import net.minecraft.util.Direction.Axis; - -public class ControlledContraptionEntityRenderer extends AbstractContraptionEntityRenderer { - - public ControlledContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { - super(p_i46179_1_); - } - - @Override - protected void transform(ControlledContraptionEntity entity, float partialTicks, - MatrixStack[] matrixStacks) { - float angle = entity.getAngle(partialTicks); - Axis axis = entity.getRotationAxis(); - - for (MatrixStack stack : matrixStacks) - MatrixStacker.of(stack) - .nudge(entity.getEntityId()) - .centre() - .rotate(angle, axis) - .unCentre(); - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java index 33abfc9fb..1a34952ef 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/IDisplayAssemblyExceptions.java @@ -1,12 +1,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement; -import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; -import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.util.text.TextFormatting; - import java.util.Arrays; import java.util.List; +import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.util.text.TextFormatting; + public interface IDisplayAssemblyExceptions { default boolean addExceptionToTooltip(List tooltip) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java index bf25055fe..062a1601a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MovementBehaviour.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.entity.item.ItemEntity; @@ -47,14 +48,21 @@ public abstract class MovementBehaviour { } - public boolean hasSpecialMovementRenderer() { - return true; + public boolean renderAsNormalTileEntity() { + return false; + } + + public boolean hasSpecialInstancedRendering() { + return false; } @OnlyIn(Dist.CLIENT) public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, IRenderTypeBuffer buffer) {} + @OnlyIn(Dist.CLIENT) + public void addInstance(RenderedContraption contraption, MovementContext context) {} + public void onSpeedChanged(MovementContext context, Vec3d oldMotion, Vec3d motion) { } 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 new file mode 100644 index 000000000..f93fd9beb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.contraptions.components.structureMovement; + +import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; + +public class NonStationaryLighter extends ContraptionLighter { + public NonStationaryLighter(C contraption) { + super(contraption); + } + + @Override + protected GridAlignedBB contraptionBoundsToVolume(GridAlignedBB bounds) { + bounds.grow(2); // 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; + } + + @Override + public void tick(RenderedContraption owner) { + super.tick(owner); + GridAlignedBB contraptionBounds = getContraptionBounds(); + + if (!contraptionBounds.sameAs(bounds)) { + lightVolume.move(contraption.entity.world, contraptionBoundsToVolume(contraptionBounds)); + bounds = contraptionBounds; + } + } + + @Override + public GridAlignedBB getContraptionBounds() { + GridAlignedBB bb = GridAlignedBB.fromAABB(contraption.bounds); + + bb.translate(contraption.entity.getPosition()); + + return bb; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java index cf77d0a14..6d241061a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntity.java @@ -7,6 +7,7 @@ import java.util.UUID; import javax.annotation.Nullable; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.StabilizedContraption; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; @@ -16,6 +17,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -40,6 +42,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.util.LazyOptional; /** @@ -494,4 +498,89 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { yaw = angle; } + @Override + @OnlyIn(Dist.CLIENT) + public void doLocalTransforms(float partialTicks, MatrixStack[] matrixStacks) { + float angleInitialYaw = getInitialYaw(); + float angleYaw = getYaw(partialTicks); + float anglePitch = getPitch(partialTicks); + + for (MatrixStack stack : matrixStacks) + stack.translate(-.5f, 0, -.5f); + + Entity ridingEntity = getRidingEntity(); + if (ridingEntity instanceof AbstractMinecartEntity) + repositionOnCart(partialTicks, matrixStacks, ridingEntity); + else if (ridingEntity instanceof AbstractContraptionEntity) { + if (ridingEntity.getRidingEntity() instanceof AbstractMinecartEntity) + repositionOnCart(partialTicks, matrixStacks, ridingEntity.getRidingEntity()); + else + repositionOnContraption(partialTicks, matrixStacks, ridingEntity); + } + + for (MatrixStack stack : matrixStacks) + MatrixStacker.of(stack) + .nudge(getEntityId()) + .centre() + .rotateY(angleYaw) + .rotateZ(anglePitch) + .rotateY(angleInitialYaw) + .unCentre(); + } + + @OnlyIn(Dist.CLIENT) + private void repositionOnContraption(float partialTicks, MatrixStack[] matrixStacks, Entity ridingEntity) { + Vec3d pos = getContraptionOffset(partialTicks, ridingEntity); + for (MatrixStack stack : matrixStacks) + stack.translate(pos.x, pos.y, pos.z); + } + + // Minecarts do not always render at their exact location, so the contraption + // has to adjust aswell + @OnlyIn(Dist.CLIENT) + private void repositionOnCart(float partialTicks, MatrixStack[] matrixStacks, Entity ridingEntity) { + Vec3d cartPos = getCartOffset(partialTicks, ridingEntity); + + if (cartPos == Vec3d.ZERO) return; + + for (MatrixStack stack : matrixStacks) + stack.translate(cartPos.x, cartPos.y, cartPos.z); + } + + @OnlyIn(Dist.CLIENT) + private Vec3d getContraptionOffset(float partialTicks, Entity ridingEntity) { + AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity; + Vec3d passengerPosition = parent.getPassengerPosition(this, partialTicks); + double x = passengerPosition.x - MathHelper.lerp(partialTicks, this.lastTickPosX, this.getX()); + double y = passengerPosition.y - MathHelper.lerp(partialTicks, this.lastTickPosY, this.getY()); + double z = passengerPosition.z - MathHelper.lerp(partialTicks, this.lastTickPosZ, this.getZ()); + + return new Vec3d(x, y, z); + } + + @OnlyIn(Dist.CLIENT) + private Vec3d getCartOffset(float partialTicks, Entity ridingEntity) { + AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity; + double cartX = MathHelper.lerp(partialTicks, cart.lastTickPosX, cart.getX()); + double cartY = MathHelper.lerp(partialTicks, cart.lastTickPosY, cart.getY()); + double cartZ = MathHelper.lerp(partialTicks, cart.lastTickPosZ, cart.getZ()); + Vec3d cartPos = cart.getPos(cartX, cartY, cartZ); + + if (cartPos != null) { + Vec3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F); + Vec3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F); + if (cartPosFront == null) + cartPosFront = cartPos; + if (cartPosBack == null) + cartPosBack = cartPos; + + cartX = cartPos.x - cartX; + cartY = (cartPosFront.y + cartPosBack.y) / 2.0D - cartY; + cartZ = cartPos.z - cartZ; + + return new Vec3d(cartX, cartY, cartZ); + } + + return Vec3d.ZERO; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java index bbef43c57..f3f6fd7b2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/OrientedContraptionEntityRenderer.java @@ -1,16 +1,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement; -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.utility.MatrixStacker; - import net.minecraft.client.renderer.culling.ClippingHelperImpl; import net.minecraft.client.renderer.entity.EntityRendererManager; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.minecart.AbstractMinecartEntity; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; -public class OrientedContraptionEntityRenderer extends AbstractContraptionEntityRenderer { +public class OrientedContraptionEntityRenderer extends ContraptionEntityRenderer { public OrientedContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { super(p_i46179_1_); @@ -18,79 +11,12 @@ public class OrientedContraptionEntityRenderer extends AbstractContraptionEntity @Override public boolean shouldRender(OrientedContraptionEntity entity, ClippingHelperImpl p_225626_2_, double p_225626_3_, - double p_225626_5_, double p_225626_7_) { + double p_225626_5_, double p_225626_7_) { if (!super.shouldRender(entity, p_225626_2_, p_225626_3_, p_225626_5_, p_225626_7_)) return false; if (entity.getContraption() - .getType() == ContraptionType.MOUNTED && entity.getRidingEntity() == null) + .getType() == ContraptionType.MOUNTED && entity.getRidingEntity() == null) return false; return true; } - - @Override - protected void transform(OrientedContraptionEntity entity, float partialTicks, MatrixStack[] matrixStacks) { - float angleInitialYaw = entity.getInitialYaw(); - float angleYaw = entity.getYaw(partialTicks); - float anglePitch = entity.getPitch(partialTicks); - - for (MatrixStack stack : matrixStacks) - stack.translate(-.5f, 0, -.5f); - - Entity ridingEntity = entity.getRidingEntity(); - if (ridingEntity instanceof AbstractMinecartEntity) - repositionOnCart(partialTicks, matrixStacks, ridingEntity); - if (ridingEntity instanceof AbstractContraptionEntity) { - if (ridingEntity.getRidingEntity() instanceof AbstractMinecartEntity) - repositionOnCart(partialTicks, matrixStacks, ridingEntity.getRidingEntity()); - else - repositionOnContraption(entity, partialTicks, matrixStacks, ridingEntity); - } - - for (MatrixStack stack : matrixStacks) - MatrixStacker.of(stack) - .nudge(entity.getEntityId()) - .centre() - .rotateY(angleYaw) - .rotateZ(anglePitch) - .rotateY(angleInitialYaw) - .unCentre(); - } - - private void repositionOnContraption(OrientedContraptionEntity entity, float partialTicks, - MatrixStack[] matrixStacks, Entity ridingEntity) { - AbstractContraptionEntity parent = (AbstractContraptionEntity) ridingEntity; - Vec3d passengerPosition = parent.getPassengerPosition(entity, partialTicks); - double x = passengerPosition.x - MathHelper.lerp(partialTicks, entity.lastTickPosX, entity.getX()); - double y = passengerPosition.y - MathHelper.lerp(partialTicks, entity.lastTickPosY, entity.getY()); - double z = passengerPosition.z - MathHelper.lerp(partialTicks, entity.lastTickPosZ, entity.getZ()); - for (MatrixStack stack : matrixStacks) - stack.translate(x, y, z); - } - - // Minecarts do not always render at their exact location, so the contraption - // has to adjust aswell - private void repositionOnCart(float partialTicks, MatrixStack[] matrixStacks, Entity ridingEntity) { - AbstractMinecartEntity cart = (AbstractMinecartEntity) ridingEntity; - double cartX = MathHelper.lerp(partialTicks, cart.lastTickPosX, cart.getX()); - double cartY = MathHelper.lerp(partialTicks, cart.lastTickPosY, cart.getY()); - double cartZ = MathHelper.lerp(partialTicks, cart.lastTickPosZ, cart.getZ()); - Vec3d cartPos = cart.getPos(cartX, cartY, cartZ); - - if (cartPos != null) { - Vec3d cartPosFront = cart.getPosOffset(cartX, cartY, cartZ, (double) 0.3F); - Vec3d cartPosBack = cart.getPosOffset(cartX, cartY, cartZ, (double) -0.3F); - if (cartPosFront == null) - cartPosFront = cartPos; - if (cartPosBack == null) - cartPosBack = cartPos; - - cartX = cartPos.x - cartX; - cartY = (cartPosFront.y + cartPosBack.y) / 2.0D - cartY; - cartZ = cartPos.z - cartZ; - - for (MatrixStack stack : matrixStacks) - stack.translate(cartX, cartY, cartZ); - } - } - } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java index 49656f15e..7b1fc465f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingContraption.java @@ -3,9 +3,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllTags.AllBlockTags; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; @@ -13,6 +14,8 @@ import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class BearingContraption extends Contraption { @@ -90,4 +93,9 @@ public class BearingContraption extends Contraption { return facing.getAxis() == this.facing.getAxis(); } + @OnlyIn(Dist.CLIENT) + @Override + public ContraptionLighter makeLighter() { + return new BearingLighter(this); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingLighter.java new file mode 100644 index 000000000..f2b3e5eec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingLighter.java @@ -0,0 +1,55 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.bearing; + +import java.util.Set; + +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; + +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; + +public class BearingLighter extends ContraptionLighter { + + public BearingLighter(BearingContraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + Set blocks = contraption.getBlocks().keySet(); + + Direction orientation = contraption.facing; + + float maxDistanceSq = -1; + for (BlockPos pos : blocks) { + float x = pos.getX(); + float y = pos.getY(); + float z = pos.getZ(); + + float distSq = x * x + y * y + z * z; + + if (distSq > maxDistanceSq) maxDistanceSq = distSq; + } + + int radius = (int) (Math.ceil(Math.sqrt(maxDistanceSq))); + + GridAlignedBB betterBounds = GridAlignedBB.ofRadius(radius); + GridAlignedBB contraptionBounds = GridAlignedBB.fromAABB(contraption.bounds); + + Direction.Axis axis = orientation.getAxis(); + + if (axis == Direction.Axis.X) { + betterBounds.maxX = contraptionBounds.maxX; + betterBounds.minX = contraptionBounds.minX; + } else if (axis == Direction.Axis.Y) { + betterBounds.maxY = contraptionBounds.maxY; + betterBounds.minY = contraptionBounds.minY; + } else if (axis == Direction.Axis.Z) { + betterBounds.maxZ = contraptionBounds.maxZ; + betterBounds.minZ = contraptionBounds.minZ; + } + + betterBounds.translate(contraption.anchor); + return betterBounds; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java index e1f7978f5..f94d29e89 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingRenderer.java @@ -4,8 +4,8 @@ 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.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java index 69b40f6fd..49cba252a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkBearingTileEntity.java @@ -1,5 +1,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import java.util.List; + +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; @@ -14,6 +18,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.ServerSpeedProvider; + import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.BlockStateProperties; @@ -22,9 +27,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.List; public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions { @@ -408,4 +410,8 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe return pos; } + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java index a105ad0d2..1dea812eb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/ClockworkContraption.java @@ -1,25 +1,21 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; -import com.simibubi.create.foundation.utility.NBTHelper; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import org.apache.commons.lang3.tuple.Pair; - import java.util.HashSet; import java.util.Queue; import java.util.Set; +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; +import com.simibubi.create.foundation.utility.NBTHelper; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + public class ClockworkContraption extends Contraption { protected Direction facing; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java index 65573cb35..42460217a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/MechanicalBearingTileEntity.java @@ -1,5 +1,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import static net.minecraft.state.properties.BlockStateProperties.FACING; + +import java.util.List; + import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; @@ -12,6 +16,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.ServerSpeedProvider; + import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.BlockStateProperties; @@ -20,10 +25,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -import java.util.List; - -import static net.minecraft.state.properties.BlockStateProperties.FACING; - public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions { protected ScrollOptionBehaviour movementMode; @@ -298,4 +299,9 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp TooltipHelper.addHint(tooltip, "hint.empty_bearing"); return true; } + + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java index 9c2255629..7acf1e590 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlock.java @@ -1,21 +1,33 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Predicate; + +import javax.annotation.Nullable; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.utility.DyeHelper; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementOffset; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.*; +import net.minecraft.item.BlockItem; +import net.minecraft.item.BlockItemUseContext; +import net.minecraft.item.DyeColor; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ShearsItem; import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; import net.minecraft.util.Hand; @@ -28,13 +40,6 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.function.Predicate; - public class SailBlock extends ProperDirectionalBlock { public static SailBlock frame(Properties properties) { @@ -216,7 +221,8 @@ public class SailBlock extends ProperDirectionalBlock { @Override public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), state.get(FACING)); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), state.get(FACING)); + displayGhost(offset); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java index 3bec0cedf..b2a517625 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingMovementBehaviour.java @@ -7,10 +7,11 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.state.properties.BlockStateProperties; @@ -28,8 +29,7 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { Direction facing = context.state.get(BlockStateProperties.FACING); AllBlockPartials top = AllBlockPartials.BEARING_TOP; SuperByteBuffer superBuffer = top.renderOn(context.state); - float renderPartialTicks = Minecraft.getInstance() - .getRenderPartialTicks(); + float renderPartialTicks = AnimationTickHolder.getPartialTicks(); // rotate to match blockstate Axis axis = facing.getAxis(); @@ -63,7 +63,7 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { // render superBuffer.light(msLocal.peek() - .getModel()); + .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java index a8b726cd2..4eec742bc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedContraption.java @@ -1,12 +1,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; +import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; -import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -26,12 +27,11 @@ public class StabilizedContraption extends Contraption { if (!searchMovedStructure(world, offset, null)) return false; startMoving(world); - expandBoundsAroundAxis(Axis.Y); if (blocks.isEmpty()) return false; return true; } - + @Override protected boolean isAnchoringBlockAt(BlockPos pos) { return false; @@ -64,4 +64,8 @@ public class StabilizedContraption extends Contraption { return facing; } + @Override + public ContraptionLighter makeLighter() { + return new NonStationaryLighter<>(this); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java index b9cae7e36..68b053ab6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/AbstractChassisBlock.java @@ -89,7 +89,6 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock implements return ActionResultType.SUCCESS; } - @SuppressWarnings("deprecation") @Override public BlockState rotate(BlockState state, Rotation rotation) { if (rotation == Rotation.NONE) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java index fcb4f1c1b..1f8396922 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisTileEntity.java @@ -49,7 +49,7 @@ public class ChassisTileEntity extends SmartTileEntity { range.between(1, max); range .withClientCallback( - i -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this))); + i -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this))); range.value = max / 2; behaviours.add(range); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java index 8bc426b3e..0db74075e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraption.java @@ -2,8 +2,11 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ga import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; +import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; + import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -60,4 +63,8 @@ public class GantryContraption extends TranslatingContraption { return super.shouldUpdateAfterMovement(info) && !AllBlocks.GANTRY_PINION.has(info.state); } + @Override + public ContraptionLighter makeLighter() { + return new NonStationaryLighter<>(this); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java index ac2aacbc7..c16b3d03d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntity.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; @@ -172,6 +173,9 @@ public class GantryContraptionEntity extends AbstractContraptionEntity { return ContraptionRotationState.NONE; } + @Override + public void doLocalTransforms(float partialTicks, MatrixStack[] matrixStacks) { } + public void updateClientMotion() { float modifier = movementAxis.getAxisDirection() .getOffset(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntityRenderer.java deleted file mode 100644 index b7eafa361..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionEntityRenderer.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.gantry; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntityRenderer; - -import net.minecraft.client.renderer.entity.EntityRendererManager; - -public class GantryContraptionEntityRenderer extends AbstractContraptionEntityRenderer { - - public GantryContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { - super(p_i46179_1_); - } - - @Override - protected void transform(GantryContraptionEntity contraptionEntity, float partialTicks, - MatrixStack[] matrixStacks) {} - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java index 1e0637497..54463c051 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryContraptionUpdatePacket.java @@ -38,7 +38,7 @@ public class GantryContraptionUpdatePacket extends SimplePacketBase { public void handle(Supplier context) { context.get() .enqueueWork( - () -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> GantryContraptionEntity.handlePacket(this))); + () -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> GantryContraptionEntity.handlePacket(this))); context.get() .setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionRenderer.java index 86a498d12..7772d70de 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionRenderer.java @@ -5,6 +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.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -59,7 +60,7 @@ public class GantryPinionRenderer extends KineticTileEntityRenderer { .rotateY(alongFirst ^ facing.getAxis() == Axis.Z ? 90 : 0); ms.translate(0, -9 / 16f, 0); - ms.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-angleForTe / 2f)); + ms.multiply(Vector3f.POSITIVE_X.getRadialQuaternion(-angleForTe)); ms.translate(0, 9 / 16f, 0); msr.unCentre(); @@ -70,6 +71,12 @@ public class GantryPinionRenderer extends KineticTileEntityRenderer { ms.pop(); } + public static float getAngleForTe(KineticTileEntity te, final BlockPos pos, Axis axis) { + float time = AnimationTickHolder.getRenderTick(); + float offset = getRotationOffsetForPosition(te, pos, axis); + return ((time * te.getSpeed() * 3f / 20 + offset) % 360) / 180 * (float) Math.PI; + } + @Override protected BlockState getRenderedBlockState(KineticTileEntity te) { return shaft(getRotationAxisOf(te)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionTileEntity.java index 000a944ba..582b7d749 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryPinionTileEntity.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +import static net.minecraft.state.properties.BlockStateProperties.FACING; + import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; @@ -7,6 +9,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity; + import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntity; @@ -15,8 +18,6 @@ import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.BlockPos; -import static net.minecraft.state.properties.BlockStateProperties.FACING; - public class GantryPinionTileEntity extends KineticTileEntity implements IDisplayAssemblyExceptions { boolean assembleNextTick; @@ -164,4 +165,8 @@ public class GantryPinionTileEntity extends KineticTileEntity implements IDispla return te instanceof GantryShaftTileEntity && ((GantryShaftTileEntity) te).canAssembleOn(); } + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java index d2d6c6917..8d454a134 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueEffectPacket.java @@ -39,7 +39,7 @@ public class GlueEffectPacket extends SimplePacketBase { @OnlyIn(Dist.CLIENT) public void handle(Supplier context) { - context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { Minecraft mc = Minecraft.getInstance(); if (!mc.player.getPosition().withinDistance(pos, 100)) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java index eba72ea54..547aeb02c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueEntity.java @@ -12,6 +12,7 @@ import com.simibubi.create.content.schematics.ISpecialEntityItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.BlockFace; import net.minecraft.block.BlockState; @@ -43,8 +44,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.RayTraceResult.Type; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -250,7 +251,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat @Override public boolean processInitialInteract(PlayerEntity player, Hand hand) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { triggerPlaceBlock(player, hand); }); return true; @@ -266,7 +267,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat ClientPlayerEntity cPlayer = (ClientPlayerEntity) player; Minecraft mc = Minecraft.getInstance(); RayTraceResult ray = - cPlayer.pick(mc.playerController.getBlockReachDistance(), mc.getRenderPartialTicks(), false); + cPlayer.pick(mc.playerController.getBlockReachDistance(), AnimationTickHolder.getPartialTicks(), false); if (!(ray instanceof BlockRayTraceResult)) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java index c9862ba88..425f0b567 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueHandler.java @@ -1,9 +1,14 @@ package com.simibubi.create.content.contraptions.components.structureMovement.glue; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import com.simibubi.create.AllItems; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld; + import net.minecraft.block.Blocks; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; @@ -11,8 +16,12 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; -import net.minecraft.util.math.*; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.RayTraceContext; import net.minecraft.util.math.RayTraceResult.Type; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent; @@ -20,10 +29,6 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.network.PacketDistributor; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - @EventBusSubscriber public class SuperGlueHandler { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java index e256f03ac..c82c00e85 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssembleRailType.java @@ -1,19 +1,19 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +import java.util.function.Predicate; +import java.util.function.Supplier; + import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; import com.simibubi.create.foundation.utility.Lang; - import com.tterrag.registrate.util.entry.BlockEntry; + import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.item.Item; import net.minecraft.util.IStringSerializable; -import java.util.function.Predicate; -import java.util.function.Supplier; - public enum CartAssembleRailType implements IStringSerializable { REGULAR(Blocks.RAIL), diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java index 8a50eb7cf..f6f67fe4f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerBlock.java @@ -1,5 +1,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; @@ -18,6 +26,7 @@ import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.VecHelper; + import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -38,9 +47,18 @@ import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.RailShape; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.*; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; -import net.minecraft.util.math.*; +import net.minecraft.util.Hand; +import net.minecraft.util.Rotation; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; @@ -52,13 +70,6 @@ import net.minecraft.world.storage.loot.LootContext; import net.minecraft.world.storage.loot.LootParameters; import net.minecraftforge.common.util.LazyOptional; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.UUID; - public class CartAssemblerBlock extends AbstractRailBlock implements ITE, IWrenchable, ISpecialBlockItemRequirement { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java index f94f0bdc7..10964f6db 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/CartAssemblerTileEntity.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mounted; +import java.util.List; + import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; import com.simibubi.create.foundation.gui.AllIcons; @@ -11,14 +13,13 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIco import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.VecHelper; + import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.RailShape; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction.Axis; import net.minecraft.util.math.Vec3d; -import java.util.List; - public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions { private static final int assemblyCooldown = 8; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java index 07868c475..a11a0b471 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MountedContraption.java @@ -7,9 +7,11 @@ import java.util.Queue; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; +import com.simibubi.create.content.contraptions.components.structureMovement.NonStationaryLighter; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; @@ -160,4 +162,9 @@ public class MountedContraption extends Contraption { IItemHandlerModifiable handlerFromInv = new InvWrapper((IInventory) cart); inventory = new CombinedInvWrapper(handlerFromInv, inventory); } + + @Override + public ContraptionLighter makeLighter() { + return new NonStationaryLighter<>(this); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java index ce3cb1470..c958b6a92 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/LinearActuatorTileEntity.java @@ -1,20 +1,25 @@ package com.simibubi.create.content.contraptions.components.structureMovement.piston; +import java.util.List; + import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.*; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; +import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption; +import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.ServerSpeedProvider; + import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -import java.util.List; - public abstract class LinearActuatorTileEntity extends KineticTileEntity implements IControlContraption, IDisplayAssemblyExceptions { public float offset; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java index bb8c2ff7e..e64ed67e8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java @@ -46,6 +46,8 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { if (!(world.getBlockState(pos) .getBlock() instanceof MechanicalPistonBlock)) return; + if (getMovementSpeed() == 0) + return; Direction direction = getBlockState().get(BlockStateProperties.FACING); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java index e0b12b263..7c1ba23b0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java @@ -1,12 +1,28 @@ package com.simibubi.create.content.contraptions.components.structureMovement.piston; +import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD; +import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isStickyPiston; +import static net.minecraft.state.properties.BlockStateProperties.FACING; + +import java.util.ArrayList; +import java.util.List; +import java.util.Queue; + +import org.apache.commons.lang3.tuple.Pair; + import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.utility.VecHelper; + import net.minecraft.block.BlockState; import net.minecraft.block.CarpetBlock; import net.minecraft.block.material.PushReaction; @@ -20,16 +36,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template.BlockInfo; -import org.apache.commons.lang3.tuple.Pair; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; - -import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD; -import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE; -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; -import static net.minecraft.state.properties.BlockStateProperties.FACING; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; public class PistonContraption extends TranslatingContraption { @@ -236,4 +244,9 @@ public class PistonContraption extends TranslatingContraption { return tag; } + @OnlyIn(Dist.CLIENT) + @Override + public ContraptionLighter makeLighter() { + return new PistonLighter(this); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java index b0cb526f2..e8519c0e3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java @@ -1,13 +1,20 @@ package com.simibubi.create.content.contraptions.components.structureMovement.piston; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPiston; +import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead; + +import java.util.function.Predicate; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; -import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; +import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.util.PoleHelper; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -34,10 +41,6 @@ import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorld; import net.minecraft.world.World; -import java.util.function.Predicate; - -import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; - public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable { private static final int placementHelperId = PlacementHelpers.register(PlacementHelper.get()); 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 new file mode 100644 index 000000000..1c8ffa5ed --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java @@ -0,0 +1,35 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.piston; + +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; + +import net.minecraft.util.math.Vec3i; + +public class PistonLighter extends ContraptionLighter { + public PistonLighter(PistonContraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + GridAlignedBB bounds = GridAlignedBB.fromAABB(contraption.bounds); + bounds.translate(contraption.anchor); + + int length = contraption.extensionLength; + Vec3i direction = contraption.orientation.getDirectionVec(); + + int shift = length / 2; + int shiftX = direction.getX() * shift; + int shiftY = direction.getY() * shift; + int shiftZ = direction.getZ() * shift; + bounds.translate(shiftX, shiftY, shiftZ); + + int grow = (length + 1) / 2; + int extendX = Math.abs(direction.getX() * grow); + int extendY = Math.abs(direction.getY() * grow); + int extendZ = Math.abs(direction.getZ() * grow); + bounds.grow(extendX, extendY, extendZ); + + return bounds; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java index e93ecf899..17d3ca9ce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyRenderer.java @@ -6,8 +6,8 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java index 5c444e4da..bb81e319e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyContraption.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; @@ -54,4 +55,8 @@ public class PulleyContraption extends TranslatingContraption { super.readNBT(world, nbt, spawnData); } + @Override + public ContraptionLighter makeLighter() { + return new PulleyLighter(this); + } } 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 new file mode 100644 index 000000000..4714a30e3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyLighter.java @@ -0,0 +1,32 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.pulley; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; +import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class PulleyLighter extends ContraptionLighter { + public PulleyLighter(PulleyContraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + + GridAlignedBB bounds = GridAlignedBB.fromAABB(contraption.bounds); + + World world = contraption.entity.world; + + BlockPos.Mutable pos = new BlockPos.Mutable(contraption.anchor); + while (!AllBlocks.ROPE_PULLEY.has(world.getBlockState(pos)) && pos.getY() < 256) { + pos.move(0, 1, 0); + } + + bounds.translate(pos); + bounds.minY = 1; // the super constructor will take care of making this 0 + + return bounds; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java index 0922e6ba1..182e063bb 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyRenderer.java @@ -5,7 +5,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java index b20ff7fdc..5fde955e9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyTileEntity.java @@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; + import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.IWaterLoggable; @@ -32,8 +33,8 @@ public class PulleyTileEntity extends LinearActuatorTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().expand(0, -offset, 0); + public AxisAlignedBB makeRenderBoundingBox() { + return super.makeRenderBoundingBox().expand(0, -offset, 0); } @Override 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 new file mode 100644 index 000000000..6733cd22a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java @@ -0,0 +1,27 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; +import com.simibubi.create.content.contraptions.base.RotatingInstancedModel; +import com.simibubi.create.content.contraptions.components.actors.RotatingActorModel; +import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel; +import com.simibubi.create.foundation.render.AllProgramSpecs; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; + +import net.minecraft.util.math.BlockPos; + +public class ContraptionKineticRenderer extends InstancedTileRenderer { + + @Override + public void registerMaterials() { + materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.CONTRAPTION_BELT, BeltInstancedModel::new)); + materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.CONTRAPTION_ROTATING, RotatingInstancedModel::new)); + materials.put(KineticRenderMaterials.ACTORS, new RenderMaterial<>(this, AllProgramSpecs.CONTRAPTION_ACTOR, RotatingActorModel::new)); + } + + @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 new file mode 100644 index 000000000..c5bb45e7b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java @@ -0,0 +1,51 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import java.nio.ByteBuffer; + +import com.simibubi.create.foundation.render.backend.BufferedModel; +import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.LightTexture; + +public class ContraptionModel extends BufferedModel { + public static final VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(ContraptionVertexAttributes.class) + .build(); + + public ContraptionModel(BufferBuilder buf) { + super(buf); + } + + @Override + protected void copyVertex(ByteBuffer to, int vertex) { + to.putFloat(getX(template, vertex)); + to.putFloat(getY(template, vertex)); + to.putFloat(getZ(template, vertex)); + + to.put(getNX(template, vertex)); + to.put(getNY(template, vertex)); + to.put(getNZ(template, vertex)); + + to.putFloat(getU(template, vertex)); + to.putFloat(getV(template, vertex)); + + to.put(getR(template, vertex)); + to.put(getG(template, vertex)); + to.put(getB(template, vertex)); + to.put(getA(template, vertex)); + + int light = getLight(template, vertex); + + byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4); + byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4); + + to.put(block); + to.put(sky); + } + + @Override + protected VertexFormat getModelFormat() { + return FORMAT; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java new file mode 100644 index 000000000..7f0950ca0 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionProgram.java @@ -0,0 +1,39 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.backend.gl.BasicProgram; + +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.AxisAlignedBB; + +public class ContraptionProgram extends BasicProgram { + protected final int uLightBoxSize; + protected final int uLightBoxMin; + protected final int uModel; + + protected int uLightVolume; + + public ContraptionProgram(ResourceLocation name, int handle) { + super(name, handle); + uLightBoxSize = getUniformLocation("uLightBoxSize"); + uLightBoxMin = getUniformLocation("uLightBoxMin"); + uModel = getUniformLocation("uModel"); + } + + @Override + protected void registerSamplers() { + super.registerSamplers(); + uLightVolume = setSamplerBinding("uLightVolume", 4); + } + + public void bind(Matrix4f model, AxisAlignedBB lightVolume) { + double sizeX = lightVolume.maxX - lightVolume.minX; + double sizeY = lightVolume.maxY - lightVolume.minY; + double sizeZ = lightVolume.maxZ - lightVolume.minZ; + GL20.glUniform3f(uLightBoxSize, (float) sizeX, (float) sizeY, (float) sizeZ); + GL20.glUniform3f(uLightBoxMin, (float) lightVolume.minX, (float) lightVolume.minY, (float) lightVolume.minZ); + uploadMatrixUniform(uModel, model); + } +} 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 new file mode 100644 index 000000000..f26e5174b --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java @@ -0,0 +1,310 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import java.util.List; +import java.util.Random; + +import org.apache.commons.lang3.tuple.Pair; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL40; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.CreateClient; +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.MovementBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +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.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.Matrix4f; +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.world.ILightReader; +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; + +public class ContraptionRenderDispatcher { + public static final Int2ObjectMap renderers = new Int2ObjectOpenHashMap<>(); + public static final Compartment> CONTRAPTION = new Compartment<>(); + protected static PlacementSimulationWorld renderWorld; + + private static boolean firstLayer = true; + + public static void notifyLightUpdate(ILightReader world, LightType type, SectionPos pos) { + for (RenderedContraption renderer : renderers.values()) { + renderer.getLighter().lightVolume.notifyLightUpdate(world, type, pos); + } + } + + public static void renderTick() { + firstLayer = true; + } + + public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, + IRenderTypeBuffer buffer) { + PlacementSimulationWorld renderWorld = null; + if (Backend.canUseVBOs()) { + RenderedContraption renderer = getRenderer(world, c); + + renderWorld = renderer.renderWorld; + } + TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); + + } + + public static void tick() { + for (RenderedContraption contraption : renderers.values()) { + contraption.getLighter().tick(contraption); + } + } + + private static RenderedContraption getRenderer(World world, Contraption c) { + int entityId = c.entity.getEntityId(); + RenderedContraption contraption = renderers.get(entityId); + + if (contraption == null) { + contraption = new RenderedContraption(world, c); + renderers.put(entityId, contraption); + } + + return contraption; + } + + public static void renderLayer(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { + removeDeadContraptions(); + + if (renderers.isEmpty()) return; + + if (firstLayer) { + + for (RenderedContraption renderer : renderers.values()) { + renderer.beginFrame(camX, camY, camZ); + } + + firstLayer = false; + } + + layer.startDrawing(); + GL11.glEnable(GL13.GL_TEXTURE_3D); + GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4 + + if (Backend.canUseVBOs()) { + ContraptionProgram structureShader = Backend.getProgram(AllProgramSpecs.CONTRAPTION_STRUCTURE); + structureShader.bind(viewProjection, camX, camY, camZ, FastRenderDispatcher.getDebugMode()); + for (RenderedContraption renderer : renderers.values()) { + renderer.doRenderLayer(layer, structureShader); + } + } + + if (Backend.canUseInstancing()) { + for (RenderedContraption renderer : renderers.values()) { + renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup); + renderer.teardown(); + } + } + + layer.endDrawing(); + GL11.glDisable(GL13.GL_TEXTURE_3D); + GL13.glActiveTexture(GL40.GL_TEXTURE0); + } + + public static void removeDeadContraptions() { + renderers.values().removeIf(renderer -> { + if (renderer.isDead()) { + renderer.invalidate(); + return true; + } + return false; + }); + } + + public static void invalidateAll() { + for (RenderedContraption renderer : renderers.values()) { + renderer.invalidate(); + } + + renderers.clear(); + } + + public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers, + MatrixStack msLocal, Contraption contraption) { + if (Backend.canUseVBOs()) { + ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers); + } else { + ContraptionRenderDispatcher.renderDynamic(entity.world, contraption, ms, msLocal, buffers); + ContraptionRenderDispatcher.renderStructure(entity.world, contraption, ms, msLocal, buffers); + } + } + + public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, + IRenderTypeBuffer buffer) { + renderTileEntities(world, c, ms, msLocal, buffer); + if (buffer instanceof IRenderTypeBuffer.Impl) + ((IRenderTypeBuffer.Impl) buffer).draw(); + renderActors(world, c, ms, msLocal, buffer); + } + + public static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, + IRenderTypeBuffer buffer) { + SuperByteBufferCache bufferCache = CreateClient.bufferCache; + List blockLayers = RenderType.getBlockLayers(); + + buffer.getBuffer(RenderType.getSolid()); + for (int i = 0; i < blockLayers.size(); i++) { + RenderType layer = blockLayers.get(i); + Pair key = Pair.of(c, i); + SuperByteBuffer contraptionBuffer = bufferCache.get(CONTRAPTION, key, () -> buildStructureBuffer(c, layer)); + if (contraptionBuffer.isEmpty()) + continue; + Matrix4f model = msLocal.peek() + .getModel(); + contraptionBuffer.light(model) + .renderInto(ms, buffer.getBuffer(layer)); + } + } + + private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { + BufferBuilder builder = buildStructure(c, layer); + return new SuperByteBuffer(builder); + } + + public static BufferBuilder buildStructure(Contraption c, RenderType layer) { + if (renderWorld == null || renderWorld.getWorld() != Minecraft.getInstance().world) + renderWorld = new PlacementSimulationWorld(Minecraft.getInstance().world); + + ForgeHooksClient.setRenderLayer(layer); + MatrixStack ms = new MatrixStack(); + BlockRendererDispatcher dispatcher = Minecraft.getInstance() + .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()) + renderWorld.setBlockState(info.pos, info.state); + + for (Template.BlockInfo info : c.getBlocks() + .values()) { + BlockState state = info.state; + + if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) + continue; + if (!RenderTypeLookup.canRenderInLayer(state, layer)) + continue; + + IBakedModel originalModel = dispatcher.getModelForState(state); + 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); + ms.pop(); + } + + builder.finishDrawing(); + renderWorld.clear(); + renderWorld = null; + return builder; + } + + protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, + IRenderTypeBuffer buffer) { + MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; + for (Pair actor : c.getActors()) { + MovementContext context = actor.getRight(); + if (context == null) + continue; + if (context.world == null) + context.world = world; + Template.BlockInfo blockInfo = actor.getLeft(); + for (MatrixStack m : matrixStacks) { + m.push(); + MatrixStacker.of(m) + .translate(blockInfo.pos); + } + + MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); + if (movementBehaviour != null) + movementBehaviour.renderInContraption(context, ms, msLocal, buffer); + + for (MatrixStack m : matrixStacks) + m.pop(); + } + } + + public static int getLight(World world, float lx, float ly, float lz) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + float sky = 0, block = 0; + float offset = 1 / 8f; + + for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) + for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) + for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { + pos.setPos(lx + xOffset, ly + yOffset, lz + zOffset); + sky += world.getLightLevel(LightType.SKY, pos) / 8f; + block += world.getLightLevel(LightType.BLOCK, pos) / 8f; + } + + return ((int) sky) << 20 | ((int) block) << 4; + } + + public static int getLightOnContraption(World world, PlacementSimulationWorld renderWorld, BlockPos pos, BlockPos lightPos) { + int worldLight = WorldRenderer.getLightmapCoordinates(world, lightPos); + + if (renderWorld != null) + return getMaxBlockLight(worldLight, renderWorld.getLightLevel(LightType.BLOCK, pos)); + + return worldLight; + } + + public static int getMaxBlockLight(int packedLight, int blockLightValue) { + int unpackedBlockLight = LightTexture.getBlockLightCoordinates(packedLight); + + if (blockLightValue > unpackedBlockLight) { + packedLight = (packedLight & 0xFFFF0000) | (blockLightValue << 4); + } + + return packedLight; + } + + public static int getLightOnContraption(MovementContext context) { + int entityId = context.contraption.entity.getEntityId(); + + RenderedContraption renderedContraption = renderers.get(entityId); + if (renderedContraption != null) { + return renderedContraption.renderWorld.getLightLevel(LightType.BLOCK, context.localPos); + } else { + return -1; + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderer.java new file mode 100644 index 000000000..cf2bd4059 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderer.java @@ -0,0 +1,7 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +public class ContraptionRenderer { + + + +} 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/ContraptionVertexAttributes.java new file mode 100644 index 000000000..6bfbf8af7 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionVertexAttributes.java @@ -0,0 +1,42 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +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 { + VERTEX_POSITION("aPos", CommonAttributes.VEC3), + NORMAL("aNormal", CommonAttributes.NORMAL), + TEXTURE("aTexCoords", CommonAttributes.UV), + COLOR("aColor", CommonAttributes.RGBA), + MODEL_LIGHT("aModelLight", CommonAttributes.LIGHT), + ; + + private final String name; + private final VertexAttribSpec spec; + + ContraptionVertexAttributes(String name, VertexAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public VertexAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 0; + } + + @Override + public int getBufferIndex() { + return 0; + } +} 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 new file mode 100644 index 000000000..c86f70336 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -0,0 +1,241 @@ +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.apache.commons.lang3.tuple.MutablePair; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; +import com.simibubi.create.content.contraptions.components.actors.ContraptionActorData; +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.ContraptionLighter; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; +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.light.GridAlignedBB; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +import net.minecraft.block.BlockRenderType; +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockModelRenderer; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderTypeLookup; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.Template; +import net.minecraft.world.lighting.WorldLightManager; +import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.client.model.data.EmptyModelData; + +public class RenderedContraption { + private final HashMap renderLayers = new HashMap<>(); + + public final PlacementSimulationWorld renderWorld; + + private final ContraptionLighter lighter; + + public final ContraptionKineticRenderer kinetics; + + public Contraption contraption; + + private Matrix4f model; + private AxisAlignedBB lightBox; + + public RenderedContraption(World world, Contraption contraption) { + this.contraption = contraption; + this.lighter = contraption.makeLighter(); + this.kinetics = new ContraptionKineticRenderer(); + this.renderWorld = setupRenderWorld(world, contraption); + + buildLayers(); + if (Backend.canUseInstancing()) { + buildInstancedTiles(); + buildActors(); + } + } + + public int getEntityId() { + return contraption.entity.getEntityId(); + } + + public boolean isDead() { + return !contraption.entity.isAlive(); + } + + public ContraptionLighter getLighter() { + return lighter; + } + + public RenderMaterial> getActorMaterial() { + return kinetics.getMaterial(KineticRenderMaterials.ACTORS); + } + + public void doRenderLayer(RenderType layer, ContraptionProgram shader) { + ContraptionModel structure = renderLayers.get(layer); + if (structure != null) { + setup(shader); + structure.render(); + teardown(); + } + } + + public void beginFrame(double camX, double camY, double camZ) { + AbstractContraptionEntity entity = contraption.entity; + float pt = AnimationTickHolder.getPartialTicks(); + + MatrixStack stack = new MatrixStack(); + + double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX()) - camX; + double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY()) - camY; + double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ()) - camZ; + stack.translate(x, y, z); + + entity.doLocalTransforms(pt, new MatrixStack[]{ stack }); + + model = stack.peek().getModel(); + + AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()); + + this.lightBox = lightBox.offset(-camX, -camY, -camZ); + } + + void setup(ContraptionProgram shader) { + if (model == null || lightBox == null) return; + shader.bind(model, lightBox); + lighter.lightVolume.bind(); + } + + void teardown() { + lighter.lightVolume.unbind(); + } + + void invalidate() { + for (ContraptionModel buffer : renderLayers.values()) { + buffer.delete(); + } + renderLayers.clear(); + + lighter.lightVolume.delete(); + + kinetics.invalidate(); + } + + private void buildLayers() { + for (ContraptionModel buffer : renderLayers.values()) { + buffer.delete(); + } + + renderLayers.clear(); + + List blockLayers = RenderType.getBlockLayers(); + + for (RenderType layer : blockLayers) { + renderLayers.put(layer, buildStructureModel(renderWorld, contraption, layer)); + } + } + + private void buildInstancedTiles() { + Collection tileEntities = contraption.maybeInstancedTileEntities; + if (!tileEntities.isEmpty()) { + for (TileEntity te : tileEntities) { + if (te instanceof IInstanceRendered) { + World world = te.getWorld(); + BlockPos pos = te.getPos(); + te.setLocation(renderWorld, pos); + kinetics.add(te); + te.setLocation(world, pos); + } + } + } + } + + private void buildActors() { + List> actors = contraption.getActors(); + + for (MutablePair actor : actors) { + Template.BlockInfo blockInfo = actor.left; + MovementContext context = actor.right; + + MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); + + if (movementBehaviour != null) { + movementBehaviour.addInstance(this, context); + } + } + } + + private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + BufferBuilder builder = buildStructure(renderWorld, c, layer); + return new ContraptionModel(builder); + } + + private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { + PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); + + renderWorld.setTileEntities(c.presentTileEntities.values()); + + for (Template.BlockInfo info : c.getBlocks() + .values()) + renderWorld.setBlockState(info.pos, info.state); + + WorldLightManager lighter = renderWorld.lighter; + + renderWorld.chunkProvider.getLightSources().forEach((pos) -> lighter.func_215573_a(pos, renderWorld.getLightValue(pos))); + + lighter.tick(Integer.MAX_VALUE, true, false); + + return renderWorld; + } + + private static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + + ForgeHooksClient.setRenderLayer(layer); + MatrixStack ms = new MatrixStack(); + BlockRendererDispatcher dispatcher = Minecraft.getInstance() + .getBlockRendererDispatcher(); + BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); + Random random = new Random(); + BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); + builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + + for (Template.BlockInfo info : c.getBlocks() + .values()) { + BlockState state = info.state; + + if (state.getRenderType() == BlockRenderType.ENTITYBLOCK_ANIMATED) + continue; + if (!RenderTypeLookup.canRenderInLayer(state, layer)) + continue; + + IBakedModel originalModel = dispatcher.getModelForState(state); + 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); + ms.pop(); + } + + builder.finishDrawing(); + return builder; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java index 35041160d..6ffbf59d2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingRenderer.java @@ -8,10 +8,11 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticDebugger; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; @@ -115,8 +116,7 @@ public class CouplingRenderer { float y = (((float) (i >> 20 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F + 0.375F; float z = (((float) (i >> 24 & 7L) + 0.5F) / 8.0F - 0.5F) * 0.004F; - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); double xIn = lerp(pt, cart.lastTickPosX, cart.getX()); double yIn = lerp(pt, cart.lastTickPosY, cart.getY()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java index 5fa47e5bc..d421c8fb1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/MinecartCouplingItem.java @@ -66,7 +66,7 @@ public class MinecartCouplingItem extends Item { return true; } if (world != null && world.isRemote) - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> cartClicked(player, minecart)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> cartClicked(player, minecart)); return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java index 5b399ffcc..58008e2c8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartControllerUpdatePacket.java @@ -39,7 +39,7 @@ public class MinecartControllerUpdatePacket extends SimplePacketBase { @Override public void handle(Supplier context) { context.get() - .enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> this::handleCL)); + .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handleCL)); context.get() .setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java index a3ba8aaf9..a6ccc5707 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/turntable/TurntableHandler.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.turntable; import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; @@ -38,7 +39,7 @@ public class TurntableHandler { if (offset.length() > 1/4f) speed *= MathHelper.clamp((1/2f - offset.length()) * 2, 0, 1); - mc.player.rotationYaw = mc.player.prevRotationYaw - speed * mc.getRenderPartialTicks(); + mc.player.rotationYaw = mc.player.prevRotationYaw - speed * AnimationTickHolder.getPartialTicks(); mc.player.renderYawOffset = mc.player.rotationYaw; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java index 882f2a15e..6b0fc0df9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/waterwheel/WaterWheelTileEntity.java @@ -36,7 +36,7 @@ public class WaterWheelTileEntity extends GeneratingKineticTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { + public AxisAlignedBB makeRenderBoundingBox() { return new AxisAlignedBB(pos).grow(1); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java index b193246c1..f82785446 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidPropagator.java @@ -182,7 +182,7 @@ public class FluidPropagator { // @Deprecated // public static OutlineParams showBlockFace(BlockFace face) { // MutableObject params = new MutableObject<>(new OutlineParams()); -// DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { +// DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { // Vec3d directionVec = new Vec3d(face.getFace() // .getDirectionVec()); // Vec3d scaleVec = directionVec.scale(-.25f * face.getFace() diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java index 7ce0b8729..efded06cf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PipeConnection.java @@ -358,11 +358,11 @@ public class PipeConnection { public static final Random r = new Random(); public void spawnSplashOnRim(World world, BlockPos pos, FluidStack fluid) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> spawnSplashOnRimInner(world, pos, fluid)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> spawnSplashOnRimInner(world, pos, fluid)); } public void spawnParticles(World world, BlockPos pos, FluidStack fluid) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> spawnParticlesInner(world, pos, fluid)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> spawnParticlesInner(world, pos, fluid)); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java new file mode 100644 index 000000000..99b4bebec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.contraptions.fluids; + +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.base.RotatingData; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class PumpCogInstance extends SingleRotatingInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, PumpCogInstance::new)); + } + + public PumpCogInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected InstancedModel getModel() { + return AllBlockPartials.MECHANICAL_PUMP_COG.renderOnDirectionalSouthRotating(modelManager, tile.getBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java index ff887c908..f091caf04 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpRenderer.java @@ -4,9 +4,9 @@ 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.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java index 901059d71..821d5f4ca 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpTileEntity.java @@ -374,4 +374,8 @@ public class PumpTileEntity extends KineticTileEntity { } + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java index 3ee683b49..8cc65f55a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidDrainingBehaviour.java @@ -8,7 +8,6 @@ import java.util.Set; import javax.annotation.Nullable; -import com.simibubi.create.AllFluids; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; @@ -133,12 +132,7 @@ public class FluidDrainingBehaviour extends FluidManipulationBehaviour { AllTriggers.triggerForNearbyPlayers(AllTriggers.HOSE_PULLEY, world, tileEntity.getPos(), 8); if (infinite) { - if (FluidHelper.isLava(fluid)) - AllTriggers.triggerForNearbyPlayers(AllTriggers.INFINITE_LAVA, world, tileEntity.getPos(), 8); - if (FluidHelper.isWater(fluid)) - AllTriggers.triggerForNearbyPlayers(AllTriggers.INFINITE_WATER, world, tileEntity.getPos(), 8); - if (fluid.isEquivalentTo(AllFluids.CHOCOLATE.get())) - AllTriggers.triggerForNearbyPlayers(AllTriggers.INFINITE_CHOCOLATE, world, tileEntity.getPos(), 8); + AllTriggers.triggerForNearbyPlayers(AllTriggers.INFINITE_FLUID.constructTriggerFor(FluidHelper.convertToStill(fluid)), world, tileEntity.getPos(), 8); return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java index 1489e52b7..f5c397c0f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidSplashPacket.java @@ -36,7 +36,7 @@ public class FluidSplashPacket extends SimplePacketBase { public void handle(Supplier ctx) { ctx.get() - .enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { if (Minecraft.getInstance().player.getPositionVector() .distanceTo(new Vec3d(pos)) > 100) return; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java index af76354d6..c0d4091c6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyRenderer.java @@ -3,7 +3,7 @@ package com.simibubi.create.content.contraptions.fluids.actors; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.AbstractPulleyRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; import net.minecraft.util.Direction.Axis; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java index 436b111f9..5745d4c1d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/HosePulleyTileEntity.java @@ -191,4 +191,8 @@ public class HosePulleyTileEntity extends KineticTileEntity { return super.getCapability(cap, side); } + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java index f7f4e3d73..33c31cc95 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/SpoutTileEntity.java @@ -27,6 +27,8 @@ import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.Vec3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; @@ -47,9 +49,14 @@ public class SpoutTileEntity extends SmartTileEntity { processingTicks = -1; } + protected AxisAlignedBB cachedBoundingBox; @Override + @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().expand(0, -2, 0); + if (cachedBoundingBox == null) { + cachedBoundingBox = super.getRenderBoundingBox().expand(0, -2, 0); + } + return cachedBoundingBox; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java index 5ced0d5f9..0192ece07 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/BracketBlock.java @@ -5,8 +5,8 @@ import java.util.Optional; import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock; import com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock; import com.simibubi.create.content.contraptions.fluids.FluidPropagator; -import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.content.contraptions.relays.elementary.AbstractShaftBlock; +import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.utility.Lang; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java index 0763e60d9..ede978f67 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidPipeTileEntity.java @@ -25,7 +25,7 @@ public class FluidPipeTileEntity extends SmartTileEntity { public void addBehaviours(List behaviours) { behaviours.add(new StandardPipeFluidTransportBehaviour(this)); behaviours.add(new BracketedTileEntityBehaviour(this, this::canHaveBracket) - .withTrigger(state -> AllTriggers.BRACKET_PIPE)); + .withTrigger(state -> AllTriggers.BRACKET_APPLY_TRIGGER.constructTriggerFor(state.getBlock()))); } private boolean canHaveBracket(BlockState state) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java index c50f78bb4..729d37d7d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveRenderer.java @@ -4,9 +4,9 @@ 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.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java index 1f964928e..72e0d86bf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/FluidValveTileEntity.java @@ -78,6 +78,11 @@ public class FluidValveTileEntity extends KineticTileEntity { public void addBehaviours(List behaviours) { behaviours.add(new ValvePipeBehaviour(this)); } + + @Override + public boolean shouldRenderAsTE() { + return true; + } class ValvePipeBehaviour extends StraightPipeFluidTransportBehaviour { diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java index 2b1d40780..d6100573c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/pipes/GlassFluidPipeBlock.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.fluids.pipes; +import javax.annotation.ParametersAreNonnullByDefault; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; @@ -22,8 +24,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -import javax.annotation.ParametersAreNonnullByDefault; - @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java index aa487a29b..bfa94720a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankTileEntity.java @@ -104,7 +104,10 @@ public class FluidTankTileEntity extends SmartTileEntity { } public boolean isController() { - return controller == null || controller.equals(pos); + return controller == null || + pos.getX() == controller.getX() && + pos.getY() == controller.getY() && + pos.getZ() == controller.getZ(); } @Override @@ -281,12 +284,17 @@ public class FluidTankTileEntity extends SmartTileEntity { return isController() ? pos : controller; } + private AxisAlignedBB cachedBoundingBox; @Override @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { - if (isController()) - return super.getRenderBoundingBox().expand(width - 1, height - 1, width - 1); - return super.getRenderBoundingBox(); + if (cachedBoundingBox == null) { + if (isController()) + cachedBoundingBox = super.getRenderBoundingBox().expand(width - 1, height - 1, width - 1); + else + cachedBoundingBox = super.getRenderBoundingBox(); + } + return cachedBoundingBox; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java index c61452bb8..81ef886ab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/goggles/GoggleOverlayRenderer.java @@ -1,5 +1,11 @@ package com.simibubi.create.content.contraptions.goggles; +import static com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation.spacing; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; @@ -14,6 +20,7 @@ import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.outliner.Outline; import com.simibubi.create.foundation.utility.outliner.Outliner.OutlineEntry; + import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; @@ -32,12 +39,6 @@ import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import static com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation.spacing; - @EventBusSubscriber(value = Dist.CLIENT) public class GoggleOverlayRenderer { diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java index a54ab7a67..3e9b5633c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/RotationIndicatorParticle.java @@ -67,7 +67,7 @@ public class RotationIndicatorParticle extends SimpleAnimatedParticle { } public void move(double x, double y, double z) { - float time = AnimationTickHolder.ticks; + float time = AnimationTickHolder.getTicks(); float angle = (float) ((time * speed) % 360) - (speed / 2 * age * (((float) age) / maxAge)); Vec3d position = VecHelper.rotate(this.offset.scale(radius), angle, axis).add(origin); posX = position.x; diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java index a3de35c6c..1f77c0caa 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinMovementBehaviour.java @@ -23,8 +23,8 @@ public class BasinMovementBehaviour extends MovementBehaviour { } @Override - public boolean hasSpecialMovementRenderer() { - return false; + public boolean renderAsNormalTileEntity() { + return true; } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java index 20383e4f4..d948c5af9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinOperatingTileEntity.java @@ -144,4 +144,8 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { protected abstract Object getRecipeCacheKey(); + @Override + public boolean shouldRenderAsTE() { + return true; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java index c41a4f751..60117276f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinTileEntity.java @@ -571,7 +571,7 @@ public class BasinTileEntity extends SmartTileEntity { Vec3d pointer = new Vec3d(1, 0, 0).scale(1 / 16f); float interval = 360f / segments; Vec3d centerOf = VecHelper.getCenterOf(pos); - float intervalOffset = (AnimationTickHolder.ticks * 18) % 360; + float intervalOffset = (AnimationTickHolder.getTicks() * 18) % 360; int currentSegment = 0; for (SmartFluidTankBehaviour behaviour : getTanks()) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java index e9e68a582..a2b7abd5c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/burner/BlazeBurnerRenderer.java @@ -3,10 +3,10 @@ package com.simibubi.create.content.contraptions.processing.burner; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java index 05078e359..db9ae172b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftBlock.java @@ -1,5 +1,9 @@ package com.simibubi.create.content.contraptions.relays.advanced; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; @@ -11,6 +15,7 @@ import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementOffset; import com.simibubi.create.foundation.utility.placement.util.PoleHelper; + import net.minecraft.block.Block; import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockState; @@ -39,10 +44,6 @@ import net.minecraft.world.IWorld; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; - public class GantryShaftBlock extends DirectionalKineticBlock { public static final IProperty PART = EnumProperty.create("part", Part.class); @@ -279,7 +280,6 @@ public class GantryShaftBlock extends DirectionalKineticBlock { return PlacementOffset.success(offset.getPos(), offset.getTransform() .andThen(s -> s.with(POWERED, state.get(POWERED)))); } - } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java index 8d15808c4..1d39ccbd5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerBlock.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.relays.advanced; +import java.util.function.Predicate; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; @@ -7,10 +9,10 @@ import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem; import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementOffset; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -20,7 +22,6 @@ import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; -import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; @@ -30,8 +31,6 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -import java.util.function.Predicate; - public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE { private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); @@ -111,9 +110,11 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements @Override public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), - Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, - state.get(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X)); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), + // Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, + // state.get(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X)); + + displayGhost(offset); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java index bf43e7db4..f4e324071 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/SpeedControllerRenderer.java @@ -5,8 +5,9 @@ import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -30,7 +31,9 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer instructions) { ListNBT list = new ListNBT(); instructions.forEach(i -> list.add(i.serialize())); @@ -95,8 +103,7 @@ public class Instruction { } static Instruction deserialize(CompoundNBT tag) { - Instruction instruction = - new Instruction(NBTHelper.readEnum(tag, "Type", SequencerInstructions.class)); + Instruction instruction = new Instruction(NBTHelper.readEnum(tag, "Type", SequencerInstructions.class)); instruction.speedModifier = NBTHelper.readEnum(tag, "Modifier", InstructionSpeedModifiers.class); instruction.value = tag.getInt("Value"); return instruction; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/OnIsPoweredResult.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/OnIsPoweredResult.java new file mode 100644 index 000000000..e942da652 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/OnIsPoweredResult.java @@ -0,0 +1,6 @@ +package com.simibubi.create.content.contraptions.relays.advanced.sequencer; + +public enum OnIsPoweredResult { + NOTHING, + CONTINUE +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java index 2974f2a3a..e206109b2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftBlock.java @@ -64,15 +64,15 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen return; boolean previouslyPowered = state.get(STATE) != 0; - if (previouslyPowered != worldIn.isBlockPowered(pos)) - withTileEntityDo(worldIn, pos, SequencedGearshiftTileEntity::onRedstoneUpdate); + boolean isPowered = worldIn.isBlockPowered(pos); + withTileEntityDo(worldIn, pos, sgte -> sgte.onRedstoneUpdate(isPowered, previouslyPowered)); } @Override protected boolean areStatesKineticallyEquivalent(BlockState oldState, BlockState newState) { return false; } - + @Override public boolean hasShaftTowards(IWorldReader world, BlockPos pos, BlockState state, Direction face) { if (state.get(VERTICAL)) @@ -93,7 +93,7 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen return ActionResultType.PASS; } - DistExecutor.runWhenOn(Dist.CLIENT, + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); return ActionResultType.SUCCESS; } @@ -146,15 +146,16 @@ public class SequencedGearshiftBlock extends HorizontalAxisKineticBlock implemen public Class getTileEntityClass() { return SequencedGearshiftTileEntity.class; } - + @Override public boolean hasComparatorInputOverride(BlockState p_149740_1_) { return true; } - + @Override public int getComparatorInputOverride(BlockState state, World world, BlockPos pos) { - return state.get(STATE).intValue(); + return state.get(STATE) + .intValue(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java index fb8aa11ef..31fbcb659 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftScreen.java @@ -101,7 +101,7 @@ public class SequencedGearshiftScreen extends AbstractSimiScreen { .withShiftStep(def.shiftStep) .setState(instruction.value) .onChanged(); - if (def == SequencerInstructions.WAIT) { + if (def == SequencerInstructions.DELAY) { value.withStepFunction(context -> { int v = context.currentValue; if (!context.forward) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java index b52e47ee2..e1d8070c8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java @@ -15,6 +15,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { int currentInstruction; int currentInstructionDuration; int timer; + boolean poweredPreviously; public SequencedGearshiftTileEntity(TileEntityType type) { super(type); @@ -22,6 +23,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { currentInstruction = -1; currentInstructionDuration = -1; timer = 0; + poweredPreviously = false; } @Override @@ -32,6 +34,8 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { return; if (world.isRemote) return; + if (currentInstructionDuration < 0) + return; if (timer < currentInstructionDuration) { timer++; return; @@ -63,9 +67,14 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { return currentInstruction == -1; } - public void onRedstoneUpdate() { + public void onRedstoneUpdate(boolean isPowered, boolean isRunning) { + if (!poweredPreviously && isPowered) + risingFlank(); + poweredPreviously = isPowered; if (!isIdle()) return; + if (isPowered == isRunning) + return; if (!world.isBlockPowered(pos)) { world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, 0), 3); return; @@ -75,6 +84,23 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { run(0); } + public void risingFlank() { + Instruction instruction = getInstruction(currentInstruction); + if (instruction == null) + return; + if (poweredPreviously) + return; + poweredPreviously = true; + + switch (instruction.onRedstonePulse()) { + case CONTINUE: + run(currentInstruction + 1); + break; + default: + break; + } + } + protected void run(int instructionIndex) { Instruction instruction = getInstruction(instructionIndex); if (instruction == null || instruction.instruction == SequencerInstructions.END) { @@ -99,7 +125,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { public Instruction getInstruction(int instructionIndex) { return instructionIndex >= 0 && instructionIndex < instructions.size() ? instructions.get(instructionIndex) - : null; + : null; } @Override @@ -107,6 +133,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { compound.putInt("InstructionIndex", currentInstruction); compound.putInt("InstructionDuration", currentInstructionDuration); compound.putInt("Timer", timer); + compound.putBoolean("PrevPowered", poweredPreviously); compound.put("Instructions", Instruction.serializeAll(instructions)); super.write(compound, clientPacket); } @@ -115,6 +142,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { protected void read(CompoundNBT compound, boolean clientPacket) { currentInstruction = compound.getInt("InstructionIndex"); currentInstructionDuration = compound.getInt("InstructionDuration"); + poweredPreviously = compound.getBoolean("PrevPowered"); timer = compound.getInt("Timer"); instructions = Instruction.deserializeAll(compound.getList("Instructions", NBT.TAG_COMPOUND)); super.read(compound, clientPacket); @@ -128,7 +156,9 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { public int getModifier() { if (currentInstruction >= instructions.size()) return 0; - return isIdle() ? 0 : instructions.get(currentInstruction).getSpeedModifier(); + return isIdle() ? 0 + : instructions.get(currentInstruction) + .getSpeedModifier(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java index 3bb06ba8e..8545a2415 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencerInstructions.java @@ -10,12 +10,14 @@ public enum SequencerInstructions { TURN_ANGLE("angle", AllGuiTextures.SEQUENCER_INSTRUCTION, true, true, 360, 45, 90), TURN_DISTANCE("distance", AllGuiTextures.SEQUENCER_INSTRUCTION, true, true, 128, 5, 5), - WAIT("duration", AllGuiTextures.SEQUENCER_WAIT, true, false, 600, 20, 10), + DELAY("duration", AllGuiTextures.SEQUENCER_DELAY, true, false, 600, 20, 10), + AWAIT("", AllGuiTextures.SEQUENCER_AWAIT), END("", AllGuiTextures.SEQUENCER_END), ; String translationKey; + String descriptiveTranslationKey; String parameterKey; boolean hasValueParameter; boolean hasSpeedParameter; @@ -37,13 +39,14 @@ public enum SequencerInstructions { this.shiftStep = shiftStep; this.defaultValue = defaultValue; translationKey = "gui.sequenced_gearshift.instruction." + Lang.asId(name()); + descriptiveTranslationKey = translationKey + ".descriptive"; parameterKey = translationKey + "." + parameterName; } static List getOptions() { List options = new ArrayList<>(); for (SequencerInstructions entry : values()) - options.add(Lang.translate(entry.translationKey)); + options.add(Lang.translate(entry.descriptiveTranslationKey)); return options; } @@ -52,7 +55,7 @@ public enum SequencerInstructions { return value + Lang.translate("generic.unit.degrees"); if (this == TURN_DISTANCE) return value + "m"; - if (this == WAIT) { + if (this == DELAY) { if (value >= 20) return (value / 20) + "s"; return value + "t"; 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 new file mode 100644 index 000000000..9f6db3daf --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java @@ -0,0 +1,71 @@ +package com.simibubi.create.content.contraptions.relays.belt; + +import java.nio.ByteBuffer; + +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; + +public class BeltData extends KineticData { + public static VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(KineticVertexAttributes.class) + .addAttributes(BeltVertexAttributes.class) + .build(); + + private float rotX; + private float rotY; + private float rotZ; + private float sourceU; + private float sourceV; + private float minU; + private float minV; + private float maxU; + private float maxV; + private byte scrollMult; + + protected BeltData(InstancedModel owner) { + super(owner); + } + + public BeltData setRotation(float rotX, float rotY, float rotZ) { + this.rotX = rotX; + this.rotY = rotY; + this.rotZ = rotZ; + return this; + } + + public BeltData setScrollTexture(SpriteShiftEntry spriteShift) { + TextureAtlasSprite source = spriteShift.getOriginal(); + TextureAtlasSprite target = spriteShift.getTarget(); + + this.sourceU = source.getMinU(); + this.sourceV = source.getMinV(); + this.minU = target.getMinU(); + this.minV = target.getMinV(); + this.maxU = target.getMaxU(); + this.maxV = target.getMaxV(); + + return this; + } + + public BeltData setScrollMult(float scrollMult) { + this.scrollMult = (byte) (scrollMult * 127); + return this; + } + + @Override + public void write(ByteBuffer buf) { + super.write(buf); + + putVec3(buf, rotX, rotY, rotZ); + + putVec2(buf, sourceU, sourceV); + putVec4(buf, minU, minV, maxU, maxV); + + put(buf, scrollMult); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java index 63360a12a..0268ea996 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java @@ -40,6 +40,10 @@ public class BeltHelper { return getSegmentTE(world, controllerPos); } + public static BeltTileEntity getBeltForOffset(BeltTileEntity controller, float offset) { + return getBeltAtSegment(controller, (int) Math.floor(offset)); + } + public static BeltTileEntity getBeltAtSegment(BeltTileEntity controller, int segment) { BlockPos pos = getPositionForOffset(controller, segment); TileEntity te = controller.getWorld() 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 new file mode 100644 index 000000000..7b8c7997a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java @@ -0,0 +1,186 @@ +package com.simibubi.create.content.contraptions.relays.belt; + +import java.util.ArrayList; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.base.KineticTileInstance; +import com.simibubi.create.content.contraptions.base.RotatingData; +import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +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.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.MatrixStacker; + +import net.minecraft.item.DyeColor; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class BeltInstance extends KineticTileInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, BeltInstance::new)); + } + + private boolean upward; + private boolean diagonal; + private boolean sideways; + private boolean vertical; + private boolean alongX; + private boolean alongZ; + private BeltSlope beltSlope; + private 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)) + return; + + keys = new ArrayList<>(2); + + beltSlope = lastState.get(BeltBlock.SLOPE); + facing = lastState.get(BeltBlock.HORIZONTAL_FACING); + upward = beltSlope == BeltSlope.UPWARD; + diagonal = beltSlope.isDiagonal(); + sideways = beltSlope == BeltSlope.SIDEWAYS; + vertical = beltSlope == BeltSlope.VERTICAL; + alongX = facing.getAxis() == Direction.Axis.X; + alongZ = facing.getAxis() == Direction.Axis.Z; + + BeltPart part = lastState.get(BeltBlock.PART); + boolean start = part == BeltPart.START; + boolean end = part == BeltPart.END; + DyeColor color = tile.color.orElse(null); + + for (boolean bottom : Iterate.trueAndFalse) { + AllBlockPartials beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom); + SpriteShiftEntry spriteShift = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom); + + InstancedModel beltModel = beltPartial.renderOnBelt(modelManager, lastState); + Consumer setupFunc = setupFunc(bottom, spriteShift); + + keys.add(beltModel.setupInstance(setupFunc)); + + if (diagonal) break; + } + + if (tile.hasPulley()) { + InstancedModel pulleyModel = getPulleyModel(); + + pulleyKey = pulleyModel.setupInstance(setupFunc(tile.getSpeed(), getRotationAxis())); + } + } + + @Override + public void onUpdate() { + DyeColor color = tile.color.orElse(null); + + boolean bottom = true; + for (InstanceKey key : keys) { + + SpriteShiftEntry spriteShiftEntry = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom); + key.modifyInstance(data -> data.setScrollTexture(spriteShiftEntry) + .setColor(tile.network) + .setRotationalSpeed(getScrollSpeed())); + bottom = false; + } + + if (pulleyKey != null) { + updateRotation(pulleyKey, getRotationAxis()); + } + } + + @Override + public void updateLight() { + for (InstanceKey key : keys) { + key.modifyInstance(this::relight); + } + + if (pulleyKey != null) pulleyKey.modifyInstance(this::relight); + } + + @Override + public void remove() { + keys.forEach(InstanceKey::delete); + keys.clear(); + if (pulleyKey != null) pulleyKey.delete(); + pulleyKey = null; + } + + private float getScrollSpeed() { + float speed = tile.getSpeed(); + if (((facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ^ upward) ^ + ((alongX && !diagonal) || (alongZ && diagonal)) ^ (vertical && facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE)) { + speed = -speed; + } + if (sideways && (facing == Direction.SOUTH || facing == Direction.WEST)) + speed = -speed; + + return speed; + } + + private InstancedModel getPulleyModel() { + Direction dir = getOrientation(); + + Direction.Axis axis = dir.getAxis(); + + Supplier ms = () -> { + MatrixStack modelTransform = new MatrixStack(); + MatrixStacker msr = MatrixStacker.of(modelTransform); + msr.centre(); + if (axis == Direction.Axis.X) + msr.rotateY(90); + if (axis == Direction.Axis.Y) + msr.rotateX(90); + msr.rotateX(90); + msr.unCentre(); + + return modelTransform; + }; + + return rotatingMaterial().getModel(AllBlockPartials.BELT_PULLEY, lastState, dir, ms); + } + + private Direction getOrientation() { + Direction dir = lastState.get(BeltBlock.HORIZONTAL_FACING) + .rotateY(); + if (beltSlope == BeltSlope.SIDEWAYS) + dir = Direction.UP; + + return dir; + } + + private Consumer setupFunc(boolean bottom, SpriteShiftEntry spriteShift) { + return data -> { + float rotX = (!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0) + (beltSlope == BeltSlope.DOWNWARD ? 180 : 0); + float rotY = facing.getHorizontalAngle() + (upward ? 180 : 0) + (sideways ? 90 : 0); + float rotZ = sideways ? 90 : ((vertical && facing.getAxisDirection() == Direction.AxisDirection.NEGATIVE) ? 180 : 0); + + BlockPos pos = tile.getPos(); + data.setTileEntity(tile) + .setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)) + .setRotation(rotX, rotY, rotZ) + .setRotationalSpeed(getScrollSpeed()) + .setRotationOffset(bottom ? 0.5f : 0f) + .setScrollTexture(spriteShift) + .setScrollMult(diagonal ? 3f / 8f : 0.5f); + }; + } + +} 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 new file mode 100644 index 000000000..86e7e26ef --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java @@ -0,0 +1,24 @@ +package com.simibubi.create.content.contraptions.relays.belt; + +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 BeltInstancedModel extends InstancedModel { + public BeltInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + super(renderer, buf); + } + + @Override + protected BeltData newInstance() { + return new BeltData(this); + } + + @Override + protected VertexFormat getInstanceFormat() { + return BeltData.FORMAT; + } + +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java index c4d6a592d..976a39d7d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltModel.java @@ -10,7 +10,7 @@ import java.util.Random; import com.simibubi.create.AllSpriteShifts; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.model.BakedQuad; 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 e5de1192e..e123a5e41 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 @@ -11,13 +11,14 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; +import com.simibubi.create.foundation.render.ShadowRenderHelper; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.ShadowRenderHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -51,113 +52,122 @@ public class BeltRenderer extends SafeTileEntityRenderer { protected void renderSafe(BeltTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - BlockState blockState = te.getBlockState(); - if (!AllBlocks.BELT.has(blockState)) - return; + if (!FastRenderDispatcher.available(te.getWorld())) { - BeltSlope beltSlope = blockState.get(BeltBlock.SLOPE); - BeltPart part = blockState.get(BeltBlock.PART); - Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING); - AxisDirection axisDirection = facing.getAxisDirection(); + BlockState blockState = te.getBlockState(); + if (!AllBlocks.BELT.has(blockState)) return; - boolean downward = beltSlope == BeltSlope.DOWNWARD; - boolean upward = beltSlope == BeltSlope.UPWARD; - boolean diagonal = downward || upward; - boolean start = part == BeltPart.START; - boolean end = part == BeltPart.END; - boolean sideways = beltSlope == BeltSlope.SIDEWAYS; - boolean alongX = facing.getAxis() == Axis.X; + BeltSlope beltSlope = blockState.get(BeltBlock.SLOPE); + BeltPart part = blockState.get(BeltBlock.PART); + Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING); + AxisDirection axisDirection = facing.getAxisDirection(); - MatrixStacker msr = MatrixStacker.of(ms); - IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - float renderTick = AnimationTickHolder.getRenderTick(); + boolean downward = beltSlope == BeltSlope.DOWNWARD; + boolean upward = beltSlope == BeltSlope.UPWARD; + boolean diagonal = downward || upward; + boolean start = part == BeltPart.START; + boolean end = part == BeltPart.END; + boolean sideways = beltSlope == BeltSlope.SIDEWAYS; + boolean alongX = facing.getAxis() == Axis.X; - ms.push(); - msr.centre(); - msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)); - msr.rotateZ(sideways ? 90 : 0); - msr.rotateX(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0); - msr.unCentre(); + MatrixStacker msr = MatrixStacker.of(ms); + IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); + float renderTick = AnimationTickHolder.getRenderTick(); - if (downward || beltSlope == BeltSlope.VERTICAL && axisDirection == AxisDirection.POSITIVE) { - boolean b = start; - start = end; - end = b; - } - - for (boolean bottom : Iterate.trueAndFalse) { - - AllBlockPartials beltPartial = diagonal - ? start ? AllBlockPartials.BELT_DIAGONAL_START - : end ? AllBlockPartials.BELT_DIAGONAL_END : AllBlockPartials.BELT_DIAGONAL_MIDDLE - : bottom - ? start ? AllBlockPartials.BELT_START_BOTTOM - : end ? AllBlockPartials.BELT_END_BOTTOM : AllBlockPartials.BELT_MIDDLE_BOTTOM - : start ? AllBlockPartials.BELT_START - : end ? AllBlockPartials.BELT_END : AllBlockPartials.BELT_MIDDLE; - - SuperByteBuffer beltBuffer = beltPartial.renderOn(blockState) - .light(light); - - SpriteShiftEntry spriteShift = null; - if (te.color.isPresent()) { - DyeColor color = te.color.get(); - spriteShift = (diagonal ? AllSpriteShifts.DYED_DIAGONAL_BELTS - : bottom ? AllSpriteShifts.DYED_OFFSET_BELTS : AllSpriteShifts.DYED_BELTS).get(color); - } else - spriteShift = diagonal ? AllSpriteShifts.BELT_DIAGONAL - : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; - - int cycleLength = diagonal ? 12 : 16; - int cycleOffset = bottom ? 8 : 0; - - // UV shift - float speed = te.getSpeed(); - if (speed != 0 || te.color.isPresent()) { - float time = renderTick * axisDirection.getOffset(); - if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX - || sideways && axisDirection == AxisDirection.NEGATIVE) - speed = -speed; - int textureIndex = (int) (((speed * time / 36) + cycleOffset) % cycleLength); - if (textureIndex < 0) - textureIndex += cycleLength; - - beltBuffer.shiftUVtoSheet(spriteShift, (textureIndex % 4) / 4f, (textureIndex / 4) / 4f, 4); - } - - beltBuffer.renderInto(ms, vb); - - // Diagonal belt do not have a separate bottom model - if (diagonal) - break; - } - ms.pop(); - - if (te.hasPulley()) { - // TODO 1.15 find a way to cache this model matrix computation - MatrixStack modelTransform = new MatrixStack(); - Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING) - .rotateY(); - if (sideways) - dir = Direction.UP; - msr = MatrixStacker.of(modelTransform); + ms.push(); msr.centre(); - if (dir.getAxis() == Axis.X) - msr.rotateY(90); - if (dir.getAxis() == Axis.Y) - msr.rotateX(90); - msr.rotateX(90); + msr.rotateY(AngleHelper.horizontalAngle(facing) + (upward ? 180 : 0) + (sideways ? 270 : 0)); + msr.rotateZ(sideways ? 90 : 0); + msr.rotateX(!diagonal && beltSlope != BeltSlope.HORIZONTAL ? 90 : 0); msr.unCentre(); - SuperByteBuffer superBuffer = CreateClient.bufferCache - .renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); - KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light) - .renderInto(ms, vb); + if (downward || beltSlope == BeltSlope.VERTICAL && axisDirection == AxisDirection.POSITIVE) { + boolean b = start; + start = end; + end = b; + } + + DyeColor color = te.color.orElse(null); + + for (boolean bottom : Iterate.trueAndFalse) { + + AllBlockPartials beltPartial = getBeltPartial(diagonal, start, end, bottom); + + SuperByteBuffer beltBuffer = beltPartial.renderOn(blockState) + .light(light); + + SpriteShiftEntry spriteShift = getSpriteShiftEntry(color, diagonal, bottom); + + // UV shift + float speed = te.getSpeed(); + if (speed != 0 || te.color.isPresent()) { + float time = renderTick * axisDirection.getOffset(); + if (diagonal && (downward ^ alongX) || !sideways && !diagonal && alongX || sideways && axisDirection == AxisDirection.NEGATIVE) + speed = -speed; + + float scrollMult = diagonal ? 3f / 8f : 0.5f; + + float spriteSize = spriteShift.getTarget().getMaxV() - spriteShift.getTarget().getMinV(); + + double scroll = speed * time / (36 * 16) + (bottom ? 0.5 : 0.0); + scroll = scroll - Math.floor(scroll); + scroll = scroll * spriteSize * scrollMult; + + beltBuffer.shiftUVScrolling(spriteShift, (float) scroll); + } + + beltBuffer.renderInto(ms, vb); + + // Diagonal belt do not have a separate bottom model + if (diagonal) break; + } + ms.pop(); + + if (te.hasPulley()) { + // TODO 1.15 find a way to cache this model matrix computation + MatrixStack modelTransform = new MatrixStack(); + Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING).rotateY(); + if (sideways) dir = Direction.UP; + msr = MatrixStacker.of(modelTransform); + msr.centre(); + if (dir.getAxis() == Axis.X) msr.rotateY(90); + if (dir.getAxis() == Axis.Y) msr.rotateX(90); + msr.rotateX(90); + msr.unCentre(); + + SuperByteBuffer superBuffer = CreateClient.bufferCache.renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, modelTransform); + KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); + } } renderItems(te, partialTicks, ms, buffer, light, overlay); } + public static SpriteShiftEntry getSpriteShiftEntry(DyeColor color, boolean diagonal, boolean bottom) { + if (color != null) { + return (diagonal ? AllSpriteShifts.DYED_DIAGONAL_BELTS + : bottom ? AllSpriteShifts.DYED_OFFSET_BELTS : AllSpriteShifts.DYED_BELTS).get(color); + } else + return diagonal ? AllSpriteShifts.BELT_DIAGONAL + : bottom ? AllSpriteShifts.BELT_OFFSET : AllSpriteShifts.BELT; + } + + public static AllBlockPartials getBeltPartial(boolean diagonal, boolean start, boolean end, boolean bottom) { + if (diagonal) { + if (start) return AllBlockPartials.BELT_DIAGONAL_START; + if (end) return AllBlockPartials.BELT_DIAGONAL_END; + return AllBlockPartials.BELT_DIAGONAL_MIDDLE; + } else if (bottom) { + if (start) return AllBlockPartials.BELT_START_BOTTOM; + if (end) return AllBlockPartials.BELT_END_BOTTOM; + return AllBlockPartials.BELT_MIDDLE_BOTTOM; + } else { + if (start) return AllBlockPartials.BELT_START; + if (end) return AllBlockPartials.BELT_END; + return AllBlockPartials.BELT_MIDDLE; + } + } + protected void renderItems(BeltTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { if (!te.isController()) @@ -167,16 +177,17 @@ public class BeltRenderer extends SafeTileEntityRenderer { ms.push(); - Vec3i directionVec = te.getBeltFacing() - .getDirectionVec(); + Direction beltFacing = te.getBeltFacing(); + Vec3i directionVec = beltFacing + .getDirectionVec(); Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5) .add(.5, 13 / 16f + .125f, .5); ms.translate(beltStartOffset.x, beltStartOffset.y, beltStartOffset.z); BeltSlope slope = te.getBlockState() .get(BeltBlock.SLOPE); int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0; - boolean slopeAlongX = te.getBeltFacing() - .getAxis() == Axis.X; + boolean slopeAlongX = beltFacing + .getAxis() == Axis.X; for (TransportedItemStack transported : te.getInventory() .getTransportedItems()) { @@ -192,6 +203,8 @@ public class BeltRenderer extends SafeTileEntityRenderer { sideOffset = transported.sideOffset; } + int stackLight = getPackedLight(te, offset); + if (offset < .5) verticalMovement = 0; verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f); @@ -199,16 +212,16 @@ public class BeltRenderer extends SafeTileEntityRenderer { .add(0, verticalMovement, 0); boolean onSlope = slope != BeltSlope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset; - boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ te.getBeltFacing() - .getAxisDirection() == AxisDirection.POSITIVE) == (te.getBeltFacing() - .getAxis() == Axis.Z); + boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ beltFacing + .getAxisDirection() == AxisDirection.POSITIVE) == (beltFacing + .getAxis() == Axis.Z); float slopeAngle = onSlope ? tiltForward ? -45 : 45 : 0; ms.translate(offsetVec.x, offsetVec.y, offsetVec.z); - boolean alongX = te.getBeltFacing() - .rotateY() - .getAxis() == Axis.X; + boolean alongX = beltFacing + .rotateY() + .getAxis() == Axis.X; if (!alongX) sideOffset *= -1; ms.translate(alongX ? sideOffset : 0, 0, alongX ? 0 : sideOffset); @@ -259,7 +272,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { } ms.scale(.5f, .5f, .5f); - itemRenderer.renderItem(transported.stack, TransformType.FIXED, light, overlay, ms, buffer); + itemRenderer.renderItem(transported.stack, TransformType.FIXED, stackLight, overlay, ms, buffer); ms.pop(); if (!renderUpright) { @@ -276,4 +289,11 @@ public class BeltRenderer extends SafeTileEntityRenderer { ms.pop(); } + protected int getPackedLight(BeltTileEntity controller, float beltPos) { + BeltTileEntity belt = BeltHelper.getBeltForOffset(controller, beltPos); + + if (belt == null) return 0; + + return (belt.skyLight << 20) | (belt.blockLight << 4); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java index 8f934e10f..56086092a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java @@ -11,4 +11,8 @@ public enum BeltSlope implements IStringSerializable { public String getName() { return Lang.asId(name()); } + + public boolean isDiagonal() { + return this == UPWARD || this == DOWNWARD; + } } \ No newline at end of file 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 e777e5a0e..a55c23825 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 @@ -22,6 +22,7 @@ import com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnel import com.simibubi.create.content.contraptions.relays.belt.transport.ItemHandlerBeltSegment; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelTileEntity; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; 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; @@ -44,11 +45,14 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.data.ModelDataMap; import net.minecraftforge.client.model.data.ModelProperty; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; @@ -67,6 +71,10 @@ public class BeltTileEntity extends KineticTileEntity { public CompoundNBT trackerUpdateTag; + // client + public byte blockLight = -1; + public byte skyLight = -1; + public static enum CasingType { NONE, ANDESITE, BRASS; } @@ -100,6 +108,9 @@ public class BeltTileEntity extends KineticTileEntity { initializeItemHandler(); + if (blockLight == -1) + updateLight(); + // Move Items if (!isController()) return; @@ -136,10 +147,11 @@ public class BeltTileEntity extends KineticTileEntity { } @Override - public AxisAlignedBB getRenderBoundingBox() { + public AxisAlignedBB makeRenderBoundingBox() { if (!isController()) - return super.getRenderBoundingBox(); - return super.getRenderBoundingBox().grow(beltLength + 1); + return super.makeRenderBoundingBox(); + else + return super.makeRenderBoundingBox().grow(beltLength + 1); } protected void initializeItemHandler() { @@ -221,6 +233,7 @@ public class BeltTileEntity extends KineticTileEntity { if (!clientPacket) return; + if (casingBefore == casing) return; requestModelDataUpdate(); @@ -251,6 +264,7 @@ public class BeltTileEntity extends KineticTileEntity { belt.color = Optional.ofNullable(colorIn); belt.markDirty(); belt.sendData(); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(belt)); } } @@ -267,6 +281,7 @@ public class BeltTileEntity extends KineticTileEntity { public void setController(BlockPos controller) { this.controller = controller; + cachedBoundingBox = null; } public BlockPos getController() { @@ -274,7 +289,10 @@ public class BeltTileEntity extends KineticTileEntity { } public boolean isController() { - return pos.equals(controller); + return controller != null && + pos.getX() == controller.getX() && + pos.getY() == controller.getY() && + pos.getZ() == controller.getZ(); } public float getBeltMovementSpeed() { @@ -495,4 +513,24 @@ public class BeltTileEntity extends KineticTileEntity { return 0; } + @Override + public void onChunkLightUpdate() { + super.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; + } + } } 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/BeltVertexAttributes.java new file mode 100644 index 000000000..ca2125848 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltVertexAttributes.java @@ -0,0 +1,41 @@ +package com.simibubi.create.content.contraptions.relays.belt; + +import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; +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 { + INSTANCE_ROTATION("aInstanceRot", CommonAttributes.VEC3), + SOURCE_TEX("aSourceTexture", CommonAttributes.UV), + SCROLL_TEX("aScrollTexture", CommonAttributes.VEC4), + SCROLL_MULT("aScrollMult", CommonAttributes.NORMALIZED_BYTE), + ; + + private final String name; + private final VertexAttribSpec spec; + + BeltVertexAttributes(String name, VertexAttribSpec spec) { + this.name = name; + this.spec = spec; + } + + @Override + public String attribName() { + return name; + } + + @Override + public VertexAttribSpec attribSpec() { + return spec; + } + + @Override + public int getDivisor() { + return 1; + } + + @Override + public int getBufferIndex() { + return 1; + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java new file mode 100644 index 000000000..5568591f1 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltCrusherInteractionHandler.java @@ -0,0 +1,75 @@ +package com.simibubi.create.content.contraptions.relays.belt.transport; + +import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerBlock; +import com.simibubi.create.content.contraptions.components.crusher.CrushingWheelControllerTileEntity; +import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; +import net.minecraft.block.BlockState; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; +import net.minecraftforge.items.ItemHandlerHelper; + +public class BeltCrusherInteractionHandler { + + public static boolean checkForCrushers(BeltInventory beltInventory, TransportedItemStack currentItem, + float nextOffset) { + + boolean beltMovementPositive = beltInventory.beltMovementPositive; + int firstUpcomingSegment = (int) Math.floor(currentItem.beltPosition); + int step = beltMovementPositive ? 1 : -1; + firstUpcomingSegment = MathHelper.clamp(firstUpcomingSegment, 0, beltInventory.belt.beltLength - 1); + + for (int segment = firstUpcomingSegment; beltMovementPositive ? segment <= nextOffset + : segment + 1 >= nextOffset; segment += step) { + BlockPos crusherPos = BeltHelper.getPositionForOffset(beltInventory.belt, segment) + .up(); + World world = beltInventory.belt.getWorld(); + BlockState crusherState = world.getBlockState(crusherPos); + if (!(crusherState.getBlock() instanceof CrushingWheelControllerBlock)) + continue; + Direction crusherFacing = crusherState.get(CrushingWheelControllerBlock.FACING); + Direction movementFacing = beltInventory.belt.getMovementFacing(); + if (crusherFacing != movementFacing) + continue; + + float crusherEntry = segment + .5f; + crusherEntry += .399f * (beltMovementPositive ? -1 : 1); + float postCrusherEntry = crusherEntry + .799f * (!beltMovementPositive ? -1 : 1); + + boolean hasCrossed = nextOffset > crusherEntry && nextOffset < postCrusherEntry && beltMovementPositive + || nextOffset < crusherEntry && nextOffset > postCrusherEntry && !beltMovementPositive; + if (!hasCrossed) + return false; + currentItem.beltPosition = crusherEntry; + + TileEntity te = world.getTileEntity(crusherPos); + if (!(te instanceof CrushingWheelControllerTileEntity)) + return true; + + CrushingWheelControllerTileEntity crusherTE = (CrushingWheelControllerTileEntity) te; + + ItemStack toInsert = currentItem.stack.copy(); + + ItemStack remainder = ItemHandlerHelper.insertItemStacked(crusherTE.inventory, toInsert, false); + if (toInsert.equals(remainder, false)) + return true; + + int notFilled = currentItem.stack.getCount() - toInsert.getCount(); + if (!remainder.isEmpty()) { + remainder.grow(notFilled); + } else if (notFilled > 0) + remainder = ItemHandlerHelper.copyStackWithSize(currentItem.stack, notFilled); + + currentItem.stack = remainder; + beltInventory.belt.sendData(); + return true; + } + + return false; + } + + +} 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 1284afba9..8b4dcbde9 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 @@ -151,6 +151,10 @@ public class BeltInventory { if (BeltFunnelInteractionHandler.checkForFunnels(this, currentItem, nextOffset)) continue; + // Horizontal Crushing Wheels + if (BeltCrusherInteractionHandler.checkForCrushers(this, currentItem, nextOffset)) + continue; + // Apply Movement currentItem.beltPosition += limitedMovement; currentItem.sideOffset += @@ -286,9 +290,7 @@ public class BeltInventory { } private Ending resolveEnding() { - int lastOffset = beltMovementPositive ? belt.beltLength - 1 : 0; World world = belt.getWorld(); - BlockPos lastPosition = BeltHelper.getPositionForOffset(belt, lastOffset); BlockPos nextPosition = BeltHelper.getPositionForOffset(belt, beltMovementPositive ? belt.beltLength : -1); // if (AllBlocks.BRASS_BELT_FUNNEL.has(world.getBlockState(lastPosition.up()))) diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java index ef69047a0..8bc847faf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java @@ -1,17 +1,11 @@ package com.simibubi.create.content.contraptions.relays.elementary; -import java.util.Optional; -import java.util.function.Function; -import java.util.function.Predicate; - -import com.google.common.base.Predicates; import com.simibubi.create.foundation.advancement.AllTriggers; -import com.simibubi.create.foundation.advancement.SimpleTrigger; +import com.simibubi.create.foundation.advancement.ITriggerable; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.NBTHelper; - import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -20,6 +14,10 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.world.World; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Predicate; + public class BracketedTileEntityBehaviour extends TileEntityBehaviour { public static BehaviourType TYPE = new BehaviourType<>(); @@ -28,10 +26,10 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { private boolean reRender; private Predicate pred; - private Function trigger; + private Function trigger; public BracketedTileEntityBehaviour(SmartTileEntity te) { - this(te, Predicates.alwaysTrue()); + this(te, state -> true); } public BracketedTileEntityBehaviour(SmartTileEntity te, Predicate pred) { @@ -40,7 +38,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { bracket = Optional.empty(); } - public BracketedTileEntityBehaviour withTrigger(Function trigger) { + public BracketedTileEntityBehaviour withTrigger(Function trigger) { this.trigger = trigger; return this; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java index 31a886453..ba6b819b8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java @@ -1,5 +1,10 @@ package com.simibubi.create.content.contraptions.relays.elementary; +import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS; + +import java.util.List; +import java.util.function.Predicate; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; @@ -7,10 +12,10 @@ import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementOffset; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -26,11 +31,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.World; -import java.util.List; -import java.util.function.Predicate; - -import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS; - public class CogwheelBlockItem extends BlockItem { boolean large; @@ -150,9 +150,11 @@ public class CogwheelBlockItem extends BlockItem { @Override public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), - Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), - ((CogWheelBlock) state.getBlock()).isLarge ? 1.5D : 0.75D); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), + // Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), + // ((CogWheelBlock) state.getBlock()).isLarge ? 1.5D : 0.75D); + + displayGhost(offset); } } @@ -227,8 +229,10 @@ public class CogwheelBlockItem extends BlockItem { @Override public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), - Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), 1D); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), + // Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), 1D); + + displayGhost(offset); } protected boolean hitOnShaft(BlockState state, BlockRayTraceResult ray) { @@ -320,10 +324,12 @@ public class CogwheelBlockItem extends BlockItem { @Override public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), - Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, offset.getTransform() - .apply(AllBlocks.LARGE_COGWHEEL.getDefaultState()) - .get(AXIS))); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), + // Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, offset.getTransform() + // .apply(AllBlocks.LARGE_COGWHEEL.getDefaultState()) + // .get(AXIS))); + + displayGhost(offset); } } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java index d68c293f0..3b0bb2e8d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.relays.elementary; +import java.util.function.Predicate; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.content.contraptions.base.KineticTileEntity; @@ -8,6 +10,7 @@ import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.util.PoleHelper; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -23,8 +26,6 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -import java.util.function.Predicate; - public class ShaftBlock extends AbstractShaftBlock { private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java index 410d15108..ddf55f972 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/SimpleKineticTileEntity.java @@ -23,12 +23,12 @@ public class SimpleKineticTileEntity extends KineticTileEntity { public void addBehaviours(List behaviours) { behaviours.add( new BracketedTileEntityBehaviour(this, state -> state.getBlock() instanceof AbstractShaftBlock).withTrigger( - state -> state.getBlock() instanceof ShaftBlock ? AllTriggers.BRACKET_SHAFT : AllTriggers.BRACKET_COG)); + state -> AllTriggers.BRACKET_APPLY_TRIGGER.constructTriggerFor(state.getBlock()))); super.addBehaviours(behaviours); } @Override - public AxisAlignedBB getRenderBoundingBox() { + public AxisAlignedBB makeRenderBoundingBox() { return new AxisAlignedBB(pos).grow(1); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftInstance.java new file mode 100644 index 000000000..3dd04f582 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/ShaftInstance.java @@ -0,0 +1,29 @@ +package com.simibubi.create.content.contraptions.relays.encased; + +import com.simibubi.create.content.contraptions.base.KineticTileEntity; +import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; + +import net.minecraft.block.BlockState; +import net.minecraft.tileentity.TileEntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class ShaftInstance extends SingleRotatingInstance { + + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, ShaftInstance::new)); + } + + public ShaftInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + super(dispatcher, tile); + } + + @Override + protected BlockState getRenderedBlockState() { + return shaft(getRotationAxis()); + } + +} 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 new file mode 100644 index 000000000..1ac7476bb --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java @@ -0,0 +1,87 @@ +package com.simibubi.create.content.contraptions.relays.encased; + +import java.util.ArrayList; + +import com.simibubi.create.AllBlockPartials; +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.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.block.Block; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class SplitShaftInstance extends KineticTileInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, SplitShaftInstance::new)); + } + + protected 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); + + float speed = tile.getSpeed(); + + for (Direction dir : Iterate.directionsInAxis(boxAxis)) { + + InstancedModel half = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, dir); + + float splitSpeed = speed * tile.getRotationSpeedModifier(dir); + + keys.add(half.setupInstance(setupFunc(splitSpeed, boxAxis))); + } + } + + @Override + public void onUpdate() { + Block block = lastState.getBlock(); + final Direction.Axis boxAxis = ((IRotate) block).getRotationAxis(lastState); + + Direction[] directions = Iterate.directionsInAxis(boxAxis); + + for (int i : Iterate.zeroAndOne) { + updateRotation(keys.get(i), directions[i]); + } + } + + @Override + public void updateLight() { + for (InstanceKey key : keys) { + key.modifyInstance(this::relight); + } + } + + @Override + public void remove() { + keys.forEach(InstanceKey::delete); + keys.clear(); + } + + protected void updateRotation(InstanceKey key, Direction dir) { + key.modifyInstance(data -> { + Direction.Axis axis = dir.getAxis(); + + data.setColor(tile.network) + .setRotationalSpeed(tile.getSpeed() * tile.getRotationSpeedModifier(dir)) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()); + }); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java index 96186728f..8aca8cccd 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftRenderer.java @@ -5,9 +5,10 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.Block; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -26,6 +27,8 @@ public class SplitShaftRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + if (FastRenderDispatcher.available(te.getWorld())) return; + Block block = te.getBlockState().getBlock(); final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); final BlockPos pos = te.getPos(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java index 8c24f63b4..3085dae58 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeRenderer.java @@ -6,8 +6,8 @@ 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.gauge.GaugeBlock.Type; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java index 3969af754..1cdec6749 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeTileEntity.java @@ -50,4 +50,8 @@ public class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInf return true; } + @Override + public boolean shouldRenderAsTE() { + return true; + } } 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 new file mode 100644 index 000000000..1d597f8ec --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java @@ -0,0 +1,117 @@ +package com.simibubi.create.content.contraptions.relays.gearbox; + +import java.util.EnumMap; +import java.util.Map; + +import com.simibubi.create.AllBlockPartials; +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.InstancedTileRenderRegistry; +import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.utility.Iterate; + +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.LightType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; + +public class GearboxInstance extends KineticTileInstance { + public static void register(TileEntityType type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, GearboxInstance::new)); + } + + protected 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); + + int blockLight = world.getLightLevel(LightType.BLOCK, pos); + int skyLight = world.getLightLevel(LightType.SKY, pos); + updateSourceFacing(); + + for (Direction direction : Iterate.directions) { + final Direction.Axis axis = direction.getAxis(); + if (boxAxis == axis) + continue; + + InstancedModel shaft = AllBlockPartials.SHAFT_HALF.renderOnDirectionalSouthRotating(modelManager, lastState, direction); + + InstanceKey key = shaft.setupInstance(data -> { + data.setBlockLight(blockLight) + .setSkyLight(skyLight) + .setRotationalSpeed(getSpeed(direction)) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()) + .setTileEntity(tile); + }); + keys.put(direction, key); + } + } + + private float getSpeed(Direction direction) { + float speed = tile.getSpeed(); + + if (speed != 0 && sourceFacing != null) { + if (sourceFacing.getAxis() == direction.getAxis()) + speed *= sourceFacing == direction ? 1 : -1; + else if (sourceFacing.getAxisDirection() == direction.getAxisDirection()) + speed *= -1; + } + return speed; + } + + protected void updateSourceFacing() { + if (tile.hasSource()) { + BlockPos source = tile.source.subtract(pos); + sourceFacing = Direction.getFacingFromVector(source.getX(), source.getY(), source.getZ()); + } else { + sourceFacing = null; + } + } + + @Override + public void onUpdate() { + updateSourceFacing(); + for (Map.Entry> key : keys.entrySet()) { + key.getValue().modifyInstance(data -> { + Direction direction = key.getKey(); + Direction.Axis axis = direction.getAxis(); + + data.setColor(tile.network) + .setRotationalSpeed(getSpeed(direction)) + .setRotationOffset(getRotationOffset(axis)) + .setRotationAxis(Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getUnitVector()); + }); + } + } + + @Override + public void updateLight() { + int blockLight = tile.getWorld().getLightLevel(LightType.BLOCK, pos); + int skyLight = tile.getWorld().getLightLevel(LightType.SKY, pos); + + for (InstanceKey key : keys.values()) { + key.modifyInstance(data -> data.setBlockLight(blockLight).setSkyLight(skyLight)); + } + } + + @Override + public void remove() { + keys.values().forEach(InstanceKey::delete); + keys.clear(); + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java index 7462e355c..bd74bcdf8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxRenderer.java @@ -4,9 +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.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -25,6 +26,8 @@ public class GearboxRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { + if (FastRenderDispatcher.available(te.getWorld())) return; + final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); final BlockPos pos = te.getPos(); float time = AnimationTickHolder.getRenderTick(); diff --git a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java index 34b5b503d..9fbb2dfe3 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java +++ b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundColor.java @@ -13,7 +13,7 @@ public class ChromaticCompoundColor implements IItemColor { @Override public int getColor(ItemStack stack, int layer) { Minecraft mc = Minecraft.getInstance(); - float pt = mc.getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); float progress = (float) ((mc.player.getYaw(pt)) / 180 * Math.PI) + (AnimationTickHolder.getRenderTick() / 10f); if (layer == 0) return ColorHelper.mixColors(0x6e5773, 0x6B3074, ((float) MathHelper.sin(progress) + 1) / 2); diff --git a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java index 5d85d663f..4b853139a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/ChromaticCompoundItem.java @@ -1,10 +1,8 @@ package com.simibubi.create.content.curiosities; -import java.util.List; import java.util.Random; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.CRecipes; import com.simibubi.create.foundation.utility.ColorHelper; @@ -13,7 +11,6 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.entity.item.ItemEntity; -import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; @@ -21,7 +18,6 @@ import net.minecraft.particles.ParticleTypes; import net.minecraft.tileentity.BeaconTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceContext; @@ -152,10 +148,6 @@ public class ChromaticCompoundItem extends Item { data.putBoolean("FromLight", true); entity.setItem(newStack); - List players = - world.getEntitiesWithinAABB(ServerPlayerEntity.class, new AxisAlignedBB(entity.getPosition()).grow(8)); - players.forEach(AllTriggers.ABSORBED_LIGHT::trigger); - return false; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java index 55b3c1138..df9ed6783 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryEffectPacket.java @@ -42,7 +42,7 @@ public class SymmetryEffectPacket extends SimplePacketBase { } public void handle(Supplier ctx) { - ctx.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { if (Minecraft.getInstance().player.getPositionVector().distanceTo(new Vec3d(mirror)) > 100) return; for (BlockPos to : positions) diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java index da65a069d..6118eb8b9 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/SymmetryWandItem.java @@ -66,7 +66,7 @@ public class SymmetryWandItem extends Item { // Shift -> open GUI if (player.isSneaking()) { if (player.world.isRemote) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { openWandGUI(wand, context.getHand()); }); player.getCooldownTracker() @@ -135,7 +135,7 @@ public class SymmetryWandItem extends Item { // Shift -> Open GUI if (playerIn.isSneaking()) { if (worldIn.isRemote) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { openWandGUI(playerIn.getHeldItem(handIn), handIn); }); playerIn.getCooldownTracker() diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java index a74a092a0..4d01867c5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItem.java @@ -7,6 +7,7 @@ import com.google.common.collect.Multimap; import com.simibubi.create.AllItems; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.ClientPlayerEntity; @@ -125,7 +126,7 @@ public class ExtendoGripItem extends Item { .getValue(); if (!player.isCreative()) d0 -= 0.5f; - Vec3d vec3d = player.getEyePosition(mc.getRenderPartialTicks()); + Vec3d vec3d = player.getEyePosition(AnimationTickHolder.getPartialTicks()); Vec3d vec3d1 = player.getLook(1.0F); Vec3d vec3d2 = vec3d.add(vec3d1.x * d0, vec3d1.y * d0, vec3d1.z * d0); AxisAlignedBB axisalignedbb = player.getBoundingBox() diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java index 3788d6000..b665e4ae8 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripItemRenderer.java @@ -7,7 +7,6 @@ import com.simibubi.create.foundation.item.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.item.ItemStack; @@ -28,9 +27,9 @@ public class ExtendoGripItemRenderer extends CustomRenderedItemModelRenderer mainHandAnimation && swingProgress > 0) mainHandAnimation = 0.95f; - float animation = MathHelper.lerp(Minecraft.getInstance() - .getRenderPartialTicks(), ExtendoGripRenderHandler.lastMainHandAnimation, - ExtendoGripRenderHandler.mainHandAnimation); + float animation = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), + ExtendoGripRenderHandler.lastMainHandAnimation, + ExtendoGripRenderHandler.mainHandAnimation); animation = animation * animation * animation; ms.translate(flip * (0.64000005F - .1f), -0.4F + equipProgress * -0.6F, -0.71999997F + .3f); diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java index 1915a3e3b..2411eb091 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItem.java @@ -77,6 +77,8 @@ public class SandPaperItem extends Item { AxisAlignedBB bb = new AxisAlignedBB(hitVec, hitVec).grow(1f); ItemEntity pickUp = null; for (ItemEntity itemEntity : worldIn.getEntitiesWithinAABB(ItemEntity.class, bb)) { + if (!itemEntity.isAlive()) + continue; if (itemEntity.getPositionVec() .distanceTo(playerIn.getPositionVec()) > 3) continue; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java index 78b741a2b..303e4dc5b 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/SandPaperItemRenderer.java @@ -25,7 +25,7 @@ public class SandPaperItemRenderer extends ItemStackTileEntityRenderer { ClientPlayerEntity player = Minecraft.getInstance().player; SandPaperModel mainModel = (SandPaperModel) itemRenderer.getItemModelWithOverrides(stack, Minecraft.getInstance().world, null); TransformType perspective = mainModel.getCurrentPerspective(); - float partialTicks = Minecraft.getInstance().getRenderPartialTicks(); + float partialTicks = AnimationTickHolder.getPartialTicks(); boolean leftHand = perspective == TransformType.FIRST_PERSON_LEFT_HAND; boolean firstPerson = leftHand || perspective == TransformType.FIRST_PERSON_RIGHT_HAND; @@ -49,7 +49,7 @@ public class SandPaperItemRenderer extends ItemStackTileEntityRenderer { // Reverse bobbing float time = (float) (!jeiMode ? player.getItemInUseCount() - : (-AnimationTickHolder.ticks) % stack.getUseDuration()) - partialTicks + 1.0F; + : (-AnimationTickHolder.getTicks()) % stack.getUseDuration()) - partialTicks + 1.0F; if (time / (float) stack.getUseDuration() < 0.8F) { float bobbing = -MathHelper.abs(MathHelper.cos(time / 4.0F * (float) Math.PI) * 0.1F); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java index 3fc30e373..f3d63fb7d 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperBeamPacket.java @@ -48,7 +48,7 @@ public class ZapperBeamPacket extends SimplePacketBase { } public void handle(Supplier context) { - context.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + context.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { if (Minecraft.getInstance().player.getPositionVector().distanceTo(start) > 100) return; ZapperRenderHandler.addBeam(new LaserBeam(start, target).followPlayer(self, hand == Hand.MAIN_HAND)); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java index 44303bf94..2c01c419a 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItem.java @@ -93,7 +93,7 @@ public abstract class ZapperItem extends Item { if (context.getPlayer() != null && context.getPlayer() .isSneaking()) { if (context.getWorld().isRemote) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { openHandgunGUI(context.getItem(), context.getHand() == Hand.OFF_HAND); }); applyCooldown(context.getPlayer(), context.getItem(), false); @@ -111,7 +111,7 @@ public abstract class ZapperItem extends Item { // Shift -> Open GUI if (player.isSneaking()) { if (world.isRemote) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { openHandgunGUI(item, hand == Hand.OFF_HAND); }); applyCooldown(player, item, false); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java index fe428b05d..05ce12201 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperRenderHandler.java @@ -8,6 +8,7 @@ import java.util.function.Supplier; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.AbstractClientPlayerEntity; @@ -63,8 +64,7 @@ public class ZapperRenderHandler { } public static Vec3d getExactBarrelPos(boolean mainHand) { - float partialTicks = Minecraft.getInstance() - .getRenderPartialTicks(); + float partialTicks = AnimationTickHolder.getPartialTicks(); ClientPlayerEntity player = Minecraft.getInstance().player; float yaw = (float) ((player.getYaw(partialTicks)) / -180 * Math.PI); float pitch = (float) ((player.getPitch(partialTicks)) / -180 * Math.PI); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java index 21d555b6b..416a7c597 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItem.java @@ -109,7 +109,7 @@ public class BlockzapperItem extends ZapperItem { continue; if (!selectedState.isValidPosition(world, placed)) continue; - if (!player.isCreative() && !canBreak(stack, world.getBlockState(placed), world, placed)) + if (!player.isCreative() && !canBreak(stack, world.getBlockState(placed), world, placed,player)) continue; if (!player.isCreative() && BlockHelper.findAndRemoveInInventory(selectedState, player, 1) == 0) { player.getCooldownTracker() @@ -278,10 +278,13 @@ public class BlockzapperItem extends ZapperItem { return list; } - public static boolean canBreak(ItemStack stack, BlockState state, World world, BlockPos pos) { + public static boolean canBreak(ItemStack stack, BlockState state, World world, BlockPos pos,PlayerEntity player) { ComponentTier tier = getTier(Components.Body, stack); float blockHardness = state.getBlockHardness(world, pos); - + //If we can't change the block (e.g chunk protection) + if (!isAllowedToPlace(world,pos,player)){ + return false; + } if (blockHardness == -1) return false; if (tier == ComponentTier.None) @@ -294,6 +297,14 @@ public class BlockzapperItem extends ZapperItem { return false; } + public static boolean isAllowedToPlace(World world, BlockPos pos,PlayerEntity player){ + BlockSnapshot blocksnapshot = BlockSnapshot.getBlockSnapshot(world, pos); + if (ForgeEventFactory.onBlockPlace(player, blocksnapshot, Direction.UP)) { + return false; + } + return true; + } + public static int getMaxAoe(ItemStack stack) { ComponentTier tier = getTier(Components.Amplifier, stack); if (tier == ComponentTier.None) diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItemRenderer.java index 3f05fca7f..6d3c512b1 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/blockzapper/BlockzapperItemRenderer.java @@ -32,8 +32,7 @@ public class BlockzapperItemRenderer extends ZapperItemRenderer type) { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> + InstancedTileRenderRegistry.instance.register(type, ArmInstance::new)); + } + + public ArmInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + super(modelManager, tile); + } + + @Override + protected InstancedModel getModel() { + return AllBlockPartials.ARM_COG.renderOnRotating(modelManager, tile.getBlockState()); + } +} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java index eff83fadb..c032ed3dc 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmItem.java @@ -33,7 +33,7 @@ public class ArmItem extends BlockItem { protected boolean onBlockPlaced(BlockPos pos, World world, PlayerEntity p_195943_3_, ItemStack p_195943_4_, BlockState p_195943_5_) { if (world.isRemote) - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ArmInteractionPointHandler.flushSettings(pos)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ArmInteractionPointHandler.flushSettings(pos)); return super.onBlockPlaced(pos, world, p_195943_3_, p_195943_4_, p_195943_5_); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java index f770012ed..8e9a47e8c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmRenderer.java @@ -6,11 +6,11 @@ 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.logistics.block.mechanicalArm.ArmTileEntity.Phase; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -29,6 +29,11 @@ public class ArmRenderer extends KineticTileEntityRenderer { super(dispatcher); } + @Override + public boolean isGlobalRenderer(KineticTileEntity te) { + return true; + } + @Override protected void renderSafe(KineticTileEntity te, float pt, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { @@ -44,14 +49,14 @@ public class ArmRenderer extends KineticTileEntityRenderer { float upperArmAngle = arm.upperArmAngle.get(pt) - 90; float headAngle = arm.headAngle.get(pt); - boolean rave = te instanceof ArmTileEntity && ((ArmTileEntity) te).phase == Phase.DANCING; + boolean rave = arm.phase == Phase.DANCING; float renderTick = AnimationTickHolder.getRenderTick() + (te.hashCode() % 64); if (rave) { 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.ticks * 100); + color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); } ms.push(); 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 6a65e0e26..f7f6fb803 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 @@ -145,8 +145,8 @@ public class ArmTileEntity extends KineticTileEntity { @Override @OnlyIn(Dist.CLIENT) - public AxisAlignedBB getRenderBoundingBox() { - return super.getRenderBoundingBox().grow(3); + public AxisAlignedBB makeRenderBoundingBox() { + return super.makeRenderBoundingBox().grow(3); } private boolean checkForMusicAmong(List list) { @@ -474,6 +474,11 @@ public class ArmTileEntity extends KineticTileEntity { return true; } + @Override + public boolean shouldRenderAsTE() { + return true; + } + private class SelectionModeValueBox extends CenteredSideValueBoxTransform { public SelectionModeValueBox() { diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java index dcc0521c8..7ed7acc93 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverRenderer.java @@ -3,10 +3,10 @@ package com.simibubi.create.content.logistics.block.redstone; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.ColorHelper; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java index a467c4cd4..8db988bfa 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneContactBlock.java @@ -1,7 +1,13 @@ package com.simibubi.create.content.logistics.block.redstone; +import java.util.Random; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.block.ProperDirectionalBlock; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -16,10 +22,6 @@ import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; -import java.util.Random; - @ParametersAreNonnullByDefault @MethodsReturnNonnullByDefault public class RedstoneContactBlock extends ProperDirectionalBlock { diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java index 3fb18767d..97c224c18 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/RedstoneLinkBlock.java @@ -5,6 +5,7 @@ import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.utility.Iterate; + import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java index 8f8ec7db3..6055c1aac 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchBlock.java @@ -100,7 +100,7 @@ public class StockpileSwitchBlock extends HorizontalBlock implements ITE () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); return ActionResultType.SUCCESS; } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java index f3f244d59..85b40b8d2 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/attribute/astralsorcery/AstralSorceryAmuletAttribute.java @@ -52,7 +52,6 @@ public class AstralSorceryAmuletAttribute implements ItemAttribute { @Override public Object[] getTranslationParameters() { - ResourceLocation traitResource = new ResourceLocation(enchName); String something = ""; Enchantment enchant = ForgeRegistries.ENCHANTMENTS.getValue(ResourceLocation.tryCreate(enchName)); diff --git a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java b/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java index 8aa9546ca..7f2a837da 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java +++ b/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java @@ -10,6 +10,7 @@ import com.tterrag.registrate.builders.ItemBuilder; import com.tterrag.registrate.providers.DataGenContext; import com.tterrag.registrate.providers.RegistrateBlockstateProvider; import com.tterrag.registrate.providers.RegistrateRecipeProvider; +import com.tterrag.registrate.providers.loot.RegistrateBlockLootTables; import com.tterrag.registrate.util.DataIngredient; import com.tterrag.registrate.util.nullness.NonnullType; @@ -185,7 +186,7 @@ public abstract class PaletteBlockPartial { protected BlockBuilder transformBlock( BlockBuilder builder, String variantName, PaletteBlockPatterns pattern) { - builder.loot((lt, block) -> lt.registerLootTable(block, lt.droppingSlab(block))); + builder.loot((lt, block) -> lt.registerLootTable(block, RegistrateBlockLootTables.droppingSlab(block))); return super.transformBlock(builder, variantName, pattern); } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java index 985338d5d..e9d13b67c 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicProcessor.java @@ -1,5 +1,9 @@ package com.simibubi.create.content.schematics; +import java.util.Optional; + +import javax.annotation.Nullable; + import com.mojang.datafixers.Dynamic; import com.mojang.datafixers.types.DynamicOps; import com.simibubi.create.foundation.utility.NBTProcessors; @@ -16,9 +20,6 @@ import net.minecraft.world.gen.feature.template.PlacementSettings; import net.minecraft.world.gen.feature.template.StructureProcessor; import net.minecraft.world.gen.feature.template.Template; -import javax.annotation.Nullable; -import java.util.Optional; - public class SchematicProcessor extends StructureProcessor { public static final SchematicProcessor INSTANCE = new SchematicProcessor(); diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java index 706d9d931..bf90d3f84 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonRenderer.java @@ -7,8 +7,8 @@ import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.schematics.block.LaunchedItem.ForBlockState; import com.simibubi.create.content.schematics.block.LaunchedItem.ForEntity; +import com.simibubi.create.foundation.render.SuperByteBuffer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; -import com.simibubi.create.foundation.utility.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java index cfdf35b51..d85b1a27b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicAndQuillHandler.java @@ -18,6 +18,7 @@ import com.simibubi.create.content.schematics.ClientSchematicLoader; import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.FilesHelper; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.RaycastHelper; @@ -139,8 +140,7 @@ public class SchematicAndQuillHandler { ClientPlayerEntity player = Minecraft.getInstance().player; if (AllKeys.ACTIVATE_TOOL.isPressed()) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); Vec3d targetVec = player.getEyePosition(pt) .add(player.getLookVec() .scale(range)); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java index 8eebde8f5..74c6b9eac 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHandler.java @@ -17,6 +17,7 @@ import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; import com.simibubi.create.foundation.gui.ToolSelectionScreen; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.outliner.AABBOutline; import net.minecraft.client.Minecraft; @@ -160,8 +161,7 @@ public class SchematicHandler { transformation.applyGLTransformations(ms); if (!renderers.isEmpty()) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); boolean lr = transformation.getScaleLR() .get(pt) < 0; boolean fb = transformation.getScaleFB() @@ -193,8 +193,7 @@ public class SchematicHandler { currentTool.getTool() .renderOverlay(ms, buffer); - selectionScreen.renderPassive(Minecraft.getInstance() - .getRenderPartialTicks()); + selectionScreen.renderPassive(AnimationTickHolder.getPartialTicks()); } public void onMouseInput(int button, boolean pressed) { diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java index 21971355a..c7c346182 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicRenderer.java @@ -11,10 +11,10 @@ import org.lwjgl.opengl.GL11; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.schematics.SchematicWorld; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.render.TileEntityRenderHelper; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.MatrixStacker; -import com.simibubi.create.foundation.utility.SuperByteBuffer; -import com.simibubi.create.foundation.utility.TileEntityRenderHelper; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -34,7 +34,7 @@ public class SchematicRenderer { private final Set startedBufferBuilders = new HashSet<>(getLayerCount()); private boolean active; private boolean changed; - private SchematicWorld schematic; + protected SchematicWorld schematic; private BlockPos anchor; public SchematicRenderer() { @@ -81,7 +81,7 @@ public class SchematicRenderer { buffer); } - private void redraw(Minecraft minecraft) { + protected void redraw(Minecraft minecraft) { usedBlockRenderLayers.clear(); startedBufferBuilders.clear(); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java index 6a78ca4a3..9e1cb9485 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicTransformation.java @@ -5,10 +5,10 @@ import static java.lang.Math.abs; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingAngle; import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; -import net.minecraft.client.Minecraft; import net.minecraft.util.Direction.Axis; import net.minecraft.util.Mirror; import net.minecraft.util.Rotation; @@ -52,8 +52,7 @@ public class SchematicTransformation { } public void applyGLTransformations(MatrixStack ms) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); // Translation ms.translate(x.get(pt), y.get(pt), z.get(pt)); @@ -93,8 +92,7 @@ public class SchematicTransformation { } public Vec3d toLocalSpace(Vec3d vec) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); Vec3d rotationOffset = getRotationOffset(true); vec = vec.subtract(x.get(pt), y.get(pt), z.get(pt)); @@ -181,8 +179,7 @@ public class SchematicTransformation { } public float getCurrentRotation() { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); return rotation.get(pt); } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java index e58e5cd85..ea5de6a18 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/DeployTool.java @@ -4,10 +4,10 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllKeys; import com.simibubi.create.content.schematics.client.SchematicTransformation; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.outliner.AABBOutline; -import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTUtil; import net.minecraft.util.math.AxisAlignedBB; @@ -43,8 +43,7 @@ public class DeployTool extends PlacementToolBase { return; ms.push(); - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); double x = MathHelper.lerp(pt, lastChasingSelectedPos.x, chasingSelectedPos.x); double y = MathHelper.lerp(pt, lastChasingSelectedPos.y, chasingSelectedPos.y); double z = MathHelper.lerp(pt, lastChasingSelectedPos.z, chasingSelectedPos.z); diff --git a/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java b/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java index c20606a52..6a7863831 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/tools/SchematicToolBase.java @@ -10,6 +10,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.schematics.client.SchematicHandler; import com.simibubi.create.content.schematics.client.SchematicTransformation; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.RaycastHelper; import com.simibubi.create.foundation.utility.RaycastHelper.PredicateTraceResult; import com.simibubi.create.foundation.utility.VecHelper; @@ -91,8 +92,7 @@ public abstract class SchematicToolBase implements ISchematicTool { // Select location at distance if (selectIgnoreBlocks) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); selectedPos = new BlockPos(player.getEyePosition(pt) .add(player.getLookVec() .scale(selectionRange))); diff --git a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java index d689372ec..ddc676657 100644 --- a/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java +++ b/src/main/java/com/simibubi/create/content/schematics/item/SchematicItem.java @@ -165,7 +165,7 @@ public class SchematicItem extends Item { if (!player.getHeldItem(hand) .hasTag()) return false; - DistExecutor.runWhenOn(Dist.CLIENT, () -> this::displayBlueprintScreen); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::displayBlueprintScreen); return true; } diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index 957bde4ad..58a641c74 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -11,6 +11,7 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.KineticDebugger; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer; @@ -29,6 +30,8 @@ import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.LeftClickPacket; import com.simibubi.create.foundation.ponder.PonderTooltipHandler; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; +import com.simibubi.create.foundation.render.backend.RenderWork; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; @@ -42,11 +45,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.client.world.ClientWorld; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.IFluidState; import net.minecraft.item.ItemStack; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; +import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.EntityViewRenderEvent; @@ -75,11 +80,12 @@ public class ClientEvents { if (event.phase == Phase.START) return; - AnimationTickHolder.tick(); - if (!isGameActive()) return; + AnimationTickHolder.tick(); + FastRenderDispatcher.tick(); + CreateClient.schematicSender.tick(); CreateClient.schematicAndQuillHandler.tick(); CreateClient.schematicHandler.tick(); @@ -108,30 +114,51 @@ public class ClientEvents { ArmInteractionPointHandler.tick(); PlacementHelpers.tick(); CreateClient.outliner.tickOutlines(); + CreateClient.ghostBlocks.tickGhosts(); + ContraptionRenderDispatcher.tick(); } @SubscribeEvent public static void onLoadWorld(WorldEvent.Load event) { - CreateClient.bufferCache.invalidate(); + IWorld world = event.getWorld(); + if (world.isRemote() && world instanceof ClientWorld) { + CreateClient.invalidateRenderers(); + AnimationTickHolder.reset(); + ((ClientWorld) world).loadedTileEntityList.forEach(CreateClient.kineticRenderer::add); + } + } + + @SubscribeEvent + public static void onUnloadWorld(WorldEvent.Unload event) { + if (event.getWorld().isRemote()) { + CreateClient.invalidateRenderers(); + AnimationTickHolder.reset(); + } } @SubscribeEvent public static void onRenderWorld(RenderWorldLastEvent event) { + Vec3d cameraPos = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); + MatrixStack ms = event.getMatrixStack(); - ActiveRenderInfo info = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); - Vec3d view = info.getProjectedView(); ms.push(); - ms.translate(-view.getX(), -view.getY(), -view.getZ()); + ms.translate(-cameraPos.getX(), -cameraPos.getY(), -cameraPos.getZ()); SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); CouplingRenderer.renderAll(ms, buffer); CreateClient.schematicHandler.render(ms, buffer); + CreateClient.ghostBlocks.renderAll(ms, buffer); + CreateClient.outliner.renderOutlines(ms, buffer); +// LightVolumeDebugger.render(ms, buffer); // CollisionDebugger.render(ms, buffer); buffer.draw(); RenderSystem.enableCull(); ms.pop(); + + RenderWork.runAll(); + FastRenderDispatcher.endFrame(); } @SubscribeEvent @@ -183,6 +210,7 @@ public class ClientEvents { if (!isGameActive()) return; TurntableHandler.gameRenderTick(); + ContraptionRenderDispatcher.renderTick(); } protected static boolean isGameActive() { diff --git a/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java b/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java index 9206a88c4..6342594b9 100644 --- a/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java +++ b/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java @@ -17,7 +17,7 @@ public class ResourceReloadHandler extends ReloadListener { @Override protected void apply(Object $, IResourceManager resourceManagerIn, IProfiler profilerIn) { SpriteShifter.reloadUVs(); - CreateClient.bufferCache.invalidate(); + CreateClient.invalidateRenderers(); } } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java index 0690927b8..013a6282e 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java @@ -6,6 +6,10 @@ import java.util.Set; import java.util.function.Consumer; import java.util.function.Supplier; +import com.simibubi.create.content.logistics.InWorldProcessing; +import net.minecraft.fluid.FlowingFluid; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.Fluids; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -61,9 +65,9 @@ public class AllAdvancements implements IDataProvider { Advancement aesthetics = advancement("aesthetics", AllBlocks.WOODEN_BRACKET.get(), TaskType.NORMAL).withParent(andesite_alloy) - .withCriterion("0", AllTriggers.BRACKET_SHAFT.instance()) - .withCriterion("1", AllTriggers.BRACKET_COG.instance()) - .withCriterion("2", AllTriggers.BRACKET_PIPE.instance()) + .withCriterion("0", AllTriggers.BRACKET_APPLY_TRIGGER.forEntries(AllBlocks.SHAFT.get())) + .withCriterion("1", AllTriggers.BRACKET_APPLY_TRIGGER.forEntries(AllBlocks.COGWHEEL.get(), AllBlocks.LARGE_COGWHEEL.get())) + .withCriterion("2", AllTriggers.BRACKET_APPLY_TRIGGER.forEntries(AllBlocks.FLUID_PIPE.get())) .register(t, id + ":aesthetics"); Advancement reinforced = @@ -122,19 +126,19 @@ public class AllAdvancements implements IDataProvider { .register(t, id + ":press"); Advancement fan = advancement("fan", AllBlocks.ENCASED_FAN.get(), TaskType.NORMAL).withParent(press) - .withCriterion("0", AllTriggers.FAN.instance()) + .withCriterion("0", AllTriggers.FAN_PROCESSING.forEntries(InWorldProcessing.Type.NONE)) .register(t, id + ":fan"); Advancement fan_lava = advancement("fan_lava", Items.LAVA_BUCKET, TaskType.NORMAL).withParent(fan) - .withCriterion("0", AllTriggers.FAN_LAVA.instance()) + .withCriterion("0", AllTriggers.FAN_PROCESSING.forEntries(InWorldProcessing.Type.BLASTING)) .register(t, id + ":fan_lava"); Advancement fan_smoke = advancement("fan_smoke", Items.CAMPFIRE, TaskType.NORMAL).withParent(fan) - .withCriterion("0", AllTriggers.FAN_SMOKE.instance()) + .withCriterion("0", AllTriggers.FAN_PROCESSING.forEntries(InWorldProcessing.Type.SMOKING)) .register(t, id + ":fan_smoke"); Advancement fan_water = advancement("fan_water", Items.WATER_BUCKET, TaskType.NORMAL).withParent(fan) - .withCriterion("0", AllTriggers.FAN_WATER.instance()) + .withCriterion("0", AllTriggers.FAN_PROCESSING.forEntries(InWorldProcessing.Type.SPLASHING)) .register(t, id + ":fan_water"); Advancement rose_quartz = @@ -157,8 +161,7 @@ public class AllAdvancements implements IDataProvider { Advancement mixer = advancement("mixer", AllBlocks.MECHANICAL_MIXER.get(), TaskType.MILESTONE) .withCriterion("0", placeBlock(AllBlocks.MECHANICAL_MIXER.get())) - .withCriterion("1", isPowered(AllBlocks.MECHANICAL_MIXER.get())) - .withCriterion("2", AllTriggers.MIXER_MIX.instance()) + .withCriterion("1", AllTriggers.MIXER_MIX.instance()) .withParent(basin) .register(t, id + ":mixer"); @@ -293,17 +296,17 @@ public class AllAdvancements implements IDataProvider { Advancement infinite_water = advancement("infinite_water", Items.WATER_BUCKET, TaskType.NORMAL).withParent(hose_pulley) - .withCriterion("0", AllTriggers.INFINITE_WATER.instance()) + .withCriterion("0", isInfinite(Fluids.WATER)) .register(t, id + ":infinite_water"); Advancement infinite_lava = advancement("infinite_lava", Items.LAVA_BUCKET, TaskType.GOAL).withParent(hose_pulley) - .withCriterion("0", AllTriggers.INFINITE_LAVA.instance()) + .withCriterion("0", isInfinite(Fluids.LAVA)) .register(t, id + ":infinite_lava"); Advancement infinite_chocolate = advancement("infinite_chocolate", AllFluids.CHOCOLATE.get() .getFilledBucket(), TaskType.CHALLENGE).withParent(hose_pulley) - .withCriterion("0", AllTriggers.INFINITE_CHOCOLATE.instance()) + .withCriterion("0", isInfinite(AllFluids.CHOCOLATE.get())) .register(t, id + ":infinite_chocolate"); } @@ -493,8 +496,8 @@ public class AllAdvancements implements IDataProvider { return PlacedBlockTrigger.Instance.placedBlock(block); } - public KineticBlockTrigger.Instance isPowered(Block block) { - return AllTriggers.KINETIC_BLOCK.forBlock(block); + public RegistryTrigger.Instance isInfinite(FlowingFluid fluid) { + return AllTriggers.INFINITE_FLUID.forEntries(fluid.getStillFluid()); } public InventoryChangeTrigger.Instance itemGathered(IItemProvider itemprovider) { diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java b/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java index 01a05f238..51ae96434 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java @@ -4,18 +4,23 @@ import java.util.LinkedList; import java.util.List; import java.util.function.Predicate; +import com.simibubi.create.content.logistics.InWorldProcessing; import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.block.Block; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.fluid.Fluid; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class AllTriggers { - private static List> triggers = new LinkedList<>(); + private static final List> triggers = new LinkedList<>(); - public static KineticBlockTrigger KINETIC_BLOCK = add(new KineticBlockTrigger("kinetic_block")); + public static RegistryTrigger INFINITE_FLUID = add(new RegistryTrigger<>("infinite_fluid", Fluid.class)); + public static RegistryTrigger BRACKET_APPLY_TRIGGER = add(new RegistryTrigger<>("bracket_apply", Block.class)); + public static EnumTrigger FAN_PROCESSING = add(new EnumTrigger<>("fan_processing", InWorldProcessing.Type.class)); public static SimpleTrigger ROTATION = simple("rotation"), @@ -27,7 +32,6 @@ public class AllTriggers { LAVA_WHEEL = simple("lava_wheel"), CHOCOLATE_WHEEL = simple("chocolate_wheel"), DEPLOYER_BOOP = simple("deployer"), - ABSORBED_LIGHT = simple("light_absorbed"), SPEED_READ = simple("speed_read"), BASIN_THROW = simple("basin"), PRESS_COMPACT = simple("compact"), @@ -37,9 +41,6 @@ public class AllTriggers { MECHANICAL_ARM = simple("mechanical_arm"), MUSICAL_ARM = simple("musical_arm"), CUCKOO = simple("cuckoo"), - BRACKET_SHAFT = simple("bracket_shaft"), - BRACKET_COG = simple("bracket_cog"), - BRACKET_PIPE = simple("bracket_pipe"), CASING_SHAFT = simple("casing_shaft"), CASING_BELT = simple("casing_belt"), CASING_PIPE = simple("casing_pipe"), @@ -48,10 +49,6 @@ public class AllTriggers { PLACE_TUNNEL = simple("place_tunnel"), CONNECT_TUNNEL = simple("connect_tunnel"), UPWARD_CHUTE = simple("upward_chute"), - FAN = simple("fan"), - FAN_LAVA = simple("fan_lava"), - FAN_SMOKE = simple("fan_smoke"), - FAN_WATER = simple("fan_water"), BELT_FUNNEL = simple("belt_funnel"), BELT_FUNNEL_KISS = simple("belt_funnel_kiss"), CLOCKWORK_BEARING = simple("clockwork_bearing"), @@ -67,9 +64,6 @@ public class AllTriggers { PIPE_COLLISION = simple("pipe_collision"), PIPE_SPILL = simple("pipe_spill"), HOSE_PULLEY = simple("hose_pulley"), - INFINITE_WATER = simple("infinite_water"), - INFINITE_LAVA = simple("infinite_lava"), - INFINITE_CHOCOLATE = simple("infinite_chocolate"), MIXER_MIX = simple("mixer"); private static SimpleTrigger simple(String id) { diff --git a/src/main/java/com/simibubi/create/foundation/advancement/CriterionTriggerBase.java b/src/main/java/com/simibubi/create/foundation/advancement/CriterionTriggerBase.java index 61fc561f6..368c3bc3c 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/CriterionTriggerBase.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/CriterionTriggerBase.java @@ -10,19 +10,25 @@ import java.util.function.Supplier; import com.google.common.collect.Maps; import com.simibubi.create.Create; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.advancements.ICriterionTrigger; import net.minecraft.advancements.PlayerAdvancements; import net.minecraft.advancements.criterion.CriterionInstance; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.util.ResourceLocation; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault public abstract class CriterionTriggerBase implements ICriterionTrigger { public CriterionTriggerBase(String id) { this.ID = new ResourceLocation(Create.ID, id); } - private ResourceLocation ID; + private final ResourceLocation ID; protected final Map>> listeners = Maps.newHashMap(); @Override @@ -53,7 +59,7 @@ public abstract class CriterionTriggerBase> suppliers){ + protected void trigger(ServerPlayerEntity player, @Nullable List> suppliers){ PlayerAdvancements playerAdvancements = player.getAdvancements(); Set> playerListeners = this.listeners.get(playerAdvancements); if (playerListeners != null){ @@ -71,13 +77,13 @@ public abstract class CriterionTriggerBase> suppliers); + protected abstract boolean test(@Nullable List> suppliers); } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/EnumTrigger.java b/src/main/java/com/simibubi/create/foundation/advancement/EnumTrigger.java new file mode 100644 index 000000000..ed3952658 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/advancement/EnumTrigger.java @@ -0,0 +1,35 @@ +package com.simibubi.create.foundation.advancement; + +import mcp.MethodsReturnNonnullByDefault; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class EnumTrigger> extends StringSerializableTrigger { + private final Class reference; + + public EnumTrigger(String id, Class reference) { + super(id); + this.reference = reference; + } + + @Nullable + @Override + protected T getValue(String key) { + try { + return Enum.valueOf(reference, key); + } catch (IllegalArgumentException | NullPointerException e) { + return null; + } + } + + @Nullable + @Override + protected String getKey(@Nullable T value) { + if (value == null) + return null; + return value.name(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/advancement/KineticBlockTrigger.java b/src/main/java/com/simibubi/create/foundation/advancement/KineticBlockTrigger.java deleted file mode 100644 index a72bc6f78..000000000 --- a/src/main/java/com/simibubi/create/foundation/advancement/KineticBlockTrigger.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.simibubi.create.foundation.advancement; - -import java.util.Arrays; -import java.util.List; -import java.util.function.Supplier; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonSyntaxException; -import com.simibubi.create.Create; - -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraft.util.JSONUtils; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.registry.Registry; - -public class KineticBlockTrigger extends CriterionTriggerBase { - - private static final ResourceLocation ID = new ResourceLocation(Create.ID, "kinetic_block"); - - public KineticBlockTrigger(String id) { - super(id); - } - - public Instance forBlock(Block block) { - return new Instance(block); - } - - @Override - @SuppressWarnings("deprecation") - public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context) { - Block block = null; - if (json.has("block")) { - ResourceLocation resourcelocation = new ResourceLocation(JSONUtils.getString(json, "block")); - block = Registry.BLOCK.getValue(resourcelocation).orElseThrow(() -> { - return new JsonSyntaxException("Unknown block type '" + resourcelocation + "'"); - }); - } - - return new Instance(block); - } - - public void trigger(ServerPlayerEntity player, BlockState state) { - trigger(player, Arrays.asList(() -> state.getBlock())); - } - - public static class Instance extends CriterionTriggerBase.Instance { - private final Block block; - - public Instance(Block block) { - super(KineticBlockTrigger.ID); - this.block = block; - } - - @Override - protected boolean test(List> suppliers) { - if (suppliers.isEmpty()) - return false; - return block == suppliers.get(0).get(); - } - - @Override - @SuppressWarnings("deprecation") - public JsonElement serialize() { - JsonObject jsonobject = new JsonObject(); - if (this.block != null) - jsonobject.addProperty("block", Registry.BLOCK.getKey(this.block).toString()); - return jsonobject; - } - } - - -} diff --git a/src/main/java/com/simibubi/create/foundation/advancement/RegistryTrigger.java b/src/main/java/com/simibubi/create/foundation/advancement/RegistryTrigger.java new file mode 100644 index 000000000..0a70e87b0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/advancement/RegistryTrigger.java @@ -0,0 +1,35 @@ +package com.simibubi.create.foundation.advancement; + +import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.registries.IForgeRegistry; +import net.minecraftforge.registries.IForgeRegistryEntry; +import net.minecraftforge.registries.RegistryManager; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public class RegistryTrigger> extends StringSerializableTrigger { + private final IForgeRegistry registry; + + public RegistryTrigger(String id, Class registryType) { + super(id); + this.registry = RegistryManager.ACTIVE.getRegistry(registryType); + } + + @Nullable + @Override + protected T getValue(String key) { + + return registry.getValue(new ResourceLocation(key)); + } + + @Nullable + @Override + protected String getKey(T value) { + ResourceLocation key = registry.getKey(value); + return key == null ? null : key.toString(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/advancement/SimpleTrigger.java b/src/main/java/com/simibubi/create/foundation/advancement/SimpleTrigger.java index 375bdb3a2..4d78b956e 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/SimpleTrigger.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/SimpleTrigger.java @@ -6,9 +6,15 @@ import java.util.function.Supplier; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; +import mcp.MethodsReturnNonnullByDefault; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.util.ResourceLocation; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault public class SimpleTrigger extends CriterionTriggerBase implements ITriggerable { public SimpleTrigger(String id) { @@ -35,7 +41,7 @@ public class SimpleTrigger extends CriterionTriggerBase } @Override - protected boolean test(List> suppliers) { + protected boolean test(@Nullable List> suppliers) { return true; } } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/StringSerializableTrigger.java b/src/main/java/com/simibubi/create/foundation/advancement/StringSerializableTrigger.java new file mode 100644 index 000000000..ae6f4d83d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/advancement/StringSerializableTrigger.java @@ -0,0 +1,103 @@ +package com.simibubi.create.foundation.advancement; + +import com.google.common.collect.Sets; +import com.google.gson.*; +import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.entity.player.ServerPlayerEntity; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +@MethodsReturnNonnullByDefault +@ParametersAreNonnullByDefault +public abstract class StringSerializableTrigger extends CriterionTriggerBase> { + public StringSerializableTrigger(String id) { + super(id); + } + + @SafeVarargs + public final Instance forEntries(@Nullable T... entries) { + return new Instance<>(this, entries == null ? null : Sets.newHashSet(entries)); + } + + public void trigger(ServerPlayerEntity player, @Nullable T registryEntry) { + trigger(player, Collections.singletonList(() -> registryEntry)); + } + + public ITriggerable constructTriggerFor(@Nullable T entry) { + BiConsumer trigger = this::trigger; + return player -> trigger.accept(player, entry); + } + + @Override + public Instance deserializeInstance(JsonObject json, JsonDeserializationContext context) { + if (json.has("accepted_entries")) { + JsonArray elements = json.getAsJsonArray("accepted_entries"); + return new Instance<>(this, + StreamSupport.stream(elements.spliterator(), false).map(JsonElement::getAsString) + .map(rl -> { + T entry = getValue(rl); + if (entry == null) + throw new JsonSyntaxException("Unknown entry '" + rl + "'"); + return entry; + }).collect(Collectors.toSet())); + } + + return forEntries((T) null); + } + + @Nullable + abstract protected T getValue(String key); + + @Nullable + abstract protected String getKey(T value); + + public static class Instance extends CriterionTriggerBase.Instance { + + @Nullable + private final Set entries; + private final StringSerializableTrigger trigger; + + public Instance(StringSerializableTrigger trigger, @Nullable Set entries) { + super(trigger.getId()); + this.trigger = trigger; + this.entries = entries; + } + + @Override + protected boolean test(@Nullable List> suppliers) { + if (entries == null || suppliers == null || suppliers.isEmpty()) + return false; + return entries.contains(suppliers.get(0).get()); + } + + @Override + public JsonElement serialize() { + JsonObject jsonobject = new JsonObject(); + JsonArray elements = new JsonArray(); + + if (entries == null) { + jsonobject.add("accepted_entries", elements); + return jsonobject; + } + + for (T entry : entries) { + if (entry == null) + continue; + String key = trigger.getKey(entry); + if (key != null) + elements.add(key); + } + + jsonobject.add("accepted_entries", elements); + return jsonobject; + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/block/ProperDirectionalBlock.java b/src/main/java/com/simibubi/create/foundation/block/ProperDirectionalBlock.java index e84a1b9e5..db0217340 100644 --- a/src/main/java/com/simibubi/create/foundation/block/ProperDirectionalBlock.java +++ b/src/main/java/com/simibubi/create/foundation/block/ProperDirectionalBlock.java @@ -2,6 +2,7 @@ package com.simibubi.create.foundation.block; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.foundation.utility.DirectionHelper; + import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.DirectionalBlock; diff --git a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java index 41741eb5b..fa99114c3 100644 --- a/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java +++ b/src/main/java/com/simibubi/create/foundation/block/connected/CTSpriteShiftEntry.java @@ -3,7 +3,7 @@ package com.simibubi.create.foundation.block.connected; import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; public abstract class CTSpriteShiftEntry extends SpriteShiftEntry { diff --git a/src/main/java/com/simibubi/create/foundation/command/AllCommands.java b/src/main/java/com/simibubi/create/foundation/command/AllCommands.java index cf36c3c7a..657535b79 100644 --- a/src/main/java/com/simibubi/create/foundation/command/AllCommands.java +++ b/src/main/java/com/simibubi/create/foundation/command/AllCommands.java @@ -1,15 +1,16 @@ package com.simibubi.create.foundation.command; +import java.util.Collections; +import java.util.function.Predicate; + import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; + import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.entity.player.PlayerEntity; -import java.util.Collections; -import java.util.function.Predicate; - public class AllCommands { public static Predicate sourceIsPlayer = (cs) -> cs.getEntity() instanceof PlayerEntity; @@ -23,6 +24,7 @@ public class AllCommands { .then(FixLightingCommand.register()) .then(ReplaceInCommandBlocksCommand.register()) .then(HighlightCommand.register()) + .then(ToggleExperimentalRenderingCommand.register()) //dev-util //Comment out for release diff --git a/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java b/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java index 2398d9406..d3c5a8962 100644 --- a/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/ClearBufferCacheCommand.java @@ -14,7 +14,7 @@ public class ClearBufferCacheCommand { static ArgumentBuilder register() { return Commands.literal("clearRenderBuffers").requires(cs -> cs.hasPermissionLevel(0)).executes(ctx -> { - DistExecutor.runWhenOn(Dist.CLIENT, () -> ClearBufferCacheCommand::execute); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClearBufferCacheCommand::execute); ctx.getSource().sendFeedback(new StringTextComponent("Cleared rendering buffers."), true); return 1; }); @@ -22,6 +22,6 @@ public class ClearBufferCacheCommand { @OnlyIn(Dist.CLIENT) private static void execute() { - CreateClient.bufferCache.invalidate(); + CreateClient.invalidateRenderers(); } } diff --git a/src/main/java/com/simibubi/create/foundation/command/ConfigureConfigPacket.java b/src/main/java/com/simibubi/create/foundation/command/ConfigureConfigPacket.java index b6790ab4b..a8d174725 100644 --- a/src/main/java/com/simibubi/create/foundation/command/ConfigureConfigPacket.java +++ b/src/main/java/com/simibubi/create/foundation/command/ConfigureConfigPacket.java @@ -9,6 +9,7 @@ import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import net.minecraft.client.Minecraft; import net.minecraft.network.PacketBuffer; @@ -42,7 +43,7 @@ public class ConfigureConfigPacket extends SimplePacketBase { @Override public void handle(Supplier ctx) { ctx.get() - .enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { try { Actions.valueOf(option) .performAction(value); @@ -61,6 +62,7 @@ public class ConfigureConfigPacket extends SimplePacketBase { overlayScreen(() -> Actions::overlayScreen), fixLighting(() -> Actions::experimentalLighting), overlayReset(() -> Actions::overlayReset), + experimentalRendering(() -> Actions::experimentalRendering), ; @@ -79,6 +81,14 @@ public class ConfigureConfigPacket extends SimplePacketBase { private static void rainbowDebug(String value) { AllConfigs.CLIENT.rainbowDebug.set(Boolean.parseBoolean(value)); } + + @OnlyIn(Dist.CLIENT) + private static void experimentalRendering(String value) { + if (!"".equals(value)) { + AllConfigs.CLIENT.experimentalRendering.set(Boolean.parseBoolean(value)); + } + FastRenderDispatcher.refresh(); + } @OnlyIn(Dist.CLIENT) private static void overlayReset(String value) { diff --git a/src/main/java/com/simibubi/create/foundation/command/HighlightCommand.java b/src/main/java/com/simibubi/create/foundation/command/HighlightCommand.java index 6071c14f9..f017c1b19 100644 --- a/src/main/java/com/simibubi/create/foundation/command/HighlightCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/HighlightCommand.java @@ -1,10 +1,13 @@ package com.simibubi.create.foundation.command; +import java.util.Collection; + import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; import com.simibubi.create.foundation.networking.AllPackets; + import net.minecraft.command.CommandSource; import net.minecraft.command.Commands; import net.minecraft.command.arguments.BlockPosArgument; @@ -12,31 +15,21 @@ import net.minecraft.command.arguments.EntityArgument; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.*; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.RayTraceContext; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.StringTextComponent; import net.minecraft.world.World; import net.minecraftforge.fml.network.PacketDistributor; -import java.util.Collection; - public class HighlightCommand { public static ArgumentBuilder register() { return Commands.literal("highlight") .requires(cs -> cs.hasPermissionLevel(0)) - .requires(AllCommands.sourceIsPlayer) .then(Commands.argument("pos", BlockPosArgument.blockPos()) - .requires(AllCommands.sourceIsPlayer) - .executes(ctx -> { - BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos"); - - AllPackets.channel.send( - PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()), - new HighlightPacket(pos) - ); - - return Command.SINGLE_SUCCESS; - }) .then(Commands.argument("players", EntityArgument.players()) .executes(ctx -> { Collection players = EntityArgument.getPlayers(ctx, "players"); @@ -52,7 +45,19 @@ public class HighlightCommand { return players.size(); }) ) + //.requires(AllCommands.sourceIsPlayer) + .executes(ctx -> { + BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos"); + + AllPackets.channel.send( + PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()), + new HighlightPacket(pos) + ); + + return Command.SINGLE_SUCCESS; + }) ) + //.requires(AllCommands.sourceIsPlayer) .executes(ctx -> { ServerPlayerEntity player = ctx.getSource().asPlayer(); return highlightAssemblyExceptionFor(player, ctx.getSource()); diff --git a/src/main/java/com/simibubi/create/foundation/command/HighlightPacket.java b/src/main/java/com/simibubi/create/foundation/command/HighlightPacket.java index 7b4b10a4c..fe7cf6f0f 100644 --- a/src/main/java/com/simibubi/create/foundation/command/HighlightPacket.java +++ b/src/main/java/com/simibubi/create/foundation/command/HighlightPacket.java @@ -1,8 +1,11 @@ package com.simibubi.create.foundation.command; +import java.util.function.Supplier; + import com.simibubi.create.AllSpecialTextures; import com.simibubi.create.CreateClient; import com.simibubi.create.foundation.networking.SimplePacketBase; + import net.minecraft.client.Minecraft; import net.minecraft.network.PacketBuffer; import net.minecraft.util.math.BlockPos; @@ -12,8 +15,6 @@ import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.network.NetworkEvent; -import java.util.function.Supplier; - public class HighlightPacket extends SimplePacketBase { private final BlockPos pos; @@ -33,7 +34,7 @@ public class HighlightPacket extends SimplePacketBase { @Override public void handle(Supplier ctx) { - ctx.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + ctx.get().enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { performHighlight(pos); })); diff --git a/src/main/java/com/simibubi/create/foundation/command/OverlayConfigCommand.java b/src/main/java/com/simibubi/create/foundation/command/OverlayConfigCommand.java index 9497a7de6..850b910e5 100644 --- a/src/main/java/com/simibubi/create/foundation/command/OverlayConfigCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/OverlayConfigCommand.java @@ -18,9 +18,9 @@ public class OverlayConfigCommand { .requires(cs -> cs.hasPermissionLevel(0)) .then(Commands.literal("reset") .executes(ctx -> { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.overlayReset.performAction("")); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.overlayReset.performAction("")); - DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () -> + DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> AllPackets.channel.send( PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()), new ConfigureConfigPacket(ConfigureConfigPacket.Actions.overlayReset.name(), ""))); @@ -31,9 +31,9 @@ public class OverlayConfigCommand { }) ) .executes(ctx -> { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.overlayScreen.performAction("")); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.overlayScreen.performAction("")); - DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () -> + DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> AllPackets.channel.send( PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()), new ConfigureConfigPacket(ConfigureConfigPacket.Actions.overlayScreen.name(), ""))); diff --git a/src/main/java/com/simibubi/create/foundation/command/ToggleDebugCommand.java b/src/main/java/com/simibubi/create/foundation/command/ToggleDebugCommand.java index a12ec72d2..918d3dc7c 100644 --- a/src/main/java/com/simibubi/create/foundation/command/ToggleDebugCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/ToggleDebugCommand.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.command; +import com.mojang.brigadier.Command; import com.mojang.brigadier.arguments.BoolArgumentType; import com.mojang.brigadier.builder.ArgumentBuilder; import com.simibubi.create.foundation.networking.AllPackets; @@ -20,17 +21,18 @@ public class ToggleDebugCommand { .then(Commands.argument("value", BoolArgumentType.bool()) .executes(ctx -> { boolean value = BoolArgumentType.getBool(ctx, "value"); - //DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> AllConfigs.CLIENT.rainbowDebug.set(value)); - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.rainbowDebug.performAction(String.valueOf(value))); + //DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AllConfigs.CLIENT.rainbowDebug.set(value)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.rainbowDebug.performAction(String.valueOf(value))); - DistExecutor.runWhenOn(Dist.DEDICATED_SERVER, () -> () -> + DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> AllPackets.channel.send( PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()), new ConfigureConfigPacket(ConfigureConfigPacket.Actions.rainbowDebug.name(), String.valueOf(value)))); ctx.getSource().sendFeedback(new StringTextComponent((value ? "enabled" : "disabled") + " rainbow debug"), true); - return 1; - })); + return Command.SINGLE_SUCCESS; + }) + ); } } diff --git a/src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java b/src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java new file mode 100644 index 000000000..25970ac7a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java @@ -0,0 +1,36 @@ +package com.simibubi.create.foundation.command; + +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.simibubi.create.foundation.networking.AllPackets; + +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.network.PacketDistributor; + +public class ToggleExperimentalRenderingCommand { + + static ArgumentBuilder register() { + return Commands.literal("experimentalRendering") + .requires(cs -> cs.hasPermissionLevel(0)) + .then(Commands.argument("value", BoolArgumentType.bool()) + .executes(ctx -> { + boolean value = BoolArgumentType.getBool(ctx, "value"); + //DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> AllConfigs.CLIENT.rainbowDebug.set(value)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ConfigureConfigPacket.Actions.experimentalRendering.performAction(String.valueOf(value))); + + DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> + AllPackets.channel.send( + PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()), + new ConfigureConfigPacket(ConfigureConfigPacket.Actions.experimentalRendering.name(), String.valueOf(value)))); + + ctx.getSource().sendFeedback(new StringTextComponent((value ? "enabled" : "disabled") + " experimental rendering"), true); + + return 1; + })); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/config/CClient.java b/src/main/java/com/simibubi/create/foundation/config/CClient.java index b4aabef30..fbd8c1d7a 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CClient.java +++ b/src/main/java/com/simibubi/create/foundation/config/CClient.java @@ -13,12 +13,15 @@ public class CClient extends ConfigBase { public ConfigBool rainbowDebug = b(true, "enableRainbowDebug", "Show colourful debug information while the F3-Menu is open."); + public ConfigBool experimentalRendering = + b(true, "experimentalRendering", "Use modern OpenGL features to drastically increase performance."); + public ConfigInt overlayOffsetX = i(20, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetX", "Offset the overlay from goggle- and hover- information by this many pixels on the X axis; Use /create overlay"); public ConfigInt overlayOffsetY = i(0, Integer.MIN_VALUE, Integer.MAX_VALUE, "overlayOffsetY", "Offset the overlay from goggle- and hover- information by this many pixels on the Y axis; Use /create overlay"); + public ConfigBool smoothPlacementIndicator = b(false, "smoothPlacementIndicator", "Use an alternative indicator when showing where the assisted placement ends up relative to your crosshair"); @Override public String getName() { return "client"; } - } diff --git a/src/main/java/com/simibubi/create/foundation/config/CRecipes.java b/src/main/java/com/simibubi/create/foundation/config/CRecipes.java index 2f5ebcd65..e042c4f85 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CRecipes.java +++ b/src/main/java/com/simibubi/create/foundation/config/CRecipes.java @@ -7,6 +7,7 @@ public class CRecipes extends ConfigBase { public ConfigBool allowRegularCraftingInCrafter = b(true, "allowRegularCraftingInCrafter", Comments.allowRegularCraftingInCrafter); public ConfigBool allowStonecuttingOnSaw = b(true, "allowStonecuttingOnSaw", Comments.allowStonecuttingOnSaw); + public ConfigBool allowWoodcuttingOnSaw = b(true, "allowWoodcuttingOnSaw", Comments.allowWoodcuttingOnSaw); public ConfigInt lightSourceCountForRefinedRadiance = i(10, 1, "lightSourceCountForRefinedRadiance", Comments.refinedRadiance); public ConfigBool enableRefinedRadianceRecipe = @@ -27,6 +28,8 @@ public class CRecipes extends ConfigBase { "When true, allows any standard crafting recipes to be processed by Mechanical Crafters."; static String allowStonecuttingOnSaw = "When true, allows any stonecutting recipes to be processed by a Mechanical Saw."; + static String allowWoodcuttingOnSaw = + "When true, allows any Druidcraft woodcutter recipes to be processed by a Mechanical Saw."; static String refinedRadiance = "The amount of Light sources destroyed before Chromatic Compound turns into Refined Radiance."; static String refinedRadianceRecipe = "Allow the standard in-world Refined Radiance recipes."; diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java index f278611be..e3e37f4f4 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -192,7 +192,7 @@ public class CreateRegistrate extends AbstractRegistrate { } protected static void onClient(Supplier toRun) { - DistExecutor.runWhenOn(Dist.CLIENT, toRun); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, toRun); } @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java index 562de30bc..b76d491cf 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/WashingRecipeGen.java @@ -1,11 +1,11 @@ package com.simibubi.create.foundation.data.recipe; import static com.simibubi.create.foundation.data.recipe.Mods.IE; +import static com.simibubi.create.foundation.data.recipe.Mods.INF; import static com.simibubi.create.foundation.data.recipe.Mods.MEK; import static com.simibubi.create.foundation.data.recipe.Mods.MW; import static com.simibubi.create.foundation.data.recipe.Mods.SM; import static com.simibubi.create.foundation.data.recipe.Mods.TH; -import static com.simibubi.create.foundation.data.recipe.Mods.INF; import java.util.function.Supplier; diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index bb7c03018..efe59e30a 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -51,9 +51,10 @@ public enum AllGuiTextures { SEQUENCER("sequencer.png", 173, 159), SEQUENCER_INSTRUCTION("sequencer.png", 0, 14, 162, 22), - SEQUENCER_WAIT("sequencer.png", 0, 58, 162, 22), + SEQUENCER_DELAY("sequencer.png", 0, 58, 162, 22), SEQUENCER_END("sequencer.png", 0, 80, 162, 22), SEQUENCER_EMPTY("sequencer.png", 0, 102, 162, 22), + SEQUENCER_AWAIT("sequencer.png", 0, 160, 162, 22), // JEI JEI_SLOT("jei/widgets.png", 18, 18), @@ -82,6 +83,9 @@ public enum AllGuiTextures { SPEECH_TOOLTIP("widgets.png", 0, 24, 8, 8), SPEECH_TOOLTIP_HIGHLIGHT("widgets.png", 8, 24, 8, 8), + // PlacementIndicator + PLACEMENT_INDICATOR_SHEET("placement_indicator.png", 0, 0, 16, 256); + ; public static final int FONT_COLOR = 0x575F7A; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java b/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java index 2f0a39636..bef5042de 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ScreenOpener.java @@ -12,7 +12,7 @@ public class ScreenOpener { private static Screen openedGuiNextTick; public static void tick() { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { if (openedGuiNextTick != null) { Minecraft.getInstance().displayGuiScreen(openedGuiNextTick); openedGuiNextTick = null; @@ -21,7 +21,7 @@ public class ScreenOpener { } public static void open(Screen gui) { - DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> { + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { openedGuiNextTick = gui; }); } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java index 22a225e60..0263c476f 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -174,7 +174,7 @@ public class ItemHelper { if (!simulate && hasEnoughItems) inv.extractItem(slot, stack.getCount(), false); - if (extracting.getCount() >= maxExtractionCount) { + if (extracting.getCount() >= maxExtractionCount || extracting.getCount() >= extracting.getMaxStackSize()) { if (checkHasEnoughItems) { hasEnoughItems = true; checkHasEnoughItems = false; @@ -234,7 +234,7 @@ public class ItemHelper { if (!simulate) inv.extractItem(slot, stack.getCount(), false); - if (extracting.getCount() == maxExtractionCount) + if (extracting.getCount() >= maxExtractionCount || extracting.getCount() >= extracting.getMaxStackSize()) break; } diff --git a/src/main/java/com/simibubi/create/foundation/mixin/CancelTileEntityRenderMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/CancelTileEntityRenderMixin.java new file mode 100644 index 000000000..fe8dfd965 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/CancelTileEntityRenderMixin.java @@ -0,0 +1,36 @@ +package com.simibubi.create.foundation.mixin; + +import java.util.List; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; +import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; + +import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher; +import net.minecraft.tileentity.TileEntity; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(ChunkRenderDispatcher.CompiledChunk.class) +public class CancelTileEntityRenderMixin { + + /** + * JUSTIFICATION: when instanced rendering is enabled, many tile entities no longer need + * to be processed by the normal game renderer. This method is only called to retrieve the + * list of tile entities to render. By filtering the output here, we prevent the game from + * doing unnecessary light lookups and frustum checks. + */ + @Inject(at = @At("RETURN"), method = "getTileEntities", cancellable = true) + private void noRenderInstancedTiles(CallbackInfoReturnable> cir) { + if (FastRenderDispatcher.available()) { + List tiles = cir.getReturnValue(); + + tiles.removeIf(tile -> tile instanceof IInstanceRendered && !((IInstanceRendered) tile).shouldRenderAsTE()); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/FogColorTrackerMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/FogColorTrackerMixin.java new file mode 100644 index 000000000..2fe7e98cf --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/FogColorTrackerMixin.java @@ -0,0 +1,21 @@ +package com.simibubi.create.foundation.mixin; + +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.foundation.render.backend.gl.GlFog; + +@Mixin(GlStateManager.class) +public class FogColorTrackerMixin { + + @Inject(at = @At("TAIL"), method = "fog") + private static void copyFogColor(int pname, float[] params, CallbackInfo ci) { + if (pname == GL11.GL_FOG_COLOR) { + GlFog.FOG_COLOR = params; + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/LightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/LightUpdateMixin.java new file mode 100644 index 000000000..e2b97b148 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/LightUpdateMixin.java @@ -0,0 +1,53 @@ +package com.simibubi.create.foundation.mixin; + +import java.util.Map; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.backend.light.ILightListener; + +import net.minecraft.client.multiplayer.ClientChunkProvider; +import net.minecraft.util.math.SectionPos; +import net.minecraft.world.ILightReader; +import net.minecraft.world.LightType; +import net.minecraft.world.chunk.AbstractChunkProvider; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(ClientChunkProvider.class) +public abstract class LightUpdateMixin extends AbstractChunkProvider { + + /** + * JUSTIFICATION: This method is called after a lighting tick once per subchunk where a + * lighting change occurred that tick. On the client, Minecraft uses this method to inform + * the rendering system that it needs to redraw a chunk. It does all that work asynchronously, + * and we should too. + */ + @Inject(at = @At("HEAD"), method = "markLightChanged") + private void onLightUpdate(LightType type, SectionPos pos, CallbackInfo ci) { + ClientChunkProvider thi = ((ClientChunkProvider) (Object) this); + + Chunk chunk = thi.getChunk(pos.getSectionX(), pos.getSectionZ(), false); + + int sectionY = pos.getSectionY(); + + if (chunk != null) { + chunk.getTileEntityMap() + .entrySet() + .stream() + .filter(entry -> SectionPos.toChunk(entry.getKey().getY()) == sectionY) + .map(Map.Entry::getValue) + .filter(tile -> tile instanceof ILightListener) + .map(tile -> (ILightListener) tile) + .forEach(ILightListener::onChunkLightUpdate); + } + + ContraptionRenderDispatcher.notifyLightUpdate((ILightReader) thi.getWorld(), type, pos); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/OnRemoveTileMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/OnRemoveTileMixin.java new file mode 100644 index 000000000..355f9426a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/OnRemoveTileMixin.java @@ -0,0 +1,34 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Final; +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 org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import com.simibubi.create.CreateClient; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(World.class) +public class OnRemoveTileMixin { + + @Shadow @Final public boolean isRemote; + + /** + * JUSTIFICATION: This method is called whenever a tile entity is removed due + * to a change in block state, even on the client. By hooking into this method, + * we gain easy access to the information while having no impact on performance. + */ + @Inject(at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/world/World;getTileEntity(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/tileentity/TileEntity;"), method = "removeTileEntity", locals = LocalCapture.CAPTURE_FAILHARD) + private void onRemoveTile(BlockPos pos, CallbackInfo ci, TileEntity te) { + if (isRemote) CreateClient.kineticRenderer.remove(te); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java new file mode 100644 index 000000000..27f8173ce --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java @@ -0,0 +1,58 @@ +package com.simibubi.create.foundation.mixin; + +import org.lwjgl.opengl.GL20; +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 com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; +import com.simibubi.create.foundation.render.backend.OptifineHandler; + +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(WorldRenderer.class) +public class RenderHooksMixin { + + @Shadow private ClientWorld world; + + /** + * JUSTIFICATION: This method is called once per layer per frame. It allows us to perform + * layer-correct custom rendering. RenderWorldLast is not refined enough for rendering world objects. + * This should probably be a forge event. + */ + @Inject(at = @At(value = "TAIL"), method = "renderLayer") + private void renderLayer(RenderType type, MatrixStack stack, double camX, double camY, double camZ, CallbackInfo ci) { + if (!Backend.available()) return; + + Matrix4f viewProjection = stack.peek().getModel().copy(); + viewProjection.multiplyBackward(FastRenderDispatcher.getProjectionMatrix()); + + FastRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ); + + ContraptionRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ); + + GL20.glUseProgram(0); + } + + @Inject(at = @At(value = "TAIL"), method = "loadRenderers") + private void refresh(CallbackInfo ci) { + CreateClient.kineticRenderer.invalidate(); + ContraptionRenderDispatcher.invalidateAll(); + OptifineHandler.refresh(); + Backend.refresh(); + + if (Backend.canUseInstancing() && world != null) world.loadedTileEntityList.forEach(CreateClient.kineticRenderer::add); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/ShaderCloseMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/ShaderCloseMixin.java new file mode 100644 index 000000000..ed2ada21e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/ShaderCloseMixin.java @@ -0,0 +1,31 @@ +package com.simibubi.create.foundation.mixin; + +import javax.annotation.Nullable; + +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 com.simibubi.create.foundation.render.backend.OptifineHandler; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.VideoSettingsScreen; + +@Mixin(Minecraft.class) +public class ShaderCloseMixin { + + @Shadow @Nullable public Screen currentScreen; + + @Inject(at = @At("HEAD"), method = "displayGuiScreen") + private void whenScreenChanges(Screen screen, CallbackInfo info) { + if (OptifineHandler.optifineInstalled() && screen instanceof VideoSettingsScreen) { + Screen old = this.currentScreen; + if (old != null && old.getClass().getName().startsWith(OptifineHandler.SHADER_PACKAGE)) { + OptifineHandler.refresh(); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java index 2cabdfb0a..0f5fca06b 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -1,11 +1,22 @@ package com.simibubi.create.foundation.networking; +import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT; +import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER; + +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket; -import com.simibubi.create.content.contraptions.components.structureMovement.sync.*; +import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket; +import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket; +import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket; +import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket; +import com.simibubi.create.content.contraptions.components.structureMovement.sync.LimbSwingUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingCreationPacket; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartControllerUpdatePacket; import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket; @@ -17,12 +28,17 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmPlacementPac import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket; import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket; -import com.simibubi.create.content.schematics.packet.*; +import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket; +import com.simibubi.create.content.schematics.packet.InstantSchematicPacket; +import com.simibubi.create.content.schematics.packet.SchematicPlacePacket; +import com.simibubi.create.content.schematics.packet.SchematicSyncPacket; +import com.simibubi.create.content.schematics.packet.SchematicUploadPacket; import com.simibubi.create.foundation.command.ConfigureConfigPacket; import com.simibubi.create.foundation.command.HighlightPacket; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.utility.ServerSpeedProvider; + import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; @@ -34,13 +50,6 @@ import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor.TargetPoint; import net.minecraftforge.fml.network.simple.SimpleChannel; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - -import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT; -import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER; - public enum AllPackets { // Client to Server diff --git a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java new file mode 100644 index 000000000..b5d5e991a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java @@ -0,0 +1,81 @@ +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.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.foundation.render.backend.gl.BasicProgram; +import com.simibubi.create.foundation.render.backend.gl.attrib.ModelVertexAttributes; +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 final ProgramSpec ROTATING = register(ProgramSpec.builder("rotating", BasicProgram::new) + .addAttributes(ModelVertexAttributes.class) + .addAttributes(KineticVertexAttributes.class) + .addAttributes(RotatingVertexAttributes.class) + .setVert(Locations.ROTATING) + .setFrag(Locations.INSTANCED) + .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.INSTANCED) + .createProgramSpec()); + + public static final ProgramSpec CONTRAPTION_STRUCTURE = register(ProgramSpec.builder("contraption_structure", ContraptionProgram::new) + .addAttributes(ContraptionVertexAttributes.class) + .setVert(Locations.CONTRAPTION_STRUCTURE) + .setFrag(Locations.CONTRAPTION) + .createProgramSpec()); + + public static final ProgramSpec CONTRAPTION_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 CONTRAPTION_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 CONTRAPTION_ACTOR = register(ProgramSpec.builder("contraption_actor", ContraptionProgram::new) + .addAttributes(ModelVertexAttributes.class) + .addAttributes(ActorVertexAttributes.class) + .setVert(Locations.CONTRAPTION_ACTOR) + .setFrag(Locations.CONTRAPTION) + .createProgramSpec()); + + public static class Locations { + public static final ResourceLocation INSTANCED = loc("instanced.frag"); + 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 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, "shader/" + name); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/Compartment.java b/src/main/java/com/simibubi/create/foundation/render/Compartment.java new file mode 100644 index 000000000..4d929dc3f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/Compartment.java @@ -0,0 +1,14 @@ +package com.simibubi.create.foundation.render; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.AllBlockPartials; + +import net.minecraft.block.BlockState; +import net.minecraft.util.Direction; + +public class Compartment { + public static final Compartment GENERIC_TILE = new Compartment<>(); + public static final Compartment PARTIAL = new Compartment<>(); + public static final Compartment> DIRECTIONAL_PARTIAL = new Compartment<>(); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java new file mode 100644 index 000000000..58e1746f2 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java @@ -0,0 +1,77 @@ +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.relays.belt.BeltInstancedModel; +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 net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.entity.Entity; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; + +public class KineticRenderer extends InstancedTileRenderer { + public static int MAX_ORIGIN_DISTANCE = 1000; + + public BlockPos originCoordinate = BlockPos.ZERO; + + @Override + public void registerMaterials() { + materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.BELT, BeltInstancedModel::new)); + materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.ROTATING, RotatingInstancedModel::new)); + } + + @Override + public BlockPos getOriginCoordinate() { + return originCoordinate; + } + + @Override + public void tick() { + super.tick(); + + Minecraft mc = Minecraft.getInstance(); + Entity renderViewEntity = mc.renderViewEntity; + + if (renderViewEntity == null) return; + + BlockPos renderViewPosition = renderViewEntity.getPosition(); + + int dX = Math.abs(renderViewPosition.getX() - originCoordinate.getX()); + int dY = Math.abs(renderViewPosition.getY() - originCoordinate.getY()); + int dZ = Math.abs(renderViewPosition.getZ() - originCoordinate.getZ()); + + if (dX > MAX_ORIGIN_DISTANCE || + dY > MAX_ORIGIN_DISTANCE || + dZ > MAX_ORIGIN_DISTANCE) { + + originCoordinate = renderViewPosition; + + ArrayList instancedTiles = new ArrayList<>(instances.keySet()); + invalidate(); + instancedTiles.forEach(this::add); + } + } + + @Override + public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, ShaderCallback callback) { + BlockPos originCoordinate = getOriginCoordinate(); + + camX -= originCoordinate.getX(); + camY -= originCoordinate.getY(); + camZ -= originCoordinate.getZ(); + + Matrix4f translate = Matrix4f.translate((float) -camX, (float) -camY, (float) -camZ); + + translate.multiplyBackward(viewProjection); + + super.render(layer, translate, camX, camY, camZ, callback); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/RenderMath.java b/src/main/java/com/simibubi/create/foundation/render/RenderMath.java new file mode 100644 index 000000000..3839ff718 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/RenderMath.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.render; + +public class RenderMath { + 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; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ShadowRenderHelper.java b/src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java similarity index 98% rename from src/main/java/com/simibubi/create/foundation/utility/ShadowRenderHelper.java rename to src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java index 0a8f5349a..c42a78ae0 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ShadowRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/ShadowRenderHelper.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.render; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; diff --git a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java similarity index 55% rename from src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java rename to src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index d7c8b0569..62c3f935f 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -1,71 +1,52 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.render; import java.nio.Buffer; import java.nio.ByteBuffer; -import java.nio.ByteOrder; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; -import com.mojang.datafixers.util.Pair; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import it.unimi.dsi.fastutil.longs.Long2DoubleMap; import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.BufferBuilder.DrawState; -import net.minecraft.client.renderer.GLAllocation; +import net.minecraft.client.renderer.Matrix3f; import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.Vector3f; import net.minecraft.client.renderer.Vector4f; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.LightType; import net.minecraft.world.World; +import net.minecraftforge.client.model.pipeline.LightUtil; -public class SuperByteBuffer { +public class SuperByteBuffer extends TemplateBuffer { public interface IVertexLighter { public int getPackedLight(float x, float y, float z); } - protected ByteBuffer template; - protected int formatSize; - // Vertex Position private MatrixStack transforms; // Vertex Texture Coords - private boolean shouldShiftUV; - private SpriteShiftEntry spriteShift; - private float uTarget, vTarget; + private SpriteShiftFunc spriteShiftFunc; // Vertex Lighting private boolean shouldLight; private int packedLightCoords; + private int otherBlockLight; private Matrix4f lightTransform; // Vertex Coloring private boolean shouldColor; private int r, g, b, a; - private float sheetSize; public SuperByteBuffer(BufferBuilder buf) { - Pair state = buf.popData(); - ByteBuffer rendered = state.getSecond(); - rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers - - formatSize = buf.getVertexFormat() - .getSize(); - int size = state.getFirst() - .getCount() * formatSize; - - template = GLAllocation.createDirectByteBuffer(size); - template.order(rendered.order()); - ((Buffer) template).limit(((Buffer) rendered).limit()); - template.put(rendered); - ((Buffer) template).rewind(); - + super(buf); transforms = new MatrixStack(); } @@ -82,6 +63,7 @@ public class SuperByteBuffer { private static final Long2DoubleMap skyLightCache = new Long2DoubleOpenHashMap(); private static final Long2DoubleMap blockLightCache = new Long2DoubleOpenHashMap(); Vector4f pos = new Vector4f(); + Vector3f normal = new Vector3f(); Vector4f lightPos = new Vector4f(); public void renderInto(MatrixStack input, IVertexBuilder builder) { @@ -90,12 +72,18 @@ public class SuperByteBuffer { return; ((Buffer) buffer).rewind(); - Matrix4f t = input.peek() - .getModel() - .copy(); + Matrix3f normalMat = transforms.peek() + .getNormal() + .copy(); + //normalMat.multiply(transforms.peek().getNormal()); + + Matrix4f modelMat = input.peek() + .getModel() + .copy(); + Matrix4f localTransforms = transforms.peek() - .getModel(); - t.multiply(localTransforms); + .getModel(); + modelMat.multiply(localTransforms); if (shouldLight && lightTransform != null) { skyLightCache.clear(); @@ -112,26 +100,39 @@ public class SuperByteBuffer { byte g = getG(buffer, i); byte b = getB(buffer, i); byte a = getA(buffer, i); + float normalX = getNX(buffer, i) / 127f; + float normalY = getNY(buffer, i) / 127f; + float normalZ = getNZ(buffer, i) / 127f; + + float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ); + normal.set(normalX, normalY, normalZ); + normal.transform(normalMat); + float instanceDiffuse = LightUtil.diffuseLight(normal.getX(), normal.getY(), normal.getZ()); pos.set(x, y, z, 1F); - pos.transform(t); + pos.transform(modelMat); builder.vertex(pos.getX(), pos.getY(), pos.getZ()); + //builder.color((byte) Math.max(0, normal.getX() * 255), (byte) Math.max(0, normal.getY() * 255), (byte) Math.max(0, normal.getZ() * 255), a); if (shouldColor) { - float lum = (r < 0 ? 255 + r : r) / 256f; - builder.color((int) (this.r * lum), (int) (this.g * lum), (int) (this.b * lum), this.a); - } else - builder.color(r, g, b, a); + //float lum = (r < 0 ? 255 + r : r) / 256f; + int colorR = Math.min(255, (int) (((float) this.r) * instanceDiffuse)); + int colorG = Math.min(255, (int) (((float) this.g) * instanceDiffuse)); + int colorB = Math.min(255, (int) (((float) this.b) * instanceDiffuse)); + builder.color(colorR, colorG, colorB, this.a); + } else { + float diffuseMult = instanceDiffuse / staticDiffuse; + int colorR = Math.min(255, (int) (((float) Byte.toUnsignedInt(r)) * diffuseMult)); + int colorG = Math.min(255, (int) (((float) Byte.toUnsignedInt(g)) * diffuseMult)); + int colorB = Math.min(255, (int) (((float) Byte.toUnsignedInt(b)) * diffuseMult)); + builder.color(colorR, colorG, colorB, a); + } float u = getU(buffer, i); float v = getV(buffer, i); - if (shouldShiftUV) { - float targetU = spriteShift.getTarget() - .getInterpolatedU((getUnInterpolatedU(spriteShift.getOriginal(), u) / sheetSize) + uTarget * 16); - float targetV = spriteShift.getTarget() - .getInterpolatedV((getUnInterpolatedV(spriteShift.getOriginal(), v) / sheetSize) + vTarget * 16); - builder.texture(targetU, targetV); + if (spriteShiftFunc != null) { + spriteShiftFunc.shift(builder, u, v); } else builder.texture(u, v); @@ -141,20 +142,26 @@ public class SuperByteBuffer { lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F); lightPos.transform(localTransforms); lightPos.transform(lightTransform); + light = getLight(Minecraft.getInstance().world, lightPos); + if (otherBlockLight >= 0) { + light = ContraptionRenderDispatcher.getMaxBlockLight(light, otherBlockLight); + } } builder.light(light); } else builder.light(getLight(buffer, i)); - builder.normal(getNX(buffer, i), getNY(buffer, i), getNZ(buffer, i)) + builder.normal(normal.getX(), normal.getY(), normal.getZ()) .endVertex(); } transforms = new MatrixStack(); - shouldShiftUV = false; + + spriteShiftFunc = null; shouldColor = false; shouldLight = false; + otherBlockLight = -1; } public SuperByteBuffer translate(double x, double y, double z) { @@ -180,20 +187,29 @@ public class SuperByteBuffer { } public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { - shouldShiftUV = true; - spriteShift = entry; - uTarget = 0; - vTarget = 0; - sheetSize = 1; + this.spriteShiftFunc = (builder, u, v) -> { + float targetU = entry.getTarget().getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u))); + float targetV = entry.getTarget().getInterpolatedV((getUnInterpolatedV(entry.getOriginal(), v))); + builder.texture(targetU, targetV); + }; + return this; + } + + public SuperByteBuffer shiftUVScrolling(SpriteShiftEntry entry, float scrollV) { + this.spriteShiftFunc = (builder, u, v) -> { + float targetU = u - entry.getOriginal().getMinU() + entry.getTarget().getMinU(); + float targetV = v - entry.getOriginal().getMinV() + entry.getTarget().getMinV() + scrollV; + builder.texture(targetU, targetV); + }; return this; } public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) { - shouldShiftUV = true; - spriteShift = entry; - this.uTarget = uTarget; - this.vTarget = vTarget; - this.sheetSize = sheetSize; + this.spriteShiftFunc = (builder, u, v) -> { + float targetU = entry.getTarget().getInterpolatedU((getUnInterpolatedU(entry.getOriginal(), u) / sheetSize) + uTarget * 16); + float targetV = entry.getTarget().getInterpolatedV((getUnInterpolatedV(entry.getOriginal(), v) / sheetSize) + vTarget * 16); + builder.texture(targetU, targetV); + }; return this; } @@ -210,6 +226,13 @@ public class SuperByteBuffer { return this; } + public SuperByteBuffer light(Matrix4f lightTransform, int otherBlockLight) { + shouldLight = true; + this.lightTransform = lightTransform; + this.otherBlockLight = otherBlockLight; + return this; + } + public SuperByteBuffer color(int color) { shouldColor = true; r = ((color >> 16) & 0xFF); @@ -219,81 +242,12 @@ public class SuperByteBuffer { return this; } - protected int vertexCount(ByteBuffer buffer) { - return ((Buffer) buffer).limit() / formatSize; - } - - protected int getBufferPosition(int vertexIndex) { - return vertexIndex * formatSize; - } - - protected float getX(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index)); - } - - protected float getY(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 4); - } - - protected float getZ(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 8); - } - - protected byte getR(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 12); - } - - protected byte getG(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 13); - } - - protected byte getB(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 14); - } - - protected byte getA(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 15); - } - - protected float getU(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 16); - } - - protected float getV(ByteBuffer buffer, int index) { - return buffer.getFloat(getBufferPosition(index) + 20); - } - - protected int getLight(ByteBuffer buffer, int index) { - return buffer.getInt(getBufferPosition(index) + 24); - } - - protected byte getNX(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 28); - } - - protected byte getNY(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 29); - } - - protected byte getNZ(ByteBuffer buffer, int index) { - return buffer.get(getBufferPosition(index) + 30); - } - private static int getLight(World world, Vector4f lightPos) { BlockPos.Mutable pos = new BlockPos.Mutable(); double sky = 0, block = 0; - float offset = 1 / 8f; -// for (float zOffset = offset; zOffset >= -offset; zOffset -= 2 * offset) { -// for (float yOffset = offset; yOffset >= -offset; yOffset -= 2 * offset) { -// for (float xOffset = offset; xOffset >= -offset; xOffset -= 2 * offset) { -// pos.setPos(lightPos.getX() + xOffset, lightPos.getY() + yOffset, lightPos.getZ() + zOffset); pos.setPos(lightPos.getX() + 0, lightPos.getY() + 0, lightPos.getZ() + 0); sky += skyLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.SKY, pos)); block += blockLightCache.computeIfAbsent(pos.toLong(), $ -> world.getLightLevel(LightType.BLOCK, pos)); -// } -// } -// } - return ((int) sky) << 20 | ((int) block) << 4; } @@ -301,4 +255,9 @@ public class SuperByteBuffer { return ((Buffer) template).limit() == 0; } + @FunctionalInterface + public interface SpriteShiftFunc { + void shift(IVertexBuilder builder, float u, float v); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java similarity index 77% rename from src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java rename to src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java index d85e749fb..0ebf74157 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/SuperByteBufferCache.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.render; import java.util.HashMap; import java.util.Map; @@ -13,6 +13,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.foundation.utility.VirtualEmptyModelData; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -27,20 +28,13 @@ import net.minecraft.util.math.BlockPos; public class SuperByteBufferCache { - public static class Compartment { - } - - public static final Compartment GENERIC_TILE = new Compartment<>(); - public static final Compartment PARTIAL = new Compartment<>(); - public static final Compartment> DIRECTIONAL_PARTIAL = new Compartment<>(); - Map, Cache> cache; public SuperByteBufferCache() { cache = new HashMap<>(); - registerCompartment(GENERIC_TILE); - registerCompartment(PARTIAL); - registerCompartment(DIRECTIONAL_PARTIAL); + registerCompartment(Compartment.GENERIC_TILE); + registerCompartment(Compartment.PARTIAL); + registerCompartment(Compartment.DIRECTIONAL_PARTIAL); } public SuperByteBuffer renderBlock(BlockState toRender) { @@ -48,24 +42,23 @@ public class SuperByteBufferCache { } public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState) { - return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState)); + return get(Compartment.PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState)); } - public SuperByteBuffer renderPartial(AllBlockPartials partial, BlockState referenceState, MatrixStack modelTransform) { - return get(PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform)); + return get(Compartment.PARTIAL, partial, () -> standardModelRender(partial.get(), referenceState, modelTransform)); } public SuperByteBuffer renderDirectionalPartial(AllBlockPartials partial, BlockState referenceState, Direction dir) { - return get(DIRECTIONAL_PARTIAL, Pair.of(dir, partial), - () -> standardModelRender(partial.get(), referenceState)); + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> standardModelRender(partial.get(), referenceState)); } public SuperByteBuffer renderDirectionalPartial(AllBlockPartials partial, BlockState referenceState, Direction dir, MatrixStack modelTransform) { - return get(DIRECTIONAL_PARTIAL, Pair.of(dir, partial), - () -> standardModelRender(partial.get(), referenceState, modelTransform)); + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> standardModelRender(partial.get(), referenceState, modelTransform)); } public SuperByteBuffer renderBlockIn(Compartment compartment, BlockState toRender) { @@ -73,7 +66,7 @@ public class SuperByteBufferCache { } SuperByteBuffer getGeneric(BlockState key, Supplier supplier) { - return get(GENERIC_TILE, key, supplier); + return get(Compartment.GENERIC_TILE, key, supplier); } public SuperByteBuffer get(Compartment compartment, T key, Supplier supplier) { @@ -113,19 +106,24 @@ public class SuperByteBufferCache { } private SuperByteBuffer standardModelRender(IBakedModel model, BlockState referenceState, MatrixStack ms) { + BufferBuilder builder = getBufferBuilder(model, referenceState, ms); + + return new SuperByteBuffer(builder); + } + + public static BufferBuilder getBufferBuilder(IBakedModel model, BlockState referenceState, MatrixStack ms) { Minecraft mc = Minecraft.getInstance(); BlockRendererDispatcher dispatcher = mc.getBlockRendererDispatcher(); BlockModelRenderer blockRenderer = dispatcher.getBlockModelRenderer(); BufferBuilder builder = new BufferBuilder(512); builder.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); - blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, - mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); + blockRenderer.renderModel(mc.world, model, referenceState, BlockPos.ZERO.up(255), ms, builder, true, mc.world.rand, 42, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); builder.finishDrawing(); - - return new SuperByteBuffer(builder); + return builder; } + public void invalidate() { cache.forEach((comp, cache) -> cache.invalidateAll()); } diff --git a/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java b/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java new file mode 100644 index 000000000..16afba34e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java @@ -0,0 +1,96 @@ +package com.simibubi.create.foundation.render; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import com.mojang.datafixers.util.Pair; + +import net.minecraft.client.renderer.BufferBuilder; + +public class TemplateBuffer { + protected ByteBuffer template; + protected int formatSize; + protected int vertexCount; + + public TemplateBuffer(BufferBuilder buf) { + Pair state = buf.popData(); + ByteBuffer rendered = state.getSecond(); + rendered.order(ByteOrder.nativeOrder()); // Vanilla bug, endianness does not carry over into sliced buffers + + formatSize = buf.getVertexFormat() + .getSize(); + vertexCount = state.getFirst().getCount(); + int size = vertexCount * formatSize; + + template = ByteBuffer.allocate(size); + template.order(rendered.order()); + ((Buffer)template).limit(((Buffer)rendered).limit()); + template.put(rendered); + ((Buffer)template).rewind(); + } + + public boolean isEmpty() { + return ((Buffer) template).limit() == 0; + } + + protected int vertexCount(ByteBuffer buffer) { + return ((Buffer)buffer).limit() / formatSize; + } + + protected int getBufferPosition(int vertexIndex) { + return vertexIndex * formatSize; + } + + protected float getX(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index)); + } + + protected float getY(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 4); + } + + protected float getZ(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 8); + } + + protected byte getR(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 12); + } + + protected byte getG(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 13); + } + + protected byte getB(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 14); + } + + protected byte getA(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 15); + } + + protected float getU(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 16); + } + + protected float getV(ByteBuffer buffer, int index) { + return buffer.getFloat(getBufferPosition(index) + 20); + } + + protected int getLight(ByteBuffer buffer, int index) { + return buffer.getInt(getBufferPosition(index) + 24); + } + + protected byte getNX(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 28); + } + + protected byte getNY(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 29); + } + + protected byte getNZ(ByteBuffer buffer, int index) { + return buffer.get(getBufferPosition(index) + 30); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/TileEntityRenderHelper.java b/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java similarity index 65% rename from src/main/java/com/simibubi/create/foundation/utility/TileEntityRenderHelper.java rename to src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java index ea9e6e361..0af8bcff9 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/TileEntityRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java @@ -1,16 +1,18 @@ -package com.simibubi.create.foundation.utility; +package com.simibubi.create.foundation.render; import java.util.Iterator; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.Matrix4f; import net.minecraft.client.renderer.Vector4f; -import net.minecraft.client.renderer.WorldRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.tileentity.TileEntityRenderer; import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher; @@ -22,13 +24,20 @@ public class TileEntityRenderHelper { public static void renderTileEntities(World world, Iterable customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + + renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer); + } + + public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Iterable customRenderTEs, MatrixStack ms, + MatrixStack localTransform, IRenderTypeBuffer buffer) { + float pt = AnimationTickHolder.getPartialTicks(); Matrix4f matrix = localTransform.peek() .getModel(); for (Iterator iterator = customRenderTEs.iterator(); iterator.hasNext();) { TileEntity tileEntity = iterator.next(); + //if (tileEntity instanceof IInstanceRendered) continue; // TODO: some things still need to render + TileEntityRenderer renderer = TileEntityRendererDispatcher.instance.getRenderer(tileEntity); if (renderer == null) { iterator.remove(); @@ -44,8 +53,10 @@ public class TileEntityRenderHelper { Vector4f vec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1); vec.transform(matrix); BlockPos lightPos = new BlockPos(vec.getX(), vec.getY(), vec.getZ()); - renderer.render(tileEntity, pt, ms, buffer, WorldRenderer.getLightmapCoordinates(world, lightPos), - OverlayTexture.DEFAULT_UV); + int worldLight = ContraptionRenderDispatcher.getLightOnContraption(world, renderWorld, pos, lightPos); + + renderer.render(tileEntity, pt, ms, buffer, worldLight, + OverlayTexture.DEFAULT_UV); ms.pop(); } catch (Exception e) { diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java new file mode 100644 index 000000000..6a416b187 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java @@ -0,0 +1,194 @@ +package com.simibubi.create.foundation.render.backend; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Predicate; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.lwjgl.opengl.GL; +import org.lwjgl.opengl.GLCapabilities; +import org.lwjgl.system.MemoryUtil; + +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram; +import com.simibubi.create.foundation.render.backend.gl.shader.GlShader; +import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec; +import com.simibubi.create.foundation.render.backend.gl.shader.ShaderType; +import com.simibubi.create.foundation.render.backend.gl.versioned.GlVersioned; +import com.simibubi.create.foundation.render.backend.gl.versioned.MapBuffer; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureUtil; +import net.minecraft.resources.IReloadableResourceManager; +import net.minecraft.resources.IResourceManager; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.resource.IResourceType; +import net.minecraftforge.resource.ISelectiveResourceReloadListener; +import net.minecraftforge.resource.VanillaResourceType; + +public class Backend { + public static final Logger log = LogManager.getLogger(Backend.class); + public static final FloatBuffer MATRIX_BUFFER = MemoryUtil.memAllocFloat(16); + + private static final Map> registry = new HashMap<>(); + private static final Map, GlProgram> programs = new HashMap<>(); + + private static boolean enabled; + + public static GLCapabilities capabilities; + private static MapBuffer mapBuffer; + + public Backend() { + throw new IllegalStateException(); + } + + public static void mapBuffer(int target, int offset, int length, Consumer upload) { + mapBuffer.mapBuffer(target, offset, length, upload); + } + + /** + * Register a shader program. TODO: replace with forge registry? + */ + public static

> S register(S spec) { + ResourceLocation name = spec.name; + if (registry.containsKey(name)) { + throw new IllegalStateException("Program spec '" + name + "' already registered."); + } + registry.put(name, spec); + return spec; + } + + @SuppressWarnings("unchecked") + public static

> P getProgram(S spec) { + return (P) programs.get(spec); + } + + /** + * Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order. + * + * @param clazz The class of the versioning enum. + * @param The type of the versioning enum. + * @return The first defined enum variant to return true. + */ + public static & GlVersioned> V getLatest(Class clazz) { + return getLatest(clazz, capabilities); + } + + /** + * Get the most compatible version of a specific OpenGL feature by iterating over enum constants in order. + * + * @param clazz The class of the versioning enum. + * @param caps The current system's supported features. + * @param The type of the versioning enum. + * @return The first defined enum variant to return true. + */ + public static & GlVersioned> V getLatest(Class clazz, GLCapabilities caps) { + V[] constants = clazz.getEnumConstants(); + V last = constants[constants.length - 1]; + if (!last.supported(caps)) { + throw new IllegalStateException(""); + } + + return Arrays.stream(constants).filter(it -> it.supported(caps)).findFirst().orElse(last); + } + + public static boolean canUseInstancing() { + return enabled && gl33(); + } + + public static boolean canUseVBOs() { + return enabled && gl20(); + } + + public static boolean available() { + return enabled && gl20(); + } + + public static boolean gl33() { + return capabilities.OpenGL33; + } + + public static boolean gl20() { + return capabilities.OpenGL20; + } + + public static void init() { + // Can be null when running datagenerators due to the unfortunate time we call this + Minecraft mc = Minecraft.getInstance(); + if (mc == null) return; + + IResourceManager manager = mc.getResourceManager(); + + if (manager instanceof IReloadableResourceManager) { + ISelectiveResourceReloadListener listener = Backend::onResourceManagerReload; + ((IReloadableResourceManager) manager).addReloadListener(listener); + } + } + + private static void onResourceManagerReload(IResourceManager manager, Predicate predicate) { + if (predicate.test(VanillaResourceType.SHADERS)) { + capabilities = GL.createCapabilities(); + mapBuffer = getLatest(MapBuffer.class); + + OptifineHandler.refresh(); + refresh(); + + if (gl20()) { + + programs.values().forEach(GlProgram::delete); + programs.clear(); + for (ProgramSpec shader : registry.values()) { + loadProgram(manager, shader); + } + } + } + } + + public static void refresh() { + enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); + } + + private static

> void loadProgram(IResourceManager manager, S programSpec) { + GlShader vert = null; + GlShader frag = null; + try { + vert = loadShader(manager, programSpec.getVert(), ShaderType.VERTEX, programSpec.defines); + frag = loadShader(manager, programSpec.getFrag(), ShaderType.FRAGMENT, programSpec.defines); + + GlProgram.Builder builder = GlProgram.builder(programSpec.name).attachShader(vert).attachShader(frag); + + programSpec.attributes.forEach(builder::addAttribute); + + P program = builder.build(programSpec.factory); + + programs.put(programSpec, program); + + log.info("Loaded program {}", programSpec.name); + } catch (IOException ex) { + log.error("Failed to load program {}", programSpec.name, ex); + } finally { + if (vert != null) vert.delete(); + if (frag != null) frag.delete(); + } + } + + private static GlShader loadShader(IResourceManager manager, ResourceLocation name, ShaderType type, GlShader.PreProcessor preProcessor) throws IOException { + try (InputStream is = new BufferedInputStream(manager.getResource(name).getInputStream())) { + String source = TextureUtil.func_225687_b_(is); + + if (source == null) { + throw new IOException("Could not load program " + name); + } else { + return new GlShader(type, name, source, preProcessor); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/BufferedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/BufferedModel.java new file mode 100644 index 000000000..79e4e4d2f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/BufferedModel.java @@ -0,0 +1,124 @@ +package com.simibubi.create.foundation.render.backend; + +import java.nio.ByteBuffer; + +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.TemplateBuffer; +import com.simibubi.create.foundation.render.backend.gl.GlBuffer; +import com.simibubi.create.foundation.render.backend.gl.GlPrimitiveType; +import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; + +import net.minecraft.client.renderer.BufferBuilder; + +public abstract class BufferedModel extends TemplateBuffer { + + protected GlBuffer ebo; + protected GlBuffer modelVBO; + protected boolean removed; + + public BufferedModel(BufferBuilder buf) { + super(buf); + if (vertexCount > 0) init(); + } + + protected void init() { + + modelVBO = new GlBuffer(GL20.GL_ARRAY_BUFFER); + + modelVBO.with(vbo -> initModel()); + + ebo = createEBO(); + } + + protected void initModel() { + int stride = getModelFormat().getStride(); + int invariantSize = vertexCount * stride; + + // allocate the buffer on the gpu + GL15.glBufferData(GL15.GL_ARRAY_BUFFER, invariantSize, GL15.GL_STATIC_DRAW); + + // mirror it in system memory so we can write to it + modelVBO.map(invariantSize, buffer -> { + for (int i = 0; i < vertexCount; i++) { + copyVertex(buffer, i); + } + }); + } + + protected final GlBuffer createEBO() { + GlBuffer ebo = new GlBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER); + + int indicesSize = vertexCount * GlPrimitiveType.USHORT.getSize(); + + ebo.bind(); + + GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesSize, GL15.GL_STATIC_DRAW); + ebo.map(indicesSize, indices -> { + for (int i = 0; i < vertexCount; i++) { + indices.putShort((short) i); + } + }); + + ebo.unbind(); + + return ebo; + } + + protected abstract void copyVertex(ByteBuffer to, int index); + + protected abstract VertexFormat getModelFormat(); + + protected int getTotalShaderAttributeCount() { + return getModelFormat().getShaderAttributeCount(); + } + + /** + * Renders this model, checking first if it should actually be rendered. + */ + public final void render() { + if (vertexCount == 0 || removed) return; + + doRender(); + } + + /** + * Override this. + */ + protected void doRender() { + modelVBO.bind(); + ebo.bind(); + + setupAttributes(); + GL20.glDrawElements(GL20.GL_QUADS, vertexCount, GlPrimitiveType.USHORT.getGlConstant(), 0); + + int numAttributes = getTotalShaderAttributeCount(); + for (int i = 0; i <= numAttributes; i++) { + GL20.glDisableVertexAttribArray(i); + } + + ebo.unbind(); + modelVBO.unbind(); + } + + protected void setupAttributes() { + int numAttributes = getTotalShaderAttributeCount(); + for (int i = 0; i <= numAttributes; i++) { + GL20.glEnableVertexAttribArray(i); + } + + getModelFormat().vertexAttribPointers(0); + } + + public void delete() { + removed = true; + if (vertexCount > 0) { + RenderWork.enqueue(this::deleteInternal); + } + } + + protected void deleteInternal() { + modelVBO.delete(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java b/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java new file mode 100644 index 000000000..17f504ab8 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java @@ -0,0 +1,124 @@ +package com.simibubi.create.foundation.render.backend; + +import java.util.concurrent.ConcurrentHashMap; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.KineticDebugger; +import com.simibubi.create.content.schematics.SchematicWorld; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.potion.Effects; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.World; + +public class FastRenderDispatcher { + + public static WorldAttached> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet); + + private static Matrix4f projectionMatrixThisFrame = null; + + public static void endFrame() { + projectionMatrixThisFrame = null; + } + + public static void enqueueUpdate(TileEntity te) { + queuedUpdates.get(te.getWorld()).add(te); + } + + public static void tick() { + ClientWorld world = Minecraft.getInstance().world; + + CreateClient.kineticRenderer.tick(); + + ConcurrentHashMap.KeySetView map = queuedUpdates.get(world); + map + .forEach(te -> { + map.remove(te); + + CreateClient.kineticRenderer.update(te); + }); + } + + public static boolean available() { + return Backend.canUseInstancing(); + } + + public static boolean available(World world) { + return Backend.canUseInstancing() && !(world instanceof SchematicWorld); + } + + public static int getDebugMode() { + return KineticDebugger.isActive() ? 1 : 0; + } + + public static void refresh() { + RenderWork.enqueue(Minecraft.getInstance().worldRenderer::loadRenderers); + } + + public static void renderLayer(RenderType layer, Matrix4f viewProjection, double cameraX, double cameraY, double cameraZ) { + if (!Backend.canUseInstancing()) return; + + layer.startDrawing(); + + RenderSystem.enableDepthTest(); + RenderSystem.enableCull(); + GL11.glCullFace(GL11.GL_BACK); + CreateClient.kineticRenderer.render(layer, viewProjection, cameraX, cameraY, cameraZ); + RenderSystem.disableCull(); + //RenderSystem.disableDepthTest(); + + layer.endDrawing(); + } + + // copied from GameRenderer.renderWorld + public static Matrix4f getProjectionMatrix() { + if (projectionMatrixThisFrame != null) return projectionMatrixThisFrame; + + float partialTicks = AnimationTickHolder.getPartialTicks(); + Minecraft mc = Minecraft.getInstance(); + GameRenderer gameRenderer = mc.gameRenderer; + ClientPlayerEntity player = mc.player; + + MatrixStack matrixstack = new MatrixStack(); + matrixstack.peek().getModel().multiply(gameRenderer.func_228382_a_(gameRenderer.getActiveRenderInfo(), partialTicks, true)); + gameRenderer.bobViewWhenHurt(matrixstack, partialTicks); + if (mc.gameSettings.viewBobbing) { + gameRenderer.bobView(matrixstack, partialTicks); + } + + float portalTime = MathHelper.lerp(partialTicks, player.prevTimeInPortal, player.timeInPortal); + if (portalTime > 0.0F) { + int i = 20; + if (player.isPotionActive(Effects.NAUSEA)) { + i = 7; + } + + float f1 = 5.0F / (portalTime * portalTime + 5.0F) - portalTime * 0.04F; + f1 = f1 * f1; + Vector3f vector3f = new Vector3f(0.0F, MathHelper.SQRT_2 / 2.0F, MathHelper.SQRT_2 / 2.0F); + matrixstack.multiply(vector3f.getDegreesQuaternion(((float)gameRenderer.rendererUpdateCount + partialTicks) * (float)i)); + matrixstack.scale(1.0F / f1, 1.0F, 1.0F); + float f2 = -((float)gameRenderer.rendererUpdateCount + partialTicks) * (float)i; + matrixstack.multiply(vector3f.getDegreesQuaternion(f2)); + } + + Matrix4f matrix4f = matrixstack.peek().getModel(); + gameRenderer.func_228379_a_(matrix4f); + + projectionMatrixThisFrame = matrix4f; + return projectionMatrixThisFrame; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/OptifineHandler.java b/src/main/java/com/simibubi/create/foundation/render/backend/OptifineHandler.java new file mode 100644 index 000000000..49b967e7b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/OptifineHandler.java @@ -0,0 +1,85 @@ +package com.simibubi.create.foundation.render.backend; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.util.Optional; + +import net.minecraft.client.Minecraft; + +public class OptifineHandler { + public static final String OPTIFINE_ROOT_PACKAGE = "net.optifine"; + public static final String SHADER_PACKAGE = "net.optifine.shaders"; + + private static Package optifine; + private static OptifineHandler handler; + + public final boolean usingShaders; + + public OptifineHandler(boolean usingShaders) { + this.usingShaders = usingShaders; + } + + /** + * Get information about the current Optifine configuration. + * @return {@link Optional#empty()} if Optifine is not installed. + */ + public static Optional get() { + return Optional.ofNullable(handler); + } + + public static boolean optifineInstalled() { + return optifine != null; + } + + public static boolean usingShaders() { + return OptifineHandler.get() + .map(OptifineHandler::isUsingShaders) + .orElse(false); + } + + public static void init() { + optifine = Package.getPackage(OPTIFINE_ROOT_PACKAGE); + + if (optifine == null) { + Backend.log.info("Optifine not detected."); + } else { + Backend.log.info("Optifine detected."); + + refresh(); + } + } + + public static void refresh() { + if (optifine == null) return; + + File dir = Minecraft.getInstance().gameDir; + + File shaderOptions = new File(dir, "optionsshaders.txt"); + + boolean shadersOff = true; + try { + BufferedReader reader = new BufferedReader(new FileReader(shaderOptions)); + + shadersOff = reader.lines() + .anyMatch(it -> { + String line = it.replaceAll("\\s", ""); + if (line.startsWith("shaderPack=")) { + String setting = line.substring("shaderPack=".length()); + + return setting.equals("OFF") || setting.equals("(internal)"); + } + return false; + }); + } catch (FileNotFoundException e) { + Backend.log.info("No shader config found."); + } + + handler = new OptifineHandler(!shadersOff); + } + + public boolean isUsingShaders() { + return usingShaders; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/RenderWork.java b/src/main/java/com/simibubi/create/foundation/render/backend/RenderWork.java new file mode 100644 index 000000000..5a44845f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/RenderWork.java @@ -0,0 +1,21 @@ +package com.simibubi.create.foundation.render.backend; + +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +public class RenderWork { + private static final Queue runs = new ConcurrentLinkedQueue<>(); + + public static void runAll() { + while (!runs.isEmpty()) { + runs.remove().run(); + } + } + + /** + * Queue work to be executed at the end of a frame + */ + public static void enqueue(Runnable run) { + runs.add(run); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java new file mode 100644 index 000000000..8d6f71711 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java @@ -0,0 +1,61 @@ +package com.simibubi.create.foundation.render.backend.gl; + +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.util.ResourceLocation; + +public class BasicProgram extends GlProgram { + protected final int uTime; + protected final int uViewProjection; + protected final int uDebug; + protected final int uCameraPos; + protected final int uFogRange; + protected final int uFogColor; + + protected int uBlockAtlas; + protected int uLightMap; + + public BasicProgram(ResourceLocation name, int handle) { + super(name, handle); + uTime = getUniformLocation("uTime"); + uViewProjection = getUniformLocation("uViewProjection"); + uDebug = getUniformLocation("uDebug"); + uCameraPos = getUniformLocation("uCameraPos"); + uFogRange = getUniformLocation("uFogRange"); + uFogColor = getUniformLocation("uFogColor"); + + bind(); + registerSamplers(); + unbind(); + } + + protected void registerSamplers() { + uBlockAtlas = setSamplerBinding("uBlockAtlas", 0); + uLightMap = setSamplerBinding("uLightMap", 2); + } + + public void bind(Matrix4f viewProjection, double camX, double camY, double camZ, int debugMode) { + super.bind(); + + GL20.glUniform1i(uDebug, debugMode); + GL20.glUniform1f(uTime, AnimationTickHolder.getRenderTick()); + + uploadMatrixUniform(uViewProjection, viewProjection); + GL20.glUniform3f(uCameraPos, (float) camX, (float) camY, (float) camZ); + + GL20.glUniform2f(uFogRange, GlFog.getFogStart(), GlFog.getFogEnd()); + GL20.glUniform4fv(uFogColor, GlFog.FOG_COLOR); + } + + protected static void uploadMatrixUniform(int uniform, Matrix4f mat) { + Backend.MATRIX_BUFFER.position(0); + mat.write(Backend.MATRIX_BUFFER); + Backend.MATRIX_BUFFER.rewind(); + GL20.glUniformMatrix4fv(uniform, false, Backend.MATRIX_BUFFER); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlBuffer.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlBuffer.java new file mode 100644 index 000000000..42a72736b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlBuffer.java @@ -0,0 +1,48 @@ +package com.simibubi.create.foundation.render.backend.gl; + +import java.nio.ByteBuffer; +import java.util.function.Consumer; + +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.backend.Backend; + +public class GlBuffer extends GlObject { + + protected final int bufferType; + + public GlBuffer(int bufferType) { + setHandle(GL20.glGenBuffers()); + this.bufferType = bufferType; + } + + public int getBufferType() { + return bufferType; + } + + public void bind() { + GL20.glBindBuffer(bufferType, handle()); + } + + public void unbind() { + GL20.glBindBuffer(bufferType, 0); + } + + public void with(Consumer action) { + bind(); + action.accept(this); + unbind(); + } + + public void map(int length, Consumer upload) { + Backend.mapBuffer(bufferType, 0, length, upload); + } + + public void map(int offset, int length, Consumer upload) { + Backend.mapBuffer(bufferType, offset, length, upload); + } + + protected void deleteInternal(int handle) { + GL20.glDeleteBuffers(handle); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFog.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFog.java new file mode 100644 index 000000000..de7958b8c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFog.java @@ -0,0 +1,27 @@ +package com.simibubi.create.foundation.render.backend.gl; + +import com.mojang.blaze3d.platform.GlStateManager; + +public class GlFog { + public static float[] FOG_COLOR = new float[] {0, 0, 0, 0}; + + public static boolean fogEnabled() { + return GlStateManager.FOG.field_179049_a.field_179201_b; + } + + public static int getFogMode() { + return GlStateManager.FOG.field_179047_b; + } + + public static float getFogDensity() { + return GlStateManager.FOG.field_179048_c; + } + + public static float getFogEnd() { + return GlStateManager.FOG.field_179046_e; + } + + public static float getFogStart() { + return GlStateManager.FOG.field_179045_d; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlObject.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlObject.java new file mode 100644 index 000000000..ef34e5ebe --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlObject.java @@ -0,0 +1,43 @@ +package com.simibubi.create.foundation.render.backend.gl; + +// Utility class for safely dealing with gl object handles. +public abstract class GlObject { + private static final int INVALID_HANDLE = Integer.MIN_VALUE; + + private int handle = INVALID_HANDLE; + + protected final void setHandle(int handle) { + this.handle = handle; + } + + public final int handle() { + this.checkHandle(); + + return this.handle; + } + + protected final void checkHandle() { + if (!this.isHandleValid()) { + throw new IllegalStateException("Handle is not valid"); + } + } + + protected final boolean isHandleValid() { + return this.handle != INVALID_HANDLE; + } + + protected final void invalidateHandle() { + this.handle = INVALID_HANDLE; + } + + public final void delete() { + if (!isHandleValid()) { + throw new IllegalStateException("Handle already deleted."); + } + + deleteInternal(handle); + invalidateHandle(); + } + + protected abstract void deleteInternal(int handle); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlPrimitiveType.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlPrimitiveType.java new file mode 100644 index 000000000..5e069fabf --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlPrimitiveType.java @@ -0,0 +1,37 @@ +package com.simibubi.create.foundation.render.backend.gl; + +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public enum GlPrimitiveType { + FLOAT(4, "float", 5126), + UBYTE(1, "ubyte", 5121), + BYTE(1, "byte", 5120), + USHORT(2, "ushort", 5123), + SHORT(2, "short", 5122), + UINT(4, "uint", 5125), + INT(4, "int", 5124); + + private final int size; + private final String displayName; + private final int glConstant; + + GlPrimitiveType(int p_i46095_3_, String p_i46095_4_, int p_i46095_5_) { + this.size = p_i46095_3_; + this.displayName = p_i46095_4_; + this.glConstant = p_i46095_5_; + } + + public int getSize() { + return this.size; + } + + public String getDisplayName() { + return this.displayName; + } + + public int getGlConstant() { + return this.glConstant; + } +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlTexture.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlTexture.java new file mode 100644 index 000000000..30b5d3f0f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlTexture.java @@ -0,0 +1,25 @@ +package com.simibubi.create.foundation.render.backend.gl; + +import org.lwjgl.opengl.GL20; + +public class GlTexture extends GlObject { + private final int textureType; + + public GlTexture(int textureType) { + this.textureType = textureType; + setHandle(GL20.glGenTextures()); + } + + @Override + protected void deleteInternal(int handle) { + GL20.glDeleteTextures(handle); + } + + public void bind() { + GL20.glBindTexture(textureType, handle()); + } + + public void unbind() { + GL20.glBindTexture(textureType, 0); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlVertexArray.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlVertexArray.java new file mode 100644 index 000000000..33ff7461b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlVertexArray.java @@ -0,0 +1,29 @@ +package com.simibubi.create.foundation.render.backend.gl; + +import java.util.function.Consumer; + +import org.lwjgl.opengl.GL30; + +public class GlVertexArray extends GlObject { + public GlVertexArray() { + setHandle(GL30.glGenVertexArrays()); + } + + public void bind() { + GL30.glBindVertexArray(handle()); + } + + public void unbind() { + GL30.glBindVertexArray(0); + } + + public void with(Consumer action) { + bind(); + action.accept(this); + unbind(); + } + + protected void deleteInternal(int handle) { + GL30.glDeleteVertexArrays(handle); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java new file mode 100644 index 000000000..d3fd9d48e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java @@ -0,0 +1,21 @@ +package com.simibubi.create.foundation.render.backend.gl.attrib; + +import com.simibubi.create.foundation.render.backend.gl.GlPrimitiveType; + +public class CommonAttributes { + + public static final VertexAttribSpec MAT4 = new VertexAttribSpec(GlPrimitiveType.FLOAT, 16); + public static final VertexAttribSpec VEC4 = new VertexAttribSpec(GlPrimitiveType.FLOAT, 4); + public static final VertexAttribSpec VEC3 = new VertexAttribSpec(GlPrimitiveType.FLOAT, 3); + public static final VertexAttribSpec VEC2 = new VertexAttribSpec(GlPrimitiveType.FLOAT, 2); + public static final VertexAttribSpec FLOAT = new VertexAttribSpec(GlPrimitiveType.FLOAT, 1); + + public static final VertexAttribSpec NORMAL = new VertexAttribSpec(GlPrimitiveType.BYTE, 3, true); + public static final VertexAttribSpec UV = new VertexAttribSpec(GlPrimitiveType.FLOAT, 2); + + public static final VertexAttribSpec RGBA = new VertexAttribSpec(GlPrimitiveType.UBYTE, 4, true); + public static final VertexAttribSpec RGB = new VertexAttribSpec(GlPrimitiveType.UBYTE, 3, true); + public static final VertexAttribSpec LIGHT = new VertexAttribSpec(GlPrimitiveType.UBYTE, 2, true); + + public static final VertexAttribSpec NORMALIZED_BYTE = new VertexAttribSpec(GlPrimitiveType.BYTE, 1, true); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/IVertexAttrib.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/IVertexAttrib.java new file mode 100644 index 000000000..5c77620f9 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/IVertexAttrib.java @@ -0,0 +1,12 @@ +package com.simibubi.create.foundation.render.backend.gl.attrib; + +public interface IVertexAttrib { + + String attribName(); + + VertexAttribSpec attribSpec(); + + int getDivisor(); + + int getBufferIndex(); +} 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 new file mode 100644 index 000000000..960289fd6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/ModelVertexAttributes.java @@ -0,0 +1,36 @@ +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 VertexAttribSpec 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/gl/attrib/VertexAttribSpec.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexAttribSpec.java new file mode 100644 index 000000000..1af7dc3a6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexAttribSpec.java @@ -0,0 +1,38 @@ +package com.simibubi.create.foundation.render.backend.gl.attrib; + +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.backend.gl.GlPrimitiveType; + +public class VertexAttribSpec { + + private final GlPrimitiveType type; + private final int count; + private final int size; + private final int attributeCount; + private final boolean normalized; + + public VertexAttribSpec(GlPrimitiveType type, int count) { + this(type, count, false); + } + + public VertexAttribSpec(GlPrimitiveType type, int count, boolean normalized) { + this.type = type; + this.count = count; + this.size = type.getSize() * count; + this.attributeCount = (this.size + 15) / 16; // ceiling division. GLSL vertex attributes can only be 16 bytes wide + this.normalized = normalized; + } + + public void vertexAttribPointer(int stride, int index, int pointer) { + GL20.glVertexAttribPointer(index, count, type.getGlConstant(), normalized, stride, pointer); + } + + public int getSize() { + return size; + } + + public int getAttributeCount() { + return attributeCount; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexFormat.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexFormat.java new file mode 100644 index 000000000..3929e3354 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexFormat.java @@ -0,0 +1,65 @@ +package com.simibubi.create.foundation.render.backend.gl.attrib; + +import java.util.ArrayList; +import java.util.Arrays; + +public class VertexFormat { + + private final ArrayList allAttributes; + + private final int numAttributes; + private final int stride; + + public VertexFormat(ArrayList allAttributes) { + this.allAttributes = allAttributes; + + int numAttributes = 0, stride = 0; + for (IVertexAttrib attrib : allAttributes) { + VertexAttribSpec spec = attrib.attribSpec(); + numAttributes += spec.getAttributeCount(); + stride += spec.getSize(); + } + this.numAttributes = numAttributes; + this.stride = stride; + } + + public int getShaderAttributeCount() { + return numAttributes; + } + + public int getStride() { + return stride; + } + + public void vertexAttribPointers(int index) { + int offset = 0; + for (IVertexAttrib attrib : this.allAttributes) { + VertexAttribSpec spec = attrib.attribSpec(); + spec.vertexAttribPointer(stride, index, offset); + index += spec.getAttributeCount(); + offset += spec.getSize(); + } + } + + public static Builder builder() { + return new Builder(); + } + + + public static class Builder { + private final ArrayList allAttributes; + + public Builder() { + allAttributes = new ArrayList<>(); + } + + public & IVertexAttrib> Builder addAttributes(Class attribEnum) { + allAttributes.addAll(Arrays.asList(attribEnum.getEnumConstants())); + return this; + } + + public VertexFormat build() { + return new VertexFormat(allAttributes); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GLSLType.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GLSLType.java new file mode 100644 index 000000000..80dc2fa16 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GLSLType.java @@ -0,0 +1,45 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +import com.simibubi.create.foundation.render.backend.gl.GlPrimitiveType; + +public class GLSLType { + public static final GLSLType FLOAT = new GLSLType("mat4", GlPrimitiveType.FLOAT, 16); + public static final GLSLType VEC2 = new GLSLType("vec4", GlPrimitiveType.FLOAT, 4); + public static final GLSLType VEC3 = new GLSLType("vec3", GlPrimitiveType.FLOAT, 3); + public static final GLSLType VEC4 = new GLSLType("vec2", GlPrimitiveType.FLOAT, 2); + public static final GLSLType MAT4 = new GLSLType("float", GlPrimitiveType.FLOAT, 1); + + private final String symbol; + private final GlPrimitiveType base; + private final int count; + private final int size; + private final int attributeCount; + + public GLSLType(String symbol, GlPrimitiveType base, int count) { + this.symbol = symbol; + this.base = base; + this.count = count; + this.size = base.getSize() * count; + this.attributeCount = (this.size + 15) / 16; // ceiling division. GLSL vertex attributes can only be 16 bytes wide + } + + public String getSymbol() { + return symbol; + } + + public GlPrimitiveType getBase() { + return base; + } + + public int getCount() { + return count; + } + + public int getSize() { + return size; + } + + public int getAttributeCount() { + return attributeCount; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlProgram.java new file mode 100644 index 000000000..c911eea5f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlProgram.java @@ -0,0 +1,124 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.gl.GlObject; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; + +import net.minecraft.util.ResourceLocation; + +public abstract class GlProgram extends GlObject { + + public final ResourceLocation name; + + protected GlProgram(ResourceLocation name, int handle) { + setHandle(handle); + this.name = name; + } + + public static Builder builder(ResourceLocation name) { + return new Builder(name); + } + + public void bind() { + GL20.glUseProgram(handle()); + } + + public void unbind() { + GL20.glUseProgram(0); + } + + /** + * Retrieves the index of the uniform with the given name. + * @param uniform The name of the uniform to find the index of + * @return The uniform's index + */ + public int getUniformLocation(String uniform) { + int index = GL20.glGetUniformLocation(this.handle(), uniform); + + if (index < 0) { + Backend.log.warn("No active uniform '{}' exists in program '{}'. Could be unused.", uniform, this.name); + } + + return index; + } + + /** + * Binds a sampler uniform to the given texture unit. + * @param name The name of the sampler uniform. + * @param binding The index of the texture unit. + * @return The sampler uniform's index. + * @throws NullPointerException If no uniform exists with the given name. + */ + public int setSamplerBinding(String name, int binding) { + int samplerUniform = getUniformLocation(name); + + if (samplerUniform >= 0) { + GL20.glUniform1i(samplerUniform, binding); + } + + return samplerUniform; + } + + @Override + protected void deleteInternal(int handle) { + GL20.glDeleteProgram(handle); + } + + public static class Builder { + private final ResourceLocation name; + private final int program; + + private int attributeIndex; + + public Builder(ResourceLocation name) { + this.name = name; + this.program = GL20.glCreateProgram(); + } + + public Builder attachShader(GlShader shader) { + GL20.glAttachShader(this.program, shader.handle()); + + return this; + } + + public Builder addAttribute(A attrib) { + GL20.glBindAttribLocation(this.program, attributeIndex, attrib.attribName()); + attributeIndex += attrib.attribSpec().getAttributeCount(); + return this; + } + + /** + * Links the attached shaders to this program and returns a user-defined container which wraps the shader + * program. This container can, for example, provide methods for updating the specific uniforms of that shader + * set. + * + * @param factory The factory which will create the shader program's container + * @param

The type which should be instantiated with the new program's handle + * @return An instantiated shader container as provided by the factory + */ + public

P build(ProgramFactory

factory) { + GL20.glLinkProgram(this.program); + + String log = GL20.glGetProgramInfoLog(this.program); + + if (!log.isEmpty()) { + Backend.log.warn("Program link log for " + this.name + ": " + log); + } + + int result = GL20.glGetProgrami(this.program, GL20.GL_LINK_STATUS); + + if (result != GL20.GL_TRUE) { + throw new RuntimeException("Shader program linking failed, see log for details"); + } + + return factory.create(this.name, this.program); + } + } + + @FunctionalInterface + public interface ProgramFactory

{ + P create(ResourceLocation name, int handle); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java new file mode 100644 index 000000000..8ef265920 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java @@ -0,0 +1,54 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +import org.lwjgl.opengl.GL20; + +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.gl.GlObject; + +import net.minecraft.util.ResourceLocation; + +public class GlShader extends GlObject { + + public final ResourceLocation name; + public final ShaderType type; + + public GlShader(ShaderType type, ResourceLocation name, String source, PreProcessor preProcessor) { + this.type = type; + this.name = name; + int handle = GL20.glCreateShader(type.glEnum); + + if (preProcessor != null) { + source = preProcessor.process(source); + Backend.log.info("Preprocessor run on " + name);// + ":\n" + source); + } + + GL20.glShaderSource(handle, source); + GL20.glCompileShader(handle); + + String log = GL20.glGetShaderInfoLog(handle); + + if (!log.isEmpty()) { + Backend.log.warn("Shader compilation log for " + name + ": " + log); + } + + if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) { + throw new RuntimeException("Could not compile shader"); + } + + setHandle(handle); + } + + @Override + protected void deleteInternal(int handle) { + GL20.glDeleteShader(handle); + } + + @FunctionalInterface + public interface PreProcessor { + String process(String source); + + default PreProcessor andThen(PreProcessor that) { + return source -> that.process(this.process(source)); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramSpec.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramSpec.java new file mode 100644 index 000000000..7c2a2ca93 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramSpec.java @@ -0,0 +1,89 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +import java.util.ArrayList; +import java.util.Arrays; + +import com.simibubi.create.Create; +import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; + +import net.minecraft.util.ResourceLocation; + +public class ProgramSpec

{ + + public final ResourceLocation name; + public final ResourceLocation vert; + public final ResourceLocation frag; + + public final ShaderConstants defines; + + public final GlProgram.ProgramFactory

factory; + + public final ArrayList attributes; + + public static

Builder

builder(String name, GlProgram.ProgramFactory

factory) { + return builder(new ResourceLocation(Create.ID, name), factory); + } + + public static

Builder

builder(ResourceLocation name, GlProgram.ProgramFactory

factory) { + return new Builder<>(name, factory); + } + + public ProgramSpec(ResourceLocation name, ResourceLocation vert, ResourceLocation frag, GlProgram.ProgramFactory

factory, ShaderConstants defines, ArrayList attributes) { + this.name = name; + this.vert = vert; + this.frag = frag; + this.defines = defines; + + + this.factory = factory; + this.attributes = attributes; + } + + public ResourceLocation getVert() { + return vert; + } + + public ResourceLocation getFrag() { + return frag; + } + + public static class Builder

{ + private ResourceLocation vert; + private ResourceLocation frag; + private ShaderConstants defines = null; + + private final ResourceLocation name; + private final GlProgram.ProgramFactory

factory; + private final ArrayList attributes; + + public Builder(ResourceLocation name, GlProgram.ProgramFactory

factory) { + this.name = name; + this.factory = factory; + attributes = new ArrayList<>(); + } + + public Builder

setVert(ResourceLocation vert) { + this.vert = vert; + return this; + } + + public Builder

setFrag(ResourceLocation frag) { + this.frag = frag; + return this; + } + + public Builder

setDefines(ShaderConstants defines) { + this.defines = defines; + return this; + } + + public & IVertexAttrib> Builder

addAttributes(Class attributeEnum) { + attributes.addAll(Arrays.asList(attributeEnum.getEnumConstants())); + return this; + } + + public ProgramSpec

createProgramSpec() { + return new ProgramSpec<>(name, vert, frag, factory, defines, attributes); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderCallback.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderCallback.java new file mode 100644 index 000000000..b410d91ff --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderCallback.java @@ -0,0 +1,17 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +/** + * A Callback for when a shader is called. Used to define shader uniforms. + */ +@FunctionalInterface +public interface ShaderCallback

{ + + void call(P program); + + default ShaderCallback

andThen(ShaderCallback

other) { + return program -> { + call(program); + other.call(program); + }; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderConstants.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderConstants.java new file mode 100644 index 000000000..3f1ed6c09 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderConstants.java @@ -0,0 +1,46 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +import java.io.BufferedReader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ShaderConstants implements GlShader.PreProcessor { + + private final ArrayList defines; + + public ShaderConstants() { + defines = new ArrayList<>(); + } + + public static ShaderConstants define(String def) { + return new ShaderConstants().def(def); + } + + public ShaderConstants def(String def) { + defines.add(def); + return this; + } + + public ArrayList getDefines() { + return defines; + } + + public Stream directives() { + return defines.stream().map(it -> "#define " + it); + } + + @Override + public String process(String source) { + return new BufferedReader(new StringReader(source)).lines().flatMap(line -> { + Stream map = Stream.of(line); + + if (line.startsWith("#version")) { + map = Stream.concat(map, directives()); + } + + return map; + }).collect(Collectors.joining("\n")); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderType.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderType.java new file mode 100644 index 000000000..b90f15cca --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderType.java @@ -0,0 +1,15 @@ +package com.simibubi.create.foundation.render.backend.gl.shader; + +import org.lwjgl.opengl.GL20; + +public enum ShaderType { + VERTEX(GL20.GL_VERTEX_SHADER), + FRAGMENT(GL20.GL_FRAGMENT_SHADER), + ; + + public final int glEnum; + + ShaderType(int glEnum) { + this.glEnum = glEnum; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlVersioned.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlVersioned.java new file mode 100644 index 000000000..53d929ea0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlVersioned.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.render.backend.gl.versioned; + +import org.lwjgl.opengl.GLCapabilities; + + +public interface GlVersioned { + boolean supported(GLCapabilities caps); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/MapBuffer.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/MapBuffer.java new file mode 100644 index 000000000..e5e03d4b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/MapBuffer.java @@ -0,0 +1,75 @@ +package com.simibubi.create.foundation.render.backend.gl.versioned; + +import java.nio.ByteBuffer; +import java.util.function.Consumer; + +import org.lwjgl.opengl.ARBMapBufferRange; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL30; +import org.lwjgl.opengl.GLCapabilities; + +public enum MapBuffer implements GlVersioned { + + GL30_RANGE { + @Override + public boolean supported(GLCapabilities caps) { + return caps.OpenGL30; + } + + @Override + public void mapBuffer(int target, int offset, int length, Consumer upload) { + ByteBuffer buffer = GL30.glMapBufferRange(target, offset, length, GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_INVALIDATE_RANGE_BIT); + + upload.accept(buffer); + buffer.rewind(); + + GL30.glUnmapBuffer(target); + } + }, + ARB_RANGE { + @Override + public boolean supported(GLCapabilities caps) { + return caps.GL_ARB_map_buffer_range; + } + + @Override + public void mapBuffer(int target, int offset, int length, Consumer upload) { + ByteBuffer buffer = ARBMapBufferRange.glMapBufferRange(target, offset, length, GL30.GL_MAP_WRITE_BIT | GL30.GL_MAP_INVALIDATE_RANGE_BIT); + + upload.accept(buffer); + buffer.rewind(); + + GL30.glUnmapBuffer(target); + } + }, + GL15_MAP { + @Override + public boolean supported(GLCapabilities caps) { + return caps.OpenGL15; + } + + @Override + public void mapBuffer(int target, int offset, int length, Consumer upload) { + ByteBuffer buffer = GL15.glMapBuffer(target, GL15.GL_WRITE_ONLY); + + buffer.position(offset); + upload.accept(buffer); + buffer.rewind(); + GL15.glUnmapBuffer(target); + } + }, + UNSUPPORTED { + @Override + public boolean supported(GLCapabilities caps) { + return true; + } + + @Override + public void mapBuffer(int target, int offset, int length, Consumer upload) { + throw new UnsupportedOperationException("glMapBuffer not supported"); + } + }; + + + public abstract void mapBuffer(int target, int offset, int length, Consumer upload); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstanceRendered.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstanceRendered.java new file mode 100644 index 000000000..a1558446f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstanceRendered.java @@ -0,0 +1,9 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import com.simibubi.create.foundation.render.backend.light.ILightListener; + +public interface IInstanceRendered extends ILightListener { + default boolean shouldRenderAsTE() { + return false; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IRendererFactory.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IRendererFactory.java new file mode 100644 index 000000000..196e029d8 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IRendererFactory.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import net.minecraft.tileentity.TileEntity; + +@FunctionalInterface +public interface IRendererFactory { + TileEntityInstance create(InstancedTileRenderer manager, T te); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceData.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceData.java new file mode 100644 index 000000000..2facfb415 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceData.java @@ -0,0 +1,51 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import java.nio.ByteBuffer; + +public abstract class InstanceData { + + protected final InstancedModel owner; + + protected InstanceData(InstancedModel owner) { + this.owner = owner; + } + + public abstract void write(ByteBuffer buf); + + public void putVec4(ByteBuffer buf, float x, float y, float z, float w) { + put(buf, x); + put(buf, y); + put(buf, z); + put(buf, w); + } + + public void putVec3(ByteBuffer buf, float x, float y, float z) { + put(buf, x); + put(buf, y); + put(buf, z); + } + + public void putVec2(ByteBuffer buf, float x, float y) { + put(buf, x); + put(buf, y); + } + + public void putVec3(ByteBuffer buf, byte x, byte y, byte z) { + put(buf, x); + put(buf, y); + put(buf, z); + } + + public void putVec2(ByteBuffer buf, byte x, byte y) { + put(buf, x); + put(buf, y); + } + + public void put(ByteBuffer buf, byte b) { + buf.put(b); + } + + public void put(ByteBuffer buf, float f) { + buf.putFloat(f); + } +} 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 new file mode 100644 index 000000000..166bf8e56 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceKey.java @@ -0,0 +1,31 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import java.util.function.Consumer; + +public class InstanceKey { + public static final int INVALID = -1; + + InstancedModel model; + int index; + + public InstanceKey(InstancedModel model, int index) { + this.model = model; + this.index = index; + } + + void invalidate() { + index = INVALID; + } + + public boolean isValid() { + return index != INVALID; + } + + public void modifyInstance(Consumer edit) { + model.modifyInstance(this, edit); + } + + public void delete() { + model.deleteInstance(this); + } +} 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 new file mode 100644 index 000000000..b18cffcc4 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java @@ -0,0 +1,222 @@ +package com.simibubi.create.foundation.render.backend.instancing; + + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.function.Consumer; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL15; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL31; +import org.lwjgl.opengl.GL33; + +import com.simibubi.create.foundation.render.RenderMath; +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.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 final InstancedTileRenderer renderer; + + protected GlVertexArray vao; + protected GlBuffer instanceVBO; + protected int glBufferSize = -1; + protected int glInstanceCount = 0; + + protected final ArrayList> keys = new ArrayList<>(); + protected final ArrayList data = new ArrayList<>(); + protected int minIndexChanged = -1; + protected int maxIndexChanged = -1; + + public InstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { + super(buf); + this.renderer = renderer; + } + + @Override + protected void init() { + vao = new GlVertexArray(); + instanceVBO = new GlBuffer(GL20.GL_ARRAY_BUFFER); + + vao.with(vao -> super.init()); + } + + @Override + protected void initModel() { + super.initModel(); + setupAttributes(); + } + + public int instanceCount() { + return data.size(); + } + + public boolean isEmpty() { + return instanceCount() == 0; + } + + protected void deleteInternal() { + keys.forEach(InstanceKey::invalidate); + super.deleteInternal(); + + instanceVBO.delete(); + vao.delete(); + } + + protected abstract D newInstance(); + + public synchronized void deleteInstance(InstanceKey key) { + verifyKey(key); + + int index = key.index; + + keys.remove(index); + data.remove(index); + + for (int i = index; i < keys.size(); i++) { + keys.get(i).index--; + } + + maxIndexChanged = keys.size() - 1; + markIndexChanged(Math.min(maxIndexChanged, index)); + + key.invalidate(); + } + + public synchronized void modifyInstance(InstanceKey key, Consumer edit) { + verifyKey(key); + + D data = this.data.get(key.index); + + edit.accept(data); + + markIndexChanged(key.index); + } + + public synchronized InstanceKey setupInstance(Consumer setup) { + D instanceData = newInstance(); + setup.accept(instanceData); + + InstanceKey key = new InstanceKey<>(this, data.size()); + data.add(instanceData); + keys.add(key); + + markIndexChanged(key.index); + + return key; + } + + protected void doRender() { + vao.with(vao -> { + renderSetup(); + GL31.glDrawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount); + }); + } + + protected void renderSetup() { + if (minIndexChanged < 0 || data.isEmpty()) return; + + VertexFormat instanceFormat = getInstanceFormat(); + + int stride = instanceFormat.getStride(); + int newInstanceCount = instanceCount(); + int instanceSize = RenderMath.nextPowerOf2((newInstanceCount + 1) * stride); + + instanceVBO.with(vbo -> { + // this probably changes enough that it's not worth reallocating the entire buffer every time. + if (instanceSize > glBufferSize) { + GL15.glBufferData(vbo.getBufferType(), instanceSize, GL15.GL_STATIC_DRAW); + glBufferSize = instanceSize; + minIndexChanged = 0; + maxIndexChanged = newInstanceCount - 1; + } + + int offset = minIndexChanged * stride; + int length = (1 + maxIndexChanged - minIndexChanged) * stride; + + vbo.map(offset, length, buffer -> { + for (int i = minIndexChanged; i <= maxIndexChanged; i++) { + data.get(i).write(buffer); + } + }); + + if (newInstanceCount < glInstanceCount) { + int clearFrom = (maxIndexChanged + 1) * stride; + int clearTo = (glInstanceCount) * stride; + vbo.map(clearFrom, clearTo - clearFrom, buffer -> { + for (int i = clearFrom; i < clearTo; i++) { + buffer.put((byte) 0); + } + }); + } + + glInstanceCount = newInstanceCount; + + int staticAttributes = getModelFormat().getShaderAttributeCount(); + instanceFormat.vertexAttribPointers(staticAttributes); + + for (int i = 0; i < instanceFormat.getShaderAttributeCount(); i++) { + GL33.glVertexAttribDivisor(i + staticAttributes, 1); + } + }); + + minIndexChanged = -1; + maxIndexChanged = -1; + } + + protected void markIndexChanged(int index) { + if (minIndexChanged < 0) { + minIndexChanged = index; + } else if (index < minIndexChanged) { + minIndexChanged = index; + } + + if (maxIndexChanged < 0) { + maxIndexChanged = index; + } else if (index > maxIndexChanged) { + maxIndexChanged = index; + } + } + + protected final void verifyKey(InstanceKey key) { + if (key.model != this) throw new IllegalStateException("Provided key does not belong to model."); + + if (!key.isValid()) throw new IllegalStateException("Provided key has been invalidated."); + + if (key.index >= data.size()) throw new IndexOutOfBoundsException("Key points out of bounds. (" + key.index + " > " + (data.size() - 1) + ")"); + + if (keys.get(key.index) != key) throw new IllegalStateException("Key desync!!"); + } + + @Override + protected void copyVertex(ByteBuffer constant, int i) { + constant.putFloat(getX(template, i)); + constant.putFloat(getY(template, i)); + constant.putFloat(getZ(template, i)); + + constant.put(getNX(template, i)); + constant.put(getNY(template, i)); + constant.put(getNZ(template, i)); + + constant.putFloat(getU(template, i)); + constant.putFloat(getV(template, i)); + } + + @Override + protected VertexFormat getModelFormat() { + return FORMAT; + } + + protected abstract VertexFormat getInstanceFormat(); + + protected int getTotalShaderAttributeCount() { + return getInstanceFormat().getShaderAttributeCount() + super.getTotalShaderAttributeCount(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderRegistry.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderRegistry.java new file mode 100644 index 000000000..26bdd4f96 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderRegistry.java @@ -0,0 +1,31 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import java.util.Map; + +import javax.annotation.Nullable; + +import com.google.common.collect.Maps; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityType; + +public class InstancedTileRenderRegistry { + public static final InstancedTileRenderRegistry instance = new InstancedTileRenderRegistry(); + + private final Map, IRendererFactory> renderers = Maps.newHashMap(); + + public void register(TileEntityType type, IRendererFactory rendererFactory) { + this.renderers.put(type, rendererFactory); + } + + @SuppressWarnings("unchecked") + @Nullable + public TileEntityInstance create(InstancedTileRenderer manager, T tile) { + TileEntityType type = tile.getType(); + IRendererFactory factory = (IRendererFactory) this.renderers.get(type); + + if (factory == null) return null; + else return factory.create(manager, tile); + } + +} 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 new file mode 100644 index 000000000..4f22c016f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java @@ -0,0 +1,159 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.gl.BasicProgram; +import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; + +public abstract class InstancedTileRenderer

{ + public static WorldAttached> addedLastTick = new WorldAttached<>(ConcurrentHashMap::new); + + protected Map> instances = new HashMap<>(); + + protected Map, RenderMaterial> materials = new HashMap<>(); + + protected InstancedTileRenderer() { + registerMaterials(); + } + + public abstract BlockPos getOriginCoordinate(); + + public abstract void registerMaterials(); + + public void tick() { + ClientWorld world = Minecraft.getInstance().world; + + int ticks = AnimationTickHolder.getTicks(); + + ConcurrentHashMap map = addedLastTick.get(world); + map + .entrySet() + .stream() + .filter(it -> ticks - it.getValue() > 10) + .map(Map.Entry::getKey) + .forEach(te -> { + map.remove(te); + + onLightUpdate(te); + }); + + + // Clean up twice a second. This doesn't have to happen every tick, + // but this does need to be run to ensure we don't miss anything. + if (ticks % 10 == 0) { + clean(); + } + } + + @SuppressWarnings("unchecked") + public > RenderMaterial getMaterial(MaterialType materialType) { + return (RenderMaterial) materials.get(materialType); + } + + @Nullable + public TileEntityInstance getInstance(T tile) { + return getInstance(tile, true); + } + + @SuppressWarnings("unchecked") + @Nullable + public TileEntityInstance getInstance(T tile, boolean create) { + 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) { + addedLastTick.get(tile.getWorld()).put(tile, AnimationTickHolder.getTicks()); + instances.put(tile, renderer); + } + + return renderer; + } else { + return null; + } + } + + public void onLightUpdate(T tile) { + if (!Backend.canUseInstancing()) return; + + if (tile instanceof IInstanceRendered) { + TileEntityInstance instance = getInstance(tile, false); + + if (instance != null) + instance.updateLight(); + } + } + + public void add(T tile) { + if (!Backend.canUseInstancing()) return; + + if (tile instanceof IInstanceRendered) { + getInstance(tile); + } + } + + public void update(T tile) { + if (!Backend.canUseInstancing()) return; + + if (tile instanceof IInstanceRendered) { + TileEntityInstance instance = getInstance(tile, false); + + if (instance != null) + instance.update(); + } + } + + public void remove(T tile) { + if (!Backend.canUseInstancing()) return; + + if (tile instanceof IInstanceRendered) { + TileEntityInstance instance = getInstance(tile, false); + + if (instance != null) { + instance.remove(); + instances.remove(tile); + } + } + } + + public void clean() { + instances.keySet().removeIf(TileEntity::isRemoved); + } + + public void invalidate() { + for (RenderMaterial material : materials.values()) { + material.delete(); + } + instances.clear(); + } + + public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { + render(layer, viewProjection, camX, camY, camZ, null); + } + + public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, ShaderCallback

callback) { + for (RenderMaterial material : materials.values()) { + if (material.canRenderInLayer(layer)) + material.render(layer, viewProjection, camX, camY, camZ, callback); + } + } +} 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 new file mode 100644 index 000000000..48ade4b2a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/MaterialType.java @@ -0,0 +1,3 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +public class MaterialType { } diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ModelFactory.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ModelFactory.java new file mode 100644 index 000000000..61d7e36ff --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ModelFactory.java @@ -0,0 +1,8 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import net.minecraft.client.renderer.BufferBuilder; + +@FunctionalInterface +public interface ModelFactory> { + B makeModel(InstancedTileRenderer renderer, BufferBuilder buf); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/RenderMaterial.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/RenderMaterial.java new file mode 100644 index 000000000..bfdd3fd4e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/RenderMaterial.java @@ -0,0 +1,152 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import static com.simibubi.create.foundation.render.Compartment.PARTIAL; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; + +import org.apache.commons.lang3.tuple.Pair; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; +import com.simibubi.create.foundation.render.Compartment; +import com.simibubi.create.foundation.render.SuperByteBufferCache; +import com.simibubi.create.foundation.render.backend.Backend; +import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; +import com.simibubi.create.foundation.render.backend.gl.BasicProgram; +import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec; +import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.util.Direction; + +public class RenderMaterial

> { + + protected final InstancedTileRenderer renderer; + protected final Map, Cache> models; + protected final ModelFactory factory; + protected final ProgramSpec

programSpec; + protected final Predicate layerPredicate; + + /** + * Creates a material that renders in the default layer (CUTOUT_MIPPED) + */ + public RenderMaterial(InstancedTileRenderer renderer, ProgramSpec

programSpec, ModelFactory factory) { + this(renderer, programSpec, factory, type -> type == RenderType.getCutoutMipped()); + } + + public RenderMaterial(InstancedTileRenderer renderer, ProgramSpec

programSpec, ModelFactory factory, Predicate layerPredicate) { + this.renderer = renderer; + this.models = new HashMap<>(); + this.factory = factory; + this.programSpec = programSpec; + this.layerPredicate = layerPredicate; + registerCompartment(Compartment.PARTIAL); + registerCompartment(Compartment.DIRECTIONAL_PARTIAL); + registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + } + + public boolean canRenderInLayer(RenderType layer) { + return layerPredicate.test(layer); + } + + public void render(RenderType layer, Matrix4f projection, double camX, double camY, double camZ) { + render(layer, projection, camX, camY, camZ, null); + } + + public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, ShaderCallback

setup) { + P program = Backend.getProgram(programSpec); + program.bind(viewProjection, camX, camY, camZ, FastRenderDispatcher.getDebugMode()); + + if (setup != null) setup.call(program); + + makeRenderCalls(); + teardown(); + } + + public void teardown() {} + + public void delete() { + runOnAll(InstancedModel::delete); + models.values().forEach(Cache::invalidateAll); + } + + protected void makeRenderCalls() { + for (Cache cache : models.values()) { + for (MODEL model : cache.asMap().values()) { + if (!model.isEmpty()) { + model.render(); + } + } + } + } + + public void runOnAll(Consumer f) { + for (Cache cache : models.values()) { + for (MODEL model : cache.asMap().values()) { + f.accept(model); + } + } + } + + public void registerCompartment(Compartment instance) { + models.put(instance, CacheBuilder.newBuilder().build()); + } + + public MODEL getModel(AllBlockPartials partial, BlockState referenceState) { + return get(PARTIAL, partial, () -> buildModel(partial.get(), referenceState)); + } + + public MODEL getModel(AllBlockPartials partial, BlockState referenceState, Direction dir) { + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> buildModel(partial.get(), referenceState)); + } + + public MODEL getModel(AllBlockPartials partial, BlockState referenceState, Direction dir, Supplier modelTransform) { + return get(Compartment.DIRECTIONAL_PARTIAL, Pair.of(dir, partial), + () -> buildModel(partial.get(), referenceState, modelTransform.get())); + } + + public MODEL getModel(Compartment compartment, BlockState toRender) { + return get(compartment, toRender, () -> buildModel(toRender)); + } + + public MODEL get(Compartment compartment, T key, Supplier supplier) { + Cache compartmentCache = models.get(compartment); + try { + return compartmentCache.get(key, supplier::get); + } catch (ExecutionException e) { + e.printStackTrace(); + return null; + } + } + + private MODEL buildModel(BlockState renderedState) { + BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); + return buildModel(dispatcher.getModelForState(renderedState), renderedState); + } + + private MODEL buildModel(IBakedModel model, BlockState renderedState) { + return buildModel(model, renderedState, new MatrixStack()); + } + + private MODEL buildModel(IBakedModel model, BlockState referenceState, MatrixStack ms) { + BufferBuilder builder = SuperByteBufferCache.getBufferBuilder(model, referenceState, ms); + + return factory.makeModel(renderer, builder); + } + +} 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 new file mode 100644 index 000000000..ed4b1f162 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java @@ -0,0 +1,56 @@ +package com.simibubi.create.foundation.render.backend.instancing; + +import net.minecraft.block.BlockState; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public abstract class TileEntityInstance { + + protected final InstancedTileRenderer modelManager; + protected final T tile; + protected final World world; + protected final BlockPos pos; + protected BlockState lastState; + + 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(); + } + } + + /** + * Acquire all {@link InstanceKey}s and initialize any data you may need to calculate the instance properties. + */ + 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 abstract void onUpdate(); + + /** + * Called when a light update occurs in the world. If your model needs it, update light here. + */ + public void updateLight() { } + + /** + * Call {@link InstanceKey#delete()} on all acquired keys. + */ + public abstract void remove(); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/CoordinateConsumer.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/CoordinateConsumer.java new file mode 100644 index 000000000..4011c19e0 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/CoordinateConsumer.java @@ -0,0 +1,6 @@ +package com.simibubi.create.foundation.render.backend.light; + +@FunctionalInterface +public interface CoordinateConsumer { + void consume(int x, int y, int z); +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/EmptyLighter.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/EmptyLighter.java new file mode 100644 index 000000000..b58653899 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/EmptyLighter.java @@ -0,0 +1,16 @@ +package com.simibubi.create.foundation.render.backend.light; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; + +// so other contraptions don't crash before they have a lighter +public class EmptyLighter extends ContraptionLighter { + public EmptyLighter(Contraption contraption) { + super(contraption); + } + + @Override + public GridAlignedBB getContraptionBounds() { + return new GridAlignedBB(0, 0, 0, 1, 1, 1); + } +} 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 new file mode 100644 index 000000000..707efc0bd --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java @@ -0,0 +1,282 @@ +package com.simibubi.create.foundation.render.backend.light; + +import static com.simibubi.create.foundation.render.RenderMath.isPowerOf2; + +import com.simibubi.create.foundation.render.RenderMath; + +import net.minecraft.util.Direction; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.SectionPos; +import net.minecraft.util.math.Vec3i; + +public class GridAlignedBB { + public int minX; + public int minY; + public int minZ; + public int maxX; + public int maxY; + public int maxZ; + + public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { + this.minX = minX; + this.minY = minY; + this.minZ = minZ; + this.maxX = maxX; + this.maxY = maxY; + this.maxZ = maxZ; + } + + public static GridAlignedBB ofRadius(int radius) { + return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1); + } + + public static GridAlignedBB copy(GridAlignedBB bb) { + return new GridAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); + } + + public static GridAlignedBB fromAABB(AxisAlignedBB aabb) { + int minX = (int) Math.floor(aabb.minX); + int minY = (int) Math.floor(aabb.minY); + int minZ = (int) Math.floor(aabb.minZ); + int maxX = (int) Math.ceil(aabb.maxX); + int maxY = (int) Math.ceil(aabb.maxY); + int maxZ = (int) Math.ceil(aabb.maxZ); + return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + + public static GridAlignedBB fromSection(SectionPos pos) { + return new GridAlignedBB(pos.getWorldStartX(), + pos.getWorldStartY(), + pos.getWorldStartZ(), + pos.getWorldEndX() + 1, + pos.getWorldEndY() + 1, + pos.getWorldEndZ() + 1); + } + + public static AxisAlignedBB toAABB(GridAlignedBB bb) { + return new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); + } + + public GridAlignedBB copy() { + return copy(this); + } + + public boolean sameAs(GridAlignedBB other) { + return minX == other.minX && + minY == other.minY && + minZ == other.minZ && + maxX == other.maxX && + maxY == other.maxY && + maxZ == other.maxZ; + } + + public int sizeX() { + return maxX - minX; + } + + public int sizeY() { + return maxY - minY; + } + + public int sizeZ() { + return maxZ - minZ; + } + + public int volume() { + return sizeX() * sizeY() * sizeZ(); + } + + public boolean empty() { + // if any dimension has side length 0 this box contains no volume + return minX == maxX || + minY == maxY || + minZ == maxZ; + } + + public void translate(Vec3i by) { + translate(by.getX(), by.getY(), by.getZ()); + } + + public void translate(int x, int y, int z) { + minX += x; + maxX += x; + minY += y; + maxY += y; + minZ += z; + maxZ += z; + } + + public void mirrorAbout(Direction.Axis axis) { + Vec3i axisVec = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis).getDirectionVec(); + int flipX = axisVec.getX() - 1; + int flipY = axisVec.getY() - 1; + int flipZ = axisVec.getZ() - 1; + + int maxX = this.maxX * flipX; + int maxY = this.maxY * flipY; + int maxZ = this.maxZ * flipZ; + this.maxX = this.minX * flipX; + this.maxY = this.minY * flipY; + this.maxZ = this.minZ * flipZ; + this.minX = maxX; + this.minY = maxY; + this.minZ = maxZ; + } + + /** + * Grow this bounding box to have power of 2 side length, scaling from the center. + */ + public void nextPowerOf2Centered() { + int sizeX = sizeX(); + int sizeY = sizeY(); + int sizeZ = sizeZ(); + + int newSizeX = RenderMath.nextPowerOf2(sizeX); + int newSizeY = RenderMath.nextPowerOf2(sizeY); + int newSizeZ = RenderMath.nextPowerOf2(sizeZ); + + int diffX = newSizeX - sizeX; + int diffY = newSizeY - sizeY; + int diffZ = newSizeZ - sizeZ; + + minX -= diffX / 2; // floor division for the minimums + minY -= diffY / 2; + minZ -= diffZ / 2; + maxX += (diffX + 1) / 2; // ceiling divison for the maximums + maxY += (diffY + 1) / 2; + maxZ += (diffZ + 1) / 2; + } + + /** + * Grow this bounding box to have power of 2 side lengths, scaling from the minimum coords. + */ + public void nextPowerOf2() { + int sizeX = RenderMath.nextPowerOf2(sizeX()); + int sizeY = RenderMath.nextPowerOf2(sizeY()); + int sizeZ = RenderMath.nextPowerOf2(sizeZ()); + + this.maxX = this.minX + sizeX; + this.maxY = this.minY + sizeY; + this.maxZ = this.minZ + sizeZ; + } + + public boolean hasPowerOf2Sides() { + // this is only true if all individual side lengths are powers of 2 + return isPowerOf2(volume()); + } + + public void grow(int s) { + this.grow(s, s, s); + } + + public void grow(int x, int y, int z) { + minX -= x; + minY -= y; + minZ -= z; + maxX += x; + maxY += y; + maxZ += z; + } + + public GridAlignedBB intersect(GridAlignedBB other) { + int minX = Math.max(this.minX, other.minX); + int minY = Math.max(this.minY, other.minY); + int minZ = Math.max(this.minZ, other.minZ); + int maxX = Math.min(this.maxX, other.maxX); + int maxY = Math.min(this.maxY, other.maxY); + int maxZ = Math.min(this.maxZ, other.maxZ); + return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + + public void intersectAssign(GridAlignedBB other) { + this.minX = Math.max(this.minX, other.minX); + this.minY = Math.max(this.minY, other.minY); + this.minZ = Math.max(this.minZ, other.minZ); + this.maxX = Math.min(this.maxX, other.maxX); + this.maxY = Math.min(this.maxY, other.maxY); + this.maxZ = Math.min(this.maxZ, other.maxZ); + } + + public GridAlignedBB union(GridAlignedBB other) { + int minX = Math.min(this.minX, other.minX); + int minY = Math.min(this.minY, other.minY); + int minZ = Math.min(this.minZ, other.minZ); + int maxX = Math.max(this.maxX, other.maxX); + int maxY = Math.max(this.maxY, other.maxY); + int maxZ = Math.max(this.maxZ, other.maxZ); + return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + + public void unionAssign(GridAlignedBB other) { + this.minX = Math.min(this.minX, other.minX); + this.minY = Math.min(this.minY, other.minY); + this.minZ = Math.min(this.minZ, other.minZ); + this.maxX = Math.max(this.maxX, other.maxX); + this.maxY = Math.max(this.maxY, other.maxY); + this.maxZ = Math.max(this.maxZ, other.maxZ); + } + + public void unionAssign(AxisAlignedBB other) { + this.minX = Math.min(this.minX, (int) Math.floor(other.minX)); + this.minY = Math.min(this.minY, (int) Math.floor(other.minY)); + this.minZ = Math.min(this.minZ, (int) Math.floor(other.minZ)); + this.maxX = Math.max(this.maxX, (int) Math.ceil(other.maxX)); + this.maxY = Math.max(this.maxY, (int) Math.ceil(other.maxY)); + this.maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ)); + } + + public boolean intersects(GridAlignedBB other) { + return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ); + } + + public boolean contains(GridAlignedBB other) { + return other.minX >= this.minX && + other.maxX <= this.maxX && + other.minY >= this.minY && + other.maxY <= this.maxY && + other.minZ >= this.minZ && + other.maxZ <= this.maxZ; + } + + public boolean isContainedBy(GridAlignedBB other) { + return other.contains(this); + } + + public boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) { + return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ; + } + + public void forEachContained(CoordinateConsumer func) { + if (empty()) return; + + for (int x = minX; x < maxX; x++) { + for (int y = Math.max(minY, 0); y < Math.min(maxY, 255); y++) { // clamp to world height limits + for (int z = minZ; z < maxZ; z++) { + func.consume(x, y, z); + } + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + GridAlignedBB that = (GridAlignedBB) o; + + return this.sameAs(that); + } + + @Override + public int hashCode() { + int result = minX; + result = 31 * result + minY; + result = 31 * result + minZ; + result = 31 * result + maxX; + result = 31 * result + maxY; + result = 31 * result + maxZ; + return result; + } + +} 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 new file mode 100644 index 000000000..5fd2ff8bd --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/ILightListener.java @@ -0,0 +1,5 @@ +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/LightVolume.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java new file mode 100644 index 000000000..143964ba5 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java @@ -0,0 +1,292 @@ +package com.simibubi.create.foundation.render.backend.light; + +import java.nio.ByteBuffer; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; +import org.lwjgl.opengl.GL13; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL40; +import org.lwjgl.system.MemoryUtil; + +import com.simibubi.create.foundation.render.backend.RenderWork; +import com.simibubi.create.foundation.render.backend.gl.GlTexture; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.SectionPos; +import net.minecraft.world.ILightReader; +import net.minecraft.world.LightType; + +public class LightVolume { + + private GridAlignedBB sampleVolume; + private GridAlignedBB textureVolume; + private ByteBuffer lightData; + + private boolean bufferDirty; + private boolean removed; + + private final GlTexture glTexture; + + public LightVolume(GridAlignedBB sampleVolume) { + setSampleVolume(sampleVolume); + + this.glTexture = new GlTexture(GL20.GL_TEXTURE_3D); + this.lightData = MemoryUtil.memAlloc(this.textureVolume.volume() * 2); // TODO: reduce this to span only sampleVolume + + // allocate space for the texture + GL20.glActiveTexture(GL20.GL_TEXTURE4); + glTexture.bind(); + + int sizeX = textureVolume.sizeX(); + int sizeY = textureVolume.sizeY(); + int sizeZ = textureVolume.sizeZ(); + GL12.glTexImage3D(GL12.GL_TEXTURE_3D, 0, GL40.GL_RG8, sizeX, sizeY, sizeZ, 0, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, 0); + + glTexture.unbind(); + GL20.glActiveTexture(GL20.GL_TEXTURE0); + } + + private void setSampleVolume(GridAlignedBB sampleVolume) { + this.sampleVolume = sampleVolume; + this.textureVolume = sampleVolume.copy(); + this.textureVolume.nextPowerOf2Centered(); + } + + public GridAlignedBB getTextureVolume() { + return GridAlignedBB.copy(textureVolume); + } + + public GridAlignedBB getSampleVolume() { + return GridAlignedBB.copy(sampleVolume); + } + + public int getMinX() { + return textureVolume.minX; + } + + public int getMinY() { + return textureVolume.minY; + } + + public int getMinZ() { + return textureVolume.minZ; + } + + public int getMaxX() { + return textureVolume.maxX; + } + + public int getMaxY() { + return textureVolume.maxY; + } + + public int getMaxZ() { + return textureVolume.maxZ; + } + + public int getSizeX() { + return textureVolume.sizeX(); + } + + public int getSizeY() { + return textureVolume.sizeY(); + } + + public int getSizeZ() { + return textureVolume.sizeZ(); + } + + public void move(ILightReader world, GridAlignedBB newSampleVolume) { + if (textureVolume.contains(newSampleVolume)) { + if (newSampleVolume.intersects(sampleVolume)) { + GridAlignedBB newArea = newSampleVolume.intersect(sampleVolume); + sampleVolume = newSampleVolume; + + copyLight(world, newArea); + } else { + sampleVolume = newSampleVolume; + initialize(world); + } + } else { + setSampleVolume(newSampleVolume); + int volume = textureVolume.volume(); + if (volume * 2 > lightData.capacity()) { + lightData = MemoryUtil.memRealloc(lightData, volume * 2); + } + initialize(world); + } + } + + public void notifyLightUpdate(ILightReader world, LightType type, SectionPos location) { + GridAlignedBB changedVolume = GridAlignedBB.fromSection(location); + if (!changedVolume.intersects(sampleVolume)) + return; + changedVolume.intersectAssign(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); + } + + /** + * Completely (re)populate this volume with block and sky lighting data. + * This is expensive and should be avoided. + */ + public void initialize(ILightReader world) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + + int shiftX = textureVolume.minX; + int shiftY = textureVolume.minY; + int shiftZ = textureVolume.minZ; + + sampleVolume.forEachContained((x, y, z) -> { + pos.setPos(x, y, z); + + int blockLight = world.getLightLevel(LightType.BLOCK, pos); + int skyLight = world.getLightLevel(LightType.SKY, pos); + + writeLight(x - shiftX, y - shiftY, z - shiftZ, blockLight, skyLight); + }); + + bufferDirty = true; + } + + /** + * Copy block light from the world into this volume. + * @param worldVolume the region in the world to copy data from. + */ + public void copyBlock(ILightReader world, GridAlignedBB worldVolume) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + + int xShift = textureVolume.minX; + int yShift = textureVolume.minY; + int zShift = textureVolume.minZ; + + worldVolume.forEachContained((x, y, z) -> { + pos.setPos(x, y, z); + + int light = world.getLightLevel(LightType.BLOCK, pos); + + writeBlock(x - xShift, y - yShift, z - zShift, light); + }); + + bufferDirty = true; + } + + /** + * Copy sky light from the world into this volume. + * @param worldVolume the region in the world to copy data from. + */ + public void copySky(ILightReader world, GridAlignedBB worldVolume) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + + int xShift = textureVolume.minX; + int yShift = textureVolume.minY; + int zShift = textureVolume.minZ; + + worldVolume.forEachContained((x, y, z) -> { + pos.setPos(x, y, z); + + int light = world.getLightLevel(LightType.SKY, pos); + + writeSky(x - xShift, y - yShift, z - zShift, light); + }); + + bufferDirty = true; + } + + /** + * Copy all light from the world into this volume. + * @param worldVolume the region in the world to copy data from. + */ + public void copyLight(ILightReader world, GridAlignedBB worldVolume) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + + int xShift = textureVolume.minX; + int yShift = textureVolume.minY; + int zShift = textureVolume.minZ; + + worldVolume.forEachContained((x, y, z) -> { + pos.setPos(x, y, z); + + int block = world.getLightLevel(LightType.BLOCK, pos); + int sky = world.getLightLevel(LightType.SKY, pos); + + writeLight(x - xShift, y - yShift, z - zShift, block, sky); + }); + + bufferDirty = true; + } + + public void bind() { + // just in case something goes wrong or we accidentally call this before this volume is properly disposed of. + if (lightData == null || removed) return; + + GL13.glActiveTexture(GL40.GL_TEXTURE4); + glTexture.bind(); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_LINEAR); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_LINEAR); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_S, GL20.GL_MIRRORED_REPEAT); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_R, GL20.GL_MIRRORED_REPEAT); + GL11.glTexParameteri(GL13.GL_TEXTURE_3D, GL13.GL_TEXTURE_WRAP_T, GL20.GL_MIRRORED_REPEAT); + + uploadTexture(); + } + + private void uploadTexture() { + if (bufferDirty) { + GL20.glPixelStorei(GL20.GL_UNPACK_ROW_LENGTH, 0); + GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_PIXELS, 0); + GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_ROWS, 0); + GL20.glPixelStorei(GL20.GL_UNPACK_SKIP_IMAGES, 0); + GL20.glPixelStorei(GL20.GL_UNPACK_IMAGE_HEIGHT, 0); + GL20.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 2); + int sizeX = textureVolume.sizeX(); + int sizeY = textureVolume.sizeY(); + int sizeZ = textureVolume.sizeZ(); + + GL12.glTexSubImage3D(GL12.GL_TEXTURE_3D, 0, 0, 0, 0, sizeX, sizeY, sizeZ, GL40.GL_RG, GL40.GL_UNSIGNED_BYTE, lightData); + + GL20.glPixelStorei(GL20.GL_UNPACK_ALIGNMENT, 4); // 4 is the default + bufferDirty = false; + } + } + + public void unbind() { + glTexture.unbind(); + } + + public void delete() { + removed = true; + RenderWork.enqueue(() -> { + glTexture.delete(); + MemoryUtil.memFree(lightData); + lightData = null; + }); + } + + private void writeLight(int x, int y, int z, int block, int sky) { + byte b = (byte) ((block & 0xF) << 4); + byte s = (byte) ((sky & 0xF) << 4); + + int i = index(x, y, z); + lightData.put(i, b); + lightData.put(i + 1, s); + } + + private void writeBlock(int x, int y, int z, int block) { + byte b = (byte) ((block & 0xF) << 4); + + lightData.put(index(x, y, z), b); + } + + private void writeSky(int x, int y, int z, int sky) { + byte b = (byte) ((sky & 0xF) << 4); + + lightData.put(index(x, y, z) + 1, b); + } + + private int index(int x, int y, int z) { + return (x + textureVolume.sizeX() * (y + z * textureVolume.sizeY())) * 2; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java new file mode 100644 index 000000000..811987c5d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java @@ -0,0 +1,34 @@ +package com.simibubi.create.foundation.render.backend.light; + +import java.util.ArrayList; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; +import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.outliner.AABBOutline; + +public class LightVolumeDebugger { + public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { + ContraptionRenderDispatcher.renderers.values() + .stream() + .flatMap(r -> { + GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume(); + GridAlignedBB sample = r.getLighter().lightVolume.getSampleVolume(); + + ArrayList> pairs = new ArrayList<>(2); + + pairs.add(Pair.of(texture, 0xFFFFFF)); + pairs.add(Pair.of(sample, 0xFFFF00)); + + return pairs.stream(); + }) + .map(pair -> { + AABBOutline outline = new AABBOutline(GridAlignedBB.toAABB(pair.getFirst())); + + outline.getParams().colored(pair.getSecond()); + return outline; + }) + .forEach(outline -> outline.render(ms, buffer)); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java index 6246d20ea..f735c21af 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkBehaviour.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation.tileEntity.behaviour.linked; import java.util.function.Function; import java.util.function.IntConsumer; import java.util.function.IntSupplier; + import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.Create; 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 b8bc4b733..23df51f8f 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 @@ -1,7 +1,7 @@ package com.simibubi.create.foundation.tileEntity.renderer; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.utility.SuperByteBuffer; +import com.simibubi.create.foundation.render.SuperByteBuffer; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java b/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java index 01f01de38..4b8f410c5 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AnimationTickHolder.java @@ -4,14 +4,28 @@ import net.minecraft.client.Minecraft; public class AnimationTickHolder { - public static int ticks; + private static int ticks; + + public static void reset() { + ticks = 0; + } public static void tick() { - ticks++; + if (!Minecraft.getInstance().isGamePaused()) { + ticks = (ticks + 1) % 1_728_000; // wrap around every 24 hours so we maintain enough floating point precision + } } public static float getRenderTick() { - return ticks + Minecraft.getInstance().getRenderPartialTicks(); + return getTicks() + getPartialTicks(); } + public static float getPartialTicks() { + Minecraft mc = Minecraft.getInstance(); + return (mc.isGamePaused() ? mc.renderPartialTicksPaused : mc.getRenderPartialTicks()); + } + + public static int getTicks() { + return ticks; + } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java index 693231353..1be8add22 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Iterate.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Iterate.java @@ -1,13 +1,13 @@ package com.simibubi.create.foundation.utility; -import net.minecraft.util.Direction; -import net.minecraft.util.Direction.Axis; -import net.minecraft.util.math.BlockPos; - import java.util.Arrays; import java.util.EnumSet; import java.util.List; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.math.BlockPos; + public class Iterate { public static final boolean[] trueAndFalse = {true, false}; diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java index 1524913fb..4cbf86483 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java @@ -59,7 +59,7 @@ public final class NBTProcessors { TileEntityType type = tileEntity.getType(); if (survival && survivalProcessors.containsKey(type)) compound = survivalProcessors.get(type).apply(compound); - if (processors.containsKey(type)) + if (compound != null && processors.containsKey(type)) return processors.get(type).apply(compound); if (tileEntity.onlyOpsCanSetNbt()) return null; 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 300f02316..7610ea984 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -4,6 +4,12 @@ import java.util.Random; import javax.annotation.Nullable; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.Quaternion; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.nbt.DoubleNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.util.Direction; @@ -150,4 +156,52 @@ public class VecHelper { return origin.add(lineDirection.scale(t)); } + //https://forums.minecraftforge.net/topic/88562-116solved-3d-to-2d-conversion/?do=findComment&comment=413573 slightly modified + public static Vec3d projectToPlayerView(Vec3d target, float partialTicks) { + /* The (centered) location on the screen of the given 3d point in the world. + * Result is (dist right of center screen, dist up from center screen, if < 0, then in front of view plane) */ + ActiveRenderInfo ari = Minecraft.getInstance().gameRenderer.getActiveRenderInfo(); + Vec3d camera_pos = ari.getProjectedView(); + Quaternion camera_rotation_conj = ari.getRotation().copy(); + camera_rotation_conj.conjugate(); + + Vector3f result3f = new Vector3f((float) (camera_pos.x - target.x), + (float) (camera_pos.y - target.y), + (float) (camera_pos.z - target.z)); + result3f.func_214905_a(camera_rotation_conj); + + // ----- compensate for view bobbing (if active) ----- + // the following code adapted from GameRenderer::applyBobbing (to invert it) + Minecraft mc = Minecraft.getInstance(); + if (mc.gameSettings.viewBobbing) { + Entity renderViewEntity = mc.getRenderViewEntity(); + if (renderViewEntity instanceof PlayerEntity) { + PlayerEntity playerentity = (PlayerEntity) renderViewEntity; + float distwalked_modified = playerentity.distanceWalkedModified; + + float f = distwalked_modified - playerentity.prevDistanceWalkedModified; + float f1 = -(distwalked_modified + f * partialTicks); + float f2 = MathHelper.lerp(partialTicks, playerentity.prevCameraYaw, playerentity.cameraYaw); + Quaternion q2 = new Quaternion(Vector3f.POSITIVE_X, Math.abs(MathHelper.cos(f1 * (float) Math.PI - 0.2F) * f2) * 5.0F, true); + q2.conjugate(); + result3f.func_214905_a(q2); + + Quaternion q1 = new Quaternion(Vector3f.POSITIVE_Z, MathHelper.sin(f1 * (float) Math.PI) * f2 * 3.0F, true); + q1.conjugate(); + result3f.func_214905_a(q1); + + Vector3f bob_translation = new Vector3f((MathHelper.sin(f1 * (float) Math.PI) * f2 * 0.5F), (-Math.abs(MathHelper.cos(f1 * (float) Math.PI) * f2)), 0.0f); + bob_translation.setY(-bob_translation.getY()); // this is weird but hey, if it works + result3f.add(bob_translation); + } + } + + // ----- adjust for fov ----- + float fov = (float) mc.gameRenderer.getFOVModifier(ari, partialTicks, true); + + float half_height = (float) mc.getWindow().getScaledHeight() / 2; + float scale_factor = half_height / (result3f.getZ() * (float) Math.tan(Math.toRadians(fov / 2))); + return new Vec3d(-result3f.getX() * scale_factor, result3f.getY() * scale_factor, result3f.getZ()); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java new file mode 100644 index 000000000..b83e7f13d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockParams.java @@ -0,0 +1,50 @@ +package com.simibubi.create.foundation.utility.ghost; + +import java.util.function.Supplier; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.util.math.BlockPos; + +public class GhostBlockParams { + + protected final BlockState state; + protected BlockPos pos; + protected Supplier alphaSupplier; + + private GhostBlockParams(BlockState state) { + this.state = state; + this.pos = BlockPos.ZERO; + this.alphaSupplier = () -> 1f; + } + + public static GhostBlockParams of(BlockState state) { + return new GhostBlockParams(state); + } + + public static GhostBlockParams of(Block block) { + return of(block.getDefaultState()); + } + + public GhostBlockParams at(BlockPos pos) { + this.pos = pos; + return this; + } + + public GhostBlockParams at(int x, int y, int z) { + return this.at(new BlockPos(x, y, z)); + } + + public GhostBlockParams alpha(Supplier alphaSupplier) { + this.alphaSupplier = alphaSupplier; + return this; + } + + public GhostBlockParams alpha(float alpha) { + return this.alpha(() -> alpha); + } + + public GhostBlockParams breathingAlpha() { + return this.alpha(() -> (float) GhostBlocks.getBreathingAlpha()); + } +} 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 new file mode 100644 index 000000000..361f524bb --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java @@ -0,0 +1,179 @@ +package com.simibubi.create.foundation.utility.ghost; + +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.IntBuffer; +import java.util.List; +import java.util.Random; + +import javax.annotation.Nullable; + +import org.lwjgl.system.MemoryStack; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.VirtualEmptyModelData; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.Matrix4f; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.RenderTypeLookup; +import net.minecraft.client.renderer.Vector3f; +import net.minecraft.client.renderer.Vector4f; +import net.minecraft.client.renderer.model.BakedQuad; +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.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3i; + +public abstract class GhostBlockRenderer { + + private static final GhostBlockRenderer transparent = new TransparentGhostBlockRenderer(); + public static GhostBlockRenderer transparent() { + return transparent; + } + + private static final GhostBlockRenderer standard = new DefaultGhostBlockRenderer(); + public static GhostBlockRenderer standard() { + return standard; + } + + + public abstract void render(MatrixStack ms, SuperRenderTypeBuffer buffer, GhostBlockParams params); + + private static class DefaultGhostBlockRenderer extends GhostBlockRenderer { + + public void render(MatrixStack ms, SuperRenderTypeBuffer buffer, GhostBlockParams params) { + ms.push(); + + BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); + + IBakedModel model = dispatcher.getModelForState(params.state); + + RenderType layer = RenderTypeLookup.getEntityBlockLayer(params.state); + IVertexBuilder vb = buffer.getEarlyBuffer(layer); + + BlockPos pos = params.pos; + ms.translate(pos.getX(), pos.getY(), pos.getZ()); + + dispatcher.getBlockModelRenderer().renderModel(ms.peek(), vb, params.state, model, 1f, 1f, 1f, 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); + + ms.pop(); + } + + } + + private static class TransparentGhostBlockRenderer extends GhostBlockRenderer { + + public void render(MatrixStack ms, SuperRenderTypeBuffer buffer, GhostBlockParams params) { + + //prepare + ms.push(); + + //RenderSystem.pushMatrix(); + + BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); + + IBakedModel model = dispatcher.getModelForState(params.state); + + //RenderType layer = RenderTypeLookup.getEntityBlockLayer(params.state); + RenderType layer = RenderType.getTranslucent(); + IVertexBuilder vb = buffer.getEarlyBuffer(layer); + + BlockPos pos = params.pos; + ms.translate(pos.getX(), pos.getY(), pos.getZ()); + + //dispatcher.getBlockModelRenderer().renderModel(ms.peek(), vb, params.state, model, 1f, 1f, 1f, 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); + renderModel(params, ms.peek(), vb, params.state, model, 1f, 1f, 1f, 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); + + //buffer.draw(); + //clean + //RenderSystem.popMatrix(); + ms.pop(); + + } + + //BlockModelRenderer + public void renderModel(GhostBlockParams params, MatrixStack.Entry entry, IVertexBuilder vb, @Nullable BlockState state, IBakedModel model, float p_228804_5_, float p_228804_6_, float p_228804_7_, int p_228804_8_, int p_228804_9_, net.minecraftforge.client.model.data.IModelData modelData) { + Random random = new Random(); + + for (Direction direction : Direction.values()) { + random.setSeed(42L); + renderQuad(params, entry, vb, p_228804_5_, p_228804_6_, p_228804_7_, model.getQuads(state, direction, random, modelData), p_228804_8_, p_228804_9_); + } + + random.setSeed(42L); + renderQuad(params, entry, vb, p_228804_5_, p_228804_6_, p_228804_7_, model.getQuads(state, (Direction) null, random, modelData), p_228804_8_, p_228804_9_); + } + + //BlockModelRenderer + private static void renderQuad(GhostBlockParams params, MatrixStack.Entry p_228803_0_, IVertexBuilder p_228803_1_, float p_228803_2_, float p_228803_3_, float p_228803_4_, List p_228803_5_, int p_228803_6_, int p_228803_7_) { + Float alpha = params.alphaSupplier.get(); + + for (BakedQuad bakedquad : p_228803_5_) { + float f; + float f1; + float f2; + if (bakedquad.hasTintIndex()) { + f = MathHelper.clamp(p_228803_2_, 0.0F, 1.0F); + f1 = MathHelper.clamp(p_228803_3_, 0.0F, 1.0F); + f2 = MathHelper.clamp(p_228803_4_, 0.0F, 1.0F); + } else { + f = 1.0F; + f1 = 1.0F; + f2 = 1.0F; + } + + quad(alpha, p_228803_1_, p_228803_0_, bakedquad, new float[]{1f, 1f, 1f, 1f}, f, f1, f2, new int[]{p_228803_6_, p_228803_6_, p_228803_6_, p_228803_6_}, p_228803_7_); + } + + } + + //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(); + Vec3i vec3i = p_227890_2_.getFace().getDirectionVec(); + Vector3f vector3f = new Vector3f((float) vec3i.getX(), (float) vec3i.getY(), (float) vec3i.getZ()); + Matrix4f matrix4f = p_227890_1_.getModel(); + vector3f.transform(p_227890_1_.getNormal()); + int j = aint.length / 8; + + try (MemoryStack memorystack = MemoryStack.stackPush()) { + ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormats.BLOCK.getSize()); + IntBuffer intbuffer = bytebuffer.asIntBuffer(); + + for (int k = 0; k < j; ++k) { + ((Buffer) intbuffer).clear(); + intbuffer.put(aint, k * 8, 8); + float f = bytebuffer.getFloat(0); + float f1 = bytebuffer.getFloat(4); + float f2 = bytebuffer.getFloat(8); + float r; + float g; + float b; + + r = p_227890_3_[k] * p_227890_4_; + g = p_227890_3_[k] * p_227890_5_; + b = p_227890_3_[k] * p_227890_6_; + + + int l = vb.applyBakedLighting(p_227890_7_[k], bytebuffer); + float f9 = bytebuffer.getFloat(16); + float f10 = bytebuffer.getFloat(20); + Vector4f vector4f = new Vector4f(f, f1, f2, 1.0F); + vector4f.transform(matrix4f); + vb.applyBakedNormals(vector3f, bytebuffer, p_227890_1_.getNormal()); + vb.vertex(vector4f.getX(), vector4f.getY(), vector4f.getZ(), r, g, b, alpha, f9, f10, p_227890_8_, l, vector3f.getX(), vector3f.getY(), vector3f.getZ()); + } + } + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java new file mode 100644 index 000000000..2c6cc6f4b --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlocks.java @@ -0,0 +1,84 @@ +package com.simibubi.create.foundation.utility.ghost; + +import java.util.HashMap; +import java.util.Map; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; + +import net.minecraft.block.BlockState; +import net.minecraft.util.math.MathHelper; + +public class GhostBlocks { + + public static double getBreathingAlpha() { + double period = 2500; + double timer = System.currentTimeMillis() % period; + double offset = MathHelper.cos((float) ((2d/period) * Math.PI * timer)); + return 0.75d - 0.2d * offset; + } + + final Map ghosts; + + public GhostBlockParams showGhostState(Object slot, BlockState state) { + return showGhostState(slot, state, 1); + } + + public GhostBlockParams showGhostState(Object slot, BlockState state, int ttl) { + Entry e = refresh(slot, GhostBlockRenderer.transparent(), GhostBlockParams.of(state), ttl); + return e.params; + } + + public GhostBlockParams showGhost(Object slot, GhostBlockRenderer ghost, GhostBlockParams params, int ttl) { + Entry e = refresh(slot, ghost, params, ttl); + return e.params; + } + + private Entry refresh(Object slot, GhostBlockRenderer ghost, GhostBlockParams params, int ttl) { + if (!ghosts.containsKey(slot)) + ghosts.put(slot, new Entry(ghost, params, ttl)); + + Entry e = ghosts.get(slot); + e.ticksToLive = ttl; + e.params = params; + e.ghost = ghost; + return e; + } + + public GhostBlocks() { + ghosts = new HashMap<>(); + } + + public void tickGhosts() { + ghosts.forEach((slot, entry) -> entry.ticksToLive--); + ghosts.entrySet().removeIf(e -> !e.getValue().isAlive()); + } + + public void renderAll(MatrixStack ms, SuperRenderTypeBuffer buffer) { + ghosts.forEach((slot, entry) -> { + GhostBlockRenderer ghost = entry.ghost; + ghost.render(ms, buffer, entry.params); + }); + } + + static class Entry { + + private GhostBlockRenderer ghost; + private GhostBlockParams params; + private int ticksToLive; + + public Entry(GhostBlockRenderer ghost, GhostBlockParams params) { + this(ghost, params, 1); + } + + public Entry(GhostBlockRenderer ghost, GhostBlockParams params, int ttl) { + this.ghost = ghost; + this.params = params; + this.ticksToLive = ttl; + } + + public boolean isAlive() { + return ticksToLive >= 0; + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java index 2fcacb96a..6621b1a0e 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/ChasingAABBOutline.java @@ -2,8 +2,8 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; -import net.minecraft.client.Minecraft; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; @@ -30,8 +30,7 @@ public class ChasingAABBOutline extends AABBOutline { @Override public void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { - renderBB(ms, buffer, interpolateBBs(prevBB, bb, Minecraft.getInstance() - .getRenderPartialTicks())); + renderBB(ms, buffer, interpolateBBs(prevBB, bb, AnimationTickHolder.getPartialTicks())); } private static AxisAlignedBB interpolateBBs(AxisAlignedBB current, AxisAlignedBB target, float pt) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java index 3f3a307ab..4a72da0da 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/LineOutline.java @@ -2,8 +2,8 @@ package com.simibubi.create.foundation.utility.outliner; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; -import net.minecraft.client.Minecraft; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -47,8 +47,7 @@ public class LineOutline extends Outline { @Override public void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { - float pt = Minecraft.getInstance() - .getRenderPartialTicks(); + float pt = AnimationTickHolder.getPartialTicks(); float distanceToTarget = 1 - MathHelper.lerp(pt, prevProgress, progress); Vec3d start = end.add(this.start.subtract(end) .scale(distanceToTarget)); diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java index 9c442b89d..3d0311265 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outliner.java @@ -1,18 +1,24 @@ package com.simibubi.create.foundation.utility.outliner; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; +import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline; import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams; -import net.minecraft.client.Minecraft; + import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -import java.util.*; - public class Outliner { final Map outlines; @@ -150,8 +156,7 @@ public class Outliner { float fadeticks = OutlineEntry.fadeTicks; float lastAlpha = prevTicks >= 0 ? 1 : 1 + (prevTicks / fadeticks); float currentAlpha = 1 + (entry.ticksTillRemoval / fadeticks); - float alpha = MathHelper.lerp(Minecraft.getInstance() - .getRenderPartialTicks(), lastAlpha, currentAlpha); + float alpha = MathHelper.lerp(AnimationTickHolder.getPartialTicks(), lastAlpha, currentAlpha); outline.params.alpha = alpha * alpha * alpha; if (outline.params.alpha < 1 / 8f) diff --git a/src/main/java/com/simibubi/create/foundation/utility/placement/IPlacementHelper.java b/src/main/java/com/simibubi/create/foundation/utility/placement/IPlacementHelper.java index 082776a7c..434d7a89f 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/placement/IPlacementHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/placement/IPlacementHelper.java @@ -1,25 +1,27 @@ package com.simibubi.create.foundation.utility.placement; -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.utility.Iterate; -import com.simibubi.create.foundation.utility.Pair; -import com.simibubi.create.foundation.utility.VecHelper; -import mcp.MethodsReturnNonnullByDefault; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Direction; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; - import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; +import com.simibubi.create.CreateClient; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Pair; +import com.simibubi.create.foundation.utility.VecHelper; + +import mcp.MethodsReturnNonnullByDefault; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.item.BlockItem; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + @MethodsReturnNonnullByDefault public interface IPlacementHelper { @@ -46,9 +48,21 @@ public interface IPlacementHelper { */ PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray); + //overrides the default ghost state of the helper with the actual state of the held block item, this is used in PlacementHelpers and can be ignored in most cases + default PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray, ItemStack heldItem) { + PlacementOffset offset = getOffset(world, state, pos, ray); + if (heldItem.getItem() instanceof BlockItem) { + BlockItem blockItem = (BlockItem) heldItem.getItem(); + offset = offset.withGhostState(blockItem.getBlock().getDefaultState()); + } + return offset; + } + //only gets called when placementOffset is successful default void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), ray.getFace()); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), ray.getFace()); + + displayGhost(offset); } static void renderArrow(Vec3d center, Vec3d target, Direction arrowPlane) { @@ -67,6 +81,15 @@ public interface IPlacementHelper { CreateClient.outliner.showLine("placementArrowB" + center + target, start.add(offset), endB.add(offset)).lineWidth(1/16f); } + default void displayGhost(PlacementOffset offset) { + if (!offset.hasGhostState()) + return; + + CreateClient.ghostBlocks.showGhostState(this, offset.getTransform().apply(offset.getGhostState())) + .at(offset.getBlockPos()) + .breathingAlpha(); + } + static List orderedByDistanceOnlyAxis(BlockPos pos, Vec3d hit, Direction.Axis axis) { return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java b/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java index 7645ef75f..92ce7983d 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java +++ b/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementHelpers.java @@ -1,22 +1,46 @@ package com.simibubi.create.foundation.utility.placement; -import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.Hand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingAngle; +import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.RenderGameOverlayEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber public class PlacementHelpers { private static final List helpers = new ArrayList<>(); + private static int animationTick = 0; + private static final InterpolatedChasingValue angle = new InterpolatedChasingAngle().withSpeed(0.25f); + private static BlockPos target = null; + private static BlockPos lastTarget = null; public static int register(IPlacementHelper helper) { helpers.add(helper); @@ -32,6 +56,23 @@ public class PlacementHelpers { @OnlyIn(Dist.CLIENT) public static void tick() { + setTarget(null); + checkHelpers(); + + if (target == null) { + if (animationTick > 0) + animationTick = Math.max(animationTick - 2, 0); + + return; + } + + if (animationTick < 10) + animationTick++; + + } + + @OnlyIn(Dist.CLIENT) + private static void checkHelpers() { Minecraft mc = Minecraft.getInstance(); ClientWorld world = mc.world; @@ -46,29 +87,212 @@ public class PlacementHelpers { if (mc.player == null) return; - List filteredForHeldItem = helpers.stream().filter(helper -> Arrays.stream(Hand.values()).anyMatch(hand -> helper.getItemPredicate().test(mc.player.getHeldItem(hand)))).collect(Collectors.toList()); - if (filteredForHeldItem.isEmpty()) - return; - if (mc.player.isSneaking())//for now, disable all helpers when sneaking TODO add helpers that respect sneaking but still show position return; - BlockPos pos = ray.getPos(); - BlockState state = world.getBlockState(pos); + for (Hand hand : Hand.values()) { - List filteredForState = filteredForHeldItem.stream().filter(helper -> helper.getStatePredicate().test(state)).collect(Collectors.toList()); + ItemStack heldItem = mc.player.getHeldItem(hand); + List filteredForHeldItem = helpers.stream().filter(helper -> helper.matchesItem(heldItem)).collect(Collectors.toList()); + if (filteredForHeldItem.isEmpty()) + continue; - if (filteredForState.isEmpty()) - return; + BlockPos pos = ray.getPos(); + BlockState state = world.getBlockState(pos); - for (IPlacementHelper h : filteredForState) { - PlacementOffset offset = h.getOffset(world, state, pos, ray); + List filteredForState = filteredForHeldItem.stream().filter(helper -> helper.matchesState(state)).collect(Collectors.toList()); + if (filteredForState.isEmpty()) + continue; + + boolean atLeastOneMatch = false; + for (IPlacementHelper h : filteredForState) { + PlacementOffset offset = h.getOffset(world, state, pos, ray, heldItem); + + if (offset.isSuccessful()) { + h.renderAt(pos, state, ray, offset); + setTarget(offset.getBlockPos()); + atLeastOneMatch = true; + break; + } - if (offset.isSuccessful()) { - h.renderAt(pos, state, ray, offset); - break; } + //at least one helper activated, no need to check the offhand if we are still in the mainhand + if (atLeastOneMatch) + return; + } } + + static void setTarget(BlockPos target) { + PlacementHelpers.target = target; + + if (target == null) + return; + + if (lastTarget == null) { + lastTarget = target; + return; + } + + if (!lastTarget.equals(target)) + lastTarget = target; + } + + @SubscribeEvent + @OnlyIn(Dist.CLIENT) + public static void onRender(RenderGameOverlayEvent.Pre event) { + if (event.getType() != RenderGameOverlayEvent.ElementType.CROSSHAIRS) + return; + + Minecraft mc = Minecraft.getInstance(); + PlayerEntity player = mc.player; + + if (player != null && animationTick > 0) { + MainWindow res = event.getWindow(); + //MatrixStack matrix = event.getMatrix(); + //String text = "( )"; + + //matrix.push(); + //matrix.translate(res.getScaledWidth() / 2F, res.getScaledHeight() / 2f - 4, 0); + float screenY = res.getScaledHeight() / 2f; + float screenX = res.getScaledWidth() / 2f; + //float y = screenY - 3.5f; + //float x = screenX; + //x -= mc.fontRenderer.getStringWidth(text)/2f - 0.25f; + + float progress = Math.min(animationTick / 10f/* + event.getPartialTicks()*/, 1f); + //int opacity = ((int) (255 * (progress * progress))) << 24; + + //mc.fontRenderer.drawString(text, x, y, 0xFFFFFF | opacity); + + drawDirectionIndicator(event.getPartialTicks(), screenX, screenY, progress); + //matrix.pop(); + } + } + + @OnlyIn(Dist.CLIENT) + private static void drawDirectionIndicator(float partialTicks, float centerX, float centerY, float progress) { + float r = .8f; + float g = .8f; + float b = .8f; + float a = progress * progress; + + Vec3d projTarget = VecHelper.projectToPlayerView(VecHelper.getCenterOf(lastTarget), partialTicks); + + Vec3d target = new Vec3d(projTarget.x, projTarget.y, 0); + if (projTarget.z > 0) { + target = target.inverse(); + } + + Vec3d norm = target.normalize(); + Vec3d ref = new Vec3d(0, 1, 0); + float targetAngle = AngleHelper.deg(Math.acos(norm.dotProduct(ref))); + + angle.withSpeed(0.25f); + + if (norm.x < 0) { + targetAngle = 360 - targetAngle; + } + + if (animationTick < 10) + angle.set(targetAngle); + + angle.target(targetAngle); + angle.tick(); + + float snapSize = 22.5f; + float snappedAngle = (snapSize * Math.round(angle.get(0f) / snapSize)) % 360f; + + float length = 10; + //TOD O if the target is off screen, use length to show a meaningful distance + + boolean flag = AllConfigs.CLIENT.smoothPlacementIndicator.get(); + if (flag) + fadedArrow(centerX, centerY, r, g, b, a, length, snappedAngle); + + else + textured(centerX, centerY, a, snappedAngle); + } + + private static void fadedArrow(float centerX, float centerY, float r, float g, float b, float a, float length, float snappedAngle) { + RenderSystem.pushMatrix(); + RenderSystem.disableTexture(); + RenderSystem.enableBlend(); + RenderSystem.disableAlphaTest(); + RenderSystem.defaultBlendFunc(); + RenderSystem.shadeModel(GL11.GL_SMOOTH); + + RenderSystem.translated(centerX, centerY, 0); + RenderSystem.rotatef(angle.get(0), 0, 0, 1); + //RenderSystem.rotatef(snappedAngle, 0, 0, 1); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + bufferbuilder.begin(GL11.GL_POLYGON, DefaultVertexFormats.POSITION_COLOR); + + bufferbuilder.vertex(0, - (10 + length), 0).color(r, g, b, a).endVertex(); + + bufferbuilder.vertex(-9, -3, 0).color(r, g, b, 0f).endVertex(); + bufferbuilder.vertex(-6, -6, 0).color(r, g, b, 0f).endVertex(); + bufferbuilder.vertex(-3, -8, 0).color(r, g, b, 0f).endVertex(); + bufferbuilder.vertex(0, -8.5, 0).color(r, g, b, 0f).endVertex(); + bufferbuilder.vertex(3, -8, 0).color(r, g, b, 0f).endVertex(); + bufferbuilder.vertex(6, -6, 0).color(r, g, b, 0f).endVertex(); + bufferbuilder.vertex(9, -3, 0).color(r, g, b, 0f).endVertex(); + + tessellator.draw(); + RenderSystem.shadeModel(GL11.GL_FLAT); + RenderSystem.disableBlend(); + RenderSystem.enableAlphaTest(); + RenderSystem.enableTexture(); + RenderSystem.popMatrix(); + } + + private static void textured(float centerX, float centerY, float alpha, float snappedAngle) { + RenderSystem.pushMatrix(); + RenderSystem.enableTexture(); + //RenderSystem.disableTexture(); + AllGuiTextures.PLACEMENT_INDICATOR_SHEET.bind(); + RenderSystem.enableBlend(); + //RenderSystem.disableAlphaTest(); + RenderSystem.enableAlphaTest(); + RenderSystem.defaultBlendFunc(); + RenderSystem.color4f(1f, 1f, 1f, 1f); + RenderSystem.shadeModel(GL11.GL_SMOOTH); + + RenderSystem.translated(centerX, centerY, 0); + //RenderSystem.rotatef(angle.get(0.1f), 0, 0, -1); + //RenderSystem.translated(0, 10, 0); + //RenderSystem.rotatef(angle.get(0.1f), 0, 0, 1); + RenderSystem.scaled(12, 12, 0); + + float index = snappedAngle / 22.5f; + float tex_size = 16f/256f; + + float tx = 0; + float ty = index * tex_size; + float tw = 1f; + float th = tex_size; + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEXTURE); + + + buffer.vertex(-1, -1, 0).color(1f, 1f, 1f, alpha).texture(tx, ty).endVertex(); + buffer.vertex(-1, 1, 0).color(1f, 1f, 1f, alpha).texture(tx, ty + th).endVertex(); + buffer.vertex(1, 1, 0).color(1f, 1f, 1f, alpha).texture(tx + tw, ty + th).endVertex(); + buffer.vertex(1, -1, 0).color(1f, 1f, 1f, alpha).texture(tx + tw, ty).endVertex(); + + tessellator.draw(); + RenderSystem.shadeModel(GL11.GL_FLAT); + + //RenderSystem.enableTexture(); + + RenderSystem.disableBlend(); + //RenderSystem.enableAlphaTest(); + RenderSystem.popMatrix(); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementOffset.java b/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementOffset.java index e9d50d6d5..f1cb89170 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementOffset.java +++ b/src/main/java/com/simibubi/create/foundation/utility/placement/PlacementOffset.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.utility.placement; +import java.util.function.Function; + import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.block.BlockState; import net.minecraft.block.SoundType; @@ -22,30 +24,49 @@ import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.event.world.BlockEvent; -import java.util.function.Function; - public class PlacementOffset { private final boolean success; - private final Vec3i pos; - private final Function stateTransform; + private Vec3i pos; + private Function stateTransform; + private BlockState ghostState; - private PlacementOffset(boolean success, Vec3i pos, Function transform) { + private PlacementOffset(boolean success) { this.success = success; - this.pos = pos; - this.stateTransform = transform == null ? Function.identity() : transform; + this.pos = BlockPos.ZERO; + this.stateTransform = Function.identity(); + this.ghostState = null; } public static PlacementOffset fail() { - return new PlacementOffset(false, Vec3i.NULL_VECTOR, null); + return new PlacementOffset(false); + } + + public static PlacementOffset success() { + return new PlacementOffset(true); } public static PlacementOffset success(Vec3i pos) { - return new PlacementOffset(true, pos, null); + return success().at(pos); } public static PlacementOffset success(Vec3i pos, Function transform) { - return new PlacementOffset(true, pos, transform); + return success().at(pos).withTransform(transform); + } + + public PlacementOffset at(Vec3i pos) { + this.pos = pos; + return this; + } + + public PlacementOffset withTransform(Function stateTransform) { + this.stateTransform = stateTransform; + return this; + } + + public PlacementOffset withGhostState(BlockState ghostState) { + this.ghostState = ghostState; + return this; } public boolean isSuccessful() { @@ -56,10 +77,25 @@ public class PlacementOffset { return pos; } + public BlockPos getBlockPos() { + if (pos instanceof BlockPos) + return (BlockPos) pos; + + return new BlockPos(pos); + } + public Function getTransform() { return stateTransform; } + public boolean hasGhostState() { + return ghostState != null; + } + + public BlockState getGhostState() { + return ghostState; + } + public boolean isReplaceable(World world) { if (!success) return false; @@ -69,16 +105,15 @@ public class PlacementOffset { public ActionResultType placeInWorld(World world, BlockItem blockItem, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { - ItemUseContext context = new ItemUseContext(player, hand, ray); + if (!isReplaceable(world)) + return ActionResultType.PASS; + ItemUseContext context = new ItemUseContext(player, hand, ray); BlockPos newPos = new BlockPos(pos); if (!world.isBlockModifiable(player, newPos)) return ActionResultType.PASS; - if (!isReplaceable(world)) - return ActionResultType.PASS; - BlockState state = stateTransform.apply(blockItem.getBlock().getDefaultState()); if (state.has(BlockStateProperties.WATERLOGGED)) { IFluidState fluidState = world.getFluidState(newPos); diff --git a/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java b/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java index f074a8d5c..4dceeaf48 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/placement/util/PoleHelper.java @@ -1,21 +1,20 @@ package com.simibubi.create.foundation.utility.placement.util; -import com.simibubi.create.foundation.utility.VecHelper; +import java.util.List; +import java.util.function.Function; +import java.util.function.Predicate; + import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.PlacementOffset; + import mcp.MethodsReturnNonnullByDefault; import net.minecraft.block.BlockState; import net.minecraft.state.IProperty; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; -import java.util.List; -import java.util.function.Function; -import java.util.function.Predicate; - @MethodsReturnNonnullByDefault public abstract class PoleHelper> implements IPlacementHelper { @@ -71,7 +70,9 @@ public abstract class PoleHelper> implements IPlacementH @Override public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) { - Vec3d centerOffset = new Vec3d(ray.getFace().getDirectionVec()).scale(.3); - IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos).add(centerOffset), VecHelper.getCenterOf(offset.getPos()).add(centerOffset), ray.getFace(), 0.75D); + //Vec3d centerOffset = new Vec3d(ray.getFace().getDirectionVec()).scale(.3); + //IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos).add(centerOffset), VecHelper.getCenterOf(offset.getPos()).add(centerOffset), ray.getFace(), 0.75D); + + displayGhost(offset); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java index adc080537..cc96987e7 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java +++ b/src/main/java/com/simibubi/create/foundation/utility/recipe/RecipeConditions.java @@ -1,12 +1,13 @@ package com.simibubi.create.foundation.utility.recipe; -import com.google.common.base.Predicate; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipeType; +import java.util.function.Predicate; + /** * Commonly used Predicates for searching through recipe collections. * @@ -15,11 +16,9 @@ import net.minecraft.item.crafting.IRecipeType; */ public class RecipeConditions { - public static Predicate> isOfType(IRecipeType type, IRecipeType... otherTypes) { + public static Predicate> isOfType(IRecipeType... otherTypes) { return recipe -> { IRecipeType recipeType = recipe.getType(); - if (recipeType == type) - return true; for (IRecipeType other : otherTypes) if (recipeType == other) return true; diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationWorld.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationWorld.java index ee209d16f..8e8d71b3c 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationWorld.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/PlacementSimulationWorld.java @@ -2,24 +2,44 @@ package com.simibubi.create.foundation.utility.worldWrappers; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.function.Predicate; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.SectionPos; import net.minecraft.world.World; +import net.minecraft.world.lighting.WorldLightManager; public class PlacementSimulationWorld extends WrappedWorld { public HashMap blocksAdded; public HashMap tesAdded; + public HashSet spannedChunks; + public WorldLightManager lighter; + public WrappedChunkProvider chunkProvider; + private final BlockPos.Mutable scratch = new BlockPos.Mutable(); + public PlacementSimulationWorld(World wrapped) { - super(wrapped); + this(wrapped, new WrappedChunkProvider()); + } + + public PlacementSimulationWorld(World wrapped, WrappedChunkProvider chunkProvider) { + super(wrapped, chunkProvider); + this.chunkProvider = chunkProvider.setWorld(this); + spannedChunks = new HashSet<>(); + lighter = new WorldLightManager(chunkProvider, true, false); // blockLight, skyLight blocksAdded = new HashMap<>(); tesAdded = new HashMap<>(); } + @Override + public WorldLightManager getLightingProvider() { + return lighter; + } + public void setTileEntities(Collection tileEntities) { tesAdded.clear(); tileEntities.forEach(te -> tesAdded.put(te.getPos(), te)); @@ -31,6 +51,15 @@ public class PlacementSimulationWorld extends WrappedWorld { @Override public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { + + SectionPos sectionPos = SectionPos.from(pos); + + if (spannedChunks.add(sectionPos)) { + lighter.updateSectionStatus(sectionPos, false); + } + + lighter.checkBlock(pos); + blocksAdded.put(pos, newState); return true; } @@ -60,11 +89,17 @@ public class PlacementSimulationWorld extends WrappedWorld { return true; } + public BlockState getBlockState(int x, int y, int z) { + return getBlockState(scratch.setPos(x, y, z)); + } + @Override public BlockState getBlockState(BlockPos pos) { - if (blocksAdded.containsKey(pos)) - return blocksAdded.get(pos); - return Blocks.AIR.getDefaultState(); + BlockState state = blocksAdded.get(pos); + if (state != null) + return state; + else + return Blocks.AIR.getDefaultState(); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedChunkProvider.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedChunkProvider.java new file mode 100644 index 000000000..f6a22d102 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedChunkProvider.java @@ -0,0 +1,83 @@ +package com.simibubi.create.foundation.utility.worldWrappers; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.stream.Stream; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.utility.worldWrappers.chunk.WrappedChunk; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.chunk.AbstractChunkProvider; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.lighting.WorldLightManager; + +public class WrappedChunkProvider extends AbstractChunkProvider { + private PlacementSimulationWorld world; + + public HashMap chunks; + + public WrappedChunkProvider setWorld(PlacementSimulationWorld world) { + this.world = world; + this.chunks = new HashMap<>(); + return this; + } + + public Stream getLightSources() { + return world.blocksAdded + .entrySet() + .stream() + .filter(it -> it.getValue().getLightValue(world, it.getKey()) != 0) + .map(Map.Entry::getKey); + } + + @Nullable + @Override + public IBlockReader getChunkForLight(int x, int z) { + return getChunk(x, z); + } + + @Override + public IBlockReader getWorld() { + return world; + } + + @Nullable + @Override + public IChunk getChunk(int x, int z, ChunkStatus status, boolean p_212849_4_) { + return getChunk(x, z); + } + + public WrappedChunk getChunk(int x, int z) { + long pos = ChunkPos.asLong(x, z); + + WrappedChunk chunk = chunks.get(pos); + + if (chunk == null) { + chunk = new WrappedChunk(world, x, z); + chunks.put(pos, chunk); + } + + return chunk; + } + + @Override + public void tick(BooleanSupplier p_217207_1_) { + + } + + @Override + public String makeString() { + return "WrappedChunkProvider"; + } + + @Override + public WorldLightManager getLightManager() { + return world.getLightingProvider(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedWorld.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedWorld.java index b198db079..e986bf8bd 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedWorld.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedWorld.java @@ -19,18 +19,30 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.ITickList; import net.minecraft.world.World; import net.minecraft.world.biome.Biome; +import net.minecraft.world.lighting.WorldLightManager; import net.minecraft.world.storage.MapData; public class WrappedWorld extends World { protected World world; + public WrappedWorld(World world, WrappedChunkProvider provider) { + super(world.getWorldInfo(), world.getDimension().getType(), (w, d) -> provider, + world.getProfiler(), world.isRemote); + this.world = world; + } + public WrappedWorld(World world) { super(world.getWorldInfo(), world.getDimension().getType(), (w, d) -> world.getChunkProvider(), world.getProfiler(), world.isRemote); this.world = world; } + @Override + public WorldLightManager getLightingProvider() { + return super.getLightingProvider(); + } + @Override public World getWorld() { return world; diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java new file mode 100644 index 000000000..c6904537d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunk.java @@ -0,0 +1,259 @@ +package com.simibubi.create.foundation.utility.worldWrappers.chunk; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.stream.Stream; + +import javax.annotation.Nullable; + +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +import it.unimi.dsi.fastutil.longs.LongSet; +import it.unimi.dsi.fastutil.shorts.ShortList; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.IFluidState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.palette.UpgradeData; +import net.minecraft.world.ITickList; +import net.minecraft.world.biome.BiomeContainer; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.IChunk; +import net.minecraft.world.gen.Heightmap; +import net.minecraft.world.gen.feature.structure.StructureStart; + +public class WrappedChunk implements IChunk { + + final PlacementSimulationWorld world; + boolean needsLight; + final int x; + final int z; + final ChunkPos pos; + + private final ChunkSection[] sections; + + public WrappedChunk(PlacementSimulationWorld world, int x, int z) { + this.world = world; + this.needsLight = true; + this.x = x; + this.z = z; + this.pos = new ChunkPos(x, z); + + this.sections = new ChunkSection[16]; + + for (int i = 0; i < 16; i++) { + sections[i] = new WrappedChunkSection(this, i << 4); + } + } + + @Override + public Stream getLightSources() { + return world.blocksAdded + .entrySet() + .stream() + .filter(it -> { + BlockPos blockPos = it.getKey(); + boolean chunkContains = blockPos.getX() >> 4 == x && blockPos.getZ() >> 4 == z; + return chunkContains && it.getValue().getLightValue(world, blockPos) != 0; + }) + .map(Map.Entry::getKey); + } + + @Override + public ChunkSection[] getSections() { + return sections; + } + + @Nullable + @Override + public BlockState setBlockState(BlockPos p_177436_1_, BlockState p_177436_2_, boolean p_177436_3_) { + return null; + } + + @Override + public void addTileEntity(BlockPos p_177426_1_, TileEntity p_177426_2_) { + + } + + @Override + public void addEntity(Entity p_76612_1_) { + + } + + @Override + public Set getTileEntitiesPos() { + return null; + } + + @Override + public Collection> func_217311_f() { + return null; + } + + @Override + public void setHeightmap(Heightmap.Type p_201607_1_, long[] p_201607_2_) { + + } + + @Override + public Heightmap getHeightmap(Heightmap.Type p_217303_1_) { + return null; + } + + @Override + public int getTopBlockY(Heightmap.Type p_201576_1_, int p_201576_2_, int p_201576_3_) { + return 0; + } + + @Override + public ChunkPos getPos() { + return null; + } + + @Override + public void setLastSaveTime(long p_177432_1_) { + + } + + @Override + public Map getStructureStarts() { + return null; + } + + @Override + public void setStructureStarts(Map p_201612_1_) { + + } + + @Nullable + @Override + public BiomeContainer getBiomeArray() { + return null; + } + + @Override + public void setModified(boolean p_177427_1_) { + + } + + @Override + public boolean isModified() { + return false; + } + + @Override + public ChunkStatus getStatus() { + return null; + } + + @Override + public void removeTileEntity(BlockPos p_177425_1_) { + + } + + @Override + public ShortList[] getPackedPositions() { + return new ShortList[0]; + } + + @Nullable + @Override + public CompoundNBT getDeferredTileEntity(BlockPos p_201579_1_) { + return null; + } + + @Nullable + @Override + public CompoundNBT func_223134_j(BlockPos p_223134_1_) { + return null; + } + + @Override + public ITickList getBlocksToBeTicked() { + return null; + } + + @Override + public ITickList getFluidsToBeTicked() { + return null; + } + + @Override + public UpgradeData getUpgradeData() { + return null; + } + + @Override + public void setInhabitedTime(long p_177415_1_) { + + } + + @Override + public long getInhabitedTime() { + return 0; + } + + @Override + public boolean hasLight() { + return needsLight; + } + + @Override + public void setLight(boolean needsLight) { + this.needsLight = needsLight; + } + + @Nullable + @Override + public TileEntity getTileEntity(BlockPos pos) { + return null; + } + + @Override + public BlockState getBlockState(BlockPos pos) { + return world.getBlockState(pos); + } + + @Override + public IFluidState getFluidState(BlockPos pos) { + return null; + } + + @Nullable + @Override + public StructureStart getStructureStart(String p_201585_1_) { + return null; + } + + @Override + public void putStructureStart(String p_201584_1_, StructureStart p_201584_2_) { + + } + + @Override + public LongSet getStructureReferences(String p_201578_1_) { + return null; + } + + @Override + public void addStructureReference(String p_201583_1_, long p_201583_2_) { + + } + + @Override + public Map getStructureReferences() { + return null; + } + + @Override + public void setStructureReferences(Map p_201606_1_) { + + } +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java new file mode 100644 index 000000000..e5e90594d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/WrappedChunkSection.java @@ -0,0 +1,32 @@ +package com.simibubi.create.foundation.utility.worldWrappers.chunk; + +import net.minecraft.block.BlockState; +import net.minecraft.world.chunk.ChunkSection; + +public class WrappedChunkSection extends ChunkSection { + + public WrappedChunk owner; + + public final int xStart; + public final int yStart; + public final int zStart; + + public WrappedChunkSection(WrappedChunk owner, int yBase) { + super(yBase); + this.owner = owner; + this.xStart = owner.pos.getXStart(); + this.yStart = yBase; + this.zStart = owner.pos.getZStart(); + } + + @Override + public BlockState getBlockState(int x, int y, int z) { + // ChunkSection#getBlockState expects local chunk coordinates, so we add to get back into world coords. + return owner.world.getBlockState(x + xStart, y + yStart, z + zStart); + } + + @Override + public BlockState setBlockState(int p_177484_1_, int p_177484_2_, int p_177484_3_, BlockState p_177484_4_, boolean p_177484_5_) { + throw new IllegalStateException("Chunk sections should not be mutated in a fake world."); + } +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index aabe3062b..9c7551a9b 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -26,4 +26,25 @@ public net.minecraft.world.server.ServerTickList field_205374_d # pendingTickLis public net.minecraft.world.server.ServerTickList field_205375_e # pendingTickListEntriesTreeSet # Particle Manager -public net.minecraft.client.particle.ParticleManager field_178932_g # factories \ No newline at end of file +public net.minecraft.client.particle.ParticleManager field_178932_g # factories + +# Lightmap information for instanced rendering +public net.minecraft.client.renderer.LightTexture field_205112_c #resourceLocation +public net.minecraft.client.Minecraft field_193996_ah #renderPartialTicksPaused + +# Functions needed to setup a projection matrix +public net.minecraft.client.renderer.GameRenderer field_78529_t #rendererUpdateCount +public net.minecraft.client.renderer.GameRenderer func_228380_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V #bobViewWhenHurt +public net.minecraft.client.renderer.GameRenderer func_228383_b_(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V #bobView + +# Expose fog state to the public +public com.mojang.blaze3d.platform.GlStateManager$FogState +public com.mojang.blaze3d.platform.GlStateManager field_225663_h_ #FOG +public com.mojang.blaze3d.platform.GlStateManager$BooleanState +public com.mojang.blaze3d.platform.GlStateManager$BooleanState field_179201_b #field_179201_b + +# GameRenderer +public net.minecraft.client.renderer.GameRenderer func_215311_a(Lnet/minecraft/client/renderer/ActiveRenderInfo;FZ)D #getFOVModifier + +# IResizeCallback +public net.minecraft.util.palette.IResizeCallback diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 3b69e270c..a77dc0b61 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -14,7 +14,7 @@ Technology that empowers the player.''' [[dependencies.create]] modId="forge" mandatory=true - versionRange="[31.2.0,)" + versionRange="[31.2.44,)" ordering="NONE" side="BOTH" diff --git a/src/main/resources/assets/create/lang/de_de.json b/src/main/resources/assets/create/lang/de_de.json index 1e281fcde..9e0aab18c 100644 --- a/src/main/resources/assets/create/lang/de_de.json +++ b/src/main/resources/assets/create/lang/de_de.json @@ -1,8 +1,8 @@ { "_": "->------------------------] Game Elements [------------------------<-", - "block.create.acacia_window": "Akazienfenster", - "block.create.acacia_window_pane": "Akazienfensterscheibe", + "block.create.acacia_window": "Akazienholzfenster", + "block.create.acacia_window_pane": "Akazienholzfensterscheibe", "block.create.adjustable_chain_gearshift": "Verstellbares Kettengetriebe", "block.create.adjustable_crate": "Verstellbare Kiste", "block.create.adjustable_pulse_repeater": "Verstellbarer Pulsverstärker", @@ -24,6 +24,8 @@ "block.create.andesite_tunnel": "Andesittunnel", "block.create.basin": "Behälter", "block.create.belt": "Mechanischer Riemen", + "block.create.birch_window": "Birkenholzfenster", + "block.create.birch_window_pane": "Birkenholzfensterscheibe", "block.create.black_sail": "Schwarzes Segel", "block.create.black_seat": "Schwarzer Sitz", "block.create.black_valve_handle": "Schwarzer Ventilgriff", @@ -52,7 +54,7 @@ "block.create.clockwork_bearing": "Uhrwerk-Lager", "block.create.clutch": "Kupplung", "block.create.cogwheel": "Zahnrad", - "block.create.content_observer": "Inhalts Beobachter", + "block.create.content_observer": "Inhaltsbeobachter", "block.create.controller_rail": "Steureungsschiene", "block.create.copper_block": "Kupfer Block", "block.create.copper_casing": "Kupferrahmen", @@ -113,43 +115,138 @@ "block.create.fancy_dark_scoria_bricks_slab": "Schicke dunkle Schlackenziegelstufe", "block.create.fancy_dark_scoria_bricks_stairs": "Schicke dunkle Schlackenziegeltreppe", "block.create.fancy_dark_scoria_bricks_wall": "Schicke dunkle Schlackenziegelmauer", - "block.create.fluid_pipe": "Wasserrohr", - "block.create.fluid_tank": "Wassertank", + "block.create.fancy_diorite_bricks": "Schöne Dioritziegel", + "block.create.fancy_diorite_bricks_slab": "Schöne Dioritziegelstufe", + "block.create.fancy_diorite_bricks_stairs": "Schöne Dioritziegeltreppe", + "block.create.fancy_diorite_bricks_wall": "Schöne Dioritziegelmauer", + "block.create.fancy_dolomite_bricks": "Schöne Dolomitziegel", + "block.create.fancy_dolomite_bricks_slab": "Schöne Dolomitziegelstufe", + "block.create.fancy_dolomite_bricks_stairs": "Schöne Dolomitziegeltreppe", + "block.create.fancy_dolomite_bricks_wall": "Schöne Dolomitziegelmauer", + "block.create.fancy_gabbro_bricks": "Schöne Gabelsteinziegel", + "block.create.fancy_gabbro_bricks_slab": "Schöne Gabelsteinziegelstufe", + "block.create.fancy_gabbro_bricks_stairs": "Schöne Gabelsteinziegeltreppe", + "block.create.fancy_gabbro_bricks_wall": "Schöne Gabelsteinziegelmauer", + "block.create.fancy_granite_bricks": "Schöne Granitziegel", + "block.create.fancy_granite_bricks_slab": "Schöne Granitziegelstufe", + "block.create.fancy_granite_bricks_stairs": "Schöne Granitziegeltreppe", + "block.create.fancy_granite_bricks_wall": "Schöne Granitziegelmauer", + "block.create.fancy_limestone_bricks": "Schöne Kalksteinziegel", + "block.create.fancy_limestone_bricks_slab": "Schöne Kalksteinziegelstufe", + "block.create.fancy_limestone_bricks_stairs": "Schöne Kalksteinziegeltreppe", + "block.create.fancy_limestone_bricks_wall": "Schöne Kalksteinziegelmauer", + "block.create.fancy_scoria_bricks": "Schöne Schlackenziegel", + "block.create.fancy_scoria_bricks_slab": "Schöne Schlackenziegelstufe", + "block.create.fancy_scoria_bricks_stairs": "Schöne Schlackenziegeltreppe", + "block.create.fancy_scoria_bricks_wall": "Schöne Schlackenziegelmauer", + "block.create.fancy_weathered_limestone_bricks": "Schöne Verwitterte Kalksteinziegel", + "block.create.fancy_weathered_limestone_bricks_slab": "Schöne Verwitterte Kalksteinziegelstufe", + "block.create.fancy_weathered_limestone_bricks_stairs": "Schöne Verwitterte Kalksteinziegeltreppe", + "block.create.fancy_weathered_limestone_bricks_wall": "Schöne Verwitterte Kalksteinziegelmauer", + "block.create.fluid_pipe": "Flüssigkeitsrohr", + "block.create.fluid_tank": "Flüssigkeitstank", "block.create.fluid_valve": "Flüssigkeitsventil", "block.create.flywheel": "Schwungrad", "block.create.framed_glass": "Gerahmtes Glas", "block.create.framed_glass_pane": "Gerahmte Glasscheibe", - "block.create.gabbro": "Gabbro", - "block.create.gabbro_bricks": "Gabbroziegel", - "block.create.gabbro_bricks_stairs": "Gabbroziegeltreppe", - "block.create.gabbro_bricks_wall": "Gabbroziegelmauer", - "block.create.gabbro_bricks_slab": "Gabbroziegelstufe", + "block.create.furnace_engine": "Ofenmotor", + "block.create.gabbro": "Gabelstein", + "block.create.gabbro_bricks": "Gabelsteinziegel", + "block.create.gabbro_bricks_slab": "Gabelsteinziegelstufe", + "block.create.gabbro_bricks_stairs": "Gabelsteinziegeltreppe", + "block.create.gabbro_bricks_wall": "Gabelsteinziegelmauer", + "block.create.gabbro_cobblestone": "Gabelsteinbruchstein", + "block.create.gabbro_cobblestone_slab": "Gabelsteinbruchstein", + "block.create.gabbro_cobblestone_stairs": "Gabelsteinbruchstein", + "block.create.gabbro_cobblestone_wall": "Gabelsteinbruchstein", + "block.create.gabbro_pillar": "Gabelsteinsäule", "block.create.gearbox": "Getriebe", "block.create.gearshift": "Gangschaltung", "block.create.glass_fluid_pipe": "Glaswasserrohr", "block.create.granite_bricks": "Granitziegel", + "block.create.granite_bricks_slab": "Granitziegelstufe", + "block.create.granite_bricks_stairs": "Granitziegeltreppe", + "block.create.granite_bricks_wall": "Granitziegelmauer", + "block.create.granite_cobblestone": "Granitbruchstein", + "block.create.granite_cobblestone_slab": "Granitbruchsteinstufe", + "block.create.granite_cobblestone_stairs": "Granitbruchtreppe", + "block.create.granite_cobblestone_wall": "Granitbruchsteinmauer", + "block.create.granite_pillar": "Granitsäule", + "block.create.gray_sail": "Graues Segel", + "block.create.gray_seat": "Grauer Sitz", + "block.create.gray_valve_handle": "Grauer Ventilgriff", + "block.create.green_sail": "Grünes Segel", + "block.create.green_seat": "Grüner Sitz", + "block.create.green_valve_handle": "Grüner Ventilgriff", + "block.create.hand_crank": "Handkurbel", + "block.create.honey": "Honig", + "block.create.horizontal_framed_glass": "Horizontal Gerahmes Glas", + "block.create.horizontal_framed_glass_pane": "Horizontal Gerahmte Glasscheibe", + "block.create.hose_pulley": "Umlenkrolle", + "block.create.item_drain": "Abfluss", + "block.create.jungle_window": "Tropenholzfenster", + "block.create.jungle_window_pane": "Tropenholzfensterscheib", "block.create.large_cogwheel": "Großes Zahnrad", + "block.create.layered_andesite": "Geschichteter Andesit", + "block.create.layered_dark_scoria": "Geschichtete Dunkle Schlacke", + "block.create.layered_diorite": "Geschichteter Diorit", + "block.create.layered_dolomite": "Geschichteter Dolomit", + "block.create.layered_gabbro": "Geschichteter Gabelstein", + "block.create.layered_granite": "Geschichteter Granit", + "block.create.layered_limestone": "Geschichteter Kalkstein", + "block.create.layered_scoria": "Geschichtete Schlacke", + "block.create.layered_weathered_limestone": "Geschichteter Verwitterter Kalkstein", + "block.create.light_blue_sail": "Hellblaues Segel", + "block.create.light_blue_seat": "Hellblauer Sitz", + "block.create.light_blue_valve_handle": "Hellblauer Ventilgriff", + "block.create.light_gray_sail": "Hellgraues Segel", + "block.create.light_gray_seat": "Hellgrauer Sitz", + "block.create.light_gray_valve_handle": "Hellgrauer Ventilgriff", + "block.create.lime_sail": "Hellgrünes Segel", + "block.create.lime_seat": "Hellgrüner Sitz", + "block.create.lime_valve_handle": "Hellgrüner Ventilgriff", "block.create.limesand": "Kalksand", "block.create.limestone": "Kalkstein", "block.create.limestone_bricks": "Kalksteinziegel", "block.create.limestone_bricks_slab": "Kalksteinziegelstufe", "block.create.limestone_bricks_stairs": "Kalksteinziegeltreppe", "block.create.limestone_bricks_wall": "Kalksteinziegelmauer", + "block.create.limestone_cobblestone": "Kalkbruchstein", + "block.create.limestone_cobblestone_slab": "Kalkbruchsteinstufe", + "block.create.limestone_cobblestone_stairs": "Kalkbruchsteintreppe", + "block.create.limestone_cobblestone_wall": "Kalkbruchsteinmauer", "block.create.limestone_pillar": "Kalksteinsäule", "block.create.linear_chassis": "Schubgerüst", + "block.create.lit_blaze_burner": "Aktiver Lohenbrenner", + "block.create.magenta_sail": "Magenta Segel", + "block.create.magenta_seat": "Magenta Sitz", + "block.create.magenta_valve_handle": "Magenta Ventilgriff", + "block.create.mechanical_arm": "Mechanischer Arm", "block.create.mechanical_bearing": "Mechanisches Lager", + "block.create.mechanical_crafter": "Mechanische Handwerkseinheit", "block.create.mechanical_drill": "Mechanischer Bohrer", "block.create.mechanical_harvester": "Mechanische Erntemaschine", + "block.create.mechanical_mixer": "Mechanischer Mixer", "block.create.mechanical_piston": "Mechanischer Kolben", "block.create.mechanical_piston_head": "Mechanisches Kolbenende", + "block.create.mechanical_plough": "Mechanischer Pflug", "block.create.mechanical_press": "Mechanische Presse", + "block.create.mechanical_pump": "Mechanische Pumpe", + "block.create.mechanical_saw": "Mechanische Säge", + "block.create.metal_bracket": "Metallhalterung", + "block.create.millstone": "Mahlstein", + "block.create.pink_sail": "Rosa Segel", + "block.create.pink_seat": "Rosa Sitz", + "block.create.pink_valve_handle": "Rosa Ventilgriff", "block.create.piston_extension_pole": "Kolben-Pleuelverlängerung", "block.create.polished_dolomite": "Polierter Dolomit", - "block.create.polished_gabbro": "Polierter Gabbro", + "block.create.polished_gabbro": "Polierter Gabelstein", "block.create.polished_limestone": "Polierter Kalkstein", "block.create.polished_limestone_slab": "Polierte Kalksteinstufe", + "block.create.polished_scoria": "Polierte Schlacke", "block.create.polished_weathered_limestone": "Polierter Verwitterter Kalkstein", "block.create.polished_weathered_limestone_slab": "Polierte Verwitterte Kalksteinstufe", + "block.create.powered_latch": "UNLOCALIZED: Powered Latch", "block.create.pulse_repeater": "Pulsierender Verstärker", "block.create.radial_chassis": "Drehgerüst", "block.create.redstone_contact": "Redstone-Kontakt", @@ -170,19 +267,30 @@ "block.create.weathered_limestone_bricks_wall": "Verwitterte Kalksteinziegelmauer", "block.create.weathered_limestone_pillar": "Verwitterte Kalksteinsäule", + "fluid.create.milk": "Milch", + "fluid.create.potion": "Trank", + "fluid.create.tea": "Bauherrentee", + + "item.create.bar_of_chocolate": "Schokoladetafel", "item.create.belt_connector": "Mechanischer Riemen", + "item.create.deforester": "Entforster", "item.create.dough": "Teig", "item.create.empty_schematic": "Leerer Bauplan", "item.create.filter": "Filter", "item.create.handheld_blockzapper": "Blockpistole", + "item.create.handheld_worldshaper": "Geländeformer", + "item.create.honey_bucket": "Honigeimer", "item.create.iron_sheet": "Eisenblech", "item.create.propeller": "Propeller", + "item.create.red_sand_paper": "Rotes Schmirgelpapier", "item.create.rose_quartz": "Rosenquarz", + "item.create.sand_paper": "Schmirgelpapier", "item.create.schematic": "Bauplan", "item.create.schematic_and_quill": "Bauplan und Feder", + "item.create.super_glue": "Superkleber", "item.create.tree_fertilizer": "Baumdünger", "item.create.wand_of_symmetry": "Symmetriestab", - + "item.create.wheat_flour": "Weizenmehl", "item.create.wrench": "Schraubenschlüssel", "item.create.zinc_ingot": "Zinkbarren", "item.create.zinc_nugget": "Zinkklumpen", @@ -203,19 +311,32 @@ "advancement.create.belt": "Befördere es alles", "advancement.create.belt.desc": "Verbinde zwei Wllen mit einem Mechanischem Riemen", + "_": "->------------------------] UI & Messages [------------------------<-", + "itemGroup.create.base": "Create", + "itemGroup.create.palettes": "Create Paletten", "death.attack.create.crush": "%1$s stolperte in ein Mahlwerk", "death.attack.create.fan_fire": "%1$s hat heiße Luft eingeatmet", "death.attack.create.fan_lava": "%1$s wurde von Lava verweht", "death.attack.create.mechanical_drill": "%1$s wurde von einem Bohrer durchlöchert", + "death.attack.create.mechanical_saw": "%1$s wurde zersägt", + "death.attack.create.cuckoo_clock_explosion": "%1$s wurde durch eine falsche Kuckucksuhr gesprengt", + "create.block.deployer.damage_source_name": "einem Finger", - "create.recipe.crushing": "Mahlen", + "create.recipe.crushing": "Mahlen (Mahlwerk)", + "create.recipe.milling": "Mahlen (Mahlstein)", "create.recipe.pressing": "Mechanische Presse", + "create.recipe.mixing": "Mixen", + "create.recipe.sawing": "Sägen", "create.recipe.blockzapper_upgrade": "Blockpistole", + "create.recipe.sandpaper_polishing": "Schleifen", "create.recipe.processing.chance": "Chance: %1$s%%", + "create.recipe.heat_requirement.none": "Keine Hitze benötigt", + "create.recipe.heat_requirement.heated": "Wenig Hitze benötigt", + "create.recipe.heat_requirement.superheated": "Viel Hitze benötigt", "create.generic.range": "Reichweite", "create.generic.radius": "Radius", @@ -224,6 +345,12 @@ "create.generic.unit.ticks": "Ticks", "create.generic.unit.seconds": "Sekunden", "create.generic.unit.minutes": "Minuten", + "create.generic.unit.rpm": "RPM", + "create.generic.unit.stress": "su", + "create.generic.unit.degrees": "°", + "create.generic.unit.millibuckets": "%1$smB", + "create.generic.clockwise": "Uhrzeigersinn", + "create.generic.counter_clockwise": "Gegen-Uhrzeigersinn", "create.action.scroll": "Wechseln", "create.action.confirm": "Bestätigen", @@ -266,7 +393,6 @@ "create.gui.blockzapper.pattern.chance50": "50%-Chance", "create.gui.blockzapper.pattern.chance75": "75%-Chance", - "create.blockzapper.usingBlock": "Auswahl: %1$s", "create.blockzapper.componentUpgrades": "Bauteil-Upgrades:", "create.blockzapper.component.body": "Rumpf", @@ -275,16 +401,16 @@ "create.blockzapper.component.retriever": "Empfänger", "create.blockzapper.component.scope": "Fernrohr", "create.blockzapper.componentTier.none": "Nichts", + "create.blockzapper.componentTier.brass": "Messing", "create.blockzapper.leftClickToSet": "Linksklick auf einen Block zum Auswählen", "create.blockzapper.empty": "Keine Blöcke übrig!", - - "create.logistics.filter": "Filter", + "create.logistics.recipe_filter": "Rezeptfilter", + "create.logistics.fluid_filter": "Flüssigkeitsfilter", "create.logistics.firstFrequency": "Freq. #1", "create.logistics.secondFrequency": "Freq. #2", - "create.gui.adjustable_crate.title": "adjustable_crate", "create.gui.adjustable_crate.storageSpace": "Lagerraum", "create.gui.stockpile_switch.title": "Vorratssensor", @@ -293,6 +419,7 @@ "create.schematicAndQuill.secondPos": "Zweite Position festgelegt.", "create.schematicAndQuill.noTarget": "Halte [Strg] zur Auswahl von Luft.", "create.schematicAndQuill.abort": "Auswahl zurückgesetzt.", + "create.schematicAndQuill.title": "Bauplanname:", "create.schematicAndQuill.fallbackName": "Mein Bauplan", "create.schematicAndQuill.saved": "Gespeichert als %1$s", @@ -421,12 +548,11 @@ "item.create.handheld_blockzapper.tooltip.action2": "_Platziert_ oder _Ersetzt_ den ausgewählten Block.", "item.create.handheld_blockzapper.tooltip.control3": "R-Klick beim Schleichen", "item.create.handheld_blockzapper.tooltip.action3": "Öffnet das _Konfigurationsmenü_", - + "item.create.tree_fertilizer.tooltip": "BAUMDÜNGER", "item.create.tree_fertilizer.tooltip.summary": "Eine Mischung aus Mineralien, die sich für weit verbreitete Baumarten eignet", "item.create.tree_fertilizer.tooltip.condition1": "Wenn auf einen Setzling angewendet", "item.create.tree_fertilizer.tooltip.behaviour1": "Lässt Bäume unabhängig vom Platz um sie herum wachsen", - "item.create.empty_schematic.tooltip": "LEERER BAUPLAN", "item.create.empty_schematic.tooltip.summary": "Wird für die Herstellung und das Schreiben auf dem _Bauplantisch_ verwendet", @@ -518,6 +644,8 @@ "block.create.mechanical_press.tooltip.behaviour1": "_Fängt_ _an_, Gegenstände, die darunter liegen, zusammenzudrücken.", "block.create.mechanical_press.tooltip.condition2": "Wenn über einem Mechanischem Riemen", "block.create.mechanical_press.tooltip.behaviour2": "Presst _automatisch_ alle auf dem Riemen vorbeigeführten Gegenstände zusammen.", + "block.create.mechanical_press.tooltip.condition3": "UNLOCALIZED: When above Basin", + "block.create.mechanical_press.tooltip.behaviour3": "UNLOCALIZED: Starts to _compact items_ in the basin whenever all necessary ingredients are present.", "block.create.mechanical_piston.tooltip": "MECHANISCHER KOLBEN", "block.create.mechanical_piston.tooltip.summary": "Eine fortgeschrittene Version des _Kolbens,_ welcher _Rotationsenergie_ benutzt, um verbundene Strukturen präzise zu bewegen. _Kolben-Pleuelverlängerungen_ auf der Hinterseite bestimmen die _Reichweite_ des Kolbens. Ohne Verlängerungen bewegt sich dieser nicht. Verwende ein _Schubgerüst,_ um mehr als nur eine Reihe von Blöcken zu bewegen.", @@ -538,6 +666,8 @@ "block.create.linear_chassis.tooltip.summary": "Eine konfigurierbare Basis für Strukturen, die durch _Mechanische_ _Kolben_ bewegt werden sollen. Diese Blöcke müssen die erste Reihe von Blöcken vor dem Kloben bilden.", "block.create.linear_chassis.tooltip.condition1": "Wenn durch einen Mechanischen Kolben bewegt", "block.create.linear_chassis.tooltip.behaviour1": "_Bewegt_ alle _verbundenen_ _Gerüste_ mit der gleichen Orientierung, und angebrachte Blöcke davor. Wenn der Kolben zurückgezogen wird, werden Blöcke nur zurückgezogen, wenn die Fläche des Gerüsts _klebrig_ ist (Siehe [Strg]).", + "block.create.linear_chassis.tooltip.condition2": "UNLOCALIZED: With Wrench", + "block.create.linear_chassis.tooltip.behaviour2": "UNLOCALIZED: Configure the _range_ for this chassis block. Hold CTRL to modify the range of all attached chassis blocks as well.", "block.create.linear_chassis.tooltip.control1": "Wenn mit einem Schleimball R-geklickt", "block.create.linear_chassis.tooltip.action1": "Lässt die Oberfläche _klebrig_ werden. Wenn der Kolben zurückgezogen wird, _zieht_ das Gerüst alle verbundenen Blöcke _zurück_ in seine Spalte und innerhalb der konfigurierten Reichweite.", @@ -545,6 +675,8 @@ "block.create.radial_chassis.tooltip.summary": "Wird für das Drehen von Strukturen mit dem _Mechanischem_ _Lager_ benutzt.", "block.create.radial_chassis.tooltip.condition1": "Wenn durch ein Lager gedreht", "block.create.radial_chassis.tooltip.behaviour1": "_Dreht_ alle an _klebrigen_ Seiten angebrachten Blöcke (Siehe [Strg]) innerhalb der konfigurierten Reichweite um sich. _Überträgt_ die Rotation zu weiter angebrachten Rotationsgerüsten.", + "block.create.radial_chassis.tooltip.condition2": "UNLOCALIZED: With Wrench", + "block.create.radial_chassis.tooltip.behaviour2": "UNLOCALIZED: Configure the _range_ for this chassis block. Hold CTRL to modify the range of all attached chassis blocks as well.", "block.create.radial_chassis.tooltip.control1": "Wenn mit einem Schleimball R-geklickt", "block.create.radial_chassis.tooltip.action1": "Lässt die geklickte Fläche _klebrig_ werden. Wenn das Gerüst gedreht wird, werden alle verbundenen Blöcke an dieser Seite mit dem Gerüst mitgedreht.", @@ -588,6 +720,8 @@ "block.create.creative_crate.tooltip": "BAUPLANKANONENMACHER", "block.create.creative_crate.tooltip.summary": "Stellt einen unendlichen Vorrat an Blöcken für benachbarte _Bauplaenkanonen_ bereit.", + "block.create.creative_crate.tooltip.condition1": "UNLOCALIZED: When Item in Filter Slot", + "block.create.creative_crate.tooltip.behaviour1": "UNLOCALIZED: Anything _extracting_ from this container will provide an _endless supply_ of the item specified. Items _inserted_ into this crate will be _voided._", "block.create.pulse_repeater.tooltip": "PULSIERENDER VERSTÄRKER", "block.create.pulse_repeater.tooltip.summary": "Ein einfacher Schaltkreis, um durchgehende Redstone-Signale auf eine Länge von _1_ _tick_ zu reduzieren.", @@ -595,6 +729,9 @@ "block.create.adjustable_repeater.tooltip": "VERZÖGERNDER VERSTÄRKER", "block.create.adjustable_repeater.tooltip.summary": "Ein fortgeschrittener _Redstone-Verstärker_ mit einer _konfigurierbaren_ _Verzögerung_ von bis zu 30 Minuten.", + "create.tooltip.wip": "WIP", + "create.tooltip.workInProgress": "Work in progress!", + "_": "Thank you for translating Create!" } diff --git a/src/main/resources/assets/create/lang/default/messages.json b/src/main/resources/assets/create/lang/default/messages.json index 94af8ae4d..deb8aed43 100644 --- a/src/main/resources/assets/create/lang/default/messages.json +++ b/src/main/resources/assets/create/lang/default/messages.json @@ -30,6 +30,7 @@ "create.recipe.mechanical_crafting": "Mechanical Crafting", "create.recipe.automatic_shaped": "Automated Shaped Crafting", "create.recipe.block_cutting": "Block Cutting", + "create.recipe.wood_cutting": "Wood Cutting", "create.recipe.blockzapper_upgrade": "Handheld Blockzapper", "create.recipe.sandpaper_polishing": "Sandpaper Polishing", "create.recipe.mystery_conversion": "Mysterious Conversion", @@ -199,13 +200,19 @@ "create.gui.sequenced_gearshift.title": "Sequenced Gearshift", "create.gui.sequenced_gearshift.instruction": "Instruction", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "Turn by angle", "create.gui.sequenced_gearshift.instruction.turn_angle": "Turn", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Angle", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "Turn to move Piston/Pulley/Gantry", "create.gui.sequenced_gearshift.instruction.turn_distance": "Piston", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distance", - "create.gui.sequenced_gearshift.instruction.wait": "Wait", - "create.gui.sequenced_gearshift.instruction.wait.duration": "Duration", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "Timed Delay", + "create.gui.sequenced_gearshift.instruction.delay": "Delay", + "create.gui.sequenced_gearshift.instruction.delay.duration": "Duration", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "End", "create.gui.sequenced_gearshift.instruction.end": "End", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "Await new Redstone Pulse", + "create.gui.sequenced_gearshift.instruction.await": "Await", "create.gui.sequenced_gearshift.speed": "Speed, Direction", "create.gui.sequenced_gearshift.speed.forward": "Input speed, Forwards", "create.gui.sequenced_gearshift.speed.forward_fast": "Double speed, Forwards", diff --git a/src/main/resources/assets/create/lang/es_es.json b/src/main/resources/assets/create/lang/es_es.json new file mode 100644 index 000000000..787422bb8 --- /dev/null +++ b/src/main/resources/assets/create/lang/es_es.json @@ -0,0 +1,1797 @@ +{ + + "_": "->------------------------] Game Elements [------------------------<-", + + "block.create.acacia_window": "Ventana de acacia", + "block.create.acacia_window_pane": "Panel de ventana de acacia", + "block.create.adjustable_chain_gearshift": "Cadena de transmisión ajustable", + "block.create.adjustable_crate": "Caja ajustable", + "block.create.adjustable_pulse_repeater": "Repetidor de pulso ajustable", + "block.create.adjustable_repeater": "Repetidor ajustable", + "block.create.analog_lever": "Palanca analógica", + "block.create.andesite_belt_funnel": "Embudo de cinta de andesita", + "block.create.andesite_bricks": "Ladrillos de andesita", + "block.create.andesite_bricks_slab": "Losa de ladrillos de andesita", + "block.create.andesite_bricks_stairs": "Escaleras de ladrillos de andesita", + "block.create.andesite_bricks_wall": "Pared de ladrillos de andesita", + "block.create.andesite_casing": "Revestidor de andesita", + "block.create.andesite_cobblestone": "Adoquín de andesita", + "block.create.andesite_cobblestone_slab": "Losa de adoquín de andesita", + "block.create.andesite_cobblestone_stairs": "Escaleras de adoquines de andesita", + "block.create.andesite_cobblestone_wall": "Muro de adoquines de andesita", + "block.create.andesite_encased_shaft": "Eje revestido de andesita", + "block.create.andesite_funnel": "Embudo de andesita", + "block.create.andesite_pillar": "Poste de andesita", + "block.create.andesite_tunnel": "Túnel de Andesita", + "block.create.basin": "Cuenca", + "block.create.belt": "Cinta", + "block.create.birch_window": "Ventana de abedul", + "block.create.birch_window_pane": "Panel de ventana de abedul", + "block.create.black_sail": "Vela negra", + "block.create.black_seat": "Asiento negro", + "block.create.black_valve_handle": "Asa de válvula negra", + "block.create.blaze_burner": "Quemador de Blaze", + "block.create.blue_sail": "Vela azul", + "block.create.blue_seat": "Asiento azul", + "block.create.blue_valve_handle": "Asa de válvula azul", + "block.create.brass_belt_funnel": "Embudo de cinta de latón", + "block.create.brass_block": "Bloque de latón", + "block.create.brass_casing": "Revestidor de latón", + "block.create.brass_encased_shaft": "Eje revestido de latón", + "block.create.brass_funnel": "Embudo de latón", + "block.create.brass_tunnel": "Túnel de latón", + "block.create.brown_sail": "Vela marrón", + "block.create.brown_seat": "Asiento marrón", + "block.create.brown_valve_handle": "Asa de válvula marrón", + "block.create.cart_assembler": "Ensamblador de vagonetas", + "block.create.chiseled_dark_scoria": "Escoria oscura cincelada", + "block.create.chiseled_dolomite": "Dolomita cincelada", + "block.create.chiseled_gabbro": "Gabro cincelado", + "block.create.chiseled_limestone": "Caliza cincelada", + "block.create.chiseled_scoria": "Escoria cincelada", + "block.create.chiseled_weathered_limestone": "Piedra caliza erosionada cincelada", + "block.create.chocolate": "Chocolate", + "block.create.chute": "Ducto", + "block.create.clockwork_bearing": "Rodamiento de reloj", + "block.create.clutch": "Embrague", + "block.create.cogwheel": "Rueda dentada", + "block.create.content_observer": "Observador de contenidos", + "block.create.controller_rail": "Raíl de control", + "block.create.copper_block": "Bloque de cobre", + "block.create.copper_casing": "Revestidor de caliza", + "block.create.copper_ore": "Mineral de cobre", + "block.create.copper_shingles": "Bloque de tejas de cobre", + "block.create.copper_tiles": "Bloque de baldosas de cobre", + "block.create.copper_valve_handle": "Asa de válvula de cobre", + "block.create.creative_crate": "Caja creativa", + "block.create.creative_fluid_tank": "Tanque de fluidos creativo", + "block.create.creative_motor": "Motor creativo", + "block.create.crushing_wheel": "Rueda trituradora", + "block.create.crushing_wheel_controller": "Controlador de Rueda trituradora", + "block.create.cuckoo_clock": "Reloj Cucú", + "block.create.cyan_sail": "Vela cian", + "block.create.cyan_seat": "Asiento cian", + "block.create.cyan_valve_handle": "Asa de válvula cian", + "block.create.dark_oak_window": "Ventana de roble oscuro", + "block.create.dark_oak_window_pane": "Panel de ventana de roble oscuro", + "block.create.dark_scoria": "Escoria oscura", + "block.create.dark_scoria_bricks": "Ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_stairs": "Escaleras de ladrillos de escoria oscura", + "block.create.dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura", + "block.create.dark_scoria_cobblestone": "Adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_slab": "Losa de adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_stairs": "Escaleras de adoquines de escoria oscura", + "block.create.dark_scoria_cobblestone_wall": "Pared de adoquines de escoria oscura", + "block.create.dark_scoria_pillar": "Pilar de escoria oscura", + "block.create.deployer": "Desplegador", + "block.create.depot": "Depósito", + "block.create.diorite_bricks": "Ladrillos de diorita", + "block.create.diorite_bricks_slab": "Losa de ladrillos de diorita", + "block.create.diorite_bricks_stairs": "Escaleras de ladrillos de diorita", + "block.create.diorite_bricks_wall": "Pared de ladrillos de diorita", + "block.create.diorite_cobblestone": "Adoquín de diorita", + "block.create.diorite_cobblestone_slab": "Losa de adoquínes de diorita", + "block.create.diorite_cobblestone_stairs": "Escaleras de adoquines de diorita", + "block.create.diorite_cobblestone_wall": "Pared de adoquines de diorita", + "block.create.diorite_pillar": "Pilar de diorita", + "block.create.dolomite": "Dolomita", + "block.create.dolomite_bricks": "Ladrillos de dolomita", + "block.create.dolomite_bricks_slab": "Losa de ladrillos de dolomita", + "block.create.dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita", + "block.create.dolomite_bricks_wall": "Pared de ladrillos de dolomita", + "block.create.dolomite_cobblestone": "Adoquín de dolomita", + "block.create.dolomite_cobblestone_slab": "Losa de adoquín de dolomita", + "block.create.dolomite_cobblestone_stairs": "Escaleras de adoquines de dolomita", + "block.create.dolomite_cobblestone_wall": "Pared de adoquines de dolomita", + "block.create.dolomite_pillar": "Pilar de dolomita", + "block.create.encased_chain_drive": "Cadena de transmisión revestida", + "block.create.encased_fan": "Ventilador revestido", + "block.create.encased_fluid_pipe": "Tubería de fluidos de cobre revestida", + "block.create.fancy_andesite_bricks": "Ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_slab": "Ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_stairs": "Escaleras de ladrillos de andesita elegantes", + "block.create.fancy_andesite_bricks_wall": "Pared de ladrillos de andesita elegantes", + "block.create.fancy_dark_scoria_bricks": "Ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_slab": "Losa de ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_stairs": "Escalera de ladrillos de escoria oscura elegantes", + "block.create.fancy_dark_scoria_bricks_wall": "Pared de ladrillos de escoria oscura elegantes", + "block.create.fancy_diorite_bricks": "Ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_slab": "Losa de ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_stairs": "Escaleras de ladrillos de diorita elegantes", + "block.create.fancy_diorite_bricks_wall": "Pared de ladrillos de diorita elegantes", + "block.create.fancy_dolomite_bricks": "Ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_slab": "Losa de ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_stairs": "Escaleras de ladrillos de dolomita elegantes", + "block.create.fancy_dolomite_bricks_wall": "Pared de ladrillos de dolomita elegantes", + "block.create.fancy_gabbro_bricks": "Ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_slab": "Losa de ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_stairs": "Escaleras de ladrillos de gabro elegantes", + "block.create.fancy_gabbro_bricks_wall": "Pared de ladrillos de gabro elegantes", + "block.create.fancy_granite_bricks": "Ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_slab": "Losa de ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_stairs": "Escaleras de ladrillos de granito elegantes", + "block.create.fancy_granite_bricks_wall": "Pared de ladrillos de granito elegantes", + "block.create.fancy_limestone_bricks": "Ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_slab": "Losa de ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza elegantes", + "block.create.fancy_limestone_bricks_wall": "Pared de ladrillos de piedra caliza elegantes", + "block.create.fancy_scoria_bricks": "Ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_slab": "Losa de ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_stairs": "Escaleras de ladrillos de escoria elegantes", + "block.create.fancy_scoria_bricks_wall": "Pared de ladrillos de escoria elegantes", + "block.create.fancy_weathered_limestone_bricks": "Ladrillos de piedra de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_slab": "Losa de ladrillos de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_stairs": "Escaleras de ladrillos de caliza erosionada elegantes", + "block.create.fancy_weathered_limestone_bricks_wall": "Pared de ladrillos de caliza erosionada elegantes", + "block.create.fluid_pipe": "Tubería de fluidos de cobre", + "block.create.fluid_tank": "Depósito de fluidos", + "block.create.fluid_valve": "Válvula de fluidos", + "block.create.flywheel": "Rueda de inercia", + "block.create.framed_glass": "Cristal enmarcado", + "block.create.framed_glass_pane": "Panel de cristal enmarcado", + "block.create.furnace_engine": "Motor de horno", + "block.create.gabbro": "Gabro", + "block.create.gabbro_bricks": "Ladrillos de gabro", + "block.create.gabbro_bricks_slab": "Losa de ladrillos de gabro", + "block.create.gabbro_bricks_stairs": "Escaleras de ladrillos de gabro", + "block.create.gabbro_bricks_wall": "Pared de ladrillos de gabro", + "block.create.gabbro_cobblestone": "Adoquín de gabro", + "block.create.gabbro_cobblestone_slab": "Losa de adoquínes de gabro", + "block.create.gabbro_cobblestone_stairs": "Escaleras de adoquínes de gabro", + "block.create.gabbro_cobblestone_wall": "Pared de adoquínes de gabro", + "block.create.gabbro_pillar": "Pilar de gabro", + "block.create.gantry_pinion": "Piñón de grúa", + "block.create.gantry_shaft": "Eje de grúa", + "block.create.gearbox": "Caja de transmisión", + "block.create.gearshift": "Caja de cambios", + "block.create.glass_fluid_pipe": "Tubo de cristal para fluidos", + "block.create.granite_bricks": "Ladrillos de granito", + "block.create.granite_bricks_slab": "Losa de ladrillos de granito", + "block.create.granite_bricks_stairs": "Escaleras de ladrillos de granito", + "block.create.granite_bricks_wall": "Pared de ladrillos de granito", + "block.create.granite_cobblestone": "Adoquín de granito", + "block.create.granite_cobblestone_slab": "Losa de adoquínes de granito", + "block.create.granite_cobblestone_stairs": "Escaleras de adoquínes de granito", + "block.create.granite_cobblestone_wall": "Pared de adoquínes de granito", + "block.create.granite_pillar": "Pilar de granito", + "block.create.gray_sail": "Vela gris", + "block.create.gray_seat": "Asiento gris", + "block.create.gray_valve_handle": "Asa de válvula gris", + "block.create.green_sail": "Vela verde", + "block.create.green_seat": "Asiento verde", + "block.create.green_valve_handle": "Asa de válvula verde", + "block.create.hand_crank": "Manivela", + "block.create.honey": "Miel", + "block.create.horizontal_framed_glass": "Cristal con marco horizontal", + "block.create.horizontal_framed_glass_pane": "Panel de cristal con marco horizontal", + "block.create.hose_pulley": "Polea de manguera", + "block.create.item_drain": "Drenador de elementos", + "block.create.jungle_window": "Ventana de jungla", + "block.create.jungle_window_pane": "Panel de ventana de jungla", + "block.create.large_cogwheel": "Rueda dentada grande", + "block.create.layered_andesite": "Andesita estratificada", + "block.create.layered_dark_scoria": "Escoria oscura estratificada", + "block.create.layered_diorite": "Diorita estratificada", + "block.create.layered_dolomite": "Dolomita estratificada", + "block.create.layered_gabbro": "Gabro estratificado", + "block.create.layered_granite": "Granito estratificado", + "block.create.layered_limestone": "Piedra caliza estratificada", + "block.create.layered_scoria": "Escoria estratificada", + "block.create.layered_weathered_limestone": "Caliza erosionada estratificada", + "block.create.light_blue_sail": "Vela azul claro", + "block.create.light_blue_seat": "Asiento azul claro", + "block.create.light_blue_valve_handle": "Asa de válvula azul claro", + "block.create.light_gray_sail": "Vela gris claro", + "block.create.light_gray_seat": "Asiento gris claro", + "block.create.light_gray_valve_handle": "Asa de válvula gris claro", + "block.create.lime_sail": "Vela lima", + "block.create.lime_seat": "Asiento lima", + "block.create.lime_valve_handle": "Asa de válvula lima", + "block.create.limesand": "Arena caliza", + "block.create.limestone": "Piedra caliza", + "block.create.limestone_bricks": "Ladrillos de piedra caliza", + "block.create.limestone_bricks_slab": "Losa de ladrillos de piedra caliza", + "block.create.limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza", + "block.create.limestone_bricks_wall": "Pared de ladrillos de piedra caliza", + "block.create.limestone_cobblestone": "Adoquínes de piedra caliza", + "block.create.limestone_cobblestone_slab": "Losa de adoquines de piedra caliza", + "block.create.limestone_cobblestone_stairs": "Escaleras de adoquines de piedra caliza", + "block.create.limestone_cobblestone_wall": "Pared de adoquines de piedra caliza", + "block.create.limestone_pillar": "Pilar de piedra caliza", + "block.create.linear_chassis": "Chasis lineal", + "block.create.lit_blaze_burner": "Quemador de Blaze encendido", + "block.create.magenta_sail": "Vela magenta", + "block.create.magenta_seat": "Asiento magenta", + "block.create.magenta_valve_handle": "Asa de válvula magenta", + "block.create.mechanical_arm": "Brazo mecánico", + "block.create.mechanical_bearing": "Rodamiento mecánico", + "block.create.mechanical_crafter": "Autoensamblador mecánico", + "block.create.mechanical_drill": "Taladro mecánico", + "block.create.mechanical_harvester": "Cosechadora mecánica", + "block.create.mechanical_mixer": "Mezcladora mecánica", + "block.create.mechanical_piston": "Pistón mecánico", + "block.create.mechanical_piston_head": "Cabezal de pistón mecánico", + "block.create.mechanical_plough": "Arado mecánico", + "block.create.mechanical_press": "Prensa mecánica", + "block.create.mechanical_pump": "Bomba mecánica", + "block.create.mechanical_saw": "Sierra mecánica", + "block.create.metal_bracket": "Soporte de metal para ejes", + "block.create.millstone": "Piedra de molino", + "block.create.minecart_anchor": "Ancla de vagonetas", + "block.create.mossy_andesite": "Andesita musgosa", + "block.create.mossy_dark_scoria": "Escoria oscura musgosa", + "block.create.mossy_diorite": "Diorita musgosa", + "block.create.mossy_dolomite": "Dolomita musgosa", + "block.create.mossy_gabbro": "Gabro musgoso", + "block.create.mossy_granite": "Granito musgoso", + "block.create.mossy_limestone": "Caliza musgosa", + "block.create.mossy_scoria": "Escoria musgosa", + "block.create.mossy_weathered_limestone": "Caliza erosionada musgosa", + "block.create.mysterious_cuckoo_clock": "Reloj cucú", + "block.create.natural_scoria": "Escoria natural", + "block.create.nixie_tube": "Tubo Nixie", + "block.create.nozzle": "Boquilla", + "block.create.oak_window": "Ventana de roble", + "block.create.oak_window_pane": "Panel de ventana de roble", + "block.create.orange_sail": "Vela naranja", + "block.create.orange_seat": "Asiento naranja", + "block.create.orange_valve_handle": "Asa de válvula naranja", + "block.create.ornate_iron_window": "Ventana de hierro ornamentada", + "block.create.ornate_iron_window_pane": "Panel de ventana de hierro ornamentada", + "block.create.overgrown_andesite": "Andesita sobredimensionada", + "block.create.overgrown_dark_scoria": "Escoria oscura sobredimensionada", + "block.create.overgrown_diorite": "Diorita sobredimensionada", + "block.create.overgrown_dolomite": "Dolomita sobredimensionada", + "block.create.overgrown_gabbro": "Gabro sobredimensionado", + "block.create.overgrown_granite": "Granito sobredimensionado", + "block.create.overgrown_limestone": "Caliza sobredimensionada", + "block.create.overgrown_scoria": "Escoria sobredimensionada", + "block.create.overgrown_weathered_limestone": "Caliza erosionada sobredimensionada", + "block.create.paved_andesite": "Andesita pavimentada", + "block.create.paved_andesite_slab": "Losa de andesita pavimentada", + "block.create.paved_andesite_stairs": "Escaleras de andesita pavimentada", + "block.create.paved_andesite_wall": "Pared de andesita pavimentada", + "block.create.paved_dark_scoria": "Escoria oscura pavimentada", + "block.create.paved_dark_scoria_slab": "Losa de escoria oscura pavimentada", + "block.create.paved_dark_scoria_stairs": "Escaleras de escoria oscura pavimentada", + "block.create.paved_dark_scoria_wall": "Pared de escoria oscura pavimentad", + "block.create.paved_diorite": "Diorita pavimentada", + "block.create.paved_diorite_slab": "Losa de diorita pavimentada", + "block.create.paved_diorite_stairs": "Escaleras de diorita pavimentada", + "block.create.paved_diorite_wall": "Pared de diorita pavimentad", + "block.create.paved_dolomite": "Dolomita pavimentada", + "block.create.paved_dolomite_slab": "Losa de dolomita pavimentada", + "block.create.paved_dolomite_stairs": "Escaleras de dolomita pavimentada", + "block.create.paved_dolomite_wall": "Pared de dolomita pavimentada", + "block.create.paved_gabbro": "Gabro pavimentado", + "block.create.paved_gabbro_slab": "Losa de gabro pavimentado", + "block.create.paved_gabbro_stairs": "Escaleras de gabro pavimentado", + "block.create.paved_gabbro_wall": "Pared de gabro pavimentado", + "block.create.paved_granite": "Granito pavimentado", + "block.create.paved_granite_slab": "Losa de granito pavimentado", + "block.create.paved_granite_stairs": "Escaleras de granito pavimentado", + "block.create.paved_granite_wall": "Pared de granito pavimentado", + "block.create.paved_limestone": "Piedra caliza pavimentada", + "block.create.paved_limestone_slab": "Losa de piedra caliza pavimentada", + "block.create.paved_limestone_stairs": "Escaleras de piedra caliza pavimentada", + "block.create.paved_limestone_wall": "Pared de piedra caliza pavimentada", + "block.create.paved_scoria": "Escoria pavimentada", + "block.create.paved_scoria_slab": "Losa de escoria pavimentada", + "block.create.paved_scoria_stairs": "Escaleras de escoria pavimentada", + "block.create.paved_scoria_wall": "Pared de escoria pavimentada", + "block.create.paved_weathered_limestone": "Piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_slab": "Losa de piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pavimentada", + "block.create.paved_weathered_limestone_wall": "Pared de piedra caliza erosionada pavimentada", + "block.create.pink_sail": "Vela rosa", + "block.create.pink_seat": "Asiento rosa", + "block.create.pink_valve_handle": "Asa de válvula rosa", + "block.create.piston_extension_pole": "Pértiga de extensión de pistón", + "block.create.polished_dark_scoria": "Escoria oscura pulida", + "block.create.polished_dark_scoria_slab": "Losa de escoria oscura pulida", + "block.create.polished_dark_scoria_stairs": "Escaleras de escoria oscura pulida", + "block.create.polished_dark_scoria_wall": "Pared de escoria oscura pulida", + "block.create.polished_dolomite": "Dolomita pulida", + "block.create.polished_dolomite_slab": "Losa de dolomita pulida", + "block.create.polished_dolomite_stairs": "Escaleras de dolomita pulidas", + "block.create.polished_dolomite_wall": "Pared de dolomita pulida", + "block.create.polished_gabbro": "Gabro pulido", + "block.create.polished_gabbro_slab": "Losa de gabro pulido", + "block.create.polished_gabbro_stairs": "Escaleras de gabro pulido", + "block.create.polished_gabbro_wall": "Pared de gabro pulido", + "block.create.polished_limestone": "Piedra caliza pulida", + "block.create.polished_limestone_slab": "Losa de piedra caliza pulida", + "block.create.polished_limestone_stairs": "Escaleras de piedra caliza pulidas", + "block.create.polished_limestone_wall": "Pared de piedra caliza pulida", + "block.create.polished_scoria": "Escoria pulida", + "block.create.polished_scoria_slab": "Losa de escoria pulida", + "block.create.polished_scoria_stairs": "Escaleras de losa pulida", + "block.create.polished_scoria_wall": "Pared de escoria pulida", + "block.create.polished_weathered_limestone": "Piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_slab": "Losa de piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_stairs": "Escaleras de piedra caliza erosionada pulida", + "block.create.polished_weathered_limestone_wall": "Pared de piedra caliza erosionada pulida", + "block.create.portable_fluid_interface": "Interfaz de fluidos portátil", + "block.create.portable_storage_interface": "Interfaz de almacenamiento portátil", + "block.create.powered_latch": "Palanca motorizada", + "block.create.powered_toggle_latch": "Palanca de cierre motorizada", + "block.create.pulley_magnet": "Imán de la polea", + "block.create.pulse_repeater": "Repetidor de pulsos de Redstone", + "block.create.purple_sail": "Vela morada", + "block.create.purple_seat": "Asiento morado", + "block.create.purple_valve_handle": "Asa de válvula morada", + "block.create.radial_chassis": "Chasis radial", + "block.create.red_sail": "Vela roja", + "block.create.red_seat": "Asiento rojo", + "block.create.red_valve_handle": "Asa de válvula roja", + "block.create.redstone_contact": "Contacto de Redstone", + "block.create.redstone_link": "Enlace de Redstone", + "block.create.refined_radiance_casing": "Revestidor de radiante", + "block.create.reinforced_rail": "Raíl reforzado", + "block.create.rope": "Soga", + "block.create.rope_pulley": "Polea de cuerda", + "block.create.rotation_speed_controller": "Controlador de velocidad de rotación", + "block.create.sail_frame": "Marco de vela", + "block.create.schematic_table": "Tabla de esquemas", + "block.create.schematicannon": "Schematicannon", + "block.create.scoria": "Escoria", + "block.create.scoria_bricks": "Ladrillos de escoria", + "block.create.scoria_bricks_slab": "Losa de ladrillos de escoria", + "block.create.scoria_bricks_stairs": "Escaleras de ladrillos de escoria", + "block.create.scoria_bricks_wall": "Pared de ladrillos de escoria", + "block.create.scoria_cobblestone": "Adoquín de escoria", + "block.create.scoria_cobblestone_slab": "Losa de adoquínes de escoria", + "block.create.scoria_cobblestone_stairs": "Escaleras de adoquines de escoria", + "block.create.scoria_cobblestone_wall": "Pared de adoquines de escoria", + "block.create.scoria_pillar": "Pilar de escoria", + "block.create.secondary_linear_chassis": "Chasis lineal secundario", + "block.create.sequenced_gearshift": "Palanca de cambios secuencial", + "block.create.shadow_steel_casing": "Revestidor sombrío", + "block.create.shaft": "Eje", + "block.create.smart_chute": "Ducto inteligente", + "block.create.smart_fluid_pipe": "Tubería de fluidos inteligente", + "block.create.speedometer": "Velocímetro", + "block.create.spout": "Surtidor", + "block.create.spruce_window": "Ventana de abeto", + "block.create.spruce_window_pane": "Panel de ventana de abeto", + "block.create.sticky_mechanical_piston": "Pistón mecánico pegajoso", + "block.create.stockpile_switch": "Interruptor de acopio", + "block.create.stressometer": "Estresómetro", + "block.create.tiled_glass": "Vidrio esmaltado", + "block.create.tiled_glass_pane": "Panel de vidrio esmaltado", + "block.create.turntable": "Plataforma giratoria mecánica", + "block.create.vertical_framed_glass": "Vidrio esmaltado vertical", + "block.create.vertical_framed_glass_pane": "Panel de vidrio esmaltado vertical", + "block.create.water_wheel": "Rueda hidráulica mecánica", + "block.create.weathered_limestone": "Piedra caliza erosionada", + "block.create.weathered_limestone_bricks": "Ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_slab": "Losa de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_stairs": "Escaleras de ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_bricks_wall": "Pared de ladrillos de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone": "Adoquín de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_slab": "Losa de adoquín de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_stairs": "Escaleras de adoquín de piedra caliza erosionada", + "block.create.weathered_limestone_cobblestone_wall": "Pared de adoquínes de piedra caliza erosionada", + "block.create.weathered_limestone_pillar": "Pilar de piedra caliza erosionada", + "block.create.white_sail": "Vela blanca", + "block.create.white_seat": "Asiento blanco", + "block.create.white_valve_handle": "Asa de válvula blanco", + "block.create.windmill_bearing": "Rodamiento del molino de viento", + "block.create.wooden_bracket": "Soporte de madera para ejes", + "block.create.yellow_sail": "Vela amarilla", + "block.create.yellow_seat": "Asiento amarillo", + "block.create.yellow_valve_handle": "Asa de válvula amarillo", + "block.create.zinc_block": "Bloque de zinc", + "block.create.zinc_ore": "Mineral de zinc", + + "entity.create.contraption": "Artilugio", + "entity.create.gantry_contraption": "Artilugio de grúa", + "entity.create.seat": "Asiento", + "entity.create.stationary_contraption": "Artilugio estacionario", + "entity.create.super_glue": "Super Pegamento", + + "fluid.create.milk": "Leche", + "fluid.create.potion": "Poción", + "fluid.create.tea": "Té del Constructor", + + "item.create.andesite_alloy": "Aleación de andesita", + "item.create.attribute_filter": "Filtro de atributos", + "item.create.bar_of_chocolate": "Barra de chocolate", + "item.create.belt_connector": "Correa", + "item.create.blaze_cake": "Pastel de Blaze", + "item.create.blaze_cake_base": "Base de Pastel de Blaze", + "item.create.brass_hand": "Mano de latón", + "item.create.brass_ingot": "Lingote de latón", + "item.create.brass_nugget": "Pepita de latón", + "item.create.brass_sheet": "Lámina de latón", + "item.create.builders_tea": "Té del Constructor", + "item.create.chest_minecart_contraption": "Artilugio de vagoneta con cofre", + "item.create.chocolate_bucket": "Cubo de chocolate", + "item.create.chromatic_compound": "Compuesto cromático", + "item.create.cinder_flour": "Harina de ceniza", + "item.create.copper_ingot": "Lingote de cobre", + "item.create.copper_nugget": "Pepita de cobre", + "item.create.copper_sheet": "Lámina de cobre", + "item.create.crafter_slot_cover": "Tapa de ranura del Autoensamblador mecánico", + "item.create.crushed_aluminum_ore": "Mineral de aluminio molido", + "item.create.crushed_brass": "Latón molido", + "item.create.crushed_copper_ore": "Mineral de cobre molido", + "item.create.crushed_gold_ore": "Mineral de oro molido", + "item.create.crushed_iron_ore": "Mineral de hierro molido", + "item.create.crushed_lead_ore": "Mineral de plomo molido", + "item.create.crushed_nickel_ore": "Mineral de níquel molido", + "item.create.crushed_osmium_ore": "Mineral de osmio molido", + "item.create.crushed_platinum_ore": "Mineral de platino molido", + "item.create.crushed_quicksilver_ore": "Mineral de mercurio molido", + "item.create.crushed_silver_ore": "Mineral de plata molido", + "item.create.crushed_tin_ore": "Mineral de estaño molido", + "item.create.crushed_uranium_ore": "Mineral de uranio molido", + "item.create.crushed_zinc_ore": "Mineral de zinc molido", + "item.create.deforester": "Deforestador", + "item.create.dough": "Masilla", + "item.create.electron_tube": "Tubo de electrones", + "item.create.empty_blaze_burner": "Quemador de Blaze vacío", + "item.create.empty_schematic": "Esquema vacío", + "item.create.extendo_grip": "Agarre extendido", + "item.create.filter": "Filtro", + "item.create.furnace_minecart_contraption": "Artilugio de vagoneta de horno", + "item.create.goggles": "Gafas del Ingeniero", + "item.create.golden_sheet": "Lámina de oro", + "item.create.handheld_blockzapper": "Blockzapper", + "item.create.handheld_worldshaper": "Worldshaper", + "item.create.honey_bucket": "Cubo de miel", + "item.create.integrated_circuit": "Chip de circuito integrado", + "item.create.iron_sheet": "Lámina de hierro", + "item.create.lapis_sheet": "Lámina de lapislázuli", + "item.create.minecart_contraption": "Artilugio de vagoneta", + "item.create.minecart_coupling": "Acoplamiento de vagoneta", + "item.create.polished_rose_quartz": "Cuarzo rosado pulido", + "item.create.powdered_obsidian": "Obsidiana en polvo", + "item.create.propeller": "Hélice", + "item.create.red_sand_paper": "Papel de lija rojo", + "item.create.refined_radiance": "Resplandor refinado", + "item.create.rose_quartz": "Cuarzo rosado", + "item.create.sand_paper": "Papel de lija", + "item.create.schematic": "Esquema", + "item.create.schematic_and_quill": "Esquema y Pluma", + "item.create.shadow_steel": "Acero sombrío", + "item.create.super_glue": "Super Pegamento", + "item.create.tree_fertilizer": "Fertilizador de árboles", + "item.create.vertical_gearbox": "Caja de transmisión vertical", + "item.create.wand_of_symmetry": "Varita de simetría", + "item.create.wheat_flour": "Harina de trigo", + "item.create.whisk": "Batidora", + "item.create.wrench": "Llave inglesa", + "item.create.zinc_ingot": "Lingote de zinc", + "item.create.zinc_nugget": "Pepita de zinc", + + + "_": "->------------------------] Advancements [------------------------<-", + + "advancement.create.root": "Bienvenido a Create", + "advancement.create.root.desc": "¡Es hora de empezar a construir increíbles Artilugios!", + "advancement.create.andesite_alloy": "Aliteraciones en abundancia", + "advancement.create.andesite_alloy.desc": "Los materiales de Create tienen nombres extraños, la aleación de andesita es uno de ellos.", + "advancement.create.its_alive": "Está Vivo!", + "advancement.create.its_alive.desc": "Vea cómo gira su primer componente cinético.", + "advancement.create.shifting_gears": "Cambiando de marcha", + "advancement.create.shifting_gears.desc": "Conecta una rueda dentada grande a una pequeña, lo que te permitirá cambiar la velocidad de tu artilugio.", + "advancement.create.overstressed": "Sobrecargado", + "advancement.create.overstressed.desc": "Experimenta los límites del estrés.", + "advancement.create.belt": "Paseo de algas", + "advancement.create.belt.desc": "Conectar dos ejes con una correa.", + "advancement.create.tunnel": "Cúbrete!", + "advancement.create.tunnel.desc": "Embellece tu correa con un Túnel.", + "advancement.create.splitter_tunnel": "Divide y vencerás", + "advancement.create.splitter_tunnel.desc": "Crear un divisor con un grupo de túneles de latón.", + "advancement.create.chute": "Caída en picado", + "advancement.create.chute.desc": "Coloque un ducto, la contrapartida vertical de la correa.", + "advancement.create.upward_chute": "Abducción aérea", + "advancement.create.upward_chute.desc": "Observe cómo un objeto lanzado vuela hacia un paracaídas impulsado por un ventilador.", + "advancement.create.belt_funnel": "Colgantes con forma de embudo", + "advancement.create.belt_funnel.desc": "Coloca un embudo lateral encima de una cinta o depósito para crear un tipo especial.", + "advancement.create.belt_funnel_kiss": "Los loros y las aletas", + "advancement.create.belt_funnel_kiss.desc": "Haz besar dos embudos montados con una cinta.", + "advancement.create.fan": "Maestro mecánico del aire", + "advancement.create.fan.desc": "Monta la corriente de aire proporcionada por un ventilador revestido.", + "advancement.create.fan_lava": "Calentador geotérmico", + "advancement.create.fan_lava.desc": "Quedar atrapado en una corriente de aire que funde las cosas.", + "advancement.create.fan_water": "Lavado de la ropa", + "advancement.create.fan_water.desc": "Quedar atrapado en una corriente de aire que lava las cosas.", + "advancement.create.fan_smoke": "Fuelle mecánico", + "advancement.create.fan_smoke.desc": "Quedar atrapado en una corriente de aire que humea los artículos.", + "advancement.create.wrench": "Configurar convenientemente", + "advancement.create.wrench.desc": "Crea una llave inglesa para ayudarte a construir tus artilugios.", + "advancement.create.goggles": "Stress-O-Vision", + "advancement.create.goggles.desc": "Crea unas Gafas del Ingeniero para ayudarte a obtener más información cinética de los componentes.", + "advancement.create.speedometer": "Pero, ¿con qué rapidez exactamente??", + "advancement.create.speedometer.desc": "Coloca y alimenta un Velocímetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.stressometer": "Pero, ¿cuán estresado exactamente??", + "advancement.create.stressometer.desc": "Coloca y alimenta un Estresómetro. Míralo a través de las gafas para leer su valor exacto.", + "advancement.create.aesthetics": "Boom, Estética!", + "advancement.create.aesthetics.desc": "Colocar los soportes en un eje, tubo y rueda dentada.", + "advancement.create.reinforced": "Boom, Reforzado!", + "advancement.create.reinforced.desc": "Utilizar bloques de revestimiento en un eje, un tubo y una correa.", + "advancement.create.water_wheel": "Aprovechar la hidráulica", + "advancement.create.water_wheel.desc": "Coloca una Rueda hidráulica e intenta hacerla girar.", + "advancement.create.chocolate_wheel": "Potencia de buen gusto", + "advancement.create.chocolate_wheel.desc": "Hacer funcionar una rueda de agua con chocolate fundido.", + "advancement.create.lava_wheel": "Rueda de Magma", + "advancement.create.lava_wheel.desc": "Esto no debió haber funcionado.", + "advancement.create.cuckoo": "¿Es el momento?", + "advancement.create.cuckoo.desc": "Presenciar cómo un Reloj de cucú anuncia la hora de acostarse.", + "advancement.create.millstone": "Triturador de bolsillo", + "advancement.create.millstone.desc": "Colocar y alimentar una Piedra de molino.", + "advancement.create.windmill": "Una suave brisa", + "advancement.create.windmill.desc": "Montar un molino de viento.", + "advancement.create.maxed_windmill": "Una fuerte brisa", + "advancement.create.maxed_windmill.desc": "Montar un molino de viento de máxima intensidad.", + "advancement.create.andesite_casing": "La edad de la andesita", + "advancement.create.andesite_casing.desc": "Utiliza un poco de aleación de andesita y madera para crear un revestimiento básico.", + "advancement.create.mechanical_drill": "Interruptores fijos", + "advancement.create.mechanical_drill.desc": "Colocar y alimentar un taladro mecánico.", + "advancement.create.press": "¡La prensa se pone en marcha!", + "advancement.create.press.desc": "Activa una prensa mecánica y utilízala para crear algunas láminas.", + "advancement.create.polished_rose_quartz": "Diamantes rosas", + "advancement.create.polished_rose_quartz.desc": "Utiliza un trozo de papel de lija para pulir el cuarzo rosa hasta que se vuelva transparente.", + "advancement.create.electron_tube": "Beep Boop", + "advancement.create.electron_tube.desc": "Haz algunos Tubos de Electrones, útiles en la fabricación de maquinaria menos primitiva.", + "advancement.create.mechanical_saw": "Picado estacionario", + "advancement.create.mechanical_saw.desc": "Colocar y alimentar una sierra mecánica.", + "advancement.create.basin": "Funcionamiento de la cuenca", + "advancement.create.basin.desc": "Coloca una Cuenca e intenta arrojar objetos en ella.", + "advancement.create.mixer": "Mezcla de colores", + "advancement.create.mixer.desc": "Coloque una batidora mecánica sobre el lavabo, enciéndala y empiece a mezclar algunos ingredientes.", + "advancement.create.blaze_burner": "Una chimenea viva", + "advancement.create.blaze_burner.desc": "Obtener un Quemador de Blaze.", + "advancement.create.compact": "Compactación automática", + "advancement.create.compact.desc": "Utiliza una prensa y una palangana para compactar algunos elementos.", + "advancement.create.brass": "Aleaciones reales", + "advancement.create.brass.desc": "Utiliza Cobre molido y Zinc molido para crear algo de latón.", + "advancement.create.brass_casing": "La Edad de Latón", + "advancement.create.brass_casing.desc": "Utiliza el latón recién obtenido y algo de madera para crear un revestimiento más avanzado.", + "advancement.create.copper_casing": "La Edad de Cobre", + "advancement.create.copper_casing.desc": "Utiliza algunas láminas de cobre y madera para crear algunos revestimientos de cobre.", + "advancement.create.spout": "Sploosh", + "advancement.create.spout.desc": "Observar el llenado de un elemento fluido usando una boquilla.", + "advancement.create.spout_potion": "Cervecera global", + "advancement.create.spout_potion.desc": "Mira cómo un pico llena una botella con líquido de poción.", + "advancement.create.chocolate": "Un mundo de imaginación", + "advancement.create.chocolate.desc": "Obtener un cubo de chocolate fundido.", + "advancement.create.item_drain": "Drenaje de la ropa", + "advancement.create.item_drain.desc": "Ver cómo se vacía un elemento fluido mediante una drenadora de elementos.", + "advancement.create.chained_item_drain": "Déjalo rodar!", + "advancement.create.chained_item_drain.desc": "Observa cómo un objeto rueda por varios drenadores de elementos encadenados.", + "advancement.create.glass_pipe": "Espía del flujo", + "advancement.create.glass_pipe.desc": "Observe cómo se propaga el fluido a través de una tubería de fluidos con ventanas. Las tuberías de fluido rectas se convierten en ventanas cuando se utiliza una llave en ellas.", + "advancement.create.pipe_collision": "No cruzar nunca los arroyos", + "advancement.create.pipe_collision.desc": "Vea cómo se unen dos fluidos en su red de tuberías.", + "advancement.create.pipe_spill": "¡Hay una fuga!", + "advancement.create.pipe_spill.desc": "Observe cómo un extremo abierto de una tubería toma o deposita fluidos en el mundo.", + "advancement.create.hose_pulley": "Vertidos industriales", + "advancement.create.hose_pulley.desc": "Bajar una polea de manguera y ver cómo se vacía o se llena un cuerpo de líquido.", + "advancement.create.infinite_water": "Drenando el océano", + "advancement.create.infinite_water.desc": "Bombea de una masa de agua lo suficientemente grande como para ser considerada infinita.", + "advancement.create.infinite_lava": "Drenaje del núcleo de los planetas", + "advancement.create.infinite_lava.desc": "Bombea de una masa de lava lo suficientemente grande como para ser considerada infinita.", + "advancement.create.infinite_chocolate": "Ahogándose en la imaginación", + "advancement.create.infinite_chocolate.desc": "Bombea desde una masa de chocolate fundido lo suficientemente grande como para ser considerado infinito.", + "advancement.create.crafter": "Montaje automatizado", + "advancement.create.crafter.desc": "Coloca y alimenta algunos autoensambladores.", + "advancement.create.clockwork_bearing": "Artilugio a la hora", + "advancement.create.clockwork_bearing.desc": "Ensamblar una estructura montada sobre un rodamiento de relojería.", + "advancement.create.nixie_tube": "Signos de estilo", + "advancement.create.nixie_tube.desc": "Obtener y colocar un par de Tubos Nixie.", + "advancement.create.deployer": "Picar, colocar y atacar", + "advancement.create.deployer.desc": "Coloca y potencia un Desplegador, el reflejo perfecto de ti mismo.", + "advancement.create.speed_controller": "Los ingenieros lo odian!", + "advancement.create.speed_controller.desc": "Coloque un regulador de velocidad de rotación, el dispositivo definitivo para cambiar de marcha.", + "advancement.create.flywheel": "El corazón de la fábrica", + "advancement.create.flywheel.desc": "Conectar con éxito un motor a la rueda de inercia.", + "advancement.create.overstress_flywheel": "Altos niveles de estrés", + "advancement.create.overstress_flywheel.desc": "Sobrecargar un Motor de Horno.", + "advancement.create.integrated_circuit": "Cálculos complejos", + "advancement.create.integrated_circuit.desc": "Ensamblar un chip de circuito integrado.", + "advancement.create.mechanical_arm": "Manos ocupadas!", + "advancement.create.mechanical_arm.desc": "Crea un brazo mecánico, selecciona las entradas y salidas, colócalo en el suelo y dale energía; luego observa cómo hace todo el trabajo por ti.", + "advancement.create.musical_arm": "Tócame la melodía!", + "advancement.create.musical_arm.desc": "Vea cómo un brazo mecánico maneja su Jukebox.", + "advancement.create.arm_many_targets": "Organize-o-Tron", + "advancement.create.arm_many_targets.desc": "Programar un brazo mecánico con diez o más posiciones de salida.", + "advancement.create.arm_blaze_burner": "Combust-o-Tron", + "advancement.create.arm_blaze_burner.desc": "Instruya un brazo mecánico para alimentar su Quemador de Blaze.", + "advancement.create.fist_bump": "¡Pégale, hermano!", + "advancement.create.fist_bump.desc": "Hacer que dos Desplegadores se den un puñetazo.", + "advancement.create.crushing_wheel": "Un par de gigantes", + "advancement.create.crushing_wheel.desc": "Crea algunas Ruedas de trituración para descomponer más materiales de forma más eficaz.", + "advancement.create.blaze_cake": "Fiebre del azúcar", + "advancement.create.blaze_cake.desc": "Hornea en tu Quemador de Blaze un pastel especial.", + "advancement.create.chromatic_compound": "Minerales bipolares", + "advancement.create.chromatic_compound.desc": "Crea una Barra de Compuesto Cromático.", + "advancement.create.shadow_steel": "Retorno del vacío", + "advancement.create.shadow_steel.desc": "Crea Acero Sombrío, una barra de metal de la nada.", + "advancement.create.refined_radiance": "Brillante e inspirador", + "advancement.create.refined_radiance.desc": "Crea un Resplandor refinado, una poderosa sustancia cromática.", + "advancement.create.chromatic_age": "La edad cromática", + "advancement.create.chromatic_age.desc": "Crear bloques de revestimiento de la luz y la oscuridad.", + "advancement.create.zapper": "Construir con estilo", + "advancement.create.zapper.desc": "Construye un Blockzapper. Una pistola láser radiante que te ayuda a construir.", + "advancement.create.upgraded_zapper": "Radiante sobrecarga", + "advancement.create.upgraded_zapper.desc": "Crear y activar un Blockzapper totalmente mejorado.", + "advancement.create.wand_of_symmetry": "Espejos radiantes", + "advancement.create.wand_of_symmetry.desc": "Crear un bastón de simetría.", + "advancement.create.deforester": "Picado radiante", + "advancement.create.deforester.desc": "Crea un Deforestador y despídete del bosque local.", + "advancement.create.extendo_grip": "Boioioing!", + "advancement.create.extendo_grip.desc": "Hazte con un Agarre extentido.", + "advancement.create.dual_extendo_grip": "La última edad del boing", + "advancement.create.dual_extendo_grip.desc": "Doble Empuñadura extendida para un alcance sobrehumano.", + "advancement.create.eob": "Fin de la beta", + "advancement.create.eob.desc": "Espere más contenido aquí en el futuro. <3", + + + "_": "->------------------------] UI & Messages [------------------------<-", + + "itemGroup.create.base": "Create", + "itemGroup.create.palettes": "Paletas", + + "death.attack.create.crush": "%1$s se procesó por las Ruedas de trituración", + "death.attack.create.fan_fire": "%1$s murió quemado por el aire caliente", + "death.attack.create.fan_lava": "%1$s murió quemado por un abanico de lava", + "death.attack.create.mechanical_drill": "%1$s fue empalado por un taladro mecánico", + "death.attack.create.mechanical_saw": "%1$s fue cortado por la mitad por una sierra mecánica", + "death.attack.create.cuckoo_clock_explosion": "%1$s fue volado por los aires por un reloj cucú manipulado", + + "create.block.deployer.damage_source_name": "un Desplegador rebelde", + "create.block.cart_assembler.invalid": "Coloque su Ensamblador de vagonetas en un bloque de Raíles", + + "create.recipe.crushing": "Trituración", + "create.recipe.milling": "Fresado", + "create.recipe.fan_washing": "Lavado a granel", + "create.recipe.fan_washing.fan": "Ventilador detrás del agua fluyente", + "create.recipe.fan_smoking": "Ahumador a granel", + "create.recipe.fan_smoking.fan": "Ventilador detrás del fuego", + "create.recipe.fan_blasting": "Voladuras a granel", + "create.recipe.fan_blasting.fan": "Ventilador detrás de la lava", + "create.recipe.pressing": "Prensando", + "create.recipe.mixing": "Mezclando", + "create.recipe.automatic_shapeless": "Elaboración automatizada de productos sin forma", + "create.recipe.automatic_brewing": "Elaboración de cerveza automatizada", + "create.recipe.packing": "Compactando", + "create.recipe.automatic_packing": "Embalaje automatizado", + "create.recipe.sawing": "Aserrando", + "create.recipe.mechanical_crafting": "Elaboración mecánica", + "create.recipe.automatic_shaped": "Elaboración automatizada de productos con forma", + "create.recipe.block_cutting": "Corte de bloques", + "create.recipe.blockzapper_upgrade": "Blockzapper", + "create.recipe.sandpaper_polishing": "Pulido con papel de lija", + "create.recipe.mystery_conversion": "Conversión misteriosa", + "create.recipe.spout_filling": "Llenar por el pico", + "create.recipe.draining": "Drenador de elementos", + "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.heat_requirement.none": "No es necesario calentar", + "create.recipe.heat_requirement.heated": "Calentado", + "create.recipe.heat_requirement.superheated": "Súper-Calentado", + + "create.generic.range": "Rango", + "create.generic.radius": "Radio", + "create.generic.width": "Ancho", + "create.generic.height": "Alto", + "create.generic.length": "Largo", + "create.generic.speed": "Velocidad", + "create.generic.delay": "Retraso", + "create.generic.unit.ticks": "Ticks", + "create.generic.unit.seconds": "Segundos", + "create.generic.unit.minutes": "Minutos", + "create.generic.unit.rpm": "RPM", + "create.generic.unit.stress": "su", + "create.generic.unit.degrees": "°", + "create.generic.unit.millibuckets": "%1$smB", + "create.generic.clockwise": "En el sentido de las agujas del reloj", + "create.generic.counter_clockwise": "En sentido contrario a las agujas del reloj", + + "create.action.scroll": "Desplazar", + "create.action.confirm": "Confirmar", + "create.action.abort": "Abortar", + "create.action.saveToFile": "Guardar", + "create.action.discard": "Descartar", + + "create.keyinfo.toolmenu": "Menú de la Herramienta de Enfoque", + "create.keyinfo.scrollup": "Simular usar la rueda del ratón hacia arriba (en el mundo)", + "create.keyinfo.scrolldown": "Simular usar la rueda del ratón hacia abajo (en el mundo)", + + "create.gui.scrollInput.defaultTitle": "Seleccione una opción:", + "create.gui.scrollInput.scrollToModify": "Usa la rueda del ratón para Modificar", + "create.gui.scrollInput.scrollToAdjustAmount": "Usa la rueda del ratón para ajustar la cantidad", + "create.gui.scrollInput.scrollToSelect": "Usa la rueda del ratón para Seleccionar", + "create.gui.scrollInput.shiftScrollsFaster": "Shift para usar la rueda del ratón más rápido", + "create.gui.toolmenu.focusKey": "Mantenga [%1$s] para enfocar", + "create.gui.toolmenu.cycle": "[RUEDA DEL RATÓN] para el ciclo", + "create.gui.symmetryWand.mirrorType": "Espejado", + "create.gui.symmetryWand.orientation": "Orientación", + + "create.symmetry.mirror.plane": "Plano de espejo", + "create.symmetry.mirror.doublePlane": "Rectangular", + "create.symmetry.mirror.triplePlane": "Octogonal", + + "create.orientation.orthogonal": "Ortogonal", + "create.orientation.diagonal": "Diagonal", + "create.orientation.horizontal": "Horizontal", + "create.orientation.alongZ": "A lo largo de Z", + "create.orientation.alongX": "A lo largo de X", + + "create.gui.blockzapper.title": "Blockzapper", + "create.gui.blockzapper.replaceMode": "Modo de sustitución", + "create.gui.blockzapper.searchDiagonal": "Seguir las diagonales", + "create.gui.blockzapper.searchFuzzy": "Ignorar los bordes del material", + "create.gui.blockzapper.range": "Alcance del margen de maniobra", + "create.gui.blockzapper.needsUpgradedAmplifier": "Requiere un amplificador mejorado", + "create.gui.blockzapper.patternSection": "Patrón", + "create.gui.blockzapper.pattern.solid": "Sólido", + "create.gui.blockzapper.pattern.checkered": "Tablero de ajedrez", + "create.gui.blockzapper.pattern.inversecheckered": "Tablero de ajedrez invertido", + "create.gui.blockzapper.pattern.chance25": "25% Roll", + "create.gui.blockzapper.pattern.chance50": "50% Roll", + "create.gui.blockzapper.pattern.chance75": "75% Roll", + "create.gui.terrainzapper.title": "Worldshaper", + "create.gui.terrainzapper.placement": "Colocación", + "create.gui.terrainzapper.placement.merged": "Fusionado", + "create.gui.terrainzapper.placement.attached": "Adjuntado", + "create.gui.terrainzapper.placement.inserted": "Insertado", + "create.gui.terrainzapper.brush": "Pincel", + "create.gui.terrainzapper.brush.cuboid": "Cuboide", + "create.gui.terrainzapper.brush.sphere": "Esfera", + "create.gui.terrainzapper.brush.cylinder": "Cilindro", + "create.gui.terrainzapper.tool": "Herramienta", + "create.gui.terrainzapper.tool.fill": "Llenar", + "create.gui.terrainzapper.tool.place": "Sitio", + "create.gui.terrainzapper.tool.replace": "Sustituir", + "create.gui.terrainzapper.tool.clear": "Borrar", + "create.gui.terrainzapper.tool.overlay": "Superposición", + "create.gui.terrainzapper.tool.flatten": "Aplanar", + + "create.terrainzapper.shiftRightClickToSet": "Shift+Clic con el botón derecho para seleccionar una forma", + + "create.blockzapper.usingBlock": "Utilizando: %1$s", + "create.blockzapper.componentUpgrades": "Mejoras de componentes:", + "create.blockzapper.component.body": "Cuerpo", + "create.blockzapper.component.amplifier": "Amplificador", + "create.blockzapper.component.accelerator": "Acelerador", + "create.blockzapper.component.retriever": "Recuperador", + "create.blockzapper.component.scope": "Mira telescópica", + "create.blockzapper.componentTier.none": "Ninguno", + "create.blockzapper.componentTier.brass": "Latón", + "create.blockzapper.componentTier.chromatic": "Cromático", + "create.blockzapper.leftClickToSet": "Clic izquierdo en un bloque para establecer el material", + "create.blockzapper.empty": "Sin bloques!", + + "create.minecart_coupling.two_couplings_max": "Las vagonetas no pueden tener más de dos enganches cada una", + "create.minecart_coupling.unloaded": "Algunas partes de su tren parecen estar en chunks no cargados", + "create.minecart_coupling.no_loops": "Los acoplamientos no pueden formar un bucle", + "create.minecart_coupling.removed": "Se han retirado todos los acoplamientos de la vagoneta", + "create.minecart_coupling.too_far": "Las vagonetas están demasiado separadas", + + "create.contraptions.movement_mode": "Modo de movimiento", + "create.contraptions.movement_mode.move_place": "Colocar siempre al detenerse", + "create.contraptions.movement_mode.move_place_returned": "Colocar sólo en la posición inicial", + "create.contraptions.movement_mode.move_never_place": "Colocar sólo cuando se destruye el ancla", + "create.contraptions.movement_mode.rotate_place": "Colocar siempre al detenerse", + "create.contraptions.movement_mode.rotate_place_returned": "Colocar sólo cerca del ángulo inicial", + "create.contraptions.movement_mode.rotate_never_place": "Colocar sólo cuando se destruye el ancla", + "create.contraptions.cart_movement_mode": "Modo de movimiento de la vagoneta", + "create.contraptions.cart_movement_mode.rotate": "Siempre de cara al movimiento", + "create.contraptions.cart_movement_mode.rotate_paused": "Pausar a los actores mientras giran", + "create.contraptions.cart_movement_mode.rotation_locked": "Bloquear rotación", + "create.contraptions.windmill.rotation_direction": "Dirección de rotación", + "create.contraptions.clockwork.clock_hands": "Manecillas de reloj", + "create.contraptions.clockwork.hour_first": "La manecilla de las horas primero", + "create.contraptions.clockwork.minute_first": "La manecilla de los minutos primero", + "create.contraptions.clockwork.hour_first_24": "La manecilla del día primero", + + "create.logistics.filter": "Filtro", + "create.logistics.recipe_filter": "Filtro de recetas", + "create.logistics.fluid_filter": "Filtro de fluidos", + "create.logistics.firstFrequency": "Freq. #1", + "create.logistics.secondFrequency": "Freq. #2", + "create.logistics.filter.apply": "Filtro aplicado a %1$s.", + "create.logistics.filter.apply_click_again": "Filtro aplicado a %1$s, haga clic de nuevo para copiar la cantidad.", + "create.logistics.filter.apply_count": "Aplicado recuento de extracciones al filtro.", + + "create.gui.goggles.generator_stats": "Estadísticas del generador:", + "create.gui.goggles.kinetic_stats": "Estadísticas cinéticas:", + "create.gui.goggles.at_current_speed": "con la velocidad actual", + "create.gui.goggles.pole_length": "Longitud del poste:", + "create.gui.assembly.exception": "Este artilugio no se pudo montar:", + "create.gui.assembly.exception.unmovableBlock": "Bloque inamovible (%4$s) en [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "El bloque en [%1$s %2$s %3$s] no estaba en un chunk cargado", + "create.gui.assembly.exception.structureTooLarge": "Hay demasiados bloques incluídos en el artilugio.\nEl máximo configurado es: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "Hay demasiadas Pértigas de extensión conectadas a este Pistón.\nEl máximo configurado es: %1$s", + "create.gui.assembly.exception.noPistonPoles": "Faltan pértigas de extensión para el Pistón", + "create.gui.gauge.info_header": "Información sobre el medidor:", + "create.gui.speedometer.title": "Velocidad de rotación", + "create.gui.stressometer.title": "Estrés de la red", + "create.gui.stressometer.capacity": "Capacidad restante", + "create.gui.stressometer.overstressed": "Sobrecargado", + "create.gui.stressometer.no_rotation": "Sin rotación", + "create.gui.contraptions.not_fast_enough": "Parece que este %1$s no está girando con _suficiente_ velocidad_.", + "create.gui.contraptions.network_overstressed": "Parece que este artilugio está _sobrecargado_. Añade más fuentes o _desacelera_ los componentes con un _impacto_ de alto estrés.", + "create.gui.adjustable_crate.title": "Caja ajustable", + "create.gui.adjustable_crate.storageSpace": "Espacio de almacenamiento", + "create.gui.stockpile_switch.title": "Interruptor de acopio", + "create.gui.stockpile_switch.invert_signal": "Invertir señal", + "create.gui.stockpile_switch.move_to_lower_at": "Pasar al carril inferior en %1$s%%", + "create.gui.stockpile_switch.move_to_upper_at": "Pasar al carril superior en %1$s%%", + "create.gui.sequenced_gearshift.title": "Cambio de marchas secuenciado", + "create.gui.sequenced_gearshift.instruction": "Instrucción", + "create.gui.sequenced_gearshift.instruction.turn_angle": "Giro", + "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "Ángulo", + "create.gui.sequenced_gearshift.instruction.turn_distance": "Pistón", + "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "Distancia", + "create.gui.sequenced_gearshift.instruction.wait": "Espera", + "create.gui.sequenced_gearshift.instruction.wait.duration": "Duración", + "create.gui.sequenced_gearshift.instruction.end": "Fin", + "create.gui.sequenced_gearshift.speed": "Velocidad, Dirección", + "create.gui.sequenced_gearshift.speed.forward": "Velocidad de entrada, hacia adelante", + "create.gui.sequenced_gearshift.speed.forward_fast": "Doble velocidad, hacia adelante", + "create.gui.sequenced_gearshift.speed.back": "Velocidad de entrada, Invertida", + "create.gui.sequenced_gearshift.speed.back_fast": "Doble velocidad, Invertida", + + "create.schematicAndQuill.dimensions": "Tamaño del esquema: %1$sx%2$sx%3$s", + "create.schematicAndQuill.firstPos": "Primera posición fijada.", + "create.schematicAndQuill.secondPos": "Segunda posición fijada.", + "create.schematicAndQuill.noTarget": "Mantenga [Ctrl] para seleccionar los bloques del aire.", + "create.schematicAndQuill.abort": "Selección eliminada.", + "create.schematicAndQuill.title": "Nombre del esquema:", + "create.schematicAndQuill.convert": "Guardar y desplegar inmediatamente", + "create.schematicAndQuill.fallbackName": "Mi esquema", + "create.schematicAndQuill.saved": "Guardado como %1$s", + + "create.schematic.invalid": "[!] Elemento no válido - Utilice la tabla de esquemas en su lugar", + "create.schematic.position": "Posición", + "create.schematic.rotation": "Rotación", + "create.schematic.rotation.none": "Ninguno", + "create.schematic.rotation.cw90": "En el sentido de las agujas del reloj 90", + "create.schematic.rotation.cw180": "En el sentido de las agujas del reloj 180", + "create.schematic.rotation.cw270": "En el sentido de las agujas del reloj 270", + "create.schematic.mirror": "Espejado", + "create.schematic.mirror.none": "Ninguno", + "create.schematic.mirror.frontBack": "Delante-detrás", + "create.schematic.mirror.leftRight": "Izquierda-Derecha", + "create.schematic.tool.deploy": "Despliegue", + "create.schematic.tool.move": "Mover XZ", + "create.schematic.tool.movey": "Mover Y", + "create.schematic.tool.rotate": "Rotar", + "create.schematic.tool.print": "Imprimir", + "create.schematic.tool.flip": "Voltear", + "create.schematic.tool.deploy.description.0": "Mueve la estructura a un lugar.", + "create.schematic.tool.deploy.description.1": "Haga clic con el botón derecho del ratón en el suelo para colocar.", + "create.schematic.tool.deploy.description.2": "Mantenga [Ctrl] para seleccionar a una distancia fija.", + "create.schematic.tool.deploy.description.3": "[Ctrl]-Rueda del ratón para cambiar la distancia.", + "create.schematic.tool.move.description.0": "Desplaza el esquema horizontalmente.", + "create.schematic.tool.move.description.1": "Apunta al Esquema y [CTRL]-Rueda del ratón para ponerlo.", + "create.schematic.tool.move.description.2": "", + "create.schematic.tool.move.description.3": "", + "create.schematic.tool.movey.description.0": "Desplaza el esquema verticalmente..", + "create.schematic.tool.movey.description.1": "[CTRL]-Rueda del ratón para moverlo hacia arriba/abajo.", + "create.schematic.tool.movey.description.2": "", + "create.schematic.tool.movey.description.3": "", + "create.schematic.tool.rotate.description.0": "Gira el esquema alrededor de su centro.", + "create.schematic.tool.rotate.description.1": "[CTRL]-Rueda del ratón para girar 90 grados.", + "create.schematic.tool.rotate.description.2": "", + "create.schematic.tool.rotate.description.3": "", + "create.schematic.tool.print.description.0": "Sitúa instantáneamente la estructura en el mundo.", + "create.schematic.tool.print.description.1": "[Clic derecho] para confirmar la colocación en el lugar actual.", + "create.schematic.tool.print.description.2": "Esta herramienta es sólo para el Modo Creativo.", + "create.schematic.tool.print.description.3": "", + "create.schematic.tool.flip.description.0": "Voltea el Esquema a lo largo de la cara que seleccione.", + "create.schematic.tool.flip.description.1": "Apunta al esquema y [CTRL]-Rueda del ratón para voltearlo.", + "create.schematic.tool.flip.description.2": "", + "create.schematic.tool.flip.description.3": "", + + "create.schematics.synchronizing": "Sincronizando...", + "create.schematics.uploadTooLarge": "Tu esquema excede las limitaciones especificadas por el servidor.", + "create.schematics.maxAllowedSize": "El tamaño máximo permitido del archivo del esquema es:", + + "create.gui.schematicTable.refresh": "Refrescar archivos", + "create.gui.schematicTable.open_folder": "Abrir carpeta", + "create.gui.schematicTable.title": "Tabla de esquemas", + "create.gui.schematicTable.availableSchematics": "Esquemas disponibles", + "create.gui.schematicTable.noSchematics": "No hay esquemas guardados", + "create.gui.schematicTable.uploading": "Subiendo...", + "create.gui.schematicTable.finished": "Subida finalizada!", + "create.gui.schematicannon.title": "Schematicannon", + "create.gui.schematicannon.listPrinter": "Lista de control de la impresora", + "create.gui.schematicannon.gunpowderLevel": "Pólvora %1$s%%", + "create.gui.schematicannon.shotsRemaining": "Disparos restantes: %1$s", + "create.gui.schematicannon.shotsRemainingWithBackup": "Con respaldo: %1$s", + "create.gui.schematicannon.optionEnabled": "Actualmente habilitado", + "create.gui.schematicannon.optionDisabled": "Actualmente deshabilitado", + "create.gui.schematicannon.showOptions": "Mostrar la configuración de la impresora", + "create.gui.schematicannon.option.dontReplaceSolid": "No sustituír los bloques sólidos", + "create.gui.schematicannon.option.replaceWithSolid": "Sustituir sólido por sólido", + "create.gui.schematicannon.option.replaceWithAny": "Sustituir sólido por cualquiera", + "create.gui.schematicannon.option.replaceWithEmpty": "Sustituir sólido por vacío", + "create.gui.schematicannon.option.skipMissing": "Omitir los bloques que faltan", + "create.gui.schematicannon.option.skipTileEntities": "Proteger a las entidades", + "create.gui.schematicannon.slot.gunpowder": "Añade pólvora para alimentar el cañón", + "create.gui.schematicannon.slot.listPrinter": "Coloque los libros aquí para imprimir una lista de comprobación para su esquema", + "create.gui.schematicannon.slot.schematic": "Añada su esquema aquí. Asegúrese de que se despliega en un lugar específico.", + "create.gui.schematicannon.option.skipMissing.description": "Si el cañón no encuentra un bloque necesario para su colocación, continuará en la siguiente ubicación.", + "create.gui.schematicannon.option.skipTileEntities.description": "El cañón evitará reemplazar los bloques que contienen datos, como los Cofres.", + "create.gui.schematicannon.option.dontReplaceSolid.description": "El cañón nunca sustituirá ningún bloque sólido en su zona de trabajo, sólo los no sólidos y el aire.", + "create.gui.schematicannon.option.replaceWithSolid.description": "El cañón sólo reemplazará los bloques sólidos en su área de trabajo si el esquema contiene un bloque sólido en la ubicación.", + "create.gui.schematicannon.option.replaceWithAny.description": "El cañón reemplazará los bloques sólidos en su área de trabajo si el esquema contiene algún bloque en la ubicación.", + "create.gui.schematicannon.option.replaceWithEmpty.description": "El cañón eliminará todos los bloques de su zona de trabajo, incluidos los sustituidos por Aire.", + + "create.schematicannon.status.idle": "Inactivo", + "create.schematicannon.status.ready": "Listo", + "create.schematicannon.status.running": "Funcionando", + "create.schematicannon.status.finished": "Finished", + "create.schematicannon.status.paused": "Pausado", + "create.schematicannon.status.stopped": "Detenido", + "create.schematicannon.status.noGunpowder": "Sin pólvora", + "create.schematicannon.status.targetNotLoaded": "El objetivo no está cargado", + "create.schematicannon.status.targetOutsideRange": "Objetivo demasiado lejano", + "create.schematicannon.status.searching": "Buscando", + "create.schematicannon.status.skipping": "Omitiendo", + "create.schematicannon.status.missingBlock": "Elementos perdidos:", + "create.schematicannon.status.placing": "Colocando", + "create.schematicannon.status.clearing": "Limpiando bloques", + "create.schematicannon.status.schematicInvalid": "Esquema inválido", + "create.schematicannon.status.schematicNotPlaced": "Esquema no desplegado", + "create.schematicannon.status.schematicExpired": "Archivo de esquemas caducado", + + "create.materialChecklist": "Lista de control del material", + "create.materialChecklist.blocksNotLoaded": "* Descargo de Responsabilidad *\n\nLa lista de materiales puede ser inexacta debido a que no se han cargado los chunks pertinentes.", + + "create.gui.filter.deny_list": "Lista de denegados", + "create.gui.filter.deny_list.description": "Los elementos pasan si NO coinciden con ninguno de los anteriores. Una lista de denegación vacía acepta todo.", + "create.gui.filter.allow_list": "Lista de permitidos", + "create.gui.filter.allow_list.description": "Los elementos pasan si coinciden con alguno de los anteriores. Una lista de permitidos vacía rechaza todo.", + "create.gui.filter.respect_data": "Respetar datos", + "create.gui.filter.respect_data.description": "Los objetos sólo coinciden si su durabilidad, encantos y otros atributos también coinciden.", + "create.gui.filter.ignore_data": "Ignorar datos", + "create.gui.filter.ignore_data.description": "Los artículos coinciden independientemente de sus atributos.", + + "create.item_attributes.placeable": "se puede colocar", + "create.item_attributes.placeable.inverted": "no se puede colocar", + "create.item_attributes.consumable": "se puede comer", + "create.item_attributes.consumable.inverted": "no se puede comer", + "create.item_attributes.smeltable": "se puede fundir", + "create.item_attributes.smeltable.inverted": "no se puede fundir", + "create.item_attributes.washable": "se puede lavar", + "create.item_attributes.washable.inverted": "no se puede lavar", + "create.item_attributes.smokable": "puede ser ahumado", + "create.item_attributes.smokable.inverted": "no puede ser ahumado", + "create.item_attributes.crushable": "puede ser molido", + "create.item_attributes.crushable.inverted": "no puede ser molido", + "create.item_attributes.blastable": "es fundible en el alto horno", + "create.item_attributes.blastable.inverted": "no es fundible en el alto horno", + "create.item_attributes.enchanted": "está encantado", + "create.item_attributes.enchanted.inverted": "no está encantado", + "create.item_attributes.damaged": "está dañado", + "create.item_attributes.damaged.inverted": "no está dañado", + "create.item_attributes.badly_damaged": "está muy dañado", + "create.item_attributes.badly_damaged.inverted": "no está muy dañado", + "create.item_attributes.not_stackable": "no se puede apilar", + "create.item_attributes.not_stackable.inverted": "se puede apilar", + "create.item_attributes.equipable": "se puede equipar", + "create.item_attributes.equipable.inverted": "no se puede equipar", + "create.item_attributes.furnace_fuel": "es combustible para hornos", + "create.item_attributes.furnace_fuel.inverted": "no es combustible para hornos", + "create.item_attributes.in_tag": "está etiquetado %1$s", + "create.item_attributes.in_tag.inverted": "no está etiquetado %1$s", + "create.item_attributes.in_item_group": "está en el grupo '%1$s'", + "create.item_attributes.in_item_group.inverted": "no está en el grupo '%1$s'", + "create.item_attributes.added_by": "fue añadido por %1$s", + "create.item_attributes.added_by.inverted": "no fue añadida por %1$s", + "create.item_attributes.has_enchant": "está encantado con %1$s", + "create.item_attributes.has_enchant.inverted": "no está encantado con %1$s", + "create.item_attributes.has_fluid": "contiene %1$s", + "create.item_attributes.has_fluid.inverted": "no contiene %1$s", + "create.item_attributes.has_name": "tiene el nombre personalizado %1$s", + "create.item_attributes.has_name.inverted": "no tiene el nombre personalizado %1$s", + "create.item_attributes.book_author": "es obra de %1$s", + "create.item_attributes.book_author.inverted": "no es es obra de %1$s", + "create.item_attributes.book_copy_original": "es un original", + "create.item_attributes.book_copy_original.inverted": "no es un original", + "create.item_attributes.book_copy_first": "es una copia de primera generación", + "create.item_attributes.book_copy_first.inverted": "no es una copia de primera generación", + "create.item_attributes.book_copy_second": "es una copia de segunda generación", + "create.item_attributes.book_copy_second.inverted": "no es una copia de segunda generación", + "create.item_attributes.book_copy_tattered": "es un desordenado desastre", + "create.item_attributes.book_copy_tattered.inverted": "no es un desordenado desastre", + "create.item_attributes.astralsorcery_crystal": "tiene el atributo de cristal %1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "no tiene atributo de cristal %1$s", + "create.item_attributes.astralsorcery_constellation": "está en sintonía con %1$s", + "create.item_attributes.astralsorcery_constellation.inverted": "no está en sintonía con %1$s", + "create.item_attributes.astralsorcery_perk_gem": "tiene el atributo ventaja %1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "no tiene el atributo ventaja %1$s", + "create.item_attributes.astralsorcery_amulet": "mejora %1$s", + "create.item_attributes.astralsorcery_amulet.inverted": "no mejora %1$s", + + "create.gui.attribute_filter.no_selected_attributes": "No hay atributos seleccionados", + "create.gui.attribute_filter.selected_attributes": "Atributos seleccionados:", + "create.gui.attribute_filter.add_attribute": "Añadir atributo a la lista", + "create.gui.attribute_filter.add_inverted_attribute": "Añadir atributo invertido a la Lista", + "create.gui.attribute_filter.allow_list_disjunctive": "Lista de permitidos (Cualquiera)", + "create.gui.attribute_filter.allow_list_disjunctive.description": "Los elementos pasan si tienen alguno de los atributos seleccionados", + "create.gui.attribute_filter.allow_list_conjunctive": "Lista de permitidos (Todos)", + "create.gui.attribute_filter.allow_list_conjunctive.description": "Los elementos pasan sólo si tienen TODOS los atributos seleccionados", + "create.gui.attribute_filter.deny_list": "Lista de denegados", + "create.gui.attribute_filter.deny_list.description": "Los elementos pasan si NO tienen ninguno de los atributos seleccionados", + "create.gui.attribute_filter.add_reference_item": "Añadir elemento de referencia", + + "create.tooltip.holdKey": "Mantener [%1$s]", + "create.tooltip.holdKeyOrKey": "Mantener [%1$s] o [%2$s]", + "create.tooltip.keyShift": "Shift", + "create.tooltip.keyCtrl": "Ctrl", + "create.tooltip.speedRequirement": "Requisitos de velocidad: %1$s", + "create.tooltip.speedRequirement.none": "Ninguno", + "create.tooltip.speedRequirement.medium": "Moderado", + "create.tooltip.speedRequirement.high": "Rápido", + "create.tooltip.stressImpact": "Impacto de estrés: %1$s", + "create.tooltip.stressImpact.low": "Bajo", + "create.tooltip.stressImpact.medium": "Moderado", + "create.tooltip.stressImpact.high": "Alto", + "create.tooltip.stressImpact.overstressed": "Sobrecargado", + "create.tooltip.capacityProvided": "Capacidad de estrés: %1$s", + "create.tooltip.capacityProvided.low": "Pequeña", + "create.tooltip.capacityProvided.medium": "Media", + "create.tooltip.capacityProvided.high": "Grande", + "create.tooltip.capacityProvided.asGenerator": "(Como generador)", + "create.tooltip.generationSpeed": "Genera en %1$s %2$s", + "create.tooltip.analogStrength": "Fuerza analógica: %1$s/15", + + "create.mechanical_arm.extract_from": "Extraer elementos de %1$s", + "create.mechanical_arm.deposit_to": "Depositar elementos en %1$s", + "create.mechanical_arm.summary": "El brazo mecánico tiene %1$s entrada(s) y %2$s salida(s)", + "create.mechanical_arm.points_outside_range": "%1$s punto(s) de interacción seleccionado(s) eliminado(s) debido a las limitaciones de rango", + + "create.logistics.when_multiple_outputs_available": "Cuando hay múltiples salidas disponibles", + + "create.mechanical_arm.selection_mode.round_robin": "Round Robin", + "create.mechanical_arm.selection_mode.forced_round_robin": "Round Robin forzado", + "create.mechanical_arm.selection_mode.prefer_first": "Preferir el primer objetivo", + + "create.tunnel.selection_mode.split": "División", + "create.tunnel.selection_mode.forced_split": "División forzada", + "create.tunnel.selection_mode.round_robin": "Round Robin", + "create.tunnel.selection_mode.forced_round_robin": "Round Robin forzado", + "create.tunnel.selection_mode.prefer_nearest": "Preferir el más cercano", + "create.tunnel.selection_mode.randomize": "Aleatorizar", + "create.tunnel.selection_mode.synchronize": "Sincronizar entradas", + + "create.tooltip.chute.header": "Información del ducto", + "create.tooltip.chute.items_move_down": "Los elementos se mueven hacia abajo", + "create.tooltip.chute.items_move_up": "Los elementos se mueven hacia arriba", + "create.tooltip.chute.no_fans_attached": "No hay ventiladores adjuntos", + "create.tooltip.chute.fans_push_up": "Los ventiladores empujan desde abajo", + "create.tooltip.chute.fans_push_down": "Los ventiladores empujan desde arriba", + "create.tooltip.chute.fans_pull_up": "Los ventiladores tiran desde arriba", + "create.tooltip.chute.fans_pull_down": "Los ventiladores tiran desde abajo", + "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + + "create.hint.hose_pulley.title": "Suministro sin fondo", + "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita", + "create.hint.mechanical_arm_no_targets.title": "No hay objetivos", + "create.hint.mechanical_arm_no_targets": "Parece que a este _brazo mecánico_ no se le ha asignado ningún _objetivo._ Selecciona correas, depósitos, embudos y otros bloques haciendo _clic derecho_ sobre ellos mientras _sostienes_ el _brazo mecánico_ en tu _mano_.", + "create.hint.horizontal_funnel.title": "Embudos horizontales", + "create.hint.horizontal_funnel": "No puede transferir entre inventarios _directamente_. Intenta pasar una _correa_ o un _depósito_ por debajo de tu embudo para extraer artículos de los inventarios", + "create.hint.upward_funnel.title": "Embudos hacia arriba", + "create.hint.upward_funnel": "sólo pueden transferir objetos insertados por _brazos_, y _ductos_ impulsados por ventilador, o elementos _lanzados_ hacia ellos. Intenta construir algunos _ductos_ si quieres mover tus objetos _verticalmente_", + "create.hint.empty_bearing.title": "Rodamiento de reloj", + "create.hint.empty_bearing": "_Haz clic con el botón derecho del ratón_ en el rodamiento con la _mano vacía_ para _adherir_ la estructura que acabas de construir delante de él", + "create.hint.full_deployer.title": "Desbordamiento de elementos del desplegador", + "create.hint.full_deployer": "Parece que este _Desplegador_ contiene _elementos_ en exceso que necesitan ser _extraídos._ Usa un _tolva,_embudo_ u otro medio para liberarlo de su desbordamiento.", + + "create.gui.config.overlay1": "Hola :)", + "create.gui.config.overlay2": "Esta es una muestra de la superposición", + "create.gui.config.overlay3": "Haga clic o arrastre con el ratón", + "create.gui.config.overlay4": "para mover esta vista previa", + "create.gui.config.overlay5": "Pulsar ESC para salir de esta pantalla", + "create.gui.config.overlay6": "y guardar la nueva posición", + "create.gui.config.overlay7": "Ejecute /create overlay reset", + "create.gui.config.overlay8": "para restablecer la posición por defecto", + + "create.command.killTPSCommand": "killtps", + "create.command.killTPSCommand.status.slowed_by.0": "[Crear]: El tick del servidor está actualmente ralentizado en %s ms :o", + "create.command.killTPSCommand.status.slowed_by.1": "[Crear]: El tick del servidor está ralentizado en %s ms ahora >:)", + "create.command.killTPSCommand.status.slowed_by.2": "[Create]: El tick del servidor ha vuelto a su velocidad normal :D", + "create.command.killTPSCommand.status.usage.0": "[Create]: usar /killtps stop para que el servidor vuelva a la velocidad normal", + "create.command.killTPSCommand.status.usage.1": "[Create]: usar /killtps start para ralentizar artificialmente el tick del servidor", + "create.command.killTPSCommand.argument.tickTime": "tickTime", + + "create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon", + "create.subtitle.schematicannon_finish": "Acabados de Schematicannon", + "create.subtitle.slime_added": "Slime aplastado", + "create.subtitle.mechanical_press_activation": "La Prensa Mecánica se activa", + "create.subtitle.mechanical_press_item_break": "Clanks de metal", + "create.subtitle.blockzapper_place": "Los bloques se colocan en su sitio", + "create.subtitle.blockzapper_confirm": "Ding afirmativo", + "create.subtitle.blockzapper_deny": "Boop declinante", + "create.subtitle.block_funnel_eat": "CHOMPS del embudo", + "create.subtitle.blaze_munch": "Blaze mastica felizmente", + + + "_": "->------------------------] Item Descriptions [------------------------<-", + + "item.create.example_item.tooltip": "EJEMPLO DE ITEM (sólo un marcador de que este tooltip existe)", + "item.create.example_item.tooltip.summary": "Una breve descripción del elemento. Los puntajes bajos resaltan un término", + "item.create.example_item.tooltip.condition1": "Cuando este", + "item.create.example_item.tooltip.behaviour1": "Entonces este elemento hace esto. (los comportamientos se muestran en el turno)", + "item.create.example_item.tooltip.condition2": "Y cuando esto", + "item.create.example_item.tooltip.behaviour2": "Puedes añadir tantos comportamientos como quieras", + "item.create.example_item.tooltip.control1": "Cuando se pulsa Ctrl", + "item.create.example_item.tooltip.action1": "Se muestran estos controles", + + "block.create.andesite_encased_shaft.tooltip": "EJE REVESTIDO DE ANDESITA", + "block.create.andesite_encased_shaft.tooltip.summary": "Elemento _sólo para el modo creativo_. Reviste los _ejes_ en el mundo usando _revestimiento de andesita_. Los bloques de revestimiento _no se consumirán_.", + + "block.create.brass_encased_shaft.tooltip": "EJE REVESTIDO DE LATÓN", + "block.create.brass_encased_shaft.tooltip.summary": "Elemento _sólo para el modo creativo_. Reviste los _ejes_ en el mundo usando _revestimiento de latón_. Los bloques de revestimiento _no se consumirán_.", + + "block.create.wooden_bracket.tooltip": "SOPORTE DE MADERA PARA EJES", + "block.create.wooden_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un refuerzo acogedor y de madera.", + + "block.create.metal_bracket.tooltip": "SOPORTE DE METAL PARA EJES", + "block.create.metal_bracket.tooltip.summary": "Decora tus _Ejes_, _Ruedas dentadas_ y _Ductos_ con un poco de refuerzo industrial robusto.", + + "block.create.andesite_casing.tooltip": "REVESTIDOR DE ANDESITA", + "block.create.andesite_casing.tooltip.summary": "Máquina de revestimiento simple con una variedad de usos. Seguro para la decoración. Puede utilizarse para _encastrar ejes_ y _correas._", + + "block.create.andesite_funnel.tooltip": "EMBUDO DE ANDESITA", + "block.create.andesite_funnel.tooltip.summary": "Un componente de transferencia de elementos en general, que hace la transición de éstos entre los medios de transporte. Se puede controlar con una _señal de Redstone_.", + "block.create.andesite_funnel.tooltip.condition1": "Comportamiento general", + "block.create.andesite_funnel.tooltip.behaviour1": "La cara _abierta_ _recogerá los objetos molidos_ en el espacio del bloque que tiene delante y los _insertará_ en cualquier contenedor del lado opuesto del embudo", + "block.create.andesite_funnel.tooltip.condition2": "Cuando se montan en correas, depósitos y similares", + "block.create.andesite_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ los elementos en el componente montado, desde o hacia el inventario _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, puede invertirse utilizando una Llave.", + "block.create.andesite_funnel.tooltip.condition3": "Cuando se encuentra verticalmente entre dos inventarios", + "block.create.andesite_funnel.tooltip.behaviour3": "Transferirá los artículos hacia abajo, como una tolva sin búfer.", + + "block.create.andesite_tunnel.tooltip": "TÚNEL DE ANDESITA", + "block.create.andesite_tunnel.tooltip.summary": "¡Una cubierta protectora para sus _correas_!. El _Túnel de Andesita_ puede separar un elemento de una pila cuando se coloca otra correa o depósito al lado de la correa principal.", + "block.create.andesite_tunnel.tooltip.control1": "Click derecho con la Llave Inglesa en el lateral", + "block.create.andesite_tunnel.tooltip.action1": "_Ajusta las persianas de las ventanas_ si el túnel tiene una ventana en esa cara.", + + "block.create.brass_funnel.tooltip": "EMBUDO DE LATÓN", + "block.create.brass_funnel.tooltip.summary": "Un componente de transferencia de elementos en general, que hace la transición de éstos entre los medios de transporte. Se puede controlar con una _señal de Redstone_. Viene con un práctico _filtro_.", + "block.create.brass_funnel.tooltip.condition1": "Comportamiento General", + "block.create.brass_funnel.tooltip.behaviour1": "La cara _abierta_ _recogerá los objetos molidos_ en el espacio del bloque que tiene delante y los _insertará_ en cualquier contenedor del lado opuesto del embudo.", + "block.create.brass_funnel.tooltip.condition2": "Cuando se montan en correas, depósitos y similares", + "block.create.brass_funnel.tooltip.behaviour2": "_Recoge_ o _Coloca_ los elementos en el componente montado, desde o hacia el inventario _detrás_ de sí mismo. Siempre que el embudo tenga una direccionalidad específica, puede invertirse utilizando una Llave Inglesa.", + "block.create.brass_funnel.tooltip.condition3": "Cuando se encuentra verticalmente entre dos inventarios", + "block.create.brass_funnel.tooltip.behaviour3": "Transfiere los artículos hacia abajo, como una tolva sin búfer.", + + "block.create.brass_tunnel.tooltip": "TÚNEL DE LATÓN", + "block.create.brass_tunnel.tooltip.summary": "Una cubierta protectora elegante para sus _correas_. Los _Túneles de latón_ también vienen con una serie de opciones de _Filtración_ y _División_ para sus artículos.", + "block.create.brass_tunnel.tooltip.condition1": "Cuando se colocan uno al lado del otro", + "block.create.brass_tunnel.tooltip.behaviour1": "Los túneles de latón se conectan entre sí y permiten redirigir el contenido de una correa a otra.", + "block.create.brass_tunnel.tooltip.condition2": "Filtrado", + "block.create.brass_tunnel.tooltip.behaviour2": "Los _Túneles de latón_ vienen con filtros tanto para la _Entrada_ como para la _Salida_. Si un _Elemento_ no está permitido desde la salida filtrada de un _Túnel_ será transferido a la salida de un _Túnel_ conectado.", + "block.create.brass_tunnel.tooltip.condition3": "Dividiendo", + "block.create.brass_tunnel.tooltip.behaviour3": "Los _Túneles de latón_ pueden ser configurados para cambiar el método en el que los _Elementos_ son ordenados en los _Túneles_ conectados.", + "block.create.brass_tunnel.tooltip.control1": "Cuando haces click derecho con una Llave Inglesa", + "block.create.brass_tunnel.tooltip.action1": "_Ajusta las persianas de las ventanas_ si el túnel tiene una ventana en esa cara.", + "block.create.brass_tunnel.tooltip.control2": "Usa la rueda del ratón con la Llave Inglesa en la parte superior", + "block.create.brass_tunnel.tooltip.action2": "Cambiar el método de división de los _Túneles_ conectados.", + + "block.create.copper_casing.tooltip": "REVESTIDOR DE COBRE", + "block.create.copper_casing.tooltip.summary": "Robusta máquina de revestimientos con una gran variedad de usos. Seguro para la decoración.", + "block.create.copper_casing.tooltip.condition1": "Cuando se utiliza en una tubería de fluidos", + "block.create.copper_casing.tooltip.behaviour1": "_Reviste_ la _Tubería de fluidos_ con _Revestimiento de cobre_. Las tuberías de fluidos revestidas _bloquean sus conexiones_ en su lugar, dejando de reaccionar a los cambios en las tuberías vecinas.", + + "block.create.encased_fluid_pipe.tooltip": "TUBO DE FLUIDOS REVESTIDO", + "block.create.encased_fluid_pipe.tooltip.summary": "Un tubo de fluidos revestido con cobre.", + + "block.create.copper_valve_handle.tooltip": "ASA DE VÁLVULA DE COBRE", + "block.create.copper_valve_handle.tooltip.summary": "Una precisa _fuente_ de _fuerza de rotación_ que requiere la interacción de los jugadores. ¡Ten cuidado de no agotarte!", + "block.create.copper_valve_handle.tooltip.condition1": "Cuando se utiliza", + "block.create.copper_valve_handle.tooltip.behaviour1": "Proporciona _Fuerza de rotación_ a un artilugio acoplado. _Shift_ para _invertir_ la rotación.", + + "block.create.seat.tooltip": "ASIENTO", + "block.create.seat.tooltip.summary": "¡Siéntate y disfruta del viaje! Anclará a un jugador en un _contrafuerte_ en movimiento. También es ideal para los muebles estáticos. Viene en una variedad de colores.", + "block.create.seat.tooltip.condition1": "Click derecho en el asiento", + "block.create.seat.tooltip.behaviour1": "Sienta al jugador en el _Asiento_. Pulsa shift izquierdo para dejar el _Asiento_.", + + "block.create.chute.tooltip": "DUCTO", + "block.create.chute.tooltip.summary": "_Recoge_ y _Transporta_ elementos en vertical o en diagonal. Puede tanto coger como colocar objetos en _contenedores de objetos_. También puede interactuar con los ductos desde el lateral utilizando _tolvas_ o _embudos montados_.", + "block.create.chute.tooltip.condition1": "Cuando se alimenta con un ventilador", + "block.create.chute.tooltip.behaviour1": "Los ductos accionados por ventilador pueden transportar _elementos_ hacia arriba, y aspirar _elementos_ de los _depósitos_ y de las _correas_.", + + "block.create.depot.tooltip": "DEPÓSITO", + "block.create.depot.tooltip.summary": "Un lugar práctico para colocar sus _elementos_. Proporciona un punto de interacción para varias máquinas", + "block.create.depot.tooltip.condition1": "Click derecho en el depósito", + "block.create.depot.tooltip.behaviour1": "Coloca o toma un _Elemento_ del _Depósito_. Los _Bloques_ y los _Artilugios_ que interactúan con una _Correa_ también funcionan en un _Depósito_.", + + "item.create.blaze_cake.tooltip": "PASTEL DE BLAZE", + "item.create.blaze_cake.tooltip.summary": "Un delicioso regalo para sus esforzados _Quemadores de blaze_. Los pone en marcha!.", + + "item.create.empty_blaze_burner.tooltip": "QUEMADOR DE BLAZE VACÍO", + "item.create.empty_blaze_burner.tooltip.summary": "Un pequeño hogar de hierro para tus amigos fogosos. Estoy seguro de que podrías darles un buen uso.", + "item.create.empty_blaze_burner.tooltip.condition1": "Cuando se utiliza en un Blaze o en un generador de Blaze", + "item.create.empty_blaze_burner.tooltip.behaviour1": "_Captura_ un Blaze en el elemento", + + "block.create.fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS DE COBRE", + "block.create.fluid_pipe.tooltip.summary": "Se utiliza para mover _fluidos_. Necesita una _bomba mecánica_ para que el _fluido_ se mueva.", + "block.create.fluid_pipe.tooltip.condition1": "Transferencia de fluidos", + "block.create.fluid_pipe.tooltip.behaviour1": "Puede conectarse a _contenedores de fluidos_ como _depósitos_ o _cuencas_. Los extremos expuestos de los _tubos_ también pueden drenar o colocar bloques de fluido. ¡Cuidado con las fugas!", + "block.create.fluid_pipe.tooltip.control1": "Cuando haces clic derecho con una Llave Inglesa", + "block.create.fluid_pipe.tooltip.action1": "Coloca una ventana en la tubería si está disponible", + + "block.create.hose_pulley.tooltip": "POLEA DE MANGUERA", + "block.create.hose_pulley.tooltip.summary": "Se utiliza para _colocar_ o _drenar_ grandes _cuerpos fluidos_ en el mundo", + "block.create.hose_pulley.tooltip.condition1": "Cuando se alimenta por cinética", + "block.create.hose_pulley.tooltip.behaviour1": "_Sube_ o _baja_ la manguera, la ubicación de la manguera determina hasta qué _altura de extracción_ o _llenado_ actuará.", + "block.create.hose_pulley.tooltip.condition2": "Cuando los fluidos se extraen de la polea", + "block.create.hose_pulley.tooltip.behaviour2": "Comienza a _tomar bloques de fluidos_ del cuerpo al que se bajó el extremo de la manguera. Los cuerpos muy _grandes_ de fluidos se _considerarán infinitos_.", + "block.create.hose_pulley.tooltip.condition3": "Cuando los fluidos son empujados a la polea", + "block.create.hose_pulley.tooltip.behaviour3": "Comienza a _llenar de fluido_ el mundo hasta la _altura_ de los extremos de la _manguera_", + + "block.create.fluid_tank.tooltip": "TANQUE DE FLUIDOS", + "block.create.fluid_tank.tooltip.summary": "Almacena todos tus _líquidos_ favoritos. Escala en anchura y altura.", + "block.create.fluid_tank.tooltip.condition1": "Cuando se hace click derecho con la Llave Inglesa", + "block.create.fluid_tank.tooltip.behaviour1": "Cambia la ventana opcional", + + "block.create.creative_fluid_tank.tooltip": "TANQUE DE FLUIDOS CREATIVO", + "block.create.creative_fluid_tank.tooltip.summary": "Este _Tanque de Fluidos_ permite la replicación infinita de cualquier Fluido. Escala en anchura y altura.", + "block.create.creative_fluid_tank.tooltip.condition1": "Cuando hay fluido en el tanque", + "block.create.creative_fluid_tank.tooltip.behaviour1": "Todo lo que se _extraiga_ de este tanque proporcionará un _suministro ilimitado_ del fluido especificado. Los fluidos _insertados_ en este tanque serán _evitados._", + "block.create.creative_fluid_tank.tooltip.condition2": "Cuando se hace clic derecho con una Llave Inglesa", + "block.create.creative_fluid_tank.tooltip.behaviour2": "Cambia la ventana opcional", + + "block.create.fluid_valve.tooltip": "VALVULA DE FLUIDOS", + "block.create.fluid_valve.tooltip.summary": "Detiene el flujo de un fluido por una tubería", + "block.create.fluid_valve.tooltip.condition1": "Flujo controlable", + "block.create.fluid_valve.tooltip.behaviour1": "La _fuerza de rotación_ aplicada obligará a la _válvula_ a cerrarse, cesando el flujo de _fluidos_. Invierta la dirección de la _fuerza de rotación_ para volver a abrir la válvula", + + "block.create.mechanical_pump.tooltip": "BOMBA MECÁNICA", + "block.create.mechanical_pump.tooltip.summary": "Toma la _fuerza de rotación_ y la utiliza para mover el _fluido_ a lo largo de un _tubo_. Tiene un rango máximo de efecto en ambas direcciones. (16 bloques por defecto)", + "block.create.mechanical_pump.tooltip.condition1": "Flujo de fluido", + "block.create.mechanical_pump.tooltip.behaviour1": "La _fuerza de rotación_ aplicada crea una presión que obliga al _fluido_ a pasar por la red de _tuberías_. Invierte la dirección de la _fuerza de rotación_ para cambiar la dirección en la que fluye el _fluido_", + "block.create.mechanical_pump.tooltip.control1": "Pulsando con el botón derecho del ratón con la Llave Inglesa", + "block.create.mechanical_pump.tooltip.action1": "Invierte la dirección de la _bomba_, cambiando la dirección por defecto del flujo", + + "block.create.smart_fluid_pipe.tooltip": "TUBERÍA DE FLUIDOS INTELIGENTE", + "block.create.smart_fluid_pipe.tooltip.summary": "Una _tubería de fluidos_ con un filtro. Puede especificar qué _fluidos_ pasan por ella", + "block.create.smart_fluid_pipe.tooltip.condition1": "Cuando se introducen fluidos en ella", + "block.create.smart_fluid_pipe.tooltip.behaviour1": "Las tuberías inteligentes que reciban fluidos que no coincidan con su filtro bloquearán el flujo", + "block.create.smart_fluid_pipe.tooltip.condition2": "Cuando es adyacente a un contenedor de fluido", + "block.create.smart_fluid_pipe.tooltip.behaviour2": "Las tuberías inteligentes que _inicien_ un _flujo_ desde cualquier contenedor sólo extraerán fluidos que _coincidan_ con su _filtro._", + + "block.create.spout.tooltip": "SURTIDOR", + "block.create.spout.tooltip.summary": "Un inyector para rellenar tus elementos de _fluidos._", + "block.create.spout.tooltip.condition1": "Transferencia de fluidos", + "block.create.spout.tooltip.behaviour1": "Cuando se coloca un _contenedor de fluidos_ como un _cubo_ o una _botella_ debajo, el caño intentará rellenarlo con su propio _fluido_ almacenado", + "block.create.spout.tooltip.condition2": "Automatización de fluidos", + "block.create.spout.tooltip.behaviour2": "El caño colocado encima de una _correa_ o _depósito_ reaccionará automáticamente con un contenedor de fluidos_ que pase por debajo", + + "block.create.item_drain.tooltip": "DRENADOR DE ELEMENTOS", + "block.create.item_drain.tooltip.summary": "Un depósito rallado para vaciar tus _artículos fluidos._", + "block.create.item_drain.tooltip.condition1": "Transferencia de fluidos", + "block.create.item_drain.tooltip.behaviour1": "Cuando un _contenedor de fluidos_, como un _cubo_ o una _botella_, se inserta desde el lateral, el desagüe intentará vaciarlo en su propio _contenedor de fluidos_. El artículo será entonces expulsado por el lado opuesto", + + "block.create.mechanical_arm.tooltip": "BRAZO MECÁNICO", + "block.create.mechanical_arm.tooltip.summary": "Artilugio avanzado para reubicar _elementos_", + "block.create.mechanical_arm.tooltip.condition1": "Transferencia de elementos", + "block.create.mechanical_arm.tooltip.behaviour1": "Puede tomar o colocar objetos en cualquier _inventario_ accesible_, como _Correas_, _Depósitos_, _Embudos_ y _Autoensambladores_", + "block.create.mechanical_arm.tooltip.control1": "Mientras está en la mano", + "block.create.mechanical_arm.tooltip.action1": "Haz clic con el botón derecho en un _objeto accesible del inventario_ para establecerlo como _fuente_ para el _brazo mecánico_. Haz clic con el botón derecho del ratón dos veces para establecerlo como _destino_", + "block.create.mechanical_arm.tooltip.control2": "Usa la rueda del ratón con la Llave Inglesa", + "block.create.mechanical_arm.tooltip.action2": "Establece el comportamiento de orden de los _items_ emitidos por el _brazo mecánico_", + + "item.create.wand_of_symmetry.tooltip": "VARITA DE SIMETRÍA", + "item.create.wand_of_symmetry.tooltip.summary": "Refleja perfectamente la colocación de bloques en los planos configurados", + "item.create.wand_of_symmetry.tooltip.condition1": "Mientras está en el inventario rápido", + "item.create.wand_of_symmetry.tooltip.behaviour1": "Permanece activo", + "item.create.wand_of_symmetry.tooltip.control1": "Click derecho en el suelo", + "item.create.wand_of_symmetry.tooltip.action1": "_Crea_ o _Mueve_ el Espejo", + "item.create.wand_of_symmetry.tooltip.control2": "Click derecho en el aire", + "item.create.wand_of_symmetry.tooltip.action2": "_Quita_ el Espejo activo", + "item.create.wand_of_symmetry.tooltip.control3": "Click derecho mientras se agacha", + "item.create.wand_of_symmetry.tooltip.action3": "Abre la _Interfaz de Configuración_", + + "item.create.handheld_blockzapper.tooltip": "BLOCKZAPPER", + "item.create.handheld_blockzapper.tooltip.summary": "Novedoso artefacto para colocar o intercambiar bloques a distancia", + "item.create.handheld_blockzapper.tooltip.control1": "Click izquierdo en un bloque", + "item.create.handheld_blockzapper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", + "item.create.handheld_blockzapper.tooltip.control2": "Click derecho en un bloque", + "item.create.handheld_blockzapper.tooltip.action2": "_Coloca_ o _Reemplaza_ el bloque objetivo", + "item.create.handheld_blockzapper.tooltip.control3": "Click derecho mientras se agacha", + "item.create.handheld_blockzapper.tooltip.action3": "Abre la _Interfaz de Configuración_", + + "item.create.handheld_worldshaper.tooltip": "WORLDSHAPER", + "item.create.handheld_worldshaper.tooltip.summary": "Práctica herramienta para crear _paisajes_ y _características del terreno_", + "item.create.handheld_worldshaper.tooltip.control1": "Click izquierdo en un bloque", + "item.create.handheld_worldshaper.tooltip.action1": "Establece los bloques colocados por la herramienta en el bloque objetivo", + "item.create.handheld_worldshaper.tooltip.control2": "Click derecho en un bloque", + "item.create.handheld_worldshaper.tooltip.action2": "Aplica el _pincel_ y la _herramienta_ actualmente seleccionadas en el lugar deseado.", + "item.create.handheld_worldshaper.tooltip.control3": "Click derecho mientras se agacha", + "item.create.handheld_worldshaper.tooltip.action3": "Abre la _Interfaz de Configuración_", + + "item.create.tree_fertilizer.tooltip": "FERTILIZANTE PARA ÁRBOLES", + "item.create.tree_fertilizer.tooltip.summary": "Una potente combinación de minerales adecuada para acelerar el crecimiento de los tipos de árboles más comunes", + "item.create.tree_fertilizer.tooltip.condition1": "Cuando se utiliza en un árbol joven", + "item.create.tree_fertilizer.tooltip.behaviour1": "Hace crecer los árboles _independientemente_ de sus condiciones de _espacio_", + + "item.create.deforester.tooltip": "DEFORESTADOR", + "item.create.deforester.tooltip.summary": "Un hacha _radiante_ capaz de talar árboles en una fracción de segundo", + + "item.create.extendo_grip.tooltip": "AGARRE EXTENDIDO", + "item.create.extendo_grip.tooltip.summary": "¡Boioioing! Aumenta enormemente la _distancia de alcance_ del portador", + "item.create.extendo_grip.tooltip.condition1": "Cuando está fuera de la mano", + "item.create.extendo_grip.tooltip.behaviour1": "Aumenta la _distancia de alcance_ de los objetos usados en la _mano principal_", + + "item.create.filter.tooltip": "FILTRO", + "item.create.filter.tooltip.summary": "Controla las salidas_ y _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de elementos_ o varios _filtros anidados_", + "item.create.filter.tooltip.condition1": "Cuando está en la ranura del filtro", + "item.create.filter.tooltip.behaviour1": "Controla_ el flujo del elemento según su _configuración_", + "item.create.filter.tooltip.condition2": "Cuando se hace clic derecho", + "item.create.filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + + "item.create.attribute_filter.tooltip": "FILTRO DE ATRIBUTOS", + "item.create.attribute_filter.tooltip.summary": "Controla las salidas_ y las _entradas_ de los dispositivos logísticos con más _precisión_, comparándolas con un _conjunto de _atributos_ y _categorías_ de artículos", + "item.create.attribute_filter.tooltip.condition1": "Cuando está en la ranura del filtro", + "item.create.attribute_filter.tooltip.behaviour1": "Controla el flujo del elemento según su _configuración_", + "item.create.attribute_filter.tooltip.condition2": "Cuando se hace clic derecho", + "item.create.attribute_filter.tooltip.behaviour2": "Abre la interfaz de _configuración_", + + "item.create.empty_schematic.tooltip": "ESQUEMA VACÍO", + "item.create.empty_schematic.tooltip.summary": "Se utiliza como ingrediente de las recetas y para escribir en la _tabla de esquemas_", + + "item.create.schematic.tooltip": "ESQUEMA", + "item.create.schematic.tooltip.summary": "Contiene una estructura para ser posicionada y colocada en el mundo. Posiciona el holograma como se desee y utiliza un _Esquematicannon_ para construirlo", + "item.create.schematic.tooltip.condition1": "Cuando se mantiene", + "item.create.schematic.tooltip.behaviour1": "Se puede posicionar utilizando las herramientas en pantalla", + "item.create.schematic.tooltip.control1": "Click derecho mientras se agacha", + "item.create.schematic.tooltip.action1": "Abre una _Interfaz_ para introducir las _Coordenadas_ exactas", + + "item.create.schematic_and_quill.tooltip": "ESQUEMA Y PLUMA", + "item.create.schematic_and_quill.tooltip.summary": "Se utiliza para guardar una estructura de tu mundo en un archivo .nbt", + "item.create.schematic_and_quill.tooltip.condition1": "Paso 1", + "item.create.schematic_and_quill.tooltip.behaviour1": "Selecciona dos puntos de esquina usando click derecho", + "item.create.schematic_and_quill.tooltip.condition2": "Paso 2", + "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrl-Rueda del ratón_ en las caras para ajustar el tamaño. Click derecho de nuevo para guardar", + "item.create.schematic_and_quill.tooltip.control1": "Click derecho", + "item.create.schematic_and_quill.tooltip.action1": "Seleccionar un punto de esquina / confirmar guardar", + "item.create.schematic_and_quill.tooltip.control2": "Al mantener Ctrl", + "item.create.schematic_and_quill.tooltip.action2": "Seleccionar puntos en _medio del aire_. Rueda del ratón para ajustar la distancia", + "item.create.schematic_and_quill.tooltip.control3": "Click derecho mientras se agacha", + "item.create.schematic_and_quill.tooltip.action3": "Reinicia_ y elimina la selección", + + "block.create.schematicannon.tooltip": "ESQUEMATICAÑÓN", + "block.create.schematicannon.tooltip.summary": "Dispara bloques para recrear un _Esquema_ desplegado en el Mundo. Utiliza elementos de los inventarios adyacentes y _Pólvora_ como combustible.", + "block.create.schematicannon.tooltip.control1": "Cuando se hace clic derecho", + "block.create.schematicannon.tooltip.action1": "Abre la _Interfaz_ de configuración", + + "block.create.schematic_table.tooltip": "TABLA DE ESQUEMAS", + "block.create.schematic_table.tooltip.summary": "Escribe los esquemas guardados en un _esquema vacío_", + "block.create.schematic_table.tooltip.condition1": "Cuando se da un esquema vacío", + "block.create.schematic_table.tooltip.behaviour1": "Carga un archivo elegido de la carpeta de esquemas", + + "block.create.shaft.tooltip": "EJE", + "block.create.shaft.tooltip.summary": "_Retransmite la rotación_ en línea recta", + + "block.create.cogwheel.tooltip": "RUEDA DENTADA", + "block.create.cogwheel.tooltip.summary": "_Retransmite la rotación_ en línea recta, y a las _ruedas dentadas_ adyacentes", + + "block.create.large_cogwheel.tooltip": "RUEDA DENTADA GRANDE", + "block.create.large_cogwheel.tooltip.summary": "Una versión más grande de la _Rueda dentada_, que permite _cambiar_ la _Velocidad de Rotación_ cuando se conecta a su contraparte más pequeña", + + "block.create.encased_shaft.tooltip": "EJE REVESTIDO", + "block.create.encased_shaft.tooltip.summary": "_Retransmite la rotación_ en línea recta. Adecuado para propagar la Rotación a través de Muros", + + "block.create.gearbox.tooltip": "CAJA DE TRANSMISIÓN", + "block.create.gearbox.tooltip.summary": "_Retransmite la rotación_ en _cuatro direcciones_. Invierte las conexiones rectas", + + "block.create.gearshift.tooltip": "CAJA DE CAMBIOS", + "block.create.gearshift.tooltip.summary": "Un control para alternar la dirección de rotación de los ejes conectados", + "block.create.gearshift.tooltip.condition1": "Cuando se alimenta", + "block.create.gearshift.tooltip.behaviour1": "_Invierte_ la rotación de salida", + + "bloque.crear.embrague.información.sobre.herramientas": "EMBRAGUE", + "block.create.clutch.tooltip.summary": "Un control para conectar/desconectar la rotación de los ejes conectados", + "block.create.clutch.tooltip.condition1": "Cuando se acciona", + "block.create.clutch.tooltip.behaviour1": "_Detiene_ el transporte de la rotación al otro lado", + + "block.create.encased_chain_drive.tooltip": "CADENA DE TRANSMISIÓN REVESTIDA", + "block.create.encased_chain_drive.tooltip.summary": "_Retransmite la rotación_ en línea recta y a las cadenas de transmisión adyacentes. Las cadenas de transmisión se conectan en un grupo cuando se colocan junto a otra en cualquier cara sin eje. Su orientación no tiene que coincidir", + "block.create.encased_chain_drive.tooltip.condition1": "Cuando se conecta", + "block.create.encased_chain_drive.tooltip.behaviour1": "Los bloques conectados transmitirán la _velocidad de rotación_ y la dirección de este componente", + + "block.create.adjustable_chain_gearshift.tooltip": "CADENA DE TRANSMISIÓN AJUSTABLE", + "block.create.adjustable_chain_gearshift.tooltip.summary": "_Retransmite el giro_ en línea recta y a las _cadenas adyacentes_. El Redstone analógo proporcionada a este bloque controlará qué tamaño de rueda motriz se acopla a las cadenas de transmisión adyacentes", + "block.create.adjustable_chain_gearshift.tooltip.condition1": "Control de Redstone", + "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "_Sin señal_, los accionamientos de cadena adyacentes transmitirán la _misma velocidad._ Con una señal de _fuerza completa_, los accionamientos de cadena adyacentes transmitirán exactamente _el doble de su velocidad._ Cualquier cosa entre medias dará resultados entre 1-2x su velocidad", + + "item.create.belt_connector.tooltip": "CORREA", + "item.create.belt_connector.tooltip.summary": "Conecta dos o más _ejes_ con una _Correa_. Los ejes conectados tendrán exactamente la misma velocidad y dirección de rotación. La correa puede actuar como _Transportador_ para _Estados_ y _Entidades_", + "item.create.belt_connector.tooltip.control1": "Click derecho en el eje", + "item.create.belt_connector.tooltip.action1": "Selecciona el eje como una polea de la correa. Los dos ejes seleccionados tienen que estar _alineados_ ya sea _Verticalmente_, _Horizontalmente_ o _Diagonalmente_ hacia la dirección de la correa", + "item.create.belt_connector.tooltip.control2": "Click derecho mientras te agachas", + "item.create.belt_connector.tooltip.action2": "_Reinicia_ la primera posición seleccionada para la correa", + + "item.create.goggles.tooltip": "GAFAS DEL INGENIERO", + "item.create.goggles.tooltip.summary": "Un par de gafas para aumentar tu visión con útil información _cinética_", + "item.create.goggles.tooltip.condition1": "Cuando se llevan puestas", + "item.create.goggles.tooltip.behaviour1": "Muestra _indicadores de color_ correspondientes al _Nivel de velocidad_ de un componente cinético colocado, así como el _Impacto de estrés_ y la _Capacidad_ de los componentes individuales.", + "item.create.goggles.tooltip.condition2": "Al mirar el medidor", + "item.create.goggles.tooltip.behaviour2": "Muestra información detallada sobre _Velocidad_ o _Estrés_ de la red a la que está conectado el medidor", + + "item.create.wrench.tooltip": "LLAVE INGLESA", + "item.create.wrench.tooltip.summary": "Una herramienta útil para trabajar en artilugios cinéticos. Se puede utilizar para _Rotar_, _Desmantelar_ y para _Configurar_ componentes", + "item.create.wrench.tooltip.control1": "Click con el botón derecho en un bloque cinético", + "item.create.wrench.tooltip.action1": "_Rota los componentes_ hacia o desde la cara con la que ha interactuado", + "item.create.wrench.tooltip.control2": "Click derecho mientras te agachas", + "item.create.wrench.tooltip.action2": "Desmonta los componentes cinéticos_ y los devuelve a _tu inventario_", + + "block.create.creative_motor.tooltip": "MOTOR CREATIVO", + "block.create.creative_motor.tooltip.summary": "Una fuente configurable de _Fuerza Rotativa_", + + "block.create.water_wheel.tooltip": "RUEDA HIDRÁULICA MECÁNICA", + "block.create.water_wheel.tooltip.summary": "Proporciona _Fuerza de rotación_ tomada de las _Corrientes de agua_ adyacentes", + + "block.create.encased_fan.tooltip": "VENTILADOR REVESTIDO", + "block.create.encased_fan.tooltip.summary": "Convierte la _fuerza de rotación_ en _corrientes de aire_ y viceversa. Tiene una gran variedad de usos", + "block.create.encased_fan.tooltip.condition1": "Cuando es alimentado por Redstone", + "block.create.encased_fan.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a partir de cualquier _fuente de calor_ inmediatamente inferior. El ventilador debe estar orientado hacia abajo", + "block.create.encased_fan.tooltip.condition2": "Cuando es impulsado por la cinética", + "block.create.encased_fan.tooltip.behaviour2": "_Empuja_ o _Tira_ de Entidades, dependiendo de la velocidad de Rotación entrante", + "block.create.encased_fan.tooltip.condition3": "Al soplar a través de bloques especiales", + "block.create.encased_fan.tooltip.behaviour3": "Se emiten partículas de _Líquidos_ y _Fuego_ en el flujo de aire. Esto puede utilizarse para _procesar objetos_", + + "block.create.nozzle.tooltip": "BOQUILLA", + "block.create.nozzle.tooltip.summary": "Se acopla a la parte delantera de un _ventilador revestido_ para distribuir su efecto sobre las entidades en _todas las direcciones_", + + "block.create.hand_crank.tooltip": "MANIVELA", + "block.create.hand_crank.tooltip.summary": "Una sencilla _fuente_ de _fuerza de rotación_ que requiere la interacción de los jugadores. Ten cuidado de no agotarte!", + "block.create.hand_crank.tooltip.condition1": "Cuando se usa", + "block.create.hand_crank.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a un artilugio acoplado. _Se puede revertir_ la rotación", + + "block.create.cuckoo_clock.tooltip": "RELOJ DE CUCO", + "block.create.cuckoo_clock.tooltip.summary": "Fina artesanía para _decorar_ un espacio y _contar el tiempo_", + "block.create.cuckoo_clock.tooltip.condition1": "Cuando es alimentado por cinética", + "block.create.cuckoo_clock.tooltip.behaviour1": "Muestra la _hora actual_ y toca una melodía dos veces al día. Se activa_ una vez al _mediodía_ y al anochecer, en cuanto _los jugadores pueden dormir_", + + "block.create.turntable.tooltip": "PLATAFORMA GIRATORIA", + "block.create.turntable.tooltip.summary": "Convierte la _fuerza de rotación_ en un refinado mareo", + + "block.create.millstone.tooltip": "PIEDRA DEL MOLINO", + "block.create.millstone.tooltip.summary": "Un componente cinético adecuado para _moler_ materiales insertados. Puede ser alimentado por una rueda dentada adyacente o conectándose al eje de la parte inferior. Los resultados tienen que ser extraídos del componente", + "block.create.millstone.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.millstone.tooltip.behaviour1": "Comienza a aplicar _recetas de fresado_ a cualquier elemento insertado desde el lateral o la parte superior del bloque", + "block.create.millstone.tooltip.condition2": "Cuando se hace clic derecho", + "block.create.millstone.tooltip.behaviour2": "Recoge las salidas manualmente", + + "block.create.crushing_wheel.tooltip": "RUEDA DE TRITURACIÓN", + "block.create.crushing_wheel.tooltip.summary": "Grandes ruedas giratorias que _rompen_ cualquier cosa", + "block.create.crushing_wheel.tooltip.condition1": "Cuando se une a otra rueda trituradora", + "block.create.crushing_wheel.tooltip.behaviour1": "Forma una máquina trituradora para procesar una variedad de cosas. Los dientes de las ruedas tienen que conectarse y moverse con la _misma velocidad_ en _direcciones opuestas_", + + "block.create.mechanical_press.tooltip": "PRENSA MECÁNICA", + "block.create.mechanical_press.tooltip.summary": "Un pistón de fuerza para comprimir los objetos que tiene debajo. Requiere una _fuerza de rotación_ constante", + "block.create.mechanical_press.tooltip.condition1": "Cuando es impulsado por Redstone", + "block.create.mechanical_press.tooltip.behaviour1": "Comienza a _comprimir_ los objetos que caen debajo", + "block.create.mechanical_press.tooltip.condition2": "Cuando está por encima de una correa", + "block.create.mechanical_press.tooltip.behaviour2": "Comprime _automáticamente_ los elementos de derivación en la correa", + "block.create.mechanical_press.tooltip.condition3": "Cuando está por encima de la Cuenca", + "block.create.mechanical_press.tooltip.behaviour3": "Comienza a _compactar artículos_ en la cuenca siempre que estén presentes todos los ingredientes necesarios", + + "block.create.basin.tooltip": "CUENCA", + "block.create.basin.tooltip.summary": "Un práctico _contenedor de elementos_ utilizado en el procesamiento con la _Mezcladora mecánica_ y la _Prensa mecánica_. Soporta _Comparadores de Redstone_. Viene con un práctico filtro que especifica qué elementos deben crearse en esta cuenca", + "block.create.basin.tooltip.condition1": "Salida automática", + "block.create.basin.tooltip.behaviour1": "Cuando los _inventarios abiertos_ como cintas, otras cuencas, depósitos, desagües de fluidos y otros están _bajo un lado_ de una cuenca, recibirán automáticamente cualquier _salida de artículos/fluidos_ creada en la cuenca. Esto es útil para la automatización", + + "block.create.blaze_burner.tooltip": "QUEMADOR DE BLAZE", + "block.create.blaze_burner.tooltip.summary": "Un bloque donde se aloja un blaze domado para calentar una cuenca", + "block.create.blaze_burner.tooltip.condition1": "Cuando se coloca debajo de una cuenca", + "block.create.blaze_burner.tooltip.behaviour1": "Proporciona _calor_ a las recetas de la cuenca", + "block.create.blaze_burner.tooltip.condition2": "Cuando se utiliza el combustible en el Quemador de Blaze", + "block.create.blaze_burner.tooltip.behaviour2": "Aumenta el tiempo de combustión restante en el tiempo de combustión del horno del elemento utilizado. Consume el objeto. Utiliza _Torta de Blaze_ para altas temperaturas", + + "block.create.reinforced_rail.tooltip": "RAÍL REFORZADO", + "block.create.reinforced_rail.tooltip.summary": "Raíl estabilizado con madera, _no necesita soportes_", + + "block.create.mechanical_mixer.tooltip": "MEZCLADOR MECÁNICO", + "block.create.mechanical_mixer.tooltip.summary": "Un batidor cinético que proporciona recetas de elaboración automatizada de múltiples ingredientes. Requiere una _fuerza de rotación_ constante y una _cuenca_ colocada debajo (con un espacio intermedio)", + "block.create.mechanical_mixer.tooltip.condition1": "Cuando está por encima de la Cuenca", + "block.create.mechanical_mixer.tooltip.behaviour1": "Comienza a mezclar los elementos en la cuenca siempre que estén presentes todos los ingredientes necesarios. Para evitar recetas no deseadas, utilice la ranura del filtro de la cuenca o reduzca la fuerza de rotación hasta que se hayan añadido todos los ingredientes deseados", + + "block.create.mechanical_crafter.tooltip": "AUTOENSAMBLADOR MECÁNICO", + "block.create.mechanical_crafter.tooltip.summary": "Un ensamblador cinético para _automatizar_ cualquier receta de _crafteo_ con forma. Coloca _múltiples en una cuadrícula_ correspondiente a tu receta, y _organiza sus correas_ para crear un _flujo_ que salga de la cuadrícula en uno de los Autoensambladores", + "block.create.mechanical_crafter.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.mechanical_crafter.tooltip.behaviour1": "_Empieza el proceso de creación_ en cuanto _todos los crafters_ de la parrilla hayan recibido un objeto_", + "block.create.mechanical_crafter.tooltip.condition2": "Con pulso de Redstone", + "block.create.mechanical_crafter.tooltip.behaviour2": "_Fuerza_ el inicio del proceso de _creación_ con todos los _artículos_ dados actualmente en la parrilla", + "block.create.mechanical_crafter.tooltip.control1": "Cuando se arranca por delante", + "block.create.mechanical_crafter.tooltip.action1": "_Circula la dirección_ hacia la que un autoensamblador individual _mueve sus objetos_. Para formar una cuadrícula de trabajo, _organiza las correas en un flujo_ que mueva todos los objetos hacia un autoensamblador final. El autoensamblador final debe _apuntar hacia fuera_ de la rejilla", + "block.create.mechanical_crafter.tooltip.control2": "Cuando se arranca hacia atrás", + "block.create.mechanical_crafter.tooltip.action2": "Conecta_ el _inventario de entrada_ de los autoensambladores adyacentes. Usa esto para _combinar ranuras_ en la cuadrícula de trabajo y _guardar el la entrada de trabajo_", + + "block.create.furnace_engine.tooltip": "MOTOR DEL HORNO", + "block.create.furnace_engine.tooltip.summary": "Una poderosa fuente de _fuerza de rotación/torque_ que requiere un _horno en funcionamiento_ para funcionar", + "block.create.furnace_engine.tooltip.condition1": "Cuando se conecta a un horno encendido", + "block.create.furnace_engine.tooltip.behaviour1": "_Empieza a alimentar_ un _Horno_ colocado delante de él (a 1m de distancia). Utiliza un Alto Horno para obtener mayores velocidades", + + "block.create.flywheel.tooltip": "RUEDA DE INERCIA", + "block.create.flywheel.tooltip.summary": "Una gran rueda metálica para _conducir y estabilizar_ la fuerza generada por un _motor conectado_. Las ruedas de inercia se conectan a los motores si están a _1m de distancia_ y en un _ángulo de 90º_ entre ellos", + "block.create.flywheel.tooltip.condition1": "Cuando está unida a un motor en marcha", + "block.create.flywheel.tooltip.behaviour1": "Proporciona _fuerza de rotación_ a un artilugio conectado en función de la fuerza y la velocidad del generador", + + "block.create.portable_storage_interface.tooltip": "INTERFAZ DE ALMACENAMIENTO PORTÁTIL", + "block.create.portable_storage_interface.tooltip.summary": "Un punto de intercambio portátil para _mover elementos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", + "block.create.portable_storage_interface.tooltip.condition1": "Mientras se mueve", + "block.create.portable_storage_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátil_ estacionarias para transferir elementos hacia o desde el artilugio. Los componentes que se inserten o extraigan de la _interfaz estacionaria_ interactuarán con los inventarios del artilugio _directamente._ La estructura se detendrá brevemente mientras se intercambian los elementos.", + "block.create.portable_storage_interface.tooltip.condition2": "Cuando es alimentado por Redstone", + "block.create.portable_storage_interface.tooltip.behaviour2": "Desactiva_ cualquier conexión activa inmediatamente", + + "block.create.portable_fluid_interface.tooltip": "INTERFAZ DE FLUIDO PORTÁTIL", + "block.create.portable_fluid_interface.tooltip.summary": "Punto de intercambio portátil para _mover fluidos_ hacia y desde una _estructura_ movida por un pistón, rodamiento, vagoneta o polea. Para cumplirse dos interfaces tienen que _enfrentarse_ y estar separadas _1-2 bloques_", + "block.create.portable_fluid_interface.tooltip.condition1": "Mientras se mueve", + "block.create.portable_fluid_interface.tooltip.behaviour1": "Interactúa con las _interfaces de almacenamiento portátiles_ estacionarias para transferir fluidos hacia o desde el artilugio. Las tuberías que se inserten en la _interfaz estacionaria_ o se extraigan de ella interactuarán con los depósitos del artilugio _directamente._ La estructura se paralizará brevemente mientras se intercambian fluidos.", + "block.create.portable_fluid_interface.tooltip.condition2": "Cuando se alimenta con Redstone", + "block.create.portable_fluid_interface.tooltip.behaviour2": "_Desconecta_ cualquier conexión activa inmediatamente", + + "block.create.rotation_speed_controller.tooltip": "CONTROLADOR DE VELOCIDAD DE ROTACIÓN", + "block.create.rotation_speed_controller.tooltip.summary": "Un _relé_ configurable_ capaz de acelerar o ralentizar el componente de destino a cualquier velocidad deseada", + "block.create.rotation_speed_controller.tooltip.condition1": "Cuando se adjunta a una rueda dentada grande", + "block.create.rotation_speed_controller.tooltip.behaviour1": "Transmite la fuerza de rotación entrante a la rueda, intentando _igualar_ la _velocidad_ a la que está configurada. La _rueda mecánica_ tiene que estar _adherida en la parte superior_ del controlador", + + "block.create.mechanical_piston.tooltip": "PISTÓN MECÁNICO", + "block.create.mechanical_piston.tooltip.summary": "Una versión más avanzada del _Pistón_. Utiliza la _Fuerza de rotación_ para mover con precisión las estructuras que tiene delante. las pértigas de extensión del pistón_ en la parte trasera definen el _alcance_ de este dispositivo. Sin las extensiones, el pistón no se moverá. Utiliza _Chasis_ o _Bloques de Slime_ para mover más de una línea de bloques", + "block.create.mechanical_piston.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.mechanical_piston.tooltip.behaviour1": "Comienza a mover la estructura adjunta. La velocidad y la dirección se correlacionan con la velocidad de rotación entrante", + + "block.create.piston_extension_pole.tooltip": "PÉRTIGA DE EXTENSIÓN", + "block.create.piston_extension_pole.tooltip.summary": "Amplía la gama de _Pistones mecánicos_", + "block.create.piston_extension_pole.tooltip.condition1": "Cuando se acopla a un pistón mecánico", + "block.create.piston_extension_pole.tooltip.behaviour1": "Extiende el alcance de un pistón en 1 bloque", + + "block.create.mechanical_bearing.tooltip": "RODAMIENTO MECÁNICO", + "block.create.mechanical_bearing.tooltip.summary": "Se utiliza para girar _estructuras más grandes_ con fuerza de rotación", + "block.create.mechanical_bearing.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.mechanical_bearing.tooltip.behaviour1": "Inicia la rotación de los bloques adjuntos. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque", + + "block.create.windmill_bearing.tooltip": "RODAMIENTO DEL MOLINO DE VIENTO", + "block.create.windmill_bearing.tooltip.summary": "Se utiliza para aprovechar la _fuerza de rotación_ del viento. Coloca tu propio diseño y mira cómo gira!", + "block.create.windmill_bearing.tooltip.condition1": "Al hacer clic con el botón derecho", + "block.create.windmill_bearing.tooltip.behaviour1": "Comienza a proporcionar _Fuerza de rotación_ generada por la rotación de su estructura adjunta. La estructura tiene que incluir bloques de vela o lana adecuados. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque.", + + "block.create.sail_frame.tooltip": "MARCO DE VELA", + "block.create.sail_frame.tooltip.summary": "Un útil bloque de construcción y fuente de energía cinética cuando forma parte de una estructura montada sobre un _Rodamiento de molino_", + + "block.create.white_sail.tooltip": "VELA BLANCA", + "block.create.white_sail.tooltip.summary": "Un útil bloque de construcción y fuente de energía cinética cuando forma parte de una estructura montada en un _Rodamiento de molino_. Viene en una variedad de colores", + "block.create.white_sail.tooltip.condition1": "Cuando se hace clic con el botón derecho del ratón con tinte", + "block.create.white_sail.tooltip.behaviour1": "Cambia el color de la vela", + + "block.create.clockwork_bearing.tooltip": "RODAMIENTO DE RELOJ", + "block.create.clockwork_bearing.tooltip.summary": "Una versión avanzada del _rodamiento mecánico_ para hacer girar hasta dos _manecillas de reloj_ según la _hora actual_ en el _juego_", + "block.create.clockwork_bearing.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.clockwork_bearing.tooltip.behaviour1": "Comienza a girar la estructura adjunta hacia la _hora actual_. Si existe una segunda estructura independiente delante de la primera, servirá de _manecilla de las horas_", + + "block.create.sequenced_gearshift.tooltip": "CAMBIO DE MARCHAS SECUENCIADO", + "block.create.sequenced_gearshift.tooltip.summary": "Un _componente de utilidad programable_, que puede cambiar su _rendimiento rotacional_ según hasta _5 instrucciones consecutivas._ Utilízalo para alimentar Rodamientos Mecánicos, Pistones o Poleas con más control sobre la sincronización y la velocidad. Puede ser menos preciso a velocidades más altas", + "block.create.sequenced_gearshift.tooltip.condition1": "Cuando es impulsado por Redstone", + "block.create.sequenced_gearshift.tooltip.behaviour1": "_Ejecuta_ las instrucciones programadas en función de la velocidad de entrada", + "block.create.sequenced_gearshift.tooltip.condition2": "Cuando se hace clic derecho", + "block.create.sequenced_gearshift.tooltip.behaviour2": "Abre la _interfaz de configuración._", + + "block.create.cart_assembler.tooltip": "ENSAMBLADOR DE VAGONETAS", + "block.create.cart_assembler.tooltip.summary": "Cuando se coloca en un _Raíl_, puede _ensamblar_ y _desensamblar_ estructuras móviles en las vagonetas que pasan. Consulta [Ctrl] para conocer el comportamiento específico del tipo de raíl", + "block.create.cart_assembler.tooltip.condition1": "Artilugio de vagoneta simple", + "block.create.cart_assembler.tooltip.behaviour1": "Con un _miembro único_, las estructuras se anclarán y girarán en _una sola vagoneta_. Utilice una _Llave Inglesa_ para especificar el _comportamiento de rotación_ deseado", + "block.create.cart_assembler.tooltip.condition2": "Artilugio de vagonetas", + "block.create.cart_assembler.tooltip.behaviour2": "Dos ensambladores de vagonetas _conectadas por_ una _estructura_, una vez que ambos contengan una vagoneta, las conectará con un artilugio montado _entre los dos_. La estructura se comportará de forma similar a un _acoplador de vagonetas_", + "block.create.cart_assembler.tooltip.control1": "Cuando se coloca sobre un Rail", + "block.create.cart_assembler.tooltip.action1": "_Se monta_ en las vagonetas que pasan _cuando está alimentado_, _se desmonta_ en caso contrario", + "block.create.cart_assembler.tooltip.control2": "Cuando se coloca sobre un raíl energizado", + "block.create.cart_assembler.tooltip.action2": "Monta y _acelera_ las vagonetas _cuando está alimentado_, desmonta y _sostiene_ en caso contrario", + "block.create.cart_assembler.tooltip.control3": "Cuando se coloca sobre el raíl detector", + "block.create.cart_assembler.tooltip.action3": "_Monta vagonetas sin montar_, _desmonta vagonetas montadas_", + "block.create.cart_assembler.tooltip.control4": "Cuando se coloca sobre el raíl activador", + "block.create.cart_assembler.tooltip.action4": "Desmonta_ vagonetas cuando se activa", + + "block.create.rope_pulley.tooltip": "POLEA DE CUERDA", + "block.create.rope_pulley.tooltip.summary": "Mueve verticalmente los _bloques_ y _estructuras_ adjuntos. Utiliza _Chasis_, _Slime_ o _Súper Pegamento_ para mover más de un bloque", + "block.create.rope_pulley.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.rope_pulley.tooltip.behaviour1": "Comienza a mover la estructura adjunta. La velocidad y la dirección se correlacionan con la velocidad de rotación entrante", + + "block.create.linear_chassis.tooltip": "CHASIS LINEAL", + "block.create.linear_chassis.tooltip.summary": "Bloque base configurable que conecta estructuras para el movimiento", + "block.create.linear_chassis.tooltip.condition1": "Cuando se mueve", + "block.create.linear_chassis.tooltip.behaviour1": "_Mueve_ todos los _Chasis adjuntos_ con la misma orientación, y una columna de Bloques dentro de su rango. Los bloques sólo serán arrastrados si la cara del chasis es _Pegajosa_ (Ver [Ctrl])", + "block.create.linear_chassis.tooltip.condition2": "Con Llave Inglesa", + "block.create.linear_chassis.tooltip.behaviour2": "Configura el _rango_ para este bloque de chasis. Mantenga pulsada la tecla CTRL para modificar también el rango de todos los bloques de chasis adjuntos", + "block.create.linear_chassis.tooltip.control1": "Cuando se hace clic derecho con slime", + "block.create.linear_chassis.tooltip.action1": "Hace que la cara sobre la que se ha hecho clic sea _pegajosa_. Cuando se mueva, el chasis _tirará_ de los bloques adjuntos, independientemente de la dirección del movimiento", + + "block.create.secondary_linear_chassis.tooltip": "CHASIS LINEAL SECUNDARIO", + "block.create.secondary_linear_chassis.tooltip.summary": "Un segundo tipo de _Chasis lineal_ que no se conecta al otro", + + "bloque.crear.chasis_radial.tooltip": "CHASIS DE ROTACIÓN", + "block.create.radial_chassis.tooltip.summary": "Bloque base configurable que conecta estructuras para el movimiento", + "block.create.radial_chassis.tooltip.condition1": "Cuando se mueve", + "block.create.radial_chassis.tooltip.behaviour1": "_Mueve_ todos los _Chasis_ adjuntos en una columna, y un cilindro de bloques a su alrededor. Los bloques que lo rodean sólo se mueven cuando están dentro del rango y están adheridos a un lado pegajoso (Ver [Ctrl]).", + "block.create.radial_chassis.tooltip.condition2": "Con Llave Inglesa", + "block.create.radial_chassis.tooltip.behaviour2": "Configura el _rango_ para este bloque de chasis. Mantenga pulsada la tecla CTRL para modificar también el rango de todos los bloques de chasis adjuntos", + "block.create.radial_chassis.tooltip.control1": "Cuando se hace clic derecho con slime", + "block.create.radial_chassis.tooltip.action1": "Hace que la cara sobre la que se ha hecho clic sea _pegajosa_. Cuando el chasis se mueve, todos los bloques designados unidos a la cara pegajosa se mueven con él", + + "block.create.mechanical_drill.tooltip": "TALADRO MECÁNICO", + "block.create.mechanical_drill.tooltip.summary": "Un dispositivo mecánico adecuado para _romper bloques_. Se puede mover con _pistones mecánicos_, _rodamientos_ u otros controladores", + "block.create.mechanical_drill.tooltip.condition1": "Cuando se mueve con cinética", + "block.create.mechanical_drill.tooltip.behaviour1": "Actúa como un rompebloques _estacionario_. También _hace daño a las entidades_ en su área efectiva", + "block.create.mechanical_drill.tooltip.condition2": "Mientras se mueve", + "block.create.mechanical_drill.tooltip.behaviour2": "Rompe los bloques con los que colisiona el taladro", + + "block.create.mechanical_harvester.tooltip": "COSECHADORA MECÁNICA", + "block.create.mechanical_harvester.tooltip.summary": "Una cosechadora mecánica adecuada para la automatización de cultivos a mediana escala. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros controladores", + "block.create.mechanical_harvester.tooltip.condition1": "Mientras se mueve", + "block.create.mechanical_harvester.tooltip.behaviour1": "_Corta_ todos los _cultivos maduros_ con los que la cuchilla colisiona y los restablece a su estado de crecimiento inicial", + + "block.create.mechanical_plough.tooltip": "ARADO MECÁNICO", + "block.create.mechanical_plough.tooltip.summary": "Un arado mecánico tiene varios usos. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros mandos", + "block.create.mechanical_plough.tooltip.condition1": "Mientras se mueve", + "block.create.mechanical_plough.tooltip.behaviour1": "_Rompe bloques_ con los que _no se puede colisionar_, como antorchas, raíles o capas de nieve. _Aplica_ su _movimiento_ a las _entidades_ sin dañarlas. _Labra bloques de tierra_ como si se usara una azada en ellos", + + "block.create.mechanical_saw.tooltip": "SIERRA MECÁNICA", + "block.create.mechanical_saw.tooltip.summary": "Adecuada para _cortar árboles_ de forma eficaz y para _cortar bloques_ en sus homólogos carpinteros. Se puede mover mediante _pistones mecánicos_ o _rodamientos_", + "block.create.mechanical_saw.tooltip.condition1": "Cuando está orientado hacia arriba", + "block.create.mechanical_saw.tooltip.behaviour1": "Aplica las recetas _Serrar_ y _Estallar_ a los objetos que se dejan caer o se introducen en ella. Cuando hay varias salidas posibles, las recorre a menos que se asigne un _filtro_", + "block.create.mechanical_saw.tooltip.condition2": "Cuando se orienta horizontalmente", + "block.create.mechanical_saw.tooltip.behaviour2": "Rompe los troncos_ que tiene delante. Si el tronco soportaba un árbol por sí mismo, el _árbol se derrumbará_ lejos de la sierra", + "block.create.mechanical_saw.tooltip.condition3": "Mientras se mueve", + "block.create.mechanical_saw.tooltip.behaviour3": "_Corta_ todos los _Árboles_ con los que colisiona la sierra", + + "block.create.stockpile_switch.tooltip": "INTERRUPTOR DE ACOPIO", + "block.create.stockpile_switch.tooltip.summary": "Activa una señal de Redstone en función de la cantidad de _Artículos almacenados_ en el Contenedor adjunto. Viene con un práctico filtro. A diferencia de un _Comparador,_ el _Interruptor de acopio_ permite la configuración de _Umbrales,_ a partir de los cuales se invierten las señales", + "block.create.stockpile_switch.tooltip.condition1": "Cuando haces click derecho", + "block.create.stockpile_switch.tooltip.behaviour1": "Abre la _Interfaz de Configuración_", + + "block.create.content_observer.tooltip": "OBSERVADOR DE CONTENIDO", + "block.create.content_observer.tooltip.summary": "_Detecta artículos_ dentro de _contenedores_ y _transportadores_ que coinciden con un _filtro_ configurado. Mientras el _inventario_, la _cinta_ o la _canaleta_ observados contengan_ un artículo que coincida, este componente emitirá una _señal de Redstone_. Cuando un _túnel observado transfiere_ un artículo coincidente, este componente emitirá un _Pulso de Redstone_", + + "block.create.redstone_link.tooltip": "ENLACE DE REDSTONE", + "block.create.redstone_link.tooltip.summary": "Puntos finales para conexiones _Inalámbricas Redstone_. Se pueden asignar _frecuencias_ utilizando cualquier elemento. El alcance de la señal es limitado, aunque razonablemente lejano", + "block.create.redstone_link.tooltip.condition1": "Cuando se alimenta", + "block.create.redstone_link.tooltip.behaviour1": "Recibir enlaces de la misma _Frecuencia_ producirá una señal de Redstone", + "block.create.redstone_link.tooltip.control1": "Cuando se hace Clic derecho con un ítem", + "block.create.redstone_link.tooltip.action1": "Establece la _Frecuencia_ a ese elemento. Se pueden utilizar un total de _dos elementos diferentes_ en combinación para definir una Frecuencia", + "block.create.redstone_link.tooltip.control2": "Cuando se hace clic derecho mientras se agacha", + "block.create.redstone_link.tooltip.action2": "Cambia entre el modo _Receptor_ y _Transmisor_", + + "block.create.nixie_tube.tooltip": "TUBO NIXIE", + "block.create.nixie_tube.tooltip.summary": "Un elegante _visualizador_ de _números y texto_ potenciados por Redstone", + "block.create.nixie_tube.tooltip.condition1": "Cuando se alimenta", + "block.create.nixie_tube.tooltip.behaviour1": "Muestra el valor actual de la _Fuerza de la señal Redstone_", + "block.create.nixie_tube.tooltip.condition2": "Con etiqueta de nombre", + "block.create.nixie_tube.tooltip.behaviour2": "Mostrar el _contenido_ de su _etiqueta de nombre_ con varios tubos nixie _ordenados_ en una _línea_", + + "block.create.redstone_contact.tooltip": "CONTACTO DE REDSTONE", + "block.create.redstone_contact.tooltip.summary": "Solo emite energía de Redstone por parejas. Se puede mover con _Pistones mecánicos_, _Rodamientos_ u otros controladores", + "block.create.redstone_contact.tooltip.condition1": "Cuando se enfrenta a otro Contacto", + "block.create.redstone_contact.tooltip.behaviour1": "Proporciona una _señal de Redstone_", + "block.create.redstone_contact.tooltip.condition2": "Mientras se mueve", + "block.create.redstone_contact.tooltip.behaviour2": "Activa todos los contactos estacionarios que pasa", + + "block.create.adjustable_crate.tooltip": "CAJA AJUSTABLE", + "block.create.adjustable_crate.tooltip.summary": "Este _Contenedor de Artículos_ permite el control manual de su capacidad. Puede contener hasta _16 pilas_ de cualquier objeto. Soporta _Comparadores de Redstone_", + "block.create.adjustable_crate.tooltip.control1": "Cuando haces click derecho", + "block.create.adjustable_crate.tooltip.action1": "Abre la _Interfaz_", + + "block.create.creative_crate.tooltip": "CAJA CREATIVA", + "block.create.creative_crate.tooltip.summary": "Este _Contenedor de Almacenamiento_ permite la replicación infinita de cualquier elemento. Colócalo junto a un _Schematicannon_ para eliminar cualquier requisito de material", + "block.create.creative_crate.tooltip.condition1": "Cuando el artículo está en la ranura del filtro", + "block.create.creative_crate.tooltip.behaviour1": "Todo lo que se _extraiga_ de este contenedor proporcionará un _suministro ilimitado_ del elemento especificado. Los elementos _insertados_ en esta caja serán _evitados._", + + "block.create.deployer.tooltip": "DESPLEGADOR", + "block.create.deployer.tooltip.summary": "_Lanza_, _Usa_ y _Activa_. Esta máquina intentará _imitar_ a un _jugador_ en la medida de lo posible. Puede _tomar_ y _depositar objetos_ en su propio _inventario_. Los objetos guardados deben ser _insertados_ y _extraídos_ del bloque directamente", + "block.create.deployer.tooltip.condition1": "Cuando se alimenta de cinética", + "block.create.deployer.tooltip.behaviour1": "Extiende su brazo y se _activa_ en el espacio del bloque _2m por delante_ de sí mismo", + "block.create.deployer.tooltip.condition2": "Click derecho con la Llave Inglesa", + "block.create.deployer.tooltip.behaviour2": "Activa el modo puñetazo. En el _modo puñetazo_, el Desplegador intentará usar su objeto para _romper bloques_ o _herir entidades_", + "block.create.deployer.tooltip.condition3": "Cuando se asigna el filtro", + "block.create.deployer.tooltip.behaviour3": "El desplegador no se activará a menos que el elemento retenido _coincida_ con el _filtro._ Los elementos que no coincidan no podrán ser insertados; los elementos retenidos que coincidan con el filtro no podrán ser extraídos.", + + "block.create.brass_casing.tooltip": "REVESTIDOR DE LATÓN", + "block.create.brass_casing.tooltip.summary": "Resistente máquina revestidora con una gran variedad de usos. Segura para la decoración. Se puede utilizar para _revestir ejes_ y _correas._", + + "block.create.pulse_repeater.tooltip": "REPETIDOR DE PULSOS DE REDSTONE", + "block.create.pulse_repeater.tooltip.summary": "Un circuito sencillo para cortar las señales de Redstone que pasan a una longitud de _1 tick_", + + "block.create.adjustable_repeater.tooltip": "REPETIDOR AJUSTABLE", + "block.create.adjustable_repeater.tooltip.summary": "Un avanzado _repetidor de Redstone_ con un _retraso configurable_ de hasta 30 minutos", + + "block.create.adjustable_pulse_repeater.tooltip": "REPETIDOR DE PULSO AJUSTABLE", + "block.create.adjustable_pulse_repeater.tooltip.summary": "Un _repetidor de pulsos_ con un _retardo configurable_ de hasta 30 minutos", + + "block.create.analog_lever.tooltip": "PALANCA ANALÓGICA", + "block.create.analog_lever.tooltip.summary": "Una palanca con un control más _preciso_ sobre su fuerza de _señal_ emitida", + + "block.create.powered_toggle_latch.tooltip": "PALANCA MECANIZADA", + "block.create.powered_toggle_latch.tooltip.summary": "Una palanca que puede ser accionada por un _Pulso de Redstone_", + + "block.create.powered_latch.tooltip": "PALANCA DE CIERRE MECANIZADA", + "block.create.powered_latch.tooltip.summary": "Una palanca que puede ser controlada por _señales de Redstone_. Una señal en la _trasera la habilita_, una señal desde el _lado la reinicia_", + + "block.create.controller_rail.tooltip": "RAÍL DE CONTROL", + "block.create.controller_rail.tooltip.summary": "Un _raíl energizado unidireccional_ capaz de _controlar con precisión_ la _velocidad de movimiento_ de una vagoneta", + "block.create.controller_rail.tooltip.condition1": "Cuando es impulsado por Redstone", + "block.create.controller_rail.tooltip.behaviour1": "_Acelera_ o _Desacelera_ pasando _vagonetas_ correspondientes a la _fuerza de la señal_. Propaga la energía de Redstone a los Raíles de control adyacentes. Al alimentar dos Raíles de control con diferentes intensidades, los carriles entre ellos interpolarán su señal", + + "block.create.speedometer.tooltip": "VELOCÍMETRO", + "block.create.speedometer.tooltip.summary": "Mide y muestra la _velocidad de rotación_ de los componentes cinéticos acoplados. Es compatible con _comparadores de Redstone_", + "block.create.speedometer.tooltip.condition1": "Cuando es impulsado por la cinética", + "block.create.speedometer.tooltip.behaviour1": "Indica un color correspondiente al nivel de velocidad. El _Verde_ indica Lento, el _Azul_ Moderado y el _Púrpura_ Rápido. Algunos componentes mecánicos requieren un nivel de velocidad suficiente para funcionar correctamente", + + "block.create.stressometer.tooltip": "ESTRESÓMETRO", + "block.create.stressometer.tooltip.summary": "Mide y muestra el _estrés global_ de la red cinética adjunta. Es compatible con _comparadores de Redstone_", + "block.create.stressometer.tooltip.condition1": "Cuando se alimenta con cinética", + "block.create.stressometer.tooltip.behaviour1": "Indica un color correspondiente al nivel de estrés. Las redes demasiado estresadas dejarán de moverse. El estrés puede aliviarse añadiendo más _fuentes de rotación_ a la red", + + "item.create.sand_paper.tooltip": "PAPEL DE LIJA", + "item.create.sand_paper.tooltip.summary": "Un papel rugoso que se puede utilizar para _pulir materiales_. Se puede aplicar automáticamente con el Desplegador", + "item.create.sand_paper.tooltip.condition1": "Cuando se usa", + "item.create.sand_paper.tooltip.behaviour1": "Aplica el pulido a los objetos sostenidos en la _mano libre_ o tirados en el _suelo_ cuando se _miran_", + + "item.create.super_glue.tooltip": "SÚPER PEGAMENTO", + "item.create.super_glue.tooltip.summary": "Pega un bloque a otro y serán inseparables para siempre", + "item.create.super_glue.tooltip.condition1": "Cuando se usa", + "item.create.super_glue.tooltip.behaviour1": "Hace que la cara _clicada_ de un bloque sea _pegajosa_. Los bloques unidos a caras pegajosas serán _arrastrados_ cuando se muevan por _pistones mecánicos_, _rodamientos_ y otros controladores", + "item.create.super_glue.tooltip.condition2": "Cuando se sostiene en la mano", + "item.create.super_glue.tooltip.behaviour2": "_Adjunta automáticamente_ los bloques colocados desde la mano principal al _lado_ contra el que fueron _colocados._", + + "item.create.builders_tea.tooltip": "TÉ DEL CONSTRUCTOR", + "item.create.builders_tea.tooltip.summary": "La bebida perfecta para empezar el día- _Motivante_ y _Saturante._", + + "item.create.refined_radiance.tooltip": "RESPLANDOR REFINADO", + "item.create.refined_radiance.tooltip.summary": "Material cromático forjado a partir de _luz absorbida_", + + "item.create.shadow_steel.tooltip": "ACERO SOMBRÍO", + "item.create.shadow_steel.tooltip.summary": "Un material cromático forjado _en el vacío_", + + "item.create.minecart_coupling.tooltip": "ENSAMBLADOR DE VAGONETAS", + "item.create.minecart_coupling.tooltip.summary": "_Encadena_ todas tus _Vagonetas_ o _Artilugios de vagoneta_ para formar un majestuoso Tren", + "item.create.minecart_coupling.tooltip.condition1": "Cuando se utiliza en Vagonetas", + "item.create.minecart_coupling.tooltip.behaviour1": "_Acopla_ dos Vagonetas, intentando mantenerlas a una _distancia constante_ mientras se mueven", + + "item.create.crafter_slot_cover.tooltip": "TAPA DE RANURA DEL AUTOENSAMBLADOR", + "item.create.crafter_slot_cover.tooltip.summary": "Se utiliza para marcar a un _Autoensamblador_ una ranura vacía en una receta. Los autoensambladores no tienen que formar necesariamente una cuadrícula completa. Esto es útil cuando hay recetas en las que los _ingredientes están en diagonal_ entre sí", + + "create.tooltip.wip": "WIP", + "create.tooltip.workInProgress": "¡Trabajo en curso!", + "create.tooltip.randomWipDescription0": "Por favor, mantenga este artículo fuera del alcance de los niños", + "create.tooltip.randomWipDescription1": "Un bebé panda muere cada vez que usas este objeto. Cada vez. Cada vez", + "create.tooltip.randomWipDescription2": "Úsalo bajo tu propio riesgo", + "create.tooltip.randomWipDescription3": "Este no es el objeto que buscas, *mueve los dedos* por favor, dispérsate", + "create.tooltip.randomWipDescription4": "Este objeto se autodestruirá en 10 segundos. 10, 9, 8...", + "create.tooltip.randomWipDescription5": "Créeme, es inútil", + "create.tooltip.randomWipDescription6": "Al utilizar este elemento, aceptas nuestra exención de responsabilidad y estás de acuerdo con sus términos", + "create.tooltip.randomWipDescription7": "Este quizás no es para ti. ¿Qué tal ese?", + "create.tooltip.randomWipDescription8": "Úsalo y arrepiéntete de tu decisión inmediatamente", + + "_": "Gracias por traducir Create!" + +} diff --git a/src/main/resources/assets/create/lang/it_it.json b/src/main/resources/assets/create/lang/it_it.json index 3874ad485..7b4edec9a 100644 --- a/src/main/resources/assets/create/lang/it_it.json +++ b/src/main/resources/assets/create/lang/it_it.json @@ -1,5 +1,4 @@ { - "_": "Missing Localizations: 849", "_": "->------------------------] Game Elements [------------------------<-", @@ -162,6 +161,8 @@ "block.create.gabbro_cobblestone_stairs": "Scalini di pietrisco di gabbro", "block.create.gabbro_cobblestone_wall": "Muretto di pietrisco di gabbro", "block.create.gabbro_pillar": "Pilastro di gabbro", + "block.create.gantry_pinion": "Pignone a portale", + "block.create.gantry_shaft": "Albero a portale", "block.create.gearbox": "Riduttore", "block.create.gearshift": "Cambio", "block.create.glass_fluid_pipe": "Tubo per fluidi con vetrata", @@ -1364,7 +1365,7 @@ "item.create.schematic_and_quill.tooltip.condition1": "Passo 1", "item.create.schematic_and_quill.tooltip.behaviour1": "Seleziona due punti d'angolo usando il clic destro.", "item.create.schematic_and_quill.tooltip.condition2": "Passo 2", - "item.create.schematic_and_quill.tooltip.behaviour2": "Premi _Ctrl_ e _scorri_ sui volti per regolare le dimensioni. Clic destro di nuovo per salvare.", + "item.create.schematic_and_quill.tooltip.behaviour2": "Premi _Ctrl_ e _scorri_ sulle facciate per regolare le dimensioni. Clic destro di nuovo per salvare.", "item.create.schematic_and_quill.tooltip.control1": "Clic-Destro", "item.create.schematic_and_quill.tooltip.action1": "Seleziona un punto d'angolo / conferma il salvataggio.", "item.create.schematic_and_quill.tooltip.control2": "Ctrl premuto", diff --git a/src/main/resources/assets/create/lang/ja_jp.json b/src/main/resources/assets/create/lang/ja_jp.json index 870e1b1fd..eefebe880 100644 --- a/src/main/resources/assets/create/lang/ja_jp.json +++ b/src/main/resources/assets/create/lang/ja_jp.json @@ -147,8 +147,8 @@ "block.create.fluid_tank": "液体タンク", "block.create.fluid_valve": "液体バルブ", "block.create.flywheel": "勢車", - "block.create.framed_glass": "大きなガラス窓", - "block.create.framed_glass_pane": "大きなガラス窓板", + "block.create.framed_glass": "ガラス窓", + "block.create.framed_glass_pane": "ガラス窓板", "block.create.furnace_engine": "かまどエンジン", "block.create.gabbro": "斑れい岩", "block.create.gabbro_bricks": "斑れい岩レンガ", @@ -160,6 +160,8 @@ "block.create.gabbro_cobblestone_stairs": "斑れい岩の丸石の階段", "block.create.gabbro_cobblestone_wall": "斑れい岩の丸石の壁", "block.create.gabbro_pillar": "斑れい岩の柱", + "block.create.gantry_pinion": "ガントリーピニオン", + "block.create.gantry_shaft": "ガントリーシャフト", "block.create.gearbox": "ギアボックス", "block.create.gearshift": "ギアシフト", "block.create.glass_fluid_pipe": "ガラスの液体パイプ", @@ -368,13 +370,13 @@ "block.create.shaft": "シャフト", "block.create.smart_chute": "スマートシュート", "block.create.smart_fluid_pipe": "スマート液体パイプ", - "block.create.speedometer": "スピードメーター", + "block.create.speedometer": "速度メーター", "block.create.spout": "アイテム注液口", "block.create.spruce_window": "マツの窓", "block.create.spruce_window_pane": "マツの窓パネル", "block.create.sticky_mechanical_piston": "粘着メカニカルピストン", "block.create.stockpile_switch": "在庫スイッチ", - "block.create.stressometer": "ストレスメーター", + "block.create.stressometer": "応力メーター", "block.create.tiled_glass": "タイルガラス", "block.create.tiled_glass_pane": "タイルガラス板", "block.create.turntable": "ターンテーブル", @@ -403,6 +405,7 @@ "block.create.zinc_ore": "亜鉛鉱石", "entity.create.contraption": "からくり", + "entity.create.gantry_contraption": "ガントリーからくり", "entity.create.seat": "シート", "entity.create.stationary_contraption": "付設からくり", "entity.create.super_glue": "接着剤", @@ -522,9 +525,9 @@ "advancement.create.goggles": "応力をこの目で", "advancement.create.goggles.desc": "機械からより多くの情報を手に入れるために、エンジニアのゴーグルを作る", "advancement.create.speedometer": "正確な速度は?", - "advancement.create.speedometer.desc": "動作中のスピードメーターをゴーグルで見て、正確な値を読み取る", + "advancement.create.speedometer.desc": "動作中の速度メーターをゴーグルで見て、正確な値を読み取る", "advancement.create.stressometer": "正確な応力は?", - "advancement.create.stressometer.desc": "動作中のストレスメーターをゴーグルを通して見て、正確な値を読み取る", + "advancement.create.stressometer.desc": "動作中の応力メーターをゴーグルを通して見て、正確な値を読み取る", "advancement.create.aesthetics": "装飾ブーム!", "advancement.create.aesthetics.desc": "シャフト、パイプ、歯車に腕木や腕金を取り付ける", "advancement.create.reinforced": "補強ブーム!", @@ -586,7 +589,7 @@ "advancement.create.pipe_spill": "漏れてる!", "advancement.create.pipe_spill.desc": "パイプの端を露出させて液体が吹き出しているところを見る", "advancement.create.hose_pulley": "工業排水", - "advancement.create.hose_pulley.desc": "ホースプーリーを下げて、液体の排出や吸引を見る", + "advancement.create.hose_pulley.desc": "ホースプーリーを下げて、液体の放出や吸引を見る", "advancement.create.infinite_water": "海の水ぜんぶ抜く大作戦", "advancement.create.infinite_water.desc": "無限と言えるほどの大量の水を吸引する", "advancement.create.infinite_lava": "星の核ぜんぶ抜く大作戦", @@ -597,7 +600,7 @@ "advancement.create.crafter.desc": "メカニカルクラフターを設置して、回転力を与える", "advancement.create.clockwork_bearing": "時計仕掛け", "advancement.create.clockwork_bearing.desc": "時計仕掛けのベアリングの上に構造物を組み立てる", - "advancement.create.nixie_tube": "派手な看板", + "advancement.create.nixie_tube": "イカした看板", "advancement.create.nixie_tube.desc": "ニキシー管を手に入れて、設置する", "advancement.create.deployer": "突く、置く、殴る!", "advancement.create.deployer.desc": "自分の手と全く同じ動きをするデプロイヤーを設置して、稼働させる", @@ -605,7 +608,7 @@ "advancement.create.speed_controller.desc": "究極の伝動機、回転速度コントローラーを設置する", "advancement.create.flywheel": "工場の心臓部", "advancement.create.flywheel.desc": "かまどエンジンを勢車に繋ぐ", - "advancement.create.overstress_flywheel": "高レベル応力", + "advancement.create.overstress_flywheel": "ハイレベル応力", "advancement.create.overstress_flywheel.desc": "かまどエンジンに超過応力をかける", "advancement.create.integrated_circuit": "複素数の計算", "advancement.create.integrated_circuit.desc": "集積回路を組み立てる", @@ -675,7 +678,7 @@ "create.recipe.automatic_shapeless": "自動不定形クラフト", "create.recipe.automatic_brewing": "自動醸造", "create.recipe.packing": "圧縮", - "create.recipe.automatic_packing": "自動包装", + "create.recipe.automatic_packing": "自動圧縮クラフト", "create.recipe.sawing": "製材", "create.recipe.mechanical_crafting": "メカニカルクラフト", "create.recipe.automatic_shaped": "自動定形クラフト", @@ -825,7 +828,7 @@ "create.gui.stressometer.overstressed": "超過応力", "create.gui.stressometer.no_rotation": "回転なし", "create.gui.contraptions.not_fast_enough": "この %1$s は_十分な_回転を_していない_ようです。", - "create.gui.contraptions.network_overstressed": "この仕掛けは_超過応力_のようです。さらに原動機を追加するか、_応力_の影響が大きい機械のスピードを_下げて_ください。", + "create.gui.contraptions.network_overstressed": "この仕掛けは_超過応力_のようです。さらに原動機を追加するか、_応力_の影響が大きい機械の速度を_下げて_ください。", "create.gui.adjustable_crate.title": "可変クレート", "create.gui.adjustable_crate.storageSpace": "収納スペース", "create.gui.stockpile_switch.title": "在庫スイッチ", @@ -956,9 +959,9 @@ "create.materialChecklist.blocksNotLoaded": "*免責事項*\n\n素材チェックリストは関連するチャンクがロードされていないため、不正確な場合があります。", "create.gui.filter.deny_list": "ブラックリスト", - "create.gui.filter.deny_list.description": "上記のいずれにも一致しない場合、アイテムは通り抜けます。 空のブラックリストはすべてを受け入れます。", + "create.gui.filter.deny_list.description": "上記のいずれにも一致しない場合、アイテムは通り抜けます。空のブラックリストはすべてを受け入れます。", "create.gui.filter.allow_list": "ホワイトリスト", - "create.gui.filter.allow_list.description": "上記のいずれかに一致した場合、アイテムは通り抜けます。 空のホワイトリストはすべてを拒否します。", + "create.gui.filter.allow_list.description": "上記のいずれかに一致した場合、アイテムは通り抜けます。空のホワイトリストはすべてを拒否します。", "create.gui.filter.respect_data": "データを重視", "create.gui.filter.respect_data.description": "アイテムは、耐久性、エンチャント、その他の属性も一致する場合にのみ一致します。", "create.gui.filter.ignore_data": "データを無視", @@ -1017,7 +1020,7 @@ "create.gui.attribute_filter.selected_attributes": "選択された属性:", "create.gui.attribute_filter.add_attribute": "属性をリストに追加する", "create.gui.attribute_filter.add_inverted_attribute": "反属性をリストに追加する", - "create.gui.attribute_filter.allow_list_disjunctive": "ホワイトリスト(どれか)", + "create.gui.attribute_filter.allow_list_disjunctive": "ホワイトリスト(いずれか)", "create.gui.attribute_filter.allow_list_disjunctive.description": "選択した属性のいずれかを持っている場合、アイテムは通り抜けます。", "create.gui.attribute_filter.allow_list_conjunctive": "ホワイトリスト(全て)", "create.gui.attribute_filter.allow_list_conjunctive.description": "選択した属性をすべてを持っている場合、アイテムは通り抜けます。", @@ -1033,12 +1036,12 @@ "create.tooltip.speedRequirement.none": "無し", "create.tooltip.speedRequirement.medium": "中速", "create.tooltip.speedRequirement.high": "高速", - "create.tooltip.stressImpact": "応力への影響: %1$s", + "create.tooltip.stressImpact": "応力の影響: %1$s", "create.tooltip.stressImpact.low": "低", "create.tooltip.stressImpact.medium": "中", "create.tooltip.stressImpact.high": "高", "create.tooltip.stressImpact.overstressed": "超過応力", - "create.tooltip.capacityProvided": "応力許容量: %1$s", + "create.tooltip.capacityProvided": "応力の容量: %1$s", "create.tooltip.capacityProvided.low": "小", "create.tooltip.capacityProvided.medium": "中", "create.tooltip.capacityProvided.high": "大", @@ -1106,7 +1109,7 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", - "create.subtitle.schematicannon_finish": "概略図砲が完了する", + "create.subtitle.schematicannon_finish": "概略図砲が作業を終える", "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", "create.subtitle.mechanical_press_activation": "メカニカルプレスが作動する", "create.subtitle.mechanical_press_item_break": "金属がガチャンと鳴る", @@ -1167,11 +1170,11 @@ "block.create.brass_funnel.tooltip.behaviour3": "下向きホッパーのように、_アイテム_を_下方向_に_移動_させます。", "block.create.brass_tunnel.tooltip": "真鍮トンネル", - "block.create.brass_tunnel.tooltip.summary": "派手な_メカニカルベルト_の保護カバー!_真鍮トンネル_にはアイテムの_フィルター機能_や、_分割機能_の設定項目も多数用意されています。", + "block.create.brass_tunnel.tooltip.summary": "オシャレな_メカニカルベルト_の保護カバー!_真鍮トンネル_にはアイテムの_フィルター機能_や、_分割機能_の設定項目も多数用意されています。", "block.create.brass_tunnel.tooltip.condition1": "並べて設置したとき", "block.create.brass_tunnel.tooltip.behaviour1": "_真鍮トンネル_は相互に接続し、ある_メカニカルベルト_のアイテムを別の_メカニカルベルト_に送ったりできるようにします。", "block.create.brass_tunnel.tooltip.condition2": "フィルター機能", - "block.create.brass_tunnel.tooltip.behaviour2": "_真鍮トンネル_は_搬入_と_搬出_、両方のフィルターを搭載しています。 _トンネル_のフィルター付き出力から_アイテム_が出てくることが許可されていない場合、並べて設置された_トンネル_の出力に送られます。", + "block.create.brass_tunnel.tooltip.behaviour2": "_真鍮トンネル_は_搬入_と_搬出_、両方のフィルターを搭載しています。_トンネル_のフィルター付き出力から_アイテム_が出てくることが許可されていない場合、並べて設置された_トンネル_の出力に送られます。", "block.create.brass_tunnel.tooltip.condition3": "分割機能", "block.create.brass_tunnel.tooltip.behaviour3": "_真鍮トンネル_は、_アイテム_が接続された_メカニカルベルト_に分類して並べる方法を変更するように設定できます。", "block.create.brass_tunnel.tooltip.control1": "側面をレンチで右クリックしたとき。", @@ -1225,14 +1228,14 @@ "block.create.hose_pulley.tooltip": "ホースプーリー", "block.create.hose_pulley.tooltip.summary": "ワールドの大量の_液体_を_吸引_したり、_放出_したりするのに使います。", "block.create.hose_pulley.tooltip.condition1": "回転したとき", - "block.create.hose_pulley.tooltip.behaviour1": "ホースを_上げ下げ_して、どの程度の_高さ_まで_吸引_や_排出_を行うか決めます。", + "block.create.hose_pulley.tooltip.behaviour1": "ホースを_上げ下げ_して、どの程度の_高さ_まで_吸引_や_放出_を行うか決めます。", "block.create.hose_pulley.tooltip.condition2": "プーリーから液体が吸い込まれたとき", "block.create.hose_pulley.tooltip.behaviour2": "ホースの端がおろされた本体から_液体_ブロックを_吸引_し始めます。非常に_大量_の液体は_無限_と_みなされます_。", "block.create.hose_pulley.tooltip.condition3": "液体がプーリーに押しこまれたとき", "block.create.hose_pulley.tooltip.behaviour3": "ホースの端の_高さ_まで、_液体_の_放出_を始めます。", "block.create.fluid_tank.tooltip": "液体タンク", - "block.create.fluid_tank.tooltip.summary": "あなたのお気に入りの_液体_をすべて_貯蔵_します。縦横に並べて大きさを調整できます。", + "block.create.fluid_tank.tooltip.summary": "あなたのお気に入りのあらゆる_液体_を_貯蔵_できます。縦横に並べて大きさを調整できます。", "block.create.fluid_tank.tooltip.condition1": "レンチで右クリックしたとき", "block.create.fluid_tank.tooltip.behaviour1": "窓の設定を変更します。", @@ -1271,7 +1274,7 @@ "block.create.item_drain.tooltip": "アイテム排液口", "block.create.item_drain.tooltip.summary": "_液体アイテム_を空にする格子付きデポ。", - "block.create.item_drain.tooltip.condition1": "液体排液 ", + "block.create.item_drain.tooltip.condition1": "液体排液", "block.create.item_drain.tooltip.behaviour1": "_バケツ_や_ボトル_などの_液体入り容器_を横から搬入すると、アイテム排液口はその_液体入り容器_に空にしようとします。その後、アイテムは反対側に排出されます。", "block.create.mechanical_arm.tooltip": "メカニカルアーム", @@ -1297,7 +1300,7 @@ "item.create.handheld_blockzapper.tooltip": "携帯ブロックザッパー", "item.create.handheld_blockzapper.tooltip.summary": "離れた場所にブロックを設置または交換する新しいガジェット。", "item.create.handheld_blockzapper.tooltip.control1": "ブロックを左クリックしたとき", - "item.create.handheld_blockzapper.tooltip.action": "ターゲットのブロックをこのツールに設定します。", + "item.create.handheld_blockzapper.tooltip.action1": "ターゲットのブロックをこのツールに設定します。", "item.create.handheld_blockzapper.tooltip.control2": "ブロックを右クリックしたとき", "item.create.handheld_blockzapper.tooltip.action2": "ターゲットブロックを_配置_または_置換_します。", "item.create.handheld_blockzapper.tooltip.control3": "スニークしながら右クリックしたとき。", @@ -1343,7 +1346,7 @@ "item.create.empty_schematic.tooltip.summary": "レシピの材料、および_概略図テーブル_での書き込みに使用されます。", "item.create.schematic.tooltip": "概略図", - "item.create.schematic.tooltip.summary": "ワールドに設置できる構造物を保持します。 ホログラムを必要に応じて配置し、_概略図砲_を使用して建築します。", + "item.create.schematic.tooltip.summary": "ワールドに設置できる構造物を保持します。ホログラムを必要に応じて配置し、_概略図砲_を使用して建築します。", "item.create.schematic.tooltip.condition1": "持ったとき", "item.create.schematic.tooltip.behaviour1": "画面上のツールを使用して配置できます。", "item.create.schematic.tooltip.control1": "スニークしながら右クリックしたとき", @@ -1354,11 +1357,11 @@ "item.create.schematic_and_quill.tooltip.condition1": "ステップ1", "item.create.schematic_and_quill.tooltip.behaviour1": "右クリックして2つのコーナーポイントを選択します。", "item.create.schematic_and_quill.tooltip.condition2": "ステップ2", - "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrlキーを押しながらスクロール_して、サイズを調整します。 もう一度右クリックして保存します。", + "item.create.schematic_and_quill.tooltip.behaviour2": "_Ctrlキーを押しながらスクロール_して、サイズを調整します。もう一度右クリックして保存します。", "item.create.schematic_and_quill.tooltip.control1": "右クリックしたとき", "item.create.schematic_and_quill.tooltip.action1": "コーナーポイントを選択/保存を確認します。", "item.create.schematic_and_quill.tooltip.control2": "Ctrlを長押してるとき", - "item.create.schematic_and_quill.tooltip.action2": "_空中_でポイントを選択します。 _スクロール_して距離を調整します。", + "item.create.schematic_and_quill.tooltip.action2": "_空中_でポイントを選択します。_スクロール_して距離を調整します。", "item.create.schematic_and_quill.tooltip.control3": "スニークしながら右クリックしたとき", "item.create.schematic_and_quill.tooltip.action3": "選択を_リセット_して削除します。", @@ -1378,11 +1381,11 @@ "block.create.cogwheel.tooltip": "歯車", "block.create.cogwheel.tooltip.summary": "_回転_を直線で、または隣接する_歯車_に_伝達_します。", - "block.create.large_cogwheel.tooltip": "大型歯車", + "block.create.large_cogwheel.tooltip": "大きな歯車", "block.create.large_cogwheel.tooltip.summary": "小さな歯車に接続したときに_回転速度_を_変更_できる歯車の大型バージョン。", "block.create.encased_shaft.tooltip": "ケース入りシャフト", - "block.create.encased_shaft.tooltip.summary": "_回転_を直線で_伝達_します。 壁を通過する回転の伝達に適しています。", + "block.create.encased_shaft.tooltip.summary": "_回転_を直線で_伝達_します。壁を通過する回転の伝達に適しています。", "block.create.gearbox.tooltip": "ギアボックス", "block.create.gearbox.tooltip.summary": "接続された_4方向_の_回転_方向を逆にして_伝達_します。", @@ -1408,9 +1411,9 @@ "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "レッドストーン信号を受けて_いない_ときは、隣接するチェーンドライブと_同じ速度_で回転を伝達します。_レッドストーン信号強度が最大_のときは隣接するチェーンドライブは_その2倍_の速度で伝達します。その間にあるものは1-2倍の速度で伝達されます。", "item.create.belt_connector.tooltip": "メカニカルベルト", - "item.create.belt_connector.tooltip.summary": "2本以上の_シャフト_を_メカニカルベルト_で接続します。接続されたシャフトは全く同じ速度と方向で回転します。 メカニカルベルトは_アイテム_と_エンティティ_を_運搬_するベルトコンベアとして使えます。", + "item.create.belt_connector.tooltip.summary": "2本以上の_シャフト_を_メカニカルベルト_で接続します。接続されたシャフトは全く同じ速度と方向で回転します。メカニカルベルトは_アイテム_と_エンティティ_を_運搬_するベルトコンベアとして使えます。", "item.create.belt_connector.tooltip.control1": "シャフトを右クリックしたとき", - "item.create.belt_connector.tooltip.action1": "ベルトの片端のシャフトを選択します。 選択する2つのシャフトは_ベルトの方向_に向かって_縦_、_横_、または_斜め_に_並べる_必要があります。", + "item.create.belt_connector.tooltip.action1": "ベルトの片端のシャフトを選択します。選択する2つのシャフトは_ベルトの方向_に向かって_縦_、_横_、または_斜め_に_並べる_必要があります。", "item.create.belt_connector.tooltip.control2": "スニークしながら右クリックしたとき", "item.create.belt_connector.tooltip.action2": "ベルトの最初に選択した位置を_リセット_します。", @@ -1422,7 +1425,7 @@ "item.create.goggles.tooltip.behaviour2": "計器が接続されているネットワークの_速度_または_応力_に関する詳細情報を表示します。", "item.create.wrench.tooltip": "レンチ", - "item.create.wrench.tooltip.summary": "動的からくりに取り組むための便利なツール。 コンポーネントの_回転_、_解体_、_設定_に使用できます。", + "item.create.wrench.tooltip.summary": "動的からくりに取り組むための便利なツール。コンポーネントの_回転_、_解体_、_設定_に使用できます。", "item.create.wrench.tooltip.control1": "機械を右クリックしたとき", "item.create.wrench.tooltip.action1": "操作した面に向かって、または面から離れるように機械を_回転_させます。", "item.create.wrench.tooltip.control2": "スニークしながら右クリックしたとき", @@ -1437,7 +1440,7 @@ "block.create.encased_fan.tooltip": "ケース入りファン", "block.create.encased_fan.tooltip.summary": "_回転力_を_気流_に変換し往復させます。色んな使い方があります。", "block.create.encased_fan.tooltip.condition1": "レッドストーン信号を受けたとき", - "block.create.encased_fan.tooltip.behaviour1": "真下の_熱源_から_回転力_を供給します。 ファンは下向きにする必要があります。", + "block.create.encased_fan.tooltip.behaviour1": "真下の_熱源_から_回転力_を供給します。ファンは下向きにする必要があります。", "block.create.encased_fan.tooltip.condition2": "回転したとき", "block.create.encased_fan.tooltip.behaviour2": "回転速度に応じてエンティティを_押し_たり、_吸い戻し_たりします。", "block.create.encased_fan.tooltip.condition3": "特別なブロックを吹き抜けるとき", @@ -1449,18 +1452,18 @@ "block.create.hand_crank.tooltip": "ハンドクランク", "block.create.hand_crank.tooltip.summary": "プレイヤーの相互作用を必要とする_シンプル_な_原動機_。", "block.create.hand_crank.tooltip.condition1": "使っているとき", - "block.create.hand_crank.tooltip.behaviour1": "接続したに_回転力_を供給します。 _スニークで回転を逆_にできます。", + "block.create.hand_crank.tooltip.behaviour1": "接続したに_回転力_を供給します。_スニークで回転を逆_にできます。", "block.create.cuckoo_clock.tooltip": "鳩時計", "block.create.cuckoo_clock.tooltip.summary": "空間を_彩り_、_時間を刻む_素晴らしい細工。", "block.create.cuckoo_clock.tooltip.condition1": "回転したとき", - "block.create.cuckoo_clock.tooltip.behaviour1": "_現在の時刻_を表示し、1日に2回曲を再生します。 、_正午_と夕暮れにプレイヤーが_眠れるようになるとすぐ_に_アクティブ_になります。", + "block.create.cuckoo_clock.tooltip.behaviour1": "_現在の時刻_を表示し、1日に2回曲を再生します。、_正午_と夕暮れにプレイヤーが_眠れるようになるとすぐ_に_アクティブ_になります。", "block.create.turntable.tooltip": "ターンテーブル", "block.create.turntable.tooltip.summary": "_回転力_を洗練された乗り物酔いに変えます。", "block.create.millstone.tooltip": "石臼", - "block.create.millstone.tooltip.summary": "搬入された_材料_の_研削_に適した機械。 隣接する歯車によって、または下部のシャフトに接続することによって、回転力を供給できます。 完成品は機械から搬出する必要があります。", + "block.create.millstone.tooltip.summary": "搬入された_材料_の_研削_に適した機械。隣接する歯車によって、または下部のシャフトに接続することによって、回転力を供給できます。完成品は機械から搬出する必要があります。", "block.create.millstone.tooltip.condition1": "回転したとき", "block.create.millstone.tooltip.behaviour1": "ブロックの側面または上面から搬入されたアイテムを_粉砕_を開始します。", "block.create.millstone.tooltip.condition2": "右クリックしたとき", @@ -1469,10 +1472,10 @@ "block.create.crushing_wheel.tooltip": "破砕ホイール", "block.create.crushing_wheel.tooltip.summary": "何かを_破砕_する大きな回転させられるホイール。", "block.create.crushing_wheel.tooltip.condition1": "他の破砕ホイールに取り付けたとき", - "block.create.crushing_wheel.tooltip.behaviour1": "様々な物を処理する破砕機を形成します。 ホイールの歯は、_同じ速度_で_反対方向_に回る必要があります。", + "block.create.crushing_wheel.tooltip.behaviour1": "様々な物を処理する破砕機を形成します。ホイールの歯は、_同じ速度_で_反対方向_に回る必要があります。", "block.create.mechanical_press.tooltip": "メカニカルプレス", - "block.create.mechanical_press.tooltip.summary": "その下のアイテムを圧縮する強力なピストン。 一定の_回転力_が必要です。", + "block.create.mechanical_press.tooltip.summary": "その下のアイテムを圧縮する強力なピストン。一定の_回転力_が必要です。", "block.create.mechanical_press.tooltip.condition1": "レッドストーン信号を受けたとき", "block.create.mechanical_press.tooltip.behaviour1": "その下にドロップされたアイテムの圧縮を_開始_します。", "block.create.mechanical_press.tooltip.condition2": "メカニカルベルトの上にあるとき", @@ -1507,9 +1510,9 @@ "block.create.mechanical_crafter.tooltip.condition2": "レッドストーンパルスがオンの時", "block.create.mechanical_crafter.tooltip.behaviour2": "現在与えられているすべての_アイテム_を使って、_強制的_に_クラフト_を開始します。", "block.create.mechanical_crafter.tooltip.control1": "正面をレンチで使ったとき", - "block.create.mechanical_crafter.tooltip.action1": "_個々のクラフターが_アイテムを移動_させる_方向_を循環させます。 クラフトグリッドを形成するには、すべてのアイテムを最後のクラフターに向かって_移動させる流れ_を作るように_ベルト_を設置する必要があります。最後のクラフターはグリッドから_離れる_方向を指す必要があります。", + "block.create.mechanical_crafter.tooltip.action1": "_個々のクラフターが_アイテムを移動_させる_方向_を循環させます。クラフトグリッドを形成するには、すべてのアイテムを最後のクラフターに向かって_移動させる流れ_を作るように_ベルト_を設置する必要があります。最後のクラフターはグリッドから_離れる_方向を指す必要があります。", "block.create.mechanical_crafter.tooltip.control2": "背面をレンチで使ったとき", - "block.create.mechanical_crafter.tooltip.action2": "隣接するクラフターの_搬入インベントリ_を_接続_します。 これを使用してクラフトグリッドの_スロットを_結合_し、_搬入作業_を_簡略化_できます。", + "block.create.mechanical_crafter.tooltip.action2": "隣接するクラフターの_搬入インベントリ_を_接続_します。これを使用してクラフトグリッドの_スロットを_結合_し、_搬入作業_を_簡略化_できます。", "block.create.furnace_engine.tooltip": "かまどエンジン", "block.create.furnace_engine.tooltip.summary": "_稼動しているかまど_で動く強力な_原動機_。", @@ -1536,14 +1539,14 @@ "block.create.portable_fluid_interface.tooltip.behaviour2": "アクティブな接続を即座に_切断_します。", "block.create.rotation_speed_controller.tooltip": "回転速度コントローラー", - "block.create.rotation_speed_controller.tooltip.summary": "回転を任意の速度にスピードアップまたはスローダウンさせることができる_設定_可能な_伝達機_。", + "block.create.rotation_speed_controller.tooltip.summary": "回転を任意の速度に上げたり下げたりさせることができる_設定_可能な_伝達機_。", "block.create.rotation_speed_controller.tooltip.condition1": "大きな歯車を取り付けたとき", "block.create.rotation_speed_controller.tooltip.behaviour1": "入ってくる回転力を歯車に伝達して、目標とする_速度_に_合わせ_ようとします。_歯車_はコントローラの_上_に_取り付ける_必要があります。", "block.create.mechanical_piston.tooltip": "メカニカルピストン", "block.create.mechanical_piston.tooltip.summary": "ピストンのさらに進化したバージョン。回転力を利用して前にある構造物を正確に移動させます。後部にあるピストン延長ポールは、このの稼働範囲を決めます。延長ポールがないと、ピストンは動きません。_シャーシ_や_スライムボール_、_接着剤_を使用して、1列以上のブロックを移動させることができます。", "block.create.mechanical_piston.tooltip.condition1": "回転したとき", - "block.create.mechanical_piston.tooltip.behaviour1": "取り付けられた構造物の移動を開始します。 速度と方向は、入力される回転速度と相関します。", + "block.create.mechanical_piston.tooltip.behaviour1": "取り付けられた構造物の移動を開始します。速度と方向は、入力される回転速度と相関します。", "block.create.piston_extension_pole.tooltip": "ピストン延長ポール", "block.create.piston_extension_pole.tooltip.summary": "メカニカルピストンの範囲を拡張します。", @@ -1571,7 +1574,7 @@ "block.create.clockwork_bearing.tooltip": "時計仕掛けのベアリング", "block.create.clockwork_bearing.tooltip.summary": "現在の_ゲーム内時間_に応じて最大2つの_時計の針_を回転させる、_メカニカルベアリング_の進化版。", "block.create.clockwork_bearing.tooltip.condition1": "回転したとき", - "block.create.clockwork_bearing.tooltip.behaviour1": "現在の時間に向かって取り付けた構造物の回転を開始します。 2番目の構造物が存在する場合、それは分針として機能します。", + "block.create.clockwork_bearing.tooltip.behaviour1": "現在の時間に向かって取り付けた構造物の回転を開始します。2番目の構造物が存在する場合、それは分針として機能します。", "block.create.sequenced_gearshift.tooltip": "シーケンスギアシフト", "block.create.sequenced_gearshift.tooltip.summary": "_プログラミング_できる_便利_な伝達機械。最大_5つ_の_連続_した_命令_に従って_回転処理_を変更することができます。高速になると精度が悪くなる可能性があります。", @@ -1598,7 +1601,7 @@ "block.create.rope_pulley.tooltip": "ローププーリー", "block.create.rope_pulley.tooltip.summary": "_取り付けられたブロック_や_構造物_を_垂直_方向に移動させます。_シャーシ_、_スライムボール_、_接着剤_を使用して、1つ以上のブロックを移動させることもできます。", "block.create.rope_pulley.tooltip.condition1": "回転したとき", - "block.create.rope_pulley.tooltip.behaviour1": "取り付けた構造物の移動を開始します。 速度と方向は、回転速度に相関します。", + "block.create.rope_pulley.tooltip.behaviour1": "取り付けた構造物の移動を開始します。速度と方向は、回転速度に相関します。", "block.create.linear_chassis.tooltip": "線形シャーシ", "block.create.linear_chassis.tooltip.summary": "移動用の構造物を接続する設定可能な土台ブロック。", @@ -1617,19 +1620,19 @@ "block.create.radial_chassis.tooltip.condition1": "動かしたとき", "block.create.radial_chassis.tooltip.behaviour1": "柱状に_接続_したすべての_シャーシ_と、周囲のブロックを_移動_させます。周囲のブロックは、範囲内にあり、かつ粘着面に面している場合にのみ_引っ張られ_ます([Ctrl]を参照)。", "block.create.radial_chassis.tooltip.condition2": "レンチを持ったとき", - "block.create.radial_chassis.tooltip.behaviour2": "このシャーシブロックの有効_範囲_を設定します。 Ctrlキーを押したままにすると、接続されているすべてのシャーシブロックの範囲も同時に変更できます。", + "block.create.radial_chassis.tooltip.behaviour2": "このシャーシブロックの有効_範囲_を設定します。Ctrlキーを押したままにすると、接続されているすべてのシャーシブロックの範囲も同時に変更できます。", "block.create.radial_chassis.tooltip.control1": "スライムボールで右クリックしたとき", - "block.create.radial_chassis.tooltip.action1": "クリックした面を_粘着面_にします。 シャーシが移動すると、粘着面に接続されているすべての指定のブロックも一緒に移動します。", + "block.create.radial_chassis.tooltip.action1": "クリックした面を_粘着面_にします。シャーシが移動すると、粘着面に接続されているすべての指定のブロックも一緒に移動します。", "block.create.mechanical_drill.tooltip": "メカニカルドリル", - "block.create.mechanical_drill.tooltip.summary": "_ブロックを壊す_のに適した作業機。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.mechanical_drill.tooltip.summary": "_ブロックを壊す_のに適した作業機。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.mechanical_drill.tooltip.condition1": "回転したとき", - "block.create.mechanical_drill.tooltip.behaviour1": "_固定式_のブロック破壊機として機能します。 また、有効範囲の_エンティティを傷つけます_。", + "block.create.mechanical_drill.tooltip.behaviour1": "_固定式_のブロック破壊機として機能します。また、有効範囲の_エンティティを傷つけます_。", "block.create.mechanical_drill.tooltip.condition2": "動かしたとき", "block.create.mechanical_drill.tooltip.behaviour2": "ドリルが衝突するブロックを壊します。", "block.create.mechanical_harvester.tooltip": "メカニカルハーベスター", - "block.create.mechanical_harvester.tooltip.summary": "中規模の作物の自動化に適した機械式植物カッター。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.mechanical_harvester.tooltip.summary": "中規模の作物の自動化に適した機械式植物カッター。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.mechanical_harvester.tooltip.condition1": "動かしたとき", "block.create.mechanical_harvester.tooltip.behaviour1": "ブレードが衝突する_すべての成熟した作物を収穫_し、それらを初期の成長状態にリセットします。", @@ -1639,9 +1642,9 @@ "block.create.mechanical_plough.tooltip.behaviour1": "松明や雪など、当たり判定がないブロックを壊します。エンティティを傷付けることはありません。また、クワを使うように土を耕します。", "block.create.mechanical_saw.tooltip": "メカニカルノコギリ", - "block.create.mechanical_saw.tooltip.summary": "_木_を効率的に_切り倒したり_、_ブロック_を_加工_したりするのに適しています。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.mechanical_saw.tooltip.summary": "_木_を効率的に_切り倒したり_、_ブロック_を_加工_したりするのに適しています。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.mechanical_saw.tooltip.condition1": "上向きのとき", - "block.create.mechanical_saw.tooltip.behaviour1": "そこにドロップまたは搬入されたアイテムに_製材_および石工レシピを適用します。 複数の出力が可能な場合、フィルターが割り当てられていない限り、出力が循環します。", + "block.create.mechanical_saw.tooltip.behaviour1": "そこにドロップまたは搬入されたアイテムに_製材_および石工レシピを適用します。複数の出力が可能な場合、フィルターが割り当てられていない限り、出力が循環します。", "block.create.mechanical_saw.tooltip.condition2": "横向きの場合", "block.create.mechanical_saw.tooltip.behaviour2": "その前の_原木_を_切り倒す_。その原木が木を支えていた場合、_木_は_崩壊_します。", "block.create.mechanical_saw.tooltip.condition3": "動かしたとき", @@ -1656,30 +1659,30 @@ "block.create.content_observer.tooltip.summary": "設定された_フィルター_に一致する_コンテナ_や_メカニカルベルト_内の_アイテム_を検出します。観察している_インベントリ_、_ベルト_、または_シュート_に一致するアイテムが含まれている場合、このは_レッドストーン信号_を発します。観察された_ファンネル_が一致するアイテムを_輸送_すると、このコンポーネントは_レッドストーンパルス_を発します。", "block.create.redstone_link.tooltip": "レッドストーンリンク", - "block.create.redstone_link.tooltip.summary": "_ワイヤレスレッドストーン_接続の終点。 任意のアイテムを使用して_周波数_を割り当てることができます。 通信距離は限られていますが、かなり離れても通信することができます。", + "block.create.redstone_link.tooltip.summary": "_ワイヤレスレッドストーン_接続の終点。任意のアイテムを使用して_周波数_を割り当てることができます。通信距離は限られていますが、かなり離れても通信することができます。", "block.create.redstone_link.tooltip.condition1": "信号を受信したとき", "block.create.redstone_link.tooltip.behaviour1": "同じ周波数のリンクから信号を受信すると、レッドストーン信号を出力します。", "block.create.redstone_link.tooltip.control1": "アイテムで右クリックしたとき", - "block.create.redstone_link.tooltip.action1": "_周波数_をそのアイテムに設定します。 周波数を定義するために、_合計2つの異なるアイテム_を組み合わせて使えます。", + "block.create.redstone_link.tooltip.action1": "_周波数_をそのアイテムに設定します。周波数を定義するために、_合計2つの異なるアイテム_を組み合わせて使えます。", "block.create.redstone_link.tooltip.control2": "スニークしながら右クリックしたとき", "block.create.redstone_link.tooltip.action2": "_受信_モードと_送信_モードを切り替えます。", "block.create.nixie_tube.tooltip": "ニキシー管", - "block.create.nixie_tube.tooltip.summary": "派手にレッドストーン強度と文字を表示します。", + "block.create.nixie_tube.tooltip.summary": "オシャレにレッドストーン強度と文字を表示します。", "block.create.nixie_tube.tooltip.condition1": "レッドストーン信号を受けたとき", "block.create.nixie_tube.tooltip.behaviour1": "現在のレッドストーンの_信号強度_を表示します。", "block.create.nixie_tube.tooltip.condition2": "名札を使ったとき", "block.create.nixie_tube.tooltip.behaviour2": "_名札_の_内容_を複数のニキシー管を並べて表示します。", "block.create.redstone_contact.tooltip": "レッドストーンコンタクト", - "block.create.redstone_contact.tooltip.summary": "レッドストーン信号をペアで出力します。 _メカニカルピストン_や_ベアリング_等で移動できます。", + "block.create.redstone_contact.tooltip.summary": "レッドストーン信号をペアで出力します。_メカニカルピストン_や_ベアリング_等で移動できます。", "block.create.redstone_contact.tooltip.condition1": "他のコンタクトと向かい合ったとき", "block.create.redstone_contact.tooltip.behaviour1": "レッドストーン信号を出力します。", "block.create.redstone_contact.tooltip.condition2": "動かしたとき", "block.create.redstone_contact.tooltip.behaviour2": "通過するすべての固定したレッドストーンコンタクトに反応します。", "block.create.adjustable_crate.tooltip": "可変クレート", - "block.create.adjustable_crate.tooltip.summary": "この_収納ブロック_は、容量を手動で制御できます。任意のアイテムを_16スタック_まで収納できます。 _レッドストーンコンパレーター_に対応しています。", + "block.create.adjustable_crate.tooltip.summary": "この_収納ブロック_は、容量を手動で制御できます。任意のアイテムを_16スタック_まで収納できます。_レッドストーンコンパレーター_に対応しています。", "block.create.adjustable_crate.tooltip.control1": "右クリックしたとき", "block.create.adjustable_crate.tooltip.action1": "_インターフェース_を開きます。", @@ -1689,7 +1692,7 @@ "block.create.creative_crate.tooltip.behaviour1": "このクレートから何かを_搬出_すると、指定されたアイテムが_無限_に_搬出_されます。このクレートに_搬入_されたアイテムは_消滅_します。", "block.create.deployer.tooltip": "デプロイヤー", - "block.create.deployer.tooltip.summary": "_殴る_、_使う_、_起動する_。この機械は、_プレイヤー_をできるだけ_真似_しようとします。_アイテムを自分のインベントリに入れたり_、_預けたり_できます。 持っているアイテムはブロックから直接搬入・搬出する必要があります。", + "block.create.deployer.tooltip.summary": "_殴る_、_使う_、_起動する_。この機械は、_プレイヤー_をできるだけ_真似_しようとします。_アイテムを自分のインベントリに入れたり_、_預けたり_できます。持っているアイテムはブロックから直接搬入・搬出する必要があります。", "block.create.deployer.tooltip.condition1": "回転したとき", "block.create.deployer.tooltip.behaviour1": "腕を機械の2m先まで伸ばし、アイテムを_発動_する。", "block.create.deployer.tooltip.condition2": "レンチで右クリックしたとき", @@ -1698,7 +1701,7 @@ "block.create.deployer.tooltip.behaviour3": "合わないアイテムは搬入できません。逆に合うアイテムは搬出できません。", "block.create.brass_casing.tooltip": "真ちゅうのケーシング", - "block.create.brass_casing.tooltip.summary": "さまざまな用途に使用できる頑丈な機械ケーシング。 装飾にも安心してお使いいただけます。", + "block.create.brass_casing.tooltip.summary": "さまざまな用途に使用できる頑丈な機械ケーシング。装飾にも安心してお使いいただけます。", "block.create.pulse_repeater.tooltip": "パルスリピーター", "block.create.pulse_repeater.tooltip.summary": "通過するレッドストーン信号を_1ティック_の長さにカットする簡単な回路。", @@ -1716,22 +1719,22 @@ "block.create.powered_toggle_latch.tooltip.summary": "レッドストーンパルスによって切替できるレバー。", "block.create.powered_latch.tooltip": "パワードラッチ", - "block.create.powered_latch.tooltip.summary": "_レッドストーン信号_で制御できるレバー。 _背面のレッドストーン信号_でオンになり、_側面からのレッドストーン信号_でリセットされます。", + "block.create.powered_latch.tooltip.summary": "_レッドストーン信号_で制御できるレバー。_背面のレッドストーン信号_でオンになり、_側面からのレッドストーン信号_でリセットされます。", "block.create.controller_rail.tooltip": "コントローラーレール", "block.create.controller_rail.tooltip.summary": "トロッコの_移動速度_を_細かく制御_できる一方通行の_パワード_レール", "block.create.controller_rail.tooltip.condition1": "レッドストーン信号を受けたとき", "block.create.controller_rail.tooltip.behaviour1": "通過する_トロッコ_を_信号の強度_に対応した速度に_加速_または_減速_します。また、隣接するコントローラレールにレッドストーン信号を伝達します。強度の異なる2つのコントローラレールにレッドストーン信号を供給すると、それらの間のレールはその信号の変化を補間します。", - "block.create.speedometer.tooltip": "スピードメーター", - "block.create.speedometer.tooltip.summary": "接続された機械の_回転速度_を測定して表示します。 _レッドストーンコンパレーター_に対応しています。", + "block.create.speedometer.tooltip": "速度メーター", + "block.create.speedometer.tooltip.summary": "接続された機械の_回転速度_を測定して表示します。_レッドストーンコンパレーター_に対応しています。", "block.create.speedometer.tooltip.condition1": "回転したとき", - "block.create.speedometer.tooltip.behaviour1": "速度レベルに対応する色を表示します。 _緑_は低速、_青_は中速、_紫_は高速を示します。 一部の機械は、稼働に十分なレベルの速度を必要とします。", + "block.create.speedometer.tooltip.behaviour1": "速度レベルに対応する色を表示します。_緑_は低速、_青_は中速、_紫_は高速を示します。一部の機械は、稼働に十分なレベルの速度を必要とします。", - "block.create.stressometer.tooltip": "ストレスメーター", - "block.create.stressometer.tooltip.summary": "接続された動力ネットワーク全体の応力を測定して表示します。 _レッドストーンコンパレーター_に対応しています。", + "block.create.stressometer.tooltip": "速度メーター", + "block.create.stressometer.tooltip.summary": "接続された動力ネットワーク全体の応力を測定して表示します。_レッドストーンコンパレーター_に対応しています。", "block.create.stressometer.tooltip.condition1": "回転したとき", - "block.create.stressometer.tooltip.behaviour1": "応力レベルに対応する色を表示します。 _過度に応力がかかった(超過応力)ネットワーク_の機械は全て停止します。応力は動力ネットワークに_原動機_を追加することで緩和することができます。", + "block.create.stressometer.tooltip.behaviour1": "応力レベルに対応する色を表示します。_過度に応力がかかった(超過応力)ネットワーク_の機械は全て停止します。応力は動力ネットワークに_原動機_を追加することで緩和することができます。", "item.create.sand_paper.tooltip": "紙やすり", "item.create.sand_paper.tooltip.summary": "_素材_を_磨く_のに使える荒い紙。デプロイヤーに自動的で磨かせることもできます。", @@ -1749,7 +1752,7 @@ "item.create.builders_tea.tooltip.summary": "_やる気_がみなぎる、一日の始まりに最適な飲み物。", "item.create.refined_radiance.tooltip": "洗練された輝き", - "item.create.refined_radiance.tooltip.summary": "_吸収した光_から鍛造した色彩素材。", + "item.create.refined_radiance.tooltip.summary": "_吸収した輝き_から鍛造した色彩素材。", "item.create.shadow_steel.tooltip": "シャドウスチール", "item.create.shadow_steel.tooltip.summary": "_奈落の虚無_から鍛造した色彩素材。", @@ -1760,7 +1763,7 @@ "item.create.minecart_coupling.tooltip.behaviour1": "2台のトロッコを連結します。それらは移動中に一定の距離を保とうします。", "item.create.crafter_slot_cover.tooltip": "スロットカバー", - "item.create.crafter_slot_cover.tooltip.summary": "取り付けた_メカニカルクラフター_をレシピの空のスロットとして示します。 クラフターは必ずしも正方形である必要はありません。 これは、_同じアイテムが離れた場所にある_レシピに便利です。", + "item.create.crafter_slot_cover.tooltip.summary": "取り付けた_メカニカルクラフター_をレシピの空のスロットとして示します。クラフターは必ずしも正方形である必要はありません。これは、_同じアイテムが離れた場所にある_レシピに便利です。", "create.tooltip.wip": "WIP", "create.tooltip.workInProgress": "作業中です!", @@ -1768,10 +1771,10 @@ "create.tooltip.randomWipDescription1": "赤ちゃんパンダは、このアイテムを使用するたびに死にます。そう、いつでもね。", "create.tooltip.randomWipDescription2": "自己責任。", "create.tooltip.randomWipDescription3": "これはあなたが探しているアイテムではありません。*人差し指を振って*ちっちっちっ、解散!", - "create.tooltip.randomWipDescription4": "このアイテムは10秒で自爆します。 10、9、8 ...", + "create.tooltip.randomWipDescription4": "このアイテムは10秒で自爆します。10、9、8 ...", "create.tooltip.randomWipDescription5": "私を信じて、それは無駄だ。", "create.tooltip.randomWipDescription6": "このアイテムを使用することにより、お客様はここに免責事項に同意し、その条件に同意するものとします。", - "create.tooltip.randomWipDescription7": "これは君に向いていないかもしれない。 あれはどう??", + "create.tooltip.randomWipDescription7": "これは君に向いていないかもしれない。あれはどう??", "create.tooltip.randomWipDescription8": "それを使ったことをすぐ後悔する。", "_": "Thank you for translating Create!" diff --git a/src/main/resources/assets/create/models/block/gantry_shaft/block_end.json b/src/main/resources/assets/create/models/block/gantry_shaft/block_end.json index a459fd12b..23c06e41f 100644 --- a/src/main/resources/assets/create/models/block/gantry_shaft/block_end.json +++ b/src/main/resources/assets/create/models/block/gantry_shaft/block_end.json @@ -26,9 +26,9 @@ "to": [11, 11, 11], "shade": false, "faces": { - "north": {"uv": [8, 5, 14, 16], "texture": "#2"}, - "east": {"uv": [2, 5, 8, 16], "texture": "#2"}, - "south": {"uv": [4, 5, 10, 16], "texture": "#2"}, + "north": {"uv": [0, 5, 6, 16], "texture": "#2"}, + "east": {"uv": [6, 5, 12, 16], "texture": "#2"}, + "south": {"uv": [0, 5, 6, 16], "texture": "#2"}, "west": {"uv": [6, 5, 12, 16], "texture": "#2"} } }, diff --git a/src/main/resources/assets/create/models/block/gantry_shaft/block_middle.json b/src/main/resources/assets/create/models/block/gantry_shaft/block_middle.json index 8d4416d92..cc9ee7946 100644 --- a/src/main/resources/assets/create/models/block/gantry_shaft/block_middle.json +++ b/src/main/resources/assets/create/models/block/gantry_shaft/block_middle.json @@ -12,8 +12,8 @@ "shade": false, "faces": { "north": {"uv": [0, 0, 6, 16], "texture": "#2"}, - "east": {"uv": [2, 0, 8, 16], "texture": "#2"}, - "south": {"uv": [4, 0, 10, 16], "texture": "#2"}, + "east": {"uv": [6, 0, 12, 16], "texture": "#2"}, + "south": {"uv": [0, 0, 6, 16], "texture": "#2"}, "west": {"uv": [6, 0, 12, 16], "texture": "#2"} } } diff --git a/src/main/resources/assets/create/models/block/gantry_shaft/block_single.json b/src/main/resources/assets/create/models/block/gantry_shaft/block_single.json index cccb1fd78..495caf396 100644 --- a/src/main/resources/assets/create/models/block/gantry_shaft/block_single.json +++ b/src/main/resources/assets/create/models/block/gantry_shaft/block_single.json @@ -52,8 +52,8 @@ "to": [11, 11, 11], "shade": false, "faces": { - "north": {"uv": [4, 5, 10, 11], "rotation": 180, "texture": "#2"}, - "east": {"uv": [3, 5, 9, 11], "rotation": 180, "texture": "#2"}, + "north": {"uv": [0, 5, 6, 11], "rotation": 180, "texture": "#2"}, + "east": {"uv": [6, 5, 12, 11], "rotation": 180, "texture": "#2"}, "south": {"uv": [0, 5, 6, 11], "rotation": 180, "texture": "#2"}, "west": {"uv": [6, 5, 12, 11], "rotation": 180, "texture": "#2"} } diff --git a/src/main/resources/assets/create/models/block/gantry_shaft/block_start.json b/src/main/resources/assets/create/models/block/gantry_shaft/block_start.json index b77bfceba..15ab79845 100644 --- a/src/main/resources/assets/create/models/block/gantry_shaft/block_start.json +++ b/src/main/resources/assets/create/models/block/gantry_shaft/block_start.json @@ -27,8 +27,8 @@ "shade": false, "faces": { "north": {"uv": [0, 0, 6, 11], "texture": "#2"}, - "east": {"uv": [2, 0, 8, 11], "texture": "#2"}, - "south": {"uv": [4, 0, 10, 11], "texture": "#2"}, + "east": {"uv": [6, 0, 12, 11], "texture": "#2"}, + "south": {"uv": [0, 0, 6, 11], "texture": "#2"}, "west": {"uv": [6, 0, 12, 11], "texture": "#2"} } }, diff --git a/src/main/resources/assets/create/shader/belt.vert b/src/main/resources/assets/create/shader/belt.vert new file mode 100644 index 000000000..c150f012b --- /dev/null +++ b/src/main/resources/assets/create/shader/belt.vert @@ -0,0 +1,106 @@ +#version 110 +#define PI 3.1415926538 + +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; + +attribute vec3 aInstancePos; +attribute vec2 aLight; +attribute vec3 aNetworkTint; +attribute float aSpeed; +attribute float aOffset; +attribute vec3 aInstanceRot; +attribute vec2 aSourceTexture; +attribute vec4 aScrollTexture; +attribute float aScrollMult; + +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; +varying float FragDistance; + +mat4 rotate(vec3 axis, float angle) { + float s = sin(angle); + float c = cos(angle); + float oc = 1. - c; + + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0., + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0., + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0., + 0., 0., 0., 1.); +} + +float diffuse(vec3 normal) { + float x = normal.x; + float y = normal.y; + float z = normal.z; + return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); +} + +mat4 rotation(vec3 rot) { + return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); +} + +mat4 localRotation() { + vec3 rot = fract(aInstanceRot / 360.) * PI * 2.; + return rotation(rot); +} + +void main() { + mat4 localRotation = localRotation(); + vec4 worldPos = localRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.); + + #ifdef CONTRAPTION + worldPos = uModel * worldPos; + mat4 normalMat = uModel * localRotation; + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + FragDistance = length(worldPos.xyz); + #else + mat4 normalMat = localRotation; + + FragDistance = length(worldPos.xyz - uCameraPos); + #endif + + vec3 norm = normalize(normalMat * vec4(aNormal, 0.)).xyz; + + float scrollSize = aScrollTexture.w - aScrollTexture.y; + float scroll = fract(aSpeed * uTime / (36. * 16.) + aOffset) * scrollSize * aScrollMult; + + Diffuse = diffuse(norm); + TexCoords = aTexCoords - aSourceTexture + aScrollTexture.xy + vec2(0, scroll); + Light = aLight; + gl_Position = uViewProjection * worldPos; + + #ifdef CONTRAPTION + if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } + #else + if (uDebug == 1) { + Color = vec4(aNetworkTint, 1.); + } else if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } + #endif +} diff --git a/src/main/resources/assets/create/shader/contraption.frag b/src/main/resources/assets/create/shader/contraption.frag new file mode 100644 index 000000000..5d90b40ff --- /dev/null +++ b/src/main/resources/assets/create/shader/contraption.frag @@ -0,0 +1,33 @@ +#version 110 + +varying vec2 TexCoords; +varying vec4 Color; +varying float Diffuse; +varying vec2 Light; +varying float FragDistance; + +varying vec3 BoxCoord; + +uniform vec2 uFogRange; +uniform vec4 uFogColor; + +uniform sampler2D uBlockAtlas; +uniform sampler2D uLightMap; +uniform sampler3D uLightVolume; + +vec4 light() { + vec2 lm = texture3D(uLightVolume, BoxCoord).rg * 0.9375 + 0.03125; + return texture2D(uLightMap, max(lm, Light)); +} + +void main() { + vec4 tex = texture2D(uBlockAtlas, TexCoords); + + vec4 color = vec4(tex.rgb * light().rgb * Diffuse * Color.rgb, tex.a); + + float fog = (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); + fog = clamp(fog, 0., 1.); + + gl_FragColor = mix(uFogColor, color, fog); + gl_FragColor.a = color.a; +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/contraption_actor.vert b/src/main/resources/assets/create/shader/contraption_actor.vert new file mode 100644 index 000000000..7dbae771c --- /dev/null +++ b/src/main/resources/assets/create/shader/contraption_actor.vert @@ -0,0 +1,88 @@ +#version 110 +#define PI 3.1415926538 +// model data +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; + +// instance data +attribute vec3 aInstancePos; +attribute vec2 aModelLight; +attribute float aOffset; +attribute vec3 aAxis; +attribute vec3 aInstanceRot; +attribute vec3 aRotationCenter; + + +varying float Diffuse; +varying vec2 TexCoords; +varying vec4 Color; +varying vec3 BoxCoord; +varying vec2 Light; + +uniform vec3 uLightBoxSize; +uniform vec3 uLightBoxMin; +uniform mat4 uModel; + +uniform float uTime; +uniform mat4 uViewProjection; +uniform int uDebug; + +uniform vec3 uCameraPos; +varying float FragDistance; + +mat4 rotate(vec3 axis, float angle) { + float s = sin(angle); + float c = cos(angle); + float oc = 1. - c; + + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0., + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0., + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0., + 0., 0., 0., 1.); +} + +float diffuse(vec3 normal) { + float x = normal.x; + float y = normal.y; + float z = normal.z; + return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); +} + +mat4 rotation(vec3 rot) { + return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); +} + +mat4 kineticRotation() { + const float speed = -20.; + float degrees = aOffset + uTime * speed * -3./10.; + float angle = fract(degrees / 360.) * PI * 2.; + + return rotate(normalize(aAxis), angle); +} + +void main() { + mat4 kineticRotation = kineticRotation(); + vec4 localPos = kineticRotation * vec4(aPos - aRotationCenter, 1.) + vec4(aRotationCenter, 0.); + + vec3 rot = fract(aInstanceRot / 360.) * PI * 2.; + mat4 localRot = rotation(rot); + localPos = localRot * vec4(localPos.xyz - .5, 1.) + vec4(aInstancePos + .5, 0.); + + vec4 worldPos = uModel * localPos; + + vec3 norm = normalize(uModel * localRot * kineticRotation * vec4(aNormal, 0.)).xyz; + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + Diffuse = diffuse(norm); + TexCoords = aTexCoords; + Light = aModelLight; + FragDistance = length(worldPos.xyz); + gl_Position = uViewProjection * worldPos; + + if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/contraption_structure.vert b/src/main/resources/assets/create/shader/contraption_structure.vert new file mode 100644 index 000000000..a665ea8ff --- /dev/null +++ b/src/main/resources/assets/create/shader/contraption_structure.vert @@ -0,0 +1,63 @@ +#version 110 +#define PI 3.1415926538 + +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; +attribute vec4 aColor; +attribute vec2 aModelLight; + +varying float Diffuse; +varying vec2 TexCoords; +varying vec4 Color; +varying vec3 BoxCoord; +varying vec2 Light; + +uniform vec3 uLightBoxSize; +uniform vec3 uLightBoxMin; +uniform mat4 uModel; + +uniform float uTime; +uniform mat4 uViewProjection; +uniform int uDebug; + +uniform vec3 uCameraPos; +varying float FragDistance; + +mat4 rotate(vec3 axis, float angle) { + float s = sin(angle); + float c = cos(angle); + float oc = 1. - c; + + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0., + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0., + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0., + 0., 0., 0., 1.); +} + +float diffuse(vec3 normal) { + float x = normal.x; + float y = normal.y; + float z = normal.z; + return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); +} + +void main() { + vec4 viewPos = uModel * vec4(aPos, 1.); + + vec3 norm = (uModel * vec4(aNormal, 0.)).xyz; + + BoxCoord = (viewPos.xyz - uLightBoxMin) / uLightBoxSize; + Diffuse = diffuse(norm); + Color = aColor / diffuse(aNormal); + TexCoords = aTexCoords; + Light = aModelLight; + FragDistance = length(viewPos.xyz); + gl_Position = uViewProjection * viewPos; + + if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = aColor / diffuse(aNormal); + } +} diff --git a/src/main/resources/assets/create/shader/instanced.frag b/src/main/resources/assets/create/shader/instanced.frag new file mode 100644 index 000000000..cb85241f5 --- /dev/null +++ b/src/main/resources/assets/create/shader/instanced.frag @@ -0,0 +1,30 @@ +#version 110 + +varying vec2 TexCoords; +varying vec2 Light; +varying float Diffuse; +varying vec4 Color; +varying float FragDistance; + +uniform vec2 uFogRange; +uniform vec4 uFogColor; + +uniform sampler2D uBlockAtlas; +uniform sampler2D uLightMap; + +vec4 light() { + vec2 lm = Light * 0.9375 + 0.03125; + return texture2D(uLightMap, lm); +} + +void main() { + vec4 tex = texture2D(uBlockAtlas, TexCoords); + + vec4 color = vec4(tex.rgb * light().rgb * Diffuse, tex.a) * Color; + + float fog = (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); + fog = clamp(fog, 0., 1.); + + gl_FragColor = mix(uFogColor, color, fog); + gl_FragColor.a = color.a; +} \ No newline at end of file diff --git a/src/main/resources/assets/create/shader/rotating.vert b/src/main/resources/assets/create/shader/rotating.vert new file mode 100644 index 000000000..a1f803139 --- /dev/null +++ b/src/main/resources/assets/create/shader/rotating.vert @@ -0,0 +1,101 @@ +#version 110 +#define PI 3.1415926538 +attribute vec3 aPos; +attribute vec3 aNormal; +attribute vec2 aTexCoords; + +attribute vec3 aInstancePos; +attribute vec2 aLight; +attribute vec3 aNetworkTint; +attribute float aSpeed; +attribute float aOffset; +attribute vec3 aAxis; + +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; +varying float FragDistance; + +mat4 rotate(vec3 axis, float angle) { + float s = sin(angle); + float c = cos(angle); + float oc = 1. - c; + + return mat4(oc * axis.x * axis.x + c, oc * axis.x * axis.y - axis.z * s, oc * axis.z * axis.x + axis.y * s, 0., + oc * axis.x * axis.y + axis.z * s, oc * axis.y * axis.y + c, oc * axis.y * axis.z - axis.x * s, 0., + oc * axis.z * axis.x - axis.y * s, oc * axis.y * axis.z + axis.x * s, oc * axis.z * axis.z + c, 0., + 0., 0., 0., 1.); +} + +float diffuse(vec3 normal) { + float x = normal.x; + float y = normal.y; + float z = normal.z; + return min(x * x * .6 + y * y * ((3. + y) / 4.) + z * z * .8, 1.); +} + +mat4 rotation(vec3 rot) { + return rotate(vec3(0., 1., 0.), rot.y) * rotate(vec3(0., 0., 1.), rot.z) * rotate(vec3(1., 0., 0.), rot.x); +} + +mat4 kineticRotation() { + float degrees = aOffset + uTime * aSpeed * -3./10.; + float angle = fract(degrees / 360.) * PI * 2.; + + return rotate(aAxis, angle); +} + +void main() { + mat4 kineticRotation = kineticRotation(); + vec4 worldPos = kineticRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.); + + #ifdef CONTRAPTION + worldPos = uModel * worldPos; + mat4 normalMat = uModel * kineticRotation; + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + FragDistance = length(worldPos.xyz); + #else + mat4 normalMat = kineticRotation; + + FragDistance = length(worldPos.xyz - uCameraPos); + #endif + + vec3 norm = normalize(normalMat * vec4(aNormal, 0.)).xyz; + + Diffuse = diffuse(norm); + TexCoords = aTexCoords; + Light = aLight; + gl_Position = uViewProjection * worldPos; + + #ifdef CONTRAPTION + if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } + #else + if (uDebug == 1) { + Color = vec4(aNetworkTint, 1.); + } else if (uDebug == 2) { + Color = vec4(norm, 1.); + } else { + Color = vec4(1.); + } + #endif +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/block/andesite_funnel_slope.png b/src/main/resources/assets/create/textures/block/andesite_funnel_slope.png new file mode 100644 index 000000000..cf4441c47 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/andesite_funnel_slope.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/black.png b/src/main/resources/assets/create/textures/block/belt/black.png deleted file mode 100644 index 7208c37dc..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/black.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/black_diagonal.png b/src/main/resources/assets/create/textures/block/belt/black_diagonal.png deleted file mode 100644 index 01b7556cb..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/black_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/black_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/black_diagonal_scroll.png new file mode 100644 index 000000000..7f09c1f29 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/black_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/black_scroll.png b/src/main/resources/assets/create/textures/block/belt/black_scroll.png new file mode 100644 index 000000000..8cc4f7df5 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/black_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/blue.png b/src/main/resources/assets/create/textures/block/belt/blue.png deleted file mode 100644 index 1fde542ce..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/blue.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/blue_diagonal.png b/src/main/resources/assets/create/textures/block/belt/blue_diagonal.png deleted file mode 100644 index 9f09d64cb..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/blue_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/blue_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/blue_diagonal_scroll.png new file mode 100644 index 000000000..5da06f8d1 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/blue_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/blue_scroll.png b/src/main/resources/assets/create/textures/block/belt/blue_scroll.png new file mode 100644 index 000000000..abaa0bb26 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/blue_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/brown.png b/src/main/resources/assets/create/textures/block/belt/brown.png deleted file mode 100644 index 944db3c46..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/brown.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/brown_diagonal.png b/src/main/resources/assets/create/textures/block/belt/brown_diagonal.png deleted file mode 100644 index 104903161..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/brown_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/brown_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/brown_diagonal_scroll.png new file mode 100644 index 000000000..b1f493279 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/brown_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/brown_scroll.png b/src/main/resources/assets/create/textures/block/belt/brown_scroll.png new file mode 100644 index 000000000..3b9ae0cb4 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/brown_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/cyan.png b/src/main/resources/assets/create/textures/block/belt/cyan.png deleted file mode 100644 index 414590282..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/cyan.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/cyan_diagonal.png b/src/main/resources/assets/create/textures/block/belt/cyan_diagonal.png deleted file mode 100644 index 3bcf44a87..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/cyan_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/cyan_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/cyan_diagonal_scroll.png new file mode 100644 index 000000000..5b313c3cc Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/cyan_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/cyan_scroll.png b/src/main/resources/assets/create/textures/block/belt/cyan_scroll.png new file mode 100644 index 000000000..87951f7f2 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/cyan_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/gray.png b/src/main/resources/assets/create/textures/block/belt/gray.png deleted file mode 100644 index f306a29cd..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/gray.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/gray_diagonal.png b/src/main/resources/assets/create/textures/block/belt/gray_diagonal.png deleted file mode 100644 index ff2bdc34c..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/gray_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/gray_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/gray_diagonal_scroll.png new file mode 100644 index 000000000..17be8d10e Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/gray_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/gray_scroll.png b/src/main/resources/assets/create/textures/block/belt/gray_scroll.png new file mode 100644 index 000000000..5e5e3f17c Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/gray_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/green.png b/src/main/resources/assets/create/textures/block/belt/green.png deleted file mode 100644 index cd41d7c14..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/green.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/green_diagonal.png b/src/main/resources/assets/create/textures/block/belt/green_diagonal.png deleted file mode 100644 index a79967666..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/green_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/green_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/green_diagonal_scroll.png new file mode 100644 index 000000000..55f29f0de Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/green_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/green_scroll.png b/src/main/resources/assets/create/textures/block/belt/green_scroll.png new file mode 100644 index 000000000..eac299196 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/green_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_blue.png b/src/main/resources/assets/create/textures/block/belt/light_blue.png deleted file mode 100644 index c19b5d0c5..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/light_blue.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_blue_diagonal.png b/src/main/resources/assets/create/textures/block/belt/light_blue_diagonal.png deleted file mode 100644 index ad344f524..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/light_blue_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_blue_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/light_blue_diagonal_scroll.png new file mode 100644 index 000000000..162128bac Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/light_blue_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_blue_scroll.png b/src/main/resources/assets/create/textures/block/belt/light_blue_scroll.png new file mode 100644 index 000000000..946398440 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/light_blue_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_gray.png b/src/main/resources/assets/create/textures/block/belt/light_gray.png deleted file mode 100644 index ca67d7c8e..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/light_gray.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_gray_diagonal.png b/src/main/resources/assets/create/textures/block/belt/light_gray_diagonal.png deleted file mode 100644 index f9ba32f48..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/light_gray_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_gray_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/light_gray_diagonal_scroll.png new file mode 100644 index 000000000..0f0ef3be7 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/light_gray_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/light_gray_scroll.png b/src/main/resources/assets/create/textures/block/belt/light_gray_scroll.png new file mode 100644 index 000000000..0bc6bca7a Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/light_gray_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/lime.png b/src/main/resources/assets/create/textures/block/belt/lime.png deleted file mode 100644 index ca40f812b..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/lime.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/lime_diagonal.png b/src/main/resources/assets/create/textures/block/belt/lime_diagonal.png deleted file mode 100644 index ac8405b3c..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/lime_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/lime_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/lime_diagonal_scroll.png new file mode 100644 index 000000000..8a964537b Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/lime_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/lime_scroll.png b/src/main/resources/assets/create/textures/block/belt/lime_scroll.png new file mode 100644 index 000000000..12f08decb Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/lime_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/magenta.png b/src/main/resources/assets/create/textures/block/belt/magenta.png deleted file mode 100644 index 2c751984a..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/magenta.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/magenta_diagonal.png b/src/main/resources/assets/create/textures/block/belt/magenta_diagonal.png deleted file mode 100644 index f7539d185..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/magenta_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/magenta_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/magenta_diagonal_scroll.png new file mode 100644 index 000000000..391573768 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/magenta_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/magenta_scroll.png b/src/main/resources/assets/create/textures/block/belt/magenta_scroll.png new file mode 100644 index 000000000..97730b8a0 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/magenta_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/orange.png b/src/main/resources/assets/create/textures/block/belt/orange.png deleted file mode 100644 index d4356e978..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/orange.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/orange_diagonal.png b/src/main/resources/assets/create/textures/block/belt/orange_diagonal.png deleted file mode 100644 index 7e774efee..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/orange_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/orange_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/orange_diagonal_scroll.png new file mode 100644 index 000000000..9b05628bf Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/orange_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/orange_scroll.png b/src/main/resources/assets/create/textures/block/belt/orange_scroll.png new file mode 100644 index 000000000..b17c3706e Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/orange_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/pink.png b/src/main/resources/assets/create/textures/block/belt/pink.png deleted file mode 100644 index e8271fcff..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/pink.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/pink_diagonal.png b/src/main/resources/assets/create/textures/block/belt/pink_diagonal.png deleted file mode 100644 index c4441a5ed..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/pink_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/pink_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/pink_diagonal_scroll.png new file mode 100644 index 000000000..cb45cfb80 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/pink_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/pink_scroll.png b/src/main/resources/assets/create/textures/block/belt/pink_scroll.png new file mode 100644 index 000000000..f60386562 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/pink_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/purple.png b/src/main/resources/assets/create/textures/block/belt/purple.png deleted file mode 100644 index a34dadade..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/purple.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/purple_diagonal.png b/src/main/resources/assets/create/textures/block/belt/purple_diagonal.png deleted file mode 100644 index a86fbfc6c..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/purple_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/purple_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/purple_diagonal_scroll.png new file mode 100644 index 000000000..e88f5ee04 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/purple_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/purple_scroll.png b/src/main/resources/assets/create/textures/block/belt/purple_scroll.png new file mode 100644 index 000000000..2a7dd16d5 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/purple_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/red.png b/src/main/resources/assets/create/textures/block/belt/red.png deleted file mode 100644 index 9de781a48..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/red.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/red_diagonal.png b/src/main/resources/assets/create/textures/block/belt/red_diagonal.png deleted file mode 100644 index ec53e50c9..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/red_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/red_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/red_diagonal_scroll.png new file mode 100644 index 000000000..611567dde Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/red_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/red_scroll.png b/src/main/resources/assets/create/textures/block/belt/red_scroll.png new file mode 100644 index 000000000..c09915c68 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/red_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/white.png b/src/main/resources/assets/create/textures/block/belt/white.png deleted file mode 100644 index 3edb40a1a..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/white.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/white_diagonal.png b/src/main/resources/assets/create/textures/block/belt/white_diagonal.png deleted file mode 100644 index 06694cb35..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/white_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/white_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/white_diagonal_scroll.png new file mode 100644 index 000000000..527a647af Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/white_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/white_scroll.png b/src/main/resources/assets/create/textures/block/belt/white_scroll.png new file mode 100644 index 000000000..8251b3b1f Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/white_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/yellow.png b/src/main/resources/assets/create/textures/block/belt/yellow.png deleted file mode 100644 index ef615bfcf..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/yellow.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/yellow_diagonal.png b/src/main/resources/assets/create/textures/block/belt/yellow_diagonal.png deleted file mode 100644 index b682d0be3..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt/yellow_diagonal.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt/yellow_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt/yellow_diagonal_scroll.png new file mode 100644 index 000000000..d8622414f Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/yellow_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt/yellow_scroll.png b/src/main/resources/assets/create/textures/block/belt/yellow_scroll.png new file mode 100644 index 000000000..256e1e45b Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt/yellow_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt_animated.png b/src/main/resources/assets/create/textures/block/belt_animated.png deleted file mode 100644 index 527b162fa..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt_animated.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt_diagonal_animated.png b/src/main/resources/assets/create/textures/block/belt_diagonal_animated.png deleted file mode 100644 index 29a5552d5..000000000 Binary files a/src/main/resources/assets/create/textures/block/belt_diagonal_animated.png and /dev/null differ diff --git a/src/main/resources/assets/create/textures/block/belt_diagonal_scroll.png b/src/main/resources/assets/create/textures/block/belt_diagonal_scroll.png new file mode 100644 index 000000000..e8cdb900e Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt_diagonal_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/belt_scroll.png b/src/main/resources/assets/create/textures/block/belt_scroll.png new file mode 100644 index 000000000..b5081c7d7 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/belt_scroll.png differ diff --git a/src/main/resources/assets/create/textures/block/brass_funnel_slope.png b/src/main/resources/assets/create/textures/block/brass_funnel_slope.png new file mode 100644 index 000000000..2c79bb0dc Binary files /dev/null and b/src/main/resources/assets/create/textures/block/brass_funnel_slope.png differ diff --git a/src/main/resources/assets/create/textures/block/funnel_closed.png b/src/main/resources/assets/create/textures/block/funnel_closed.png new file mode 100644 index 000000000..5815a4ae3 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/funnel_closed.png differ diff --git a/src/main/resources/assets/create/textures/block/funnel_open.png b/src/main/resources/assets/create/textures/block/funnel_open.png new file mode 100644 index 000000000..83b39cd70 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/funnel_open.png differ diff --git a/src/main/resources/assets/create/textures/block/gantry_shaft.png b/src/main/resources/assets/create/textures/block/gantry_shaft.png index b11a4a8d6..0aaab6b3f 100644 Binary files a/src/main/resources/assets/create/textures/block/gantry_shaft.png and b/src/main/resources/assets/create/textures/block/gantry_shaft.png differ diff --git a/src/main/resources/assets/create/textures/block/gantry_shaft_flipped.png b/src/main/resources/assets/create/textures/block/gantry_shaft_flipped.png index 8971a8d65..b44b71663 100644 Binary files a/src/main/resources/assets/create/textures/block/gantry_shaft_flipped.png and b/src/main/resources/assets/create/textures/block/gantry_shaft_flipped.png differ diff --git a/src/main/resources/assets/create/textures/block/gantry_shaft_powered.png b/src/main/resources/assets/create/textures/block/gantry_shaft_powered.png index b3111e74a..8b1418b79 100644 Binary files a/src/main/resources/assets/create/textures/block/gantry_shaft_powered.png and b/src/main/resources/assets/create/textures/block/gantry_shaft_powered.png differ diff --git a/src/main/resources/assets/create/textures/block/gantry_shaft_powered_flipped.png b/src/main/resources/assets/create/textures/block/gantry_shaft_powered_flipped.png index 4e7c55ddb..bff72154b 100644 Binary files a/src/main/resources/assets/create/textures/block/gantry_shaft_powered_flipped.png and b/src/main/resources/assets/create/textures/block/gantry_shaft_powered_flipped.png differ diff --git a/src/main/resources/assets/create/textures/gui/icons.png b/src/main/resources/assets/create/textures/gui/icons.png index 3276c6033..499eccc38 100644 Binary files a/src/main/resources/assets/create/textures/gui/icons.png and b/src/main/resources/assets/create/textures/gui/icons.png differ diff --git a/src/main/resources/assets/create/textures/gui/placement_indicator.png b/src/main/resources/assets/create/textures/gui/placement_indicator.png new file mode 100644 index 000000000..d433d9b2d Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/placement_indicator.png differ diff --git a/src/main/resources/assets/create/textures/gui/sequencer.png b/src/main/resources/assets/create/textures/gui/sequencer.png index 5dcbea527..c89de3c15 100644 Binary files a/src/main/resources/assets/create/textures/gui/sequencer.png and b/src/main/resources/assets/create/textures/gui/sequencer.png differ diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json new file mode 100644 index 000000000..e9d682678 --- /dev/null +++ b/src/main/resources/create.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "package": "com.simibubi.create.foundation.mixin", + "compatibilityLevel": "JAVA_8", + "refmap": "create.refmap.json", + "client": [ + "OnRemoveTileMixin", + "ShaderCloseMixin", + "CancelTileEntityRenderMixin", + "LightUpdateMixin", + "RenderHooksMixin", + "FogColorTrackerMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "minVersion": "0.8" +} \ No newline at end of file