diff --git a/build.gradle b/build.gradle index 07408da84..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 { @@ -124,6 +131,8 @@ dependencies { // 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 { @@ -136,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" ]) } } @@ -205,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/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 7546069c8..e9a21c11e 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -140,7 +140,7 @@ de8a40b7daf1497d5aecee47a43b3e0b1d030b00 assets/create/blockstates/fancy_scoria_ fc9ac0a7e7191b93516719455a17177fa6524ecc assets/create/blockstates/fancy_weathered_limestone_bricks_slab.json b2a7c321b1795f20e7433f81a55ce4683de081b8 assets/create/blockstates/fancy_weathered_limestone_bricks_stairs.json 6372fe02ba0065acb0758121c45a15a1a8fdc5de assets/create/blockstates/fancy_weathered_limestone_bricks_wall.json -4c3e0500f9382d2e426e823fe876f57f4d7ee3b4 assets/create/blockstates/fluid_pipe.json +48086bf71a824faf14841b698050cc8544b09a9b assets/create/blockstates/fluid_pipe.json f0eaab18e16c4f3f65ebf3b55b08f0dc445720fe assets/create/blockstates/fluid_tank.json 5408d92ab02af86539ac42971d4033545970bb3a assets/create/blockstates/fluid_valve.json e9da1794b6ece7f9aa8bcb43d42c23a55446133b assets/create/blockstates/flywheel.json @@ -337,7 +337,7 @@ e8b0a401c10d1ba67ed71ba31bd5f9bc28571b65 assets/create/blockstates/powered_toggl d06cd9a1101b18d306a786320aab12018b1325d6 assets/create/blockstates/purple_sail.json 92957119abd5fbcca36a113b2a80255fd70fc303 assets/create/blockstates/purple_seat.json 61035f8afe75ff7bbd291da5d8690bcbebe679eb assets/create/blockstates/purple_valve_handle.json -bdd56f32ce0a148b6e466a55ab2777f69fc08cfc assets/create/blockstates/radial_chassis.json +6fa36883e76e9e403bb429c8f86b8c0d3bba0cff assets/create/blockstates/radial_chassis.json 45877c4d90a7185c2f304edbd67379d800920439 assets/create/blockstates/red_sail.json da1b08387af7afa0855ee8d040f620c01f20660a assets/create/blockstates/red_seat.json 722fc77bbf387af8a4016e42cbf9501d2b968881 assets/create/blockstates/red_valve_handle.json @@ -401,18 +401,18 @@ 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 -acc852d80378b426d7ee6cb59c169e06b6d63b25 assets/create/lang/en_us.json -30ce93c56557cea2f384a47b549fb893700523a5 assets/create/lang/unfinished/de_de.json -77b8310f3cbed36fa0d2ee29e65ac6aee0c2adc2 assets/create/lang/unfinished/es_mx.json -8db9f9147dcef8c8182c548a524f96f578c116ec assets/create/lang/unfinished/fr_fr.json -89f7029d73733938ee9f900fc36d52ab7fc97563 assets/create/lang/unfinished/it_it.json -b1935e7f8d79d1112e1685adb42daedb976ac6d7 assets/create/lang/unfinished/ja_jp.json -23aaf879d07a24775aeba3b98c355c992b24f28b assets/create/lang/unfinished/ko_kr.json -7372533759001f094dbcad787f01f3de7422d8c0 assets/create/lang/unfinished/nl_nl.json -0d1e5d79ef196a06b273962d5ac8f2013f91209c assets/create/lang/unfinished/pt_br.json -54da7badbd4fb043f73f6e9a4dfc52bd9e7f515c assets/create/lang/unfinished/ru_ru.json -45ca54406acac857752c67a45729da953d11f94a assets/create/lang/unfinished/zh_cn.json -4093ea8612465858aa57581b36f8f60aa23ac203 assets/create/lang/unfinished/zh_tw.json +04b4c59db79887cdddd128cd4cb59320c715a76a assets/create/lang/en_us.json +92840d43a7a5056ba1ddf043fe2a4b2b54533192 assets/create/lang/unfinished/de_de.json +fcded5cc7ba38ce1f13bbcf481c52da384d4335e assets/create/lang/unfinished/es_mx.json +d926a35cff961a017a174e5bad8976b8bfa246f0 assets/create/lang/unfinished/fr_fr.json +bcf5cf92717d5d8b5b4b56dc759cc5dcd3b05ae7 assets/create/lang/unfinished/it_it.json +dddcd6a8d3842035b07172dae1b61064b210dd3b assets/create/lang/unfinished/ja_jp.json +6fc6f612108b1c4498ea90e83f1ed0a7bce198d5 assets/create/lang/unfinished/ko_kr.json +f6d7256dca3a9979ce85333a72ad787657c954ff assets/create/lang/unfinished/nl_nl.json +48adee636f2a0ff06c97b738c9552dcdd48dd72c assets/create/lang/unfinished/pt_br.json +a82ef75492ff34c22f5e480fefe826aceefa956e assets/create/lang/unfinished/ru_ru.json +25b9387af4a75d4264ff001562cc4b14fccd49e6 assets/create/lang/unfinished/zh_cn.json +21e291e10cc5194b61d82c8a271cff2682ec0aee 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 diff --git a/src/generated/resources/assets/create/blockstates/fluid_pipe.json b/src/generated/resources/assets/create/blockstates/fluid_pipe.json index a4cffcde7..80a25280c 100644 --- a/src/generated/resources/assets/create/blockstates/fluid_pipe.json +++ b/src/generated/resources/assets/create/blockstates/fluid_pipe.json @@ -61,9 +61,9 @@ { "when": { "down": "false", - "north": "true", "up": "true", - "south": "false" + "south": "false", + "north": "true" }, "apply": { "model": "create:block/fluid_pipe/lu_x" @@ -72,9 +72,9 @@ { "when": { "down": "false", - "north": "false", "up": "true", - "south": "true" + "south": "true", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/ru_x" @@ -83,9 +83,9 @@ { "when": { "down": "true", - "north": "true", "up": "false", - "south": "false" + "south": "false", + "north": "true" }, "apply": { "model": "create:block/fluid_pipe/ld_x" @@ -94,9 +94,9 @@ { "when": { "down": "true", - "north": "false", "up": "false", - "south": "true" + "south": "true", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/rd_x" @@ -105,9 +105,9 @@ { "when": { "down": "true", - "north": "false", "up": "true", - "south": "false" + "south": "false", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_x" @@ -116,9 +116,9 @@ { "when": { "down": "false", - "north": "false", "up": "true", - "south": "false" + "south": "false", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_x" @@ -127,9 +127,9 @@ { "when": { "down": "true", - "north": "false", "up": "false", - "south": "false" + "south": "false", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_x" @@ -138,9 +138,9 @@ { "when": { "down": "false", - "north": "true", "up": "false", - "south": "true" + "south": "true", + "north": "true" }, "apply": { "model": "create:block/fluid_pipe/lr_x" @@ -149,9 +149,9 @@ { "when": { "down": "false", - "north": "true", "up": "false", - "south": "false" + "south": "false", + "north": "true" }, "apply": { "model": "create:block/fluid_pipe/lr_x" @@ -160,9 +160,9 @@ { "when": { "down": "false", - "north": "false", "up": "false", - "south": "true" + "south": "true", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/lr_x" @@ -171,9 +171,9 @@ { "when": { "down": "false", - "north": "false", "up": "false", - "south": "false" + "south": "false", + "north": "false" }, "apply": { "model": "create:block/fluid_pipe/none_x" @@ -181,10 +181,10 @@ }, { "when": { + "south": "true", "west": "true", - "east": "false", "north": "false", - "south": "true" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/lu_y" @@ -192,10 +192,10 @@ }, { "when": { + "south": "true", "west": "false", - "east": "true", "north": "false", - "south": "true" + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/ru_y" @@ -203,10 +203,10 @@ }, { "when": { + "south": "false", "west": "true", - "east": "false", "north": "true", - "south": "false" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ld_y" @@ -214,10 +214,10 @@ }, { "when": { + "south": "false", "west": "false", - "east": "true", "north": "true", - "south": "false" + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/rd_y" @@ -225,10 +225,10 @@ }, { "when": { + "south": "true", "west": "false", - "east": "false", "north": "true", - "south": "true" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_y" @@ -236,10 +236,10 @@ }, { "when": { + "south": "true", "west": "false", - "east": "false", "north": "false", - "south": "true" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_y" @@ -247,10 +247,10 @@ }, { "when": { + "south": "false", "west": "false", - "east": "false", "north": "true", - "south": "false" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_y" @@ -258,10 +258,10 @@ }, { "when": { + "south": "false", "west": "true", - "east": "true", "north": "false", - "south": "false" + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/lr_y" @@ -269,10 +269,10 @@ }, { "when": { + "south": "false", "west": "true", - "east": "false", "north": "false", - "south": "false" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/lr_y" @@ -280,10 +280,10 @@ }, { "when": { + "south": "false", "west": "false", - "east": "true", "north": "false", - "south": "false" + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/lr_y" @@ -291,10 +291,10 @@ }, { "when": { + "south": "false", "west": "false", - "east": "false", "north": "false", - "south": "false" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/none_y" @@ -302,10 +302,10 @@ }, { "when": { - "west": "false", "down": "false", - "east": "true", - "up": "true" + "up": "true", + "west": "false", + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/lu_z" @@ -313,10 +313,10 @@ }, { "when": { - "west": "true", "down": "false", - "east": "false", - "up": "true" + "up": "true", + "west": "true", + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ru_z" @@ -324,10 +324,10 @@ }, { "when": { - "west": "false", "down": "true", - "east": "true", - "up": "false" + "up": "false", + "west": "false", + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/ld_z" @@ -335,10 +335,10 @@ }, { "when": { - "west": "true", "down": "true", - "east": "false", - "up": "false" + "up": "false", + "west": "true", + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/rd_z" @@ -346,10 +346,10 @@ }, { "when": { - "west": "false", "down": "true", - "east": "false", - "up": "true" + "up": "true", + "west": "false", + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_z" @@ -357,10 +357,10 @@ }, { "when": { - "west": "false", "down": "false", - "east": "false", - "up": "true" + "up": "true", + "west": "false", + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_z" @@ -368,10 +368,10 @@ }, { "when": { - "west": "false", "down": "true", - "east": "false", - "up": "false" + "up": "false", + "west": "false", + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/ud_z" @@ -379,10 +379,10 @@ }, { "when": { + "down": "false", + "up": "false", "west": "true", - "down": "false", - "east": "true", - "up": "false" + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/lr_z" @@ -390,10 +390,10 @@ }, { "when": { + "down": "false", + "up": "false", "west": "false", - "down": "false", - "east": "true", - "up": "false" + "east": "true" }, "apply": { "model": "create:block/fluid_pipe/lr_z" @@ -401,10 +401,10 @@ }, { "when": { + "down": "false", + "up": "false", "west": "true", - "down": "false", - "east": "false", - "up": "false" + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/lr_z" @@ -412,10 +412,10 @@ }, { "when": { - "west": "false", "down": "false", - "east": "false", - "up": "false" + "up": "false", + "west": "false", + "east": "false" }, "apply": { "model": "create:block/fluid_pipe/none_z" diff --git a/src/generated/resources/assets/create/blockstates/radial_chassis.json b/src/generated/resources/assets/create/blockstates/radial_chassis.json index c930cf0b5..f97d8c8bc 100644 --- a/src/generated/resources/assets/create/blockstates/radial_chassis.json +++ b/src/generated/resources/assets/create/blockstates/radial_chassis.json @@ -29,8 +29,8 @@ }, { "when": { - "sticky_south": "true", - "axis": "x" + "axis": "x", + "sticky_south": "true" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -39,8 +39,8 @@ }, { "when": { - "sticky_south": "true", - "axis": "y" + "axis": "y", + "sticky_south": "true" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky" @@ -48,8 +48,8 @@ }, { "when": { - "sticky_south": "true", - "axis": "z" + "axis": "z", + "sticky_south": "true" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -59,8 +59,8 @@ }, { "when": { - "sticky_south": "false", - "axis": "x" + "axis": "x", + "sticky_south": "false" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -69,8 +69,8 @@ }, { "when": { - "sticky_south": "false", - "axis": "y" + "axis": "y", + "sticky_south": "false" }, "apply": { "model": "create:block/radial_chassis_side_y" @@ -78,8 +78,8 @@ }, { "when": { - "sticky_south": "false", - "axis": "z" + "axis": "z", + "sticky_south": "false" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -89,8 +89,8 @@ }, { "when": { - "axis": "x", - "sticky_west": "true" + "sticky_west": "true", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -99,8 +99,8 @@ }, { "when": { - "axis": "y", - "sticky_west": "true" + "sticky_west": "true", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky", @@ -109,8 +109,8 @@ }, { "when": { - "axis": "z", - "sticky_west": "true" + "sticky_west": "true", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z_sticky", @@ -119,8 +119,8 @@ }, { "when": { - "axis": "x", - "sticky_west": "false" + "sticky_west": "false", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -129,8 +129,8 @@ }, { "when": { - "axis": "y", - "sticky_west": "false" + "sticky_west": "false", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y", @@ -139,8 +139,8 @@ }, { "when": { - "axis": "z", - "sticky_west": "false" + "sticky_west": "false", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z", @@ -207,8 +207,8 @@ }, { "when": { - "axis": "x", - "sticky_east": "true" + "sticky_east": "true", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x_sticky", @@ -217,8 +217,8 @@ }, { "when": { - "axis": "y", - "sticky_east": "true" + "sticky_east": "true", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y_sticky", @@ -227,8 +227,8 @@ }, { "when": { - "axis": "z", - "sticky_east": "true" + "sticky_east": "true", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z_sticky" @@ -236,8 +236,8 @@ }, { "when": { - "axis": "x", - "sticky_east": "false" + "sticky_east": "false", + "axis": "x" }, "apply": { "model": "create:block/radial_chassis_side_x", @@ -246,8 +246,8 @@ }, { "when": { - "axis": "y", - "sticky_east": "false" + "sticky_east": "false", + "axis": "y" }, "apply": { "model": "create:block/radial_chassis_side_y", @@ -256,8 +256,8 @@ }, { "when": { - "axis": "z", - "sticky_east": "false" + "sticky_east": "false", + "axis": "z" }, "apply": { "model": "create:block/radial_chassis_side_z" diff --git a/src/generated/resources/assets/create/lang/unfinished/de_de.json b/src/generated/resources/assets/create/lang/unfinished/de_de.json index e43663915..2970a187a 100644 --- a/src/generated/resources/assets/create/lang/unfinished/de_de.json +++ b/src/generated/resources/assets/create/lang/unfinished/de_de.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 1095", + "_": "Missing Localizations: 1101", "_": "->------------------------] Game Elements [------------------------<-", 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 5982b8d60..09e681eb2 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: 886", + "_": "Missing Localizations: 892", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:", "create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:", "create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed", "create.gui.stressometer.title": "UNLOCALIZED: Network Stress", 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 f9524d01b..e422d3ee7 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: 666", + "_": "Missing Localizations: 672", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "Statistiques cinétiques:", "create.gui.goggles.at_current_speed": "À la vitesse actuelle", "create.gui.goggles.pole_length": "Longueur de la barre", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "Informations sur la jauge:", "create.gui.speedometer.title": "Vitesse de rotation", "create.gui.stressometer.title": "Stress du réseau", 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 d8b4ba2dd..e80fd7fa6 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: 3", + "_": "Missing Localizations: 7", "_": "->------------------------] 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", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "Statistiche cinetiche:", "create.gui.goggles.at_current_speed": "Alla velocità attuale", "create.gui.goggles.pole_length": "Lunghezza palo:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "Informazioni sul calibro:", "create.gui.speedometer.title": "Velocità di rotazione", "create.gui.stressometer.title": "Stress della rete", @@ -1367,7 +1373,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/generated/resources/assets/create/lang/unfinished/ja_jp.json b/src/generated/resources/assets/create/lang/unfinished/ja_jp.json index 51e3ebb30..5416539af 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: 12", + "_": "Missing Localizations: 14", "_": "->------------------------] 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,7 +680,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": "自動定形クラフト", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "動力の統計:", "create.gui.goggles.at_current_speed": "現在の速度", "create.gui.goggles.pole_length": "ポールの長さ:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "計器の情報:", "create.gui.speedometer.title": "回転速度", "create.gui.stressometer.title": "ネットワークの応力", @@ -830,7 +836,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": "在庫スイッチ", @@ -961,9 +967,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": "データを無視", @@ -1030,7 +1036,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": "選択した属性をすべてを持っている場合、アイテムは通り抜けます。", @@ -1046,12 +1052,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": "大", @@ -1119,7 +1125,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": "金属がガチャンと鳴る", @@ -1180,11 +1186,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": "側面をレンチで右クリックしたとき。", @@ -1238,14 +1244,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": "窓の設定を変更します。", @@ -1284,7 +1290,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": "メカニカルアーム", @@ -1310,7 +1316,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": "スニークしながら右クリックしたとき。", @@ -1356,7 +1362,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": "スニークしながら右クリックしたとき", @@ -1367,11 +1373,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": "選択を_リセット_して削除します。", @@ -1391,11 +1397,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方向_の_回転_方向を逆にして_伝達_します。", @@ -1421,9 +1427,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": "ベルトの最初に選択した位置を_リセット_します。", @@ -1435,7 +1441,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": "スニークしながら右クリックしたとき", @@ -1450,7 +1456,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": "特別なブロックを吹き抜けるとき", @@ -1462,18 +1468,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": "右クリックしたとき", @@ -1482,10 +1488,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": "メカニカルベルトの上にあるとき", @@ -1520,9 +1526,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": "_稼動しているかまど_で動く強力な_原動機_。", @@ -1549,14 +1555,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": "メカニカルピストンの範囲を拡張します。", @@ -1584,7 +1590,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つ_の_連続_した_命令_に従って_回転処理_を変更することができます。高速になると精度が悪くなる可能性があります。", @@ -1611,7 +1617,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": "移動用の構造物を接続する設定可能な土台ブロック。", @@ -1630,19 +1636,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": "ブレードが衝突する_すべての成熟した作物を収穫_し、それらを初期の成長状態にリセットします。", @@ -1652,9 +1658,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": "動かしたとき", @@ -1669,30 +1675,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": "_インターフェース_を開きます。", @@ -1702,7 +1708,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": "レンチで右クリックしたとき", @@ -1711,7 +1717,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ティック_の長さにカットする簡単な回路。", @@ -1729,22 +1735,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": "_素材_を_磨く_のに使える荒い紙。デプロイヤーに自動的で磨かせることもできます。", @@ -1762,7 +1768,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": "_奈落の虚無_から鍛造した色彩素材。", @@ -1773,7 +1779,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": "作業中です!", @@ -1781,10 +1787,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/generated/resources/assets/create/lang/unfinished/ko_kr.json b/src/generated/resources/assets/create/lang/unfinished/ko_kr.json index f9779a768..3738a1056 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: 55", + "_": "Missing Localizations: 61", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "가동 상태:", "create.gui.goggles.at_current_speed": "현재 에너지량", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "게이지 정보:", "create.gui.speedometer.title": "회전 속도", "create.gui.stressometer.title": "네트워크 부하", 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 cbd42c8a8..f2d5bc807 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: 1155", + "_": "Missing Localizations: 1161", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:", "create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:", "create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed", "create.gui.stressometer.title": "UNLOCALIZED: Network Stress", 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 a967dbbe6..4a686f966 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: 1221", + "_": "Missing Localizations: 1227", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:", "create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:", "create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed", "create.gui.stressometer.title": "UNLOCALIZED: Network Stress", 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 01743b81b..4ccc0e1ab 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: 5", + "_": "Missing Localizations: 11", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "Кинетическая статистика:", "create.gui.goggles.at_current_speed": "На текущей скорости", "create.gui.goggles.pole_length": "Длина поршня", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "Калибровочная информация:", "create.gui.speedometer.title": "Скорость вращения", "create.gui.stressometer.title": "Сетевой момент", 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 625bf7385..873427b8f 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: 3", + "_": "Missing Localizations: 9", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "动力学状态:", "create.gui.goggles.at_current_speed": "当前速度应力值", "create.gui.goggles.pole_length": "活塞杆长度:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "仪表信息:", "create.gui.speedometer.title": "旋转速度", "create.gui.stressometer.title": "网络应力", 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 8fa416308..4a9a17215 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: 8", + "_": "Missing Localizations: 14", "_": "->------------------------] Game Elements [------------------------<-", @@ -823,6 +823,12 @@ "create.gui.goggles.kinetic_stats": "機械學狀態:", "create.gui.goggles.at_current_speed": "現在速度動能值", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", + "create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:", + "create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk", + "create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s", + "create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles", "create.gui.gauge.info_header": "儀表訊息:", "create.gui.speedometer.title": "旋轉速度", "create.gui.stressometer.title": "網路動能", 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/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/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 51f5007e5..e698cfe85 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; @@ -16,7 +16,11 @@ import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.item.CustomItemModels; import com.simibubi.create.foundation.item.CustomRenderedItems; -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; @@ -42,7 +46,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; @@ -56,16 +62,23 @@ 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); + + ghostBlocks = new GhostBlocks(); AllKeys.register(); AllContainerTypes.registerScreenFactories(); @@ -171,4 +184,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/category/animations/AnimatedKinetics.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java index 33fe15a29..2ff8f46ad 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedKinetics.java @@ -6,14 +6,13 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder; import mezz.jei.api.gui.drawable.IDrawable; import net.minecraft.block.BlockState; -import net.minecraft.client.Minecraft; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction.Axis; public abstract class AnimatedKinetics implements IDrawable { public static float getCurrentAngle() { - return ((AnimationTickHolder.ticks + Minecraft.getInstance().getRenderPartialTicks()) * 4f) % 360; + return ((AnimationTickHolder.getRenderTick()) * 4f) % 360; } protected BlockState shaft(Axis axis) { diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java index 4bafd18ed..849e95121 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedPress.java @@ -1,13 +1,11 @@ package com.simibubi.create.compat.jei.category.animations; -import static com.simibubi.create.foundation.utility.AnimationTickHolder.ticks; - import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.utility.AnimationTickHolder; -import net.minecraft.client.Minecraft; import net.minecraft.util.Direction.Axis; public class AnimatedPress extends AnimatedKinetics { @@ -50,8 +48,7 @@ public class AnimatedPress extends AnimatedKinetics { } private float getAnimatedHeadOffset() { - float cycle = (ticks + Minecraft.getInstance() - .getRenderPartialTicks()) % 30; + float cycle = (AnimationTickHolder.getRenderTick()) % 30; if (cycle < 10) { float progress = cycle / 10; return -(progress * progress * progress); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java index 32869ff0a..d39255552 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedSpout.java @@ -1,7 +1,5 @@ package com.simibubi.create.compat.jei.category.animations; -import static com.simibubi.create.foundation.utility.AnimationTickHolder.ticks; - import java.util.List; import com.mojang.blaze3d.matrix.MatrixStack; @@ -10,8 +8,8 @@ import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.fluid.FluidRenderer; import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.utility.AnimationTickHolder; -import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.IRenderTypeBuffer.Impl; import net.minecraft.client.renderer.Tessellator; @@ -39,8 +37,7 @@ public class AnimatedSpout extends AnimatedKinetics { .scale(scale) .render(); - float cycle = (ticks + Minecraft.getInstance() - .getRenderPartialTicks()) % 30; + float cycle = AnimationTickHolder.getRenderTick() % 30; float squeeze = cycle < 20 ? MathHelper.sin((float) (cycle / 20f * Math.PI)) : 0; squeeze *= 20; diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java new file mode 100644 index 000000000..0d566b45f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.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 BackHalfShaftInstance extends HalfShaftInstance { + public static void register(TileEntityType 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 a7d96c5be..f99113046 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; @@ -245,6 +252,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 +475,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 +496,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 +523,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 +538,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 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 { + 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 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/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 ebe0aaa57..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 @@ -413,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..26130afe4 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; @@ -597,6 +598,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/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/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/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 5ca7b26e6..dd314bfe6 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 () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); return ActionResultType.SUCCESS; } 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/BeltInventory.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java index 1284afba9..fed661dd6 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 @@ -286,9 +286,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/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..df6b20f6f 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 @@ -28,7 +28,7 @@ public class SimpleKineticTileEntity 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/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/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/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/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 6ff99a9dc..1407b4d1e 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -1,5 +1,8 @@ package com.simibubi.create.events; +import java.util.ArrayList; +import java.util.List; + import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllFluids; @@ -8,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; @@ -25,6 +29,8 @@ import com.simibubi.create.foundation.gui.ScreenOpener; 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.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; @@ -33,15 +39,18 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollVal import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.placement.PlacementHelpers; + 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; @@ -57,9 +66,6 @@ import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import java.util.ArrayList; -import java.util.List; - @EventBusSubscriber(value = Dist.CLIENT) public class ClientEvents { @@ -72,11 +78,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(); @@ -104,30 +111,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 @@ -173,6 +201,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/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/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 5528f791b..99fb3c017 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -79,6 +79,9 @@ public enum AllGuiTextures { INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6), INDICATOR_RED("widgets.png", 72, 18, 18, 6), + // 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/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 76% 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 f37b65912..ef25a5e2d 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) { @@ -108,19 +101,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..055e5dac7 --- /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().stream().filter(TileEntity::isRemoved).forEach(instances::remove); + } + + 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/VecHelper.java b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java index d5cac157a..1e620ec07 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; @@ -145,4 +151,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/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 98de531a9..d70fcdb5c 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -23,4 +23,25 @@ public net.minecraft.tileentity.BeaconTileEntity field_174909_f # beamSegments # Server Tick List (For stopping placed fluids from spilling) public net.minecraft.world.server.ServerTickList field_205374_d # pendingTickListEntriesHashSet -public net.minecraft.world.server.ServerTickList field_205375_e # pendingTickListEntriesTreeSet \ No newline at end of file +public net.minecraft.world.server.ServerTickList field_205375_e # pendingTickListEntriesTreeSet + +# 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 \ No newline at end of file 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/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/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/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/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/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