diff --git a/.gitignore b/.gitignore index 0123b6707..d785bb5c1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ gradle-app.setting ## IntelliJ IDEA .idea/ +out/ *.iml *.iws *.ipr diff --git a/README.md b/README.md index a7fc50bd6..5266e021c 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -

Logo

-

Create
- Patreon +

Logo

+

Create
+ Patreon Supported Versions License - Discord - Curseforge Downloads

+ Discord + CF

Welcome to Create, a mod offering a variety of tools and blocks for Building, Decoration and Aesthetic Automation. @@ -13,7 +13,7 @@ The added elements of tech are designed to leave as many design choices to the p Check out the wiki and in-game Tool-tips for further info on how to use these features, and stay tuned for an ever-growing selection of possibilities for Creative and Survival Minecraft. -[](https://github.com/simibubi/Create/issues "Report Issues") +[](https://github.com/Creators-of-Create/Create/issues "Report Issues") [](https://www.youtube.com/playlist?list=PLyADkcfPLU8ywCXZPaDbQ_JZJL0CGDN5Z "Watch Videos") [](https://discord.gg/hmaD7Se "Feedback & Help") [](https://www.patreon.com/simibubi "Support Us") diff --git a/build.gradle b/build.gradle index ff291cd2a..ef226ded6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,23 +1,24 @@ buildscript { repositories { - maven { url = 'https://files.minecraftforge.net/maven' } - jcenter() + maven { url = 'https://maven.minecraftforge.net' } mavenCentral() - maven { url='https://repo.spongepowered.org/repository/maven-public/' } + jcenter() + maven { url = 'https://repo.spongepowered.org/repository/maven-public/' } } dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true - classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT' + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: "${forgegradle_version}", changing: true + classpath group: 'org.spongepowered', name: 'mixingradle', version: "${mixingradle_version}" } } plugins { - id 'com.github.johnrengelman.shadow' version '5.2.0' - id 'com.matthewprenger.cursegradle' version '1.4.0' + id 'com.github.johnrengelman.shadow' version "${shadow_version}" + id 'com.matthewprenger.cursegradle' version "${cursegradle_version}" } apply plugin: 'net.minecraftforge.gradle' // Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. apply plugin: 'eclipse' apply plugin: 'maven-publish' +apply plugin: 'org.spongepowered.mixin' boolean dev = System.getenv('RELEASE') == null || System.getenv('RELEASE').equals('false'); @@ -32,15 +33,16 @@ sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = co minecraft { mappings channel: 'snapshot', version: '20200920-mixed-1.16.3' - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') runs { - client { + client { workingDirectory project.file('run') arg '-mixin.config=create.mixins.json' //jvmArgs '-XX:+UnlockCommercialFeatures' // uncomment for profiling property 'forge.logging.console.level', 'info' property 'fml.earlyprogresswindow', 'false' + property 'mixin.env.disableRefMap', 'true' mods { create { source sourceSets.main @@ -82,30 +84,37 @@ sourceSets.main.resources { srcDir 'src/generated/resources' } +mixin { + add sourceSets.main, "create.refmap.json" +} + repositories { maven { // location of the maven that hosts JEI files (And TiC) - name "Progwml6 maven" - url "https://dvs1.progwml6.com/files/maven/" + name = "Progwml6 maven" + url = "https://dvs1.progwml6.com/files/maven/" } /* maven { // location of a maven mirror for JEI files, as a fallback - name "ModMaven" - url "https://modmaven.k-4u.nl" + name = "ModMaven" + url = "https://modmaven.k-4u.nl" }*/ maven { //location of the maven for vazkii's mods - name "blamejared" - url "http://maven.blamejared.com/" + name = "blamejared" + url = "http://maven.blamejared.com/" } maven { //location of the maven for mixed mappings and registrate - name = "tterrag maven" - url = "https://maven.tterrag.com/" + name "tterrag maven" + url "https://maven.tterrag.com/" } maven { - url = "https://www.cursemaven.com" + url "https://www.cursemaven.com" + content { + includeGroup "curse.maven" + } } maven { //location of the maven for dynamic trees @@ -120,14 +129,20 @@ configurations { dependencies { minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" - def registrate = "com.tterrag.registrate:Registrate:MC1.16.2-${registrate_version}" + def registrate = "com.tterrag.registrate:Registrate:MC1.16.5-${registrate_version}" implementation fg.deobf(registrate) shade registrate // compile against the JEI API but do not include it at runtime - compileOnly fg.deobf("mezz.jei:jei-1.16.4:${jei_version}:api") + compileOnly fg.deobf("mezz.jei:jei-1.16.5:${jei_version}:api") // at runtime, use the full JEI jar - runtimeOnly fg.deobf("mezz.jei:jei-1.16.4:${jei_version}") + runtimeOnly fg.deobf("mezz.jei:jei-1.16.5:${jei_version}") + + if (findProject(':Flywheel') != null) { + compile project(':Flywheel') // jozu: I use a gradle workspace with both projects + } else { + compile fg.deobf("com.jozufozu.flywheel:Flywheel:1.16-0.0.2.8") + } // implementation fg.deobf("curse.maven:druidcraft-340991:3101903") implementation fg.deobf("com.ferreusveritas.dynamictrees:DynamicTrees-1.16.5:0.10.0-Beta12.1") @@ -136,10 +151,10 @@ 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") - // runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.3-1.6.40") - // runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.3-3.0.1.24") + //runtimeOnly fg.deobf("slimeknights.mantle:Mantle:1.16.5-1.6.103") + //runtimeOnly fg.deobf("slimeknights.tconstruct:TConstruct:1.16.5-3.0.3.168") - annotationProcessor 'org.spongepowered:mixin:0.8:processor' + annotationProcessor 'org.spongepowered:mixin:0.8.2:processor' } jar { @@ -218,13 +233,7 @@ curseforge { displayName = "Create - ${version}" } relations { - optionalDependency 'jei' + optionalDependency 'jei' } } } - -apply plugin: 'org.spongepowered.mixin' - -mixin { - add sourceSets.main, "create.refmap.json" -} diff --git a/gradle.properties b/gradle.properties index 6f4a1d878..4798b9ca7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,20 +1,26 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. -org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false +org.gradle.jvmargs = -Xmx3G +org.gradle.daemon = false # mod version info -mod_version=0.3.1c -minecraft_version=1.16.5 -forge_version=36.0.42 +mod_version = 0.3.2 +minecraft_version = 1.16.5 +forge_version = 36.1.32 + +# build dependency versions +forgegradle_version = 3.+ +mixingradle_version = 0.7-SNAPSHOT +shadow_version = 5.2.0 +cursegradle_version = 1.4.0 # dependency versions -registrate_version=1.0.0-beta.33 -jei_version=7.6.1.71 +registrate_version = 1.0.4 +jei_version = 7.7.0.106 # curseforge information -projectId=328085 -curse_type=beta +projectId = 328085 +curse_type = beta # github information -github_project=Creators-of-Create/Create +github_project = Creators-of-Create/Create diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7a3265ee9..5c2d1cf01 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a055b814c..5028f28f8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.3-bin.zip diff --git a/gradlew b/gradlew index cccdd3d51..83f2acfdc 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -109,8 +125,8 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` diff --git a/gradlew.bat b/gradlew.bat index f9553162f..9618d8d96 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -14,7 +30,7 @@ set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome diff --git a/src/generated/resources/.cache/cache b/src/generated/resources/.cache/cache index 7f62cb3f8..41feaf092 100644 --- a/src/generated/resources/.cache/cache +++ b/src/generated/resources/.cache/cache @@ -407,21 +407,21 @@ a3a11524cd3515fc01d905767b4b7ea782adaf03 assets/create/blockstates/yellow_seat.j 6801fa1f466f172700e573e5b8ee8ee5f9ca4583 assets/create/blockstates/yellow_valve_handle.json 7f39521b211441f5c3e06d60c5978cebe16cacfb assets/create/blockstates/zinc_block.json b7181bcd8182b2f17088e5aa881f374c9c65470c assets/create/blockstates/zinc_ore.json -a6d814f94926d88764c38862cc4ece9c367e023b assets/create/lang/en_ud.json -d1838140c8383ee4537db90eb8f657d0c268fe91 assets/create/lang/en_us.json -9d6f26ca7b59d3707ce996e513358cc9b873cad1 assets/create/lang/unfinished/de_de.json -7fafb7565349aa52f4ccb829d4886a179eb547dc assets/create/lang/unfinished/es_es.json -822b912d290d40c5f02011393af44bf37684f9b4 assets/create/lang/unfinished/es_mx.json -502d761465a0de7aeb15acec4147b8ec8bee92cf assets/create/lang/unfinished/fr_fr.json -dac15c17578fb37bbdb874cee5a0a078110b7481 assets/create/lang/unfinished/it_it.json -fd270c9c8bc46d4df21aa04ecc7bf059011e4b3e assets/create/lang/unfinished/ja_jp.json -a5b002e047a2f509a8d35b9e638627f970b4810e assets/create/lang/unfinished/ko_kr.json -50f65aaba8c4fec5404ab1fc40f74b4970a55edd assets/create/lang/unfinished/nl_nl.json -ff61e567f15ded6ba127522af03860232069cdd2 assets/create/lang/unfinished/pl_pl.json -a7a28fb3896bc38e00f746e650433160f5b53c90 assets/create/lang/unfinished/pt_br.json -ffa1901b392719634403048419d29b268704bd10 assets/create/lang/unfinished/ru_ru.json -38b843c5232167876b3678328b47ec95f30cf69f assets/create/lang/unfinished/zh_cn.json -b806d1e6fe9ebee27f417a3c4d6c818124ee4cde assets/create/lang/unfinished/zh_tw.json +c71f5246d2cb8e9913d1552d23fcc82c43cde7a0 assets/create/lang/en_ud.json +0352f128a214a76365bae7365d7904536ffccbba assets/create/lang/en_us.json +d2fe2b5beb7c4b7d05842dc45da6630dd1f0611f assets/create/lang/unfinished/de_de.json +a486966e82368a85f4c6c5c6b4fd17b0b6e260b4 assets/create/lang/unfinished/es_es.json +94c05715d19c5ceced368c4aa4307b5184eb9d0f assets/create/lang/unfinished/es_mx.json +44fe3efbe33085dc4248ba7ee94e35065aab5cca assets/create/lang/unfinished/fr_fr.json +c53beea261e7a64bdbe397481a2010bb166b10ce assets/create/lang/unfinished/it_it.json +2d75e6eb0c1683ef4856acf86b4f1e49d9e7b9b2 assets/create/lang/unfinished/ja_jp.json +a0d8634f363ee47f3e5ac568d5b63cc6e25a4267 assets/create/lang/unfinished/ko_kr.json +75e6dcc51ef14e39fd7ec1a87a0bbc945ef12637 assets/create/lang/unfinished/nl_nl.json +93b883e54947c1a1869984bc4e764c34b7055998 assets/create/lang/unfinished/pl_pl.json +fc093fa80821bfc4076261dcf1ec56c21edc2262 assets/create/lang/unfinished/pt_br.json +c5b4013e8758f6bfde86eb2d25ec920b5d25c7d1 assets/create/lang/unfinished/ru_ru.json +5bb493fd0d4a05d4b83db99eacea460cb96f8f1a assets/create/lang/unfinished/zh_cn.json +9c049cc88deb8b319c6de28caa417eea9baa7f79 assets/create/lang/unfinished/zh_tw.json 487a511a01b2a4531fb672f917922312db78f958 assets/create/models/block/acacia_window.json b48060cba1a382f373a05bf0039054053eccf076 assets/create/models/block/acacia_window_pane_noside.json 3066db1bf03cffa1a9c7fbacf47ae586632f4eb3 assets/create/models/block/acacia_window_pane_noside_alt.json @@ -1273,6 +1273,7 @@ d7cb2f7bac8fae893fc5179af8140786a908f3f5 assets/create/models/item/copper_shingl f56bf22324faf8958eaef4d94b958f1108d52e5a assets/create/models/item/copper_tiles.json 5583368909c319acfcf0f7a419bedf23272fe613 assets/create/models/item/copper_valve_handle.json 4e253e7c0626dfd76e2d39786ce1a34e0baaa62d assets/create/models/item/crafter_slot_cover.json +1f947dafff30da701b7675f5b026ccab3129b079 assets/create/models/item/crafting_blueprint.json 7b333dea353afaa27b182aedc647c9e9e34e92ef assets/create/models/item/creative_crate.json f7d06c52c3ca8c22ad67f5741471f06ac22e7fcb assets/create/models/item/creative_fluid_tank.json 5b39403f6c81f05e566b621b62e267267de47c41 assets/create/models/item/creative_motor.json @@ -1452,6 +1453,7 @@ ebdf23b99b7895e347c29057c8070a6e16e56beb assets/create/models/item/limestone_cob 288da8b29a4e9d0d0b694567a61b5a816a2859b8 assets/create/models/item/limestone_cobblestone_wall.json 8065de871ad2fbaed711735561b8ed91a2ce0004 assets/create/models/item/limestone_pillar.json d245aa4994ff197b1ffeb7980d05f96bd20cdeb3 assets/create/models/item/linear_chassis.json +2866bff509b060cd3ee99b4eef25a4e1e4639703 assets/create/models/item/linked_controller.json d912be3e87f2beaa8e22747f867739139667241b assets/create/models/item/magenta_seat.json 928c5e3747fb758d2610475258cc168b0d4ee7b6 assets/create/models/item/magenta_valve_handle.json 932facf4bf93b471e8630f4132a4284a9f4d0d39 assets/create/models/item/mechanical_arm.json @@ -1651,7 +1653,7 @@ d080b1b25e5bc8baf5aee68691b08c7f12ece3b0 assets/create/models/item/windmill_bear 866fbb0ce2878a73e0440d1caf6534c8bd7c384f assets/create/models/item/zinc_ingot.json a80fb25a0b655e76be986b5b49fcb0f03461a1ab assets/create/models/item/zinc_nugget.json b1689617190c05ef34bd18456b0c7ae09bb3210f assets/create/models/item/zinc_ore.json -096382a4c025b5ffdde9c496ee9da0d5345fbe17 assets/create/sounds.json +6490fa0587db770cf7c794b47f3bcd2b691f4226 assets/create/sounds.json 0f1b4b980afba9bf2caf583b88e261bba8b10313 data/create/advancements/aesthetics.json 187921fa131b06721bfaf63f2623a28c141aae9a data/create/advancements/andesite_alloy.json 0ea2db7173b5be28b289ea7c9a6a0cf5805c60c7 data/create/advancements/andesite_casing.json @@ -1712,6 +1714,7 @@ c9c4060ed207226b69fada2d61e01a97d7077eae data/create/advancements/nixie_tube.jso 4b621e5bb48fbb120853ec02c05c915d86bd6dd8 data/create/advancements/pipe_spill.json 72025d8bf73ab8096c29f12d0c8d9a346f09cd64 data/create/advancements/polished_rose_quartz.json 62d29ec01eff5d21968636a0479361ecdc11ae30 data/create/advancements/press.json +f80479b50e248ee8d6d1abb7d08866cf711ac2b2 data/create/advancements/recipes/building_blocks/andesite.json 5012e9d559439d0d62d0b34c2e39de048e8c7699 data/create/advancements/recipes/building_blocks/blasting/aluminum_ingot_compat_silents_mechanisms.json 2e253226c408dffb9dfb828b846f70ebd1cfb16e data/create/advancements/recipes/building_blocks/blasting/ingot_aluminum_compat_immersiveengineering.json 3f022f89aeb5034f2292ca71daa9f311e8af40ff data/create/advancements/recipes/building_blocks/blasting/ingot_lead_compat_immersiveengineering.json @@ -1738,6 +1741,8 @@ a61045a27757950d96fee77768bfd96f935f98b2 data/create/advancements/recipes/buildi a75f1162ac89cd50a1ca8e525dd059fb359a6550 data/create/advancements/recipes/building_blocks/blasting/tin_ingot_compat_silents_mechanisms.json 230c3da350aa45524712d5dd28b84aa59b2883e9 data/create/advancements/recipes/building_blocks/blasting/tin_ingot_compat_thermal.json 38410d4b3bbbf33c1c8913735abd1b3d71fb3829 data/create/advancements/recipes/building_blocks/blasting/uranium_ingot_compat_silents_mechanisms.json +8850272a97541e331482531c52cc94197fe808be data/create/advancements/recipes/building_blocks/diorite.json +0abb698cabe5f71675773e5eeadeccb509f1cb90 data/create/advancements/recipes/building_blocks/granite.json 22067545c460d95831d9dddf361da9becac3396e data/create/advancements/recipes/building_blocks/smelting/aluminum_ingot_compat_silents_mechanisms.json e525d8eda8d0aac6791ae935ed4f3f75cc521460 data/create/advancements/recipes/building_blocks/smelting/glass_from_framed_glass.json 295c5a61d6f175a65d25e19cbd7ca90d3b4a93b2 data/create/advancements/recipes/building_blocks/smelting/glass_from_horizontal_framed_glass.json @@ -1774,9 +1779,11 @@ c368cadffa9177fefb9e92ff4453b40bc8dd670d data/create/advancements/recipes/create 8fffce2a5c5dd88d52e3b006fa92fb18cf2f1571 data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_crushed.json 4bb60ef5e186f12a9d52e61319db8c78300c64ab data/create/advancements/recipes/create.base/blasting/zinc_ingot_from_ore.json d1d8cf6e1c95b7d99bf873fa6fee033103f995fd data/create/advancements/recipes/create.base/crafting/appliances/copper_backtank.json +f2dc28c600011e6e8e515cb4d56118b1bd45b743 data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json 46c04e685ab345a80598176f7ac68a044a76cd76 data/create/advancements/recipes/create.base/crafting/appliances/diving_boots.json 5f06b7dcf2af11f30c2e10ade4ac3fd172bc04df data/create/advancements/recipes/create.base/crafting/appliances/diving_helmet.json dd487f98c411f1ff22cb7fc208b8cc24b27deb2f data/create/advancements/recipes/create.base/crafting/appliances/dough.json +911159091a9674c36e8cd49f56f63e5442988e84 data/create/advancements/recipes/create.base/crafting/appliances/linked_controller.json 51cdcf168087f47e4458eed7543d227da1ee5ca0 data/create/advancements/recipes/create.base/crafting/appliances/tree_fertilizer.json d531f87f425d199aee4777a588c1cd6cab6f5173 data/create/advancements/recipes/create.base/crafting/curiosities/minecart_coupling.json 2eef3201017af03f6a2f0f015645e3ff5e25d9c1 data/create/advancements/recipes/create.base/crafting/curiosities/wand_of_symmetry.json @@ -1975,7 +1982,7 @@ bfb3673a30db807aa298f2fd128ec863a65818af data/create/advancements/recipes/create 47cc716674e1741f4115b04a20ac4c4a5b2a6d8a data/create/advancements/recipes/create.palettes/andesite_cobblestone_stairs_from_andesite_cobblestone_stonecutting.json bd79e63c29d68fbf87ded63ac1eedba3d7287996 data/create/advancements/recipes/create.palettes/andesite_cobblestone_wall.json 0ed4c084f05b2bd4c134293ad3554d6e31a1d568 data/create/advancements/recipes/create.palettes/andesite_cobblestone_wall_from_andesite_cobblestone_stonecutting.json -a453d05704cadb3279318192aac87e623738cdaa data/create/advancements/recipes/create.palettes/andesite_pillar.json +cc8e078ccce06e9489d8b62d88b6a2e4d4ca2d79 data/create/advancements/recipes/create.palettes/andesite_pillar.json d6f31097aef040e12eb288ab755d459f55269a70 data/create/advancements/recipes/create.palettes/andesite_pillar_from_andesite_stonecutting.json f10a4369147cc5e36d3ab1b0008d29fd36ffc8f6 data/create/advancements/recipes/create.palettes/birch_window.json bfea45da3f8df1c63f6c7ff1b63ad7e08c1d44b0 data/create/advancements/recipes/create.palettes/birch_window_pane.json @@ -1990,6 +1997,7 @@ b4651c8202331483e82b28b04edc6cd97e62ad1d data/create/advancements/recipes/create b2813566e6715c2d377dd4ef461b012cae7eb190 data/create/advancements/recipes/create.palettes/crimson_window_pane.json 25991d5667252d551e02c4fbbfa27ebf4353d28d data/create/advancements/recipes/create.palettes/dark_oak_window.json 4819383b1a7885b4401fdc25955d2c51f75b6236 data/create/advancements/recipes/create.palettes/dark_oak_window_pane.json +02cd339174aaf2c14e14f886d90fbbcae91783b6 data/create/advancements/recipes/create.palettes/dark_scoria.json ebd6413d530325eef6fcf42a0ee0ac840c1f7366 data/create/advancements/recipes/create.palettes/dark_scoria_bricks_from_dark_scoria_stonecutting.json 030ce9b61b8af158cf54e7a9ab673ccb7251483f data/create/advancements/recipes/create.palettes/dark_scoria_bricks_slab.json ac44d03859cfd4c00ddcbd1dafbb9acc51d849d7 data/create/advancements/recipes/create.palettes/dark_scoria_bricks_slab_from_dark_scoria_bricks_stonecutting.json @@ -2004,7 +2012,7 @@ eef6f85b20fb997af1b0c2383a45100be2e0cd34 data/create/advancements/recipes/create 8d44f675237a92513678a77da7a1f329475a3453 data/create/advancements/recipes/create.palettes/dark_scoria_cobblestone_stairs_from_dark_scoria_cobblestone_stonecutting.json 702527e6735770a6fcc3ad446df39d3b1b80709e data/create/advancements/recipes/create.palettes/dark_scoria_cobblestone_wall.json ce069a666d223f733bfa1cc9ca5e3e5e27de1ebc data/create/advancements/recipes/create.palettes/dark_scoria_cobblestone_wall_from_dark_scoria_cobblestone_stonecutting.json -c5d7f1e79302d47ea02cb63b99b286b90ec0287b data/create/advancements/recipes/create.palettes/dark_scoria_pillar.json +64f9ba8df2fd2357ad397b75156a4af9c26fa91b data/create/advancements/recipes/create.palettes/dark_scoria_pillar.json f3d6314d272d84c456c5df512dcc555b7694ded2 data/create/advancements/recipes/create.palettes/dark_scoria_pillar_from_dark_scoria_stonecutting.json 83e3c29d5d651a6bc6fd9d5843d8d75f4cda2b77 data/create/advancements/recipes/create.palettes/diorite_bricks_from_diorite_stonecutting.json 4649497555ca4269b1f3859f0275ca1ff7c85377 data/create/advancements/recipes/create.palettes/diorite_bricks_slab.json @@ -2020,8 +2028,9 @@ f3d6314d272d84c456c5df512dcc555b7694ded2 data/create/advancements/recipes/create 600c57c4dc3a3741d5db7ec01340e1c6a01d54b4 data/create/advancements/recipes/create.palettes/diorite_cobblestone_stairs_from_diorite_cobblestone_stonecutting.json 8b4990d3657e23a86c3e71eba77370c56692c93b data/create/advancements/recipes/create.palettes/diorite_cobblestone_wall.json e741ca0e76875ee12beecd45db764444956d5342 data/create/advancements/recipes/create.palettes/diorite_cobblestone_wall_from_diorite_cobblestone_stonecutting.json -9edb9886a6b2792dc38d5d61a2be2b7a3fd28eeb data/create/advancements/recipes/create.palettes/diorite_pillar.json +08e8495b798d54366f132da060e93e94e23f6354 data/create/advancements/recipes/create.palettes/diorite_pillar.json 87d34b8ca3dc73a778ab94ef4d852f418112adb3 data/create/advancements/recipes/create.palettes/diorite_pillar_from_diorite_stonecutting.json +17135274809b7a0f38294d2e6412b787e985e4d5 data/create/advancements/recipes/create.palettes/dolomite.json dbf201ceafc310f5cc6624c81777d50348844285 data/create/advancements/recipes/create.palettes/dolomite_bricks_from_dolomite_stonecutting.json 6716447628cce96a1f520766d019f09380ec67e5 data/create/advancements/recipes/create.palettes/dolomite_bricks_slab.json 52ae39c6f63860fa5a60c1ae70ef00eca5b961c9 data/create/advancements/recipes/create.palettes/dolomite_bricks_slab_from_dolomite_bricks_stonecutting.json @@ -2036,7 +2045,7 @@ a8904096a05eeb7e746563e1a4b97b39173d1708 data/create/advancements/recipes/create 124c586970edc5c15079bec53c734a2beb670130 data/create/advancements/recipes/create.palettes/dolomite_cobblestone_stairs_from_dolomite_cobblestone_stonecutting.json 2e9f1556a11d4d7190233be3af64453396865da9 data/create/advancements/recipes/create.palettes/dolomite_cobblestone_wall.json 1a1e8764ba05f72ffd7e5872a8f2fc9cf2108308 data/create/advancements/recipes/create.palettes/dolomite_cobblestone_wall_from_dolomite_cobblestone_stonecutting.json -4652a46d4b6590b988d57d855def253ebeb380fe data/create/advancements/recipes/create.palettes/dolomite_pillar.json +4b56a0490151fbc66dee82546b9e271a5a85fa12 data/create/advancements/recipes/create.palettes/dolomite_pillar.json a8752ee9bf9afc665c5d940d251c1cf4a83a0ae9 data/create/advancements/recipes/create.palettes/dolomite_pillar_from_dolomite_stonecutting.json ea981a446d8cc22d6b7fb4667e86dc18a48a4720 data/create/advancements/recipes/create.palettes/fancy_andesite_bricks_from_andesite_stonecutting.json 44dc6bc5a7303129db2268a025f49dcb222597a7 data/create/advancements/recipes/create.palettes/fancy_andesite_bricks_slab.json @@ -2103,6 +2112,7 @@ d51bee4b276805ecf1a93a37ec6d610e75c0117e data/create/advancements/recipes/create 17e02efc06d935c094bde5bb73a5127bc98e4758 data/create/advancements/recipes/create.palettes/fancy_weathered_limestone_bricks_wall_from_fancy_weathered_limestone_bricks_stonecutting.json 05331b5f1701453ecdfd0b3e6429b22ec209ba67 data/create/advancements/recipes/create.palettes/framed_glass_from_glass_colorless_stonecutting.json 605476eaf4e964936c031732cfef534edfdd749a data/create/advancements/recipes/create.palettes/framed_glass_pane.json +1b17b217e487b958e35ab0ad509bb8caceebda40 data/create/advancements/recipes/create.palettes/gabbro.json b835dd583d670e2d7f6af4dd74e44f5817b03b21 data/create/advancements/recipes/create.palettes/gabbro_bricks_from_gabbro_stonecutting.json 2bfac04754aaf07423b330134984d887ae43f00a data/create/advancements/recipes/create.palettes/gabbro_bricks_slab.json f05bb35d52866abc7dae9c7f3f5fc85257760564 data/create/advancements/recipes/create.palettes/gabbro_bricks_slab_from_gabbro_bricks_stonecutting.json @@ -2117,7 +2127,7 @@ c90a07c41b2e034437c8a765de7b517f89383830 data/create/advancements/recipes/create f9d917def55875dcba621246f80dc83904be3d73 data/create/advancements/recipes/create.palettes/gabbro_cobblestone_stairs_from_gabbro_cobblestone_stonecutting.json b081b91a5e11e8ce9b2455b944eb554f5f2e419e data/create/advancements/recipes/create.palettes/gabbro_cobblestone_wall.json 093f372d84c557791cebcb286b3505f32c4dc7c0 data/create/advancements/recipes/create.palettes/gabbro_cobblestone_wall_from_gabbro_cobblestone_stonecutting.json -dacb04ebd8bc20c2a0689a9e75ea67c07e43c56b data/create/advancements/recipes/create.palettes/gabbro_pillar.json +4b0f4a396397a791d08fe422fb4cfb922554779c data/create/advancements/recipes/create.palettes/gabbro_pillar.json 35288551f5146ebbf8dbbe987928dd2a1bdc7ea8 data/create/advancements/recipes/create.palettes/gabbro_pillar_from_gabbro_stonecutting.json 6a9a8b37ec264084ce0481200225017739546025 data/create/advancements/recipes/create.palettes/granite_bricks_from_granite_stonecutting.json 2ac84cb0b8b629bdfd740a6613df2a7e45964bf2 data/create/advancements/recipes/create.palettes/granite_bricks_slab.json @@ -2133,7 +2143,7 @@ c39e86c111a2c76ef9cb7046d2b87262524b06b9 data/create/advancements/recipes/create 06d3f3150db99f808a5fd4141c0fc6235d979ce5 data/create/advancements/recipes/create.palettes/granite_cobblestone_stairs_from_granite_cobblestone_stonecutting.json 6bbc97d2ac655a532eaf345fca64431dbf8af27d data/create/advancements/recipes/create.palettes/granite_cobblestone_wall.json d6b622a2cf302d0c39e0d38d24b0a17e1461d13b data/create/advancements/recipes/create.palettes/granite_cobblestone_wall_from_granite_cobblestone_stonecutting.json -03c3a88e1a320afe9866a1c09ef34b46763c8ec1 data/create/advancements/recipes/create.palettes/granite_pillar.json +5b9fe440648ae9f37b5d079cfcd1d9a72afa74fa data/create/advancements/recipes/create.palettes/granite_pillar.json 97cc61b1b510849ebc0bf51cf2b8107a5c43fc17 data/create/advancements/recipes/create.palettes/granite_pillar_from_granite_stonecutting.json cbb40e82dba460ee126966a52f0164e740ac1f11 data/create/advancements/recipes/create.palettes/horizontal_framed_glass_from_glass_colorless_stonecutting.json 29e2e2aeca3800c8ba432be30d54d046a3991217 data/create/advancements/recipes/create.palettes/horizontal_framed_glass_pane.json @@ -2148,6 +2158,7 @@ cbb40e82dba460ee126966a52f0164e740ac1f11 data/create/advancements/recipes/create c0dd961f07e85a183af7b942ed0e4bfe8f775373 data/create/advancements/recipes/create.palettes/layered_limestone_from_limestone_stonecutting.json 5d06584a83074f8a8d1a52d93d13f2718bc99152 data/create/advancements/recipes/create.palettes/layered_scoria_from_scoria_stonecutting.json b09e64b4989ef08b7ea6b9011681c2fbf780d949 data/create/advancements/recipes/create.palettes/layered_weathered_limestone_from_weathered_limestone_stonecutting.json +519234f31ee8cacc0f916df40703ba171c6a90e5 data/create/advancements/recipes/create.palettes/limestone.json 52c1902f260173fe610a4a03294a51c4cea3b37b data/create/advancements/recipes/create.palettes/limestone_bricks_from_limestone_stonecutting.json e6eb6c433541b7c4e3e5b64f240618e6df67ed58 data/create/advancements/recipes/create.palettes/limestone_bricks_slab.json 72f0586690ca4413082b2cbecf7938ba6e4756b4 data/create/advancements/recipes/create.palettes/limestone_bricks_slab_from_limestone_bricks_stonecutting.json @@ -2162,7 +2173,7 @@ d7b36c7fcf429eea7c57f2ae967e73b8e18d0d58 data/create/advancements/recipes/create 749936c7c33273c1833154a1eb1e13604ece8565 data/create/advancements/recipes/create.palettes/limestone_cobblestone_stairs_from_limestone_cobblestone_stonecutting.json c0e3f97a6f807ea8147f58bf4ca002725d1877b6 data/create/advancements/recipes/create.palettes/limestone_cobblestone_wall.json a01c91b927f50d367c3bfcca5f370002a991d45a data/create/advancements/recipes/create.palettes/limestone_cobblestone_wall_from_limestone_cobblestone_stonecutting.json -8b1ef23c71f0088230dcdd12374494bfdf700409 data/create/advancements/recipes/create.palettes/limestone_pillar.json +acf08b6a32e3678d63443fdb97e7332e05eb61f6 data/create/advancements/recipes/create.palettes/limestone_pillar.json d040f53dfb09a29c39d534d3595e35d058fe5557 data/create/advancements/recipes/create.palettes/limestone_pillar_from_limestone_stonecutting.json 3ee8ab0478344042136058be6cf870289c096bdd data/create/advancements/recipes/create.palettes/mossy_andesite_from_andesite_stonecutting.json c427e2626e468abee6fb4de83bf76f2d3c051449 data/create/advancements/recipes/create.palettes/mossy_dark_scoria_from_dark_scoria_stonecutting.json @@ -2297,6 +2308,7 @@ e46847d02ab7bfb2bc1da1a4ad4b7b54a3a28559 data/create/advancements/recipes/create 75480d0c13a80d9edf93a0eff947e5165db011c1 data/create/advancements/recipes/create.palettes/polished_weathered_limestone_stairs_from_polished_weathered_limestone_stonecutting.json 7b4b27211174e774169132a50da7bfd63ff28b30 data/create/advancements/recipes/create.palettes/polished_weathered_limestone_wall.json 81a759d9b069faedee49107642d947ea1bf1ac6c data/create/advancements/recipes/create.palettes/polished_weathered_limestone_wall_from_polished_weathered_limestone_stonecutting.json +28c7dd5fb1594295f977eff41ac677aab9660831 data/create/advancements/recipes/create.palettes/scoria.json 874023eabafb85aefacc86f395c5d4ef0cc9cfac data/create/advancements/recipes/create.palettes/scoria_bricks_from_scoria_stonecutting.json a9969fd00f8cba428715d27a8ab6af6ba6473c8a data/create/advancements/recipes/create.palettes/scoria_bricks_slab.json 1d129bb8d359de50344dcb46f77899b0651d7817 data/create/advancements/recipes/create.palettes/scoria_bricks_slab_from_scoria_bricks_stonecutting.json @@ -2311,7 +2323,7 @@ dc5df4f4feddc24a7c78b25b6ed3e7ed458342f1 data/create/advancements/recipes/create b852a9a59499c113f387ac06fdb27d3d455f18e3 data/create/advancements/recipes/create.palettes/scoria_cobblestone_stairs_from_scoria_cobblestone_stonecutting.json a43d45efa0fb0d3eaace93c18d80a14d4dcddf38 data/create/advancements/recipes/create.palettes/scoria_cobblestone_wall.json e340721aa78f260c2666214aa149241a37de216e data/create/advancements/recipes/create.palettes/scoria_cobblestone_wall_from_scoria_cobblestone_stonecutting.json -53cc5b006a19158e04094308accb66a7c35d2b26 data/create/advancements/recipes/create.palettes/scoria_pillar.json +68fc67ead3fd31885b30a5cf3e71dd33fb040634 data/create/advancements/recipes/create.palettes/scoria_pillar.json 53712a9ae59976dece952bea7ecaf73b679448f0 data/create/advancements/recipes/create.palettes/scoria_pillar_from_scoria_stonecutting.json 6b148def2f8789f9ff1d41bb71ab3608438a7207 data/create/advancements/recipes/create.palettes/smelting/dolomite.json 070720cc271767b26ad51fa089b4cf2a64d309be data/create/advancements/recipes/create.palettes/smelting/gabbro.json @@ -2326,6 +2338,7 @@ d40c7ce6b79630ace624d17b92667286998d93bc data/create/advancements/recipes/create cd5ee73117872ee98434be1d24b4f271f7e94a48 data/create/advancements/recipes/create.palettes/vertical_framed_glass_pane.json f26d1a1ee183b1b19d018fbdefc70f0bf29b41d0 data/create/advancements/recipes/create.palettes/warped_window.json faf33c9c630eecab88bb969e3b9f7fd9e9f6ccf6 data/create/advancements/recipes/create.palettes/warped_window_pane.json +5b3447ec4802fb27f1ee9a3b1bbe1936fac48fb3 data/create/advancements/recipes/create.palettes/weathered_limestone.json ef0d351d13f7e9c633581b537c59bddc1fa4c3a4 data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_from_weathered_limestone_stonecutting.json 1c931e15af3e5b5f78a0a62b8c159fdf9f0d7f3e data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_slab.json bba639941526cc23570e328e0b5e2a5545667219 data/create/advancements/recipes/create.palettes/weathered_limestone_bricks_slab_from_weathered_limestone_bricks_stonecutting.json @@ -2340,7 +2353,7 @@ b77c5aecd0b6dd37a0c69431ab7a4a40fe0770eb data/create/advancements/recipes/create 8ea05c6cdb313ff395d1f21cfb40e2d939dadf20 data/create/advancements/recipes/create.palettes/weathered_limestone_cobblestone_stairs_from_weathered_limestone_cobblestone_stonecutting.json 4d838d8ceaf207a59554444d82b80c31807341bc data/create/advancements/recipes/create.palettes/weathered_limestone_cobblestone_wall.json e548127075559307b767b802f4809ed52eedd543 data/create/advancements/recipes/create.palettes/weathered_limestone_cobblestone_wall_from_weathered_limestone_cobblestone_stonecutting.json -23ba836640a4d543db6f1cb72cc86a6543fe2fbe data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json +efab7b7f3829998a91fc506e4be3b6345f5ca168 data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json 9790a16fd56e47cb5abbfad4062672303c224d9f data/create/advancements/recipes/create.palettes/weathered_limestone_pillar_from_weathered_limestone_stonecutting.json e00155bcd00f50750e2cc4d6aa30c2f2d6e62922 data/create/advancements/recipes/decorations/smelting/glass_pane_from_framed_glass_pane.json bf9131527df4ad259b5a509753ba66417d764da2 data/create/advancements/recipes/decorations/smelting/glass_pane_from_horizontal_framed_glass_pane.json @@ -2447,7 +2460,7 @@ d370ee874b5b6b98e9a8c368218fe61f644d956d data/create/loot_tables/blocks/cuckoo_c fe24fd296812fea3f838defa2ca6270523d9d48e data/create/loot_tables/blocks/cyan_valve_handle.json fd309e1d39dcbcb25c3361edecd8c9afa0f847d0 data/create/loot_tables/blocks/dark_oak_window.json 58e6307ba0efa65a0715662a391fe7dc6fba0c68 data/create/loot_tables/blocks/dark_oak_window_pane.json -7a40002e4c05f6456b52558b9ee9607cfc868a69 data/create/loot_tables/blocks/dark_scoria.json +6769787b0c7a8d2762bae1c4826275bde8647b4e data/create/loot_tables/blocks/dark_scoria.json 502160551afd210c68582a1dfd41a2df720f53a1 data/create/loot_tables/blocks/dark_scoria_bricks.json d37adba01cd1220e265dbdc025b3f8d01b992289 data/create/loot_tables/blocks/dark_scoria_bricks_slab.json 265bb133af68497d9b4ba4bd418a198506caa45b data/create/loot_tables/blocks/dark_scoria_bricks_stairs.json @@ -2468,7 +2481,7 @@ bdaba62199f7a65e1149b742aaaf0c23a1e149b0 data/create/loot_tables/blocks/diorite_ 5141eec8eebed0feec906618dd3474ea402fbf28 data/create/loot_tables/blocks/diorite_cobblestone_stairs.json f3c963cfd51069876140373f410e868706744e9b data/create/loot_tables/blocks/diorite_cobblestone_wall.json fdcf47cddebca81730ac122925b01daeddf9233d data/create/loot_tables/blocks/diorite_pillar.json -7aa075c7fbe97447422bfcb95afb3bbe3b26301c data/create/loot_tables/blocks/dolomite.json +0be81285de44699dabb2c1e046ae109b2e39a4e9 data/create/loot_tables/blocks/dolomite.json 7ecdbfa3ebfc6865833bafed06ed7cd6eef58345 data/create/loot_tables/blocks/dolomite_bricks.json ecc855c3ce298855038eb7b53137cab519bca55a data/create/loot_tables/blocks/dolomite_bricks_slab.json 699815e110c76bcb793efdfedcb8ac3a5b9b7131 data/create/loot_tables/blocks/dolomite_bricks_stairs.json @@ -2524,7 +2537,7 @@ f37526c092c645045c22674dea6c7b1ec503c9c3 data/create/loot_tables/blocks/flywheel ce0bb978b11935bc2d1218445f8ab18099af6b8a data/create/loot_tables/blocks/framed_glass.json 89bd90ecd7a1ce1f75bd873989cc58a84c8dcef9 data/create/loot_tables/blocks/framed_glass_pane.json 4063880eda871fe63a4eb549a19daecabce849e5 data/create/loot_tables/blocks/furnace_engine.json -1070cba1c0f46cf7ebe31089f35333f5eadda6e4 data/create/loot_tables/blocks/gabbro.json +88b3438e50322b731cdd8589e36a9ea497cfe56e data/create/loot_tables/blocks/gabbro.json 0356e003d8890d31b89d0ad98e32aae892da71f9 data/create/loot_tables/blocks/gabbro_bricks.json bd93e42ebca985b8aeeaf0ea5fb736d496183615 data/create/loot_tables/blocks/gabbro_bricks_slab.json e51893e1601c470da466b35b17251238e15d0361 data/create/loot_tables/blocks/gabbro_bricks_stairs.json @@ -2581,7 +2594,7 @@ b403848d3a4b4ad7a048e70c21e200e40d0c67e3 data/create/loot_tables/blocks/light_bl f7893090c6ecb4862c90c408b7f9ce8316f8b608 data/create/loot_tables/blocks/lime_seat.json cae6d16c8967164698efbce3b91018a8e79a81e9 data/create/loot_tables/blocks/lime_valve_handle.json 7dfd638cc6f0d22bbc8fcbdb7212a3bfc8c85223 data/create/loot_tables/blocks/limesand.json -9d585f677a32a2336df5f17b5b389cdee867939f data/create/loot_tables/blocks/limestone.json +d476eed7b5f0c7438d2e517fc60cd23f19234056 data/create/loot_tables/blocks/limestone.json 57134f7d3d32fc1c48f2a20c4be84388587092bc data/create/loot_tables/blocks/limestone_bricks.json 1b59a36aa1a889c42d4b8b939f5eeee2967222d0 data/create/loot_tables/blocks/limestone_bricks_slab.json 41ed1d0750e8ddd7e7e75fd7e4cafde6346d1afe data/create/loot_tables/blocks/limestone_bricks_stairs.json @@ -2726,8 +2739,8 @@ cecaac07bd275bb1ae9e302f0bf44b581e74105d data/create/loot_tables/blocks/rope_pul aa6af37356d65105efab2503ffe75f778cfe873b data/create/loot_tables/blocks/rotation_speed_controller.json 30de11bec82606fead9d6bff7bba0232e97f1039 data/create/loot_tables/blocks/sail_frame.json 069701cb804b6522c18624a0d4f3f949ff8b0281 data/create/loot_tables/blocks/schematic_table.json -c4a89145334addfd0dd1fedf7fa75ba07a7d3490 data/create/loot_tables/blocks/schematicannon.json -af1bbbb8236b4ab05a6a8edc6db960bc758cbdf3 data/create/loot_tables/blocks/scoria.json +a2b172dc749176d4df34729007019605fc6dd150 data/create/loot_tables/blocks/schematicannon.json +5c1bd2b940fa04ab487155ca10c551dd9b0fbf37 data/create/loot_tables/blocks/scoria.json bb670ac5dd2fa4c743bc268cd0547926eb6cdb68 data/create/loot_tables/blocks/scoria_bricks.json a7217ea301a282d0ef52f2d8c06dd8683398408d data/create/loot_tables/blocks/scoria_bricks_slab.json 58a188f3ebfeb3d19323c3f8dfa3e020a7f6cdc4 data/create/loot_tables/blocks/scoria_bricks_stairs.json @@ -2759,7 +2772,7 @@ d0156602dd5f4a274c293df67e19374820c72890 data/create/loot_tables/blocks/vertical 1afc5ede08e72221e33910603fa7acd0b3c7a2ee data/create/loot_tables/blocks/warped_window.json f334fd2b9a92b0646674239e7e34e142fe2c5fad data/create/loot_tables/blocks/warped_window_pane.json 2883c63ceb1273009dbf91cb0693756cadf79a1a data/create/loot_tables/blocks/water_wheel.json -611d6195db52c074de484ec52d7ac9eb96b4ff10 data/create/loot_tables/blocks/weathered_limestone.json +6cbc693f915f409bc21c6084a4f75071bd660f7b data/create/loot_tables/blocks/weathered_limestone.json c1f379baad36a20fc767be094db10480a0378184 data/create/loot_tables/blocks/weathered_limestone_bricks.json 43be7e49b9a8a75077066aa824a0f784aa741683 data/create/loot_tables/blocks/weathered_limestone_bricks_slab.json c2a62f12680d04ed4f586c501bb026e367243dd2 data/create/loot_tables/blocks/weathered_limestone_bricks_stairs.json @@ -2782,6 +2795,7 @@ e3969f1c5966c4992b3280a06e1d6c5000c37df5 data/create/loot_tables/blocks/weighted 37248ca92d474e440b91c27e3c8e78e568328100 data/create/loot_tables/blocks/zinc_ore.json b65bac8bc2fbfd476040c1aab1c0588b8bd59ebe data/create/recipes/acacia_window.json 35b4da9c14da60584c32e959efc2223f64bb3ec2 data/create/recipes/acacia_window_pane.json +57fc55848415db3e9b74e2cc2f6dacfb1b13a6cc data/create/recipes/andesite.json 96bb0bceb7798c96d5cf9b9c24b8ef822080cb1e data/create/recipes/andesite_bricks_from_andesite_stonecutting.json 01867b07039615dc69bad1b9fd217a1d86e69062 data/create/recipes/andesite_bricks_slab.json 376ada0e08cc797c705c22ec35fe54baa5f24efe data/create/recipes/andesite_bricks_slab_from_andesite_bricks_stonecutting.json @@ -2845,10 +2859,12 @@ f7879d404d7a848d818278b4e788f285a9087e63 data/create/recipes/compacting/blaze_ca 27c23592d8fec03072a04544d3598ca9b1c798ff data/create/recipes/compacting/chocolate.json 7b2ef15dd28d1d8a450ea49a82dfb361d1adde4c data/create/recipes/compacting/diorite_from_flint.json 7657603e95ccf83dd0d4b104635db66e531d092a data/create/recipes/compacting/granite_from_flint.json -30030b15caa11b3a7c0104adb62fe74e8c7c0df1 data/create/recipes/crafting/appliances/copper_backtank.json +b187def3a843505ab42db301f5374043d90605d6 data/create/recipes/crafting/appliances/copper_backtank.json +c077375d16b4505e52548613fbc9356993556e6b data/create/recipes/crafting/appliances/crafting_blueprint.json 9ad82ac5ce02654b7af7f1a570a6b2c01e140da3 data/create/recipes/crafting/appliances/diving_boots.json 813081c6421b34e161ec44e8e470994c282f76be data/create/recipes/crafting/appliances/diving_helmet.json 19526da3a59fc136654ff1bc93c0251581f397a9 data/create/recipes/crafting/appliances/dough.json +75cdbd88973a8ca943ebe890153b01a344b96b01 data/create/recipes/crafting/appliances/linked_controller.json 7b5f863dda3d05a79cb85943a178eba0bd8a7dc7 data/create/recipes/crafting/appliances/slime_ball.json b159ba84428eee6ef6e23df1766f2a18f2c8a63e data/create/recipes/crafting/appliances/tree_fertilizer.json 660e92da2b1b6698b1c0df74bd74a56a25fb3eca data/create/recipes/crafting/curiosities/minecart_coupling.json @@ -3102,6 +3118,7 @@ a022f2d541f04a9e2bed6b72af4e74703076fcbe data/create/recipes/cutting/warped_hyph 1bd01df5540df7db06afde28a3f9ebe4d25e4001 data/create/recipes/cutting/warped_stem.json f2c317e03ac4d42fb631e1625607061e10c480fe data/create/recipes/dark_oak_window.json d9dbae6e237eb38e53a619a0f1b339fca7c59b4d data/create/recipes/dark_oak_window_pane.json +2ff8ac7eaabef52dcb173d7af388c28307559aaa data/create/recipes/dark_scoria.json 55596a590962e3ddd40949917661f0bd94408274 data/create/recipes/dark_scoria_bricks_from_dark_scoria_stonecutting.json 2489fc29c47d3c9cb63f5f2f09dc79ea1ca1728e data/create/recipes/dark_scoria_bricks_slab.json 86f4d54ebcc5bc8786c72167395d8efee833744c data/create/recipes/dark_scoria_bricks_slab_from_dark_scoria_bricks_stonecutting.json @@ -3118,6 +3135,7 @@ f3a72b45daef00035ecb17b9cd7f8985a5f9e9ef data/create/recipes/dark_scoria_cobbles 0f2c14d40ed9013d45e331000ea03d39430f9d22 data/create/recipes/dark_scoria_cobblestone_wall_from_dark_scoria_cobblestone_stonecutting.json 31b7e65165cb0dbcd95362a81905b19fe4282cf3 data/create/recipes/dark_scoria_pillar.json 681f45f03b15dc1a8a72cf72042e725d3f0cc7ef data/create/recipes/dark_scoria_pillar_from_dark_scoria_stonecutting.json +0871ced2a434838e2db8f3df85af84b0cb4e40ad data/create/recipes/diorite.json 25c0fe29d1c2cedcaf21fac6cdfcce45dbf810bf data/create/recipes/diorite_bricks_from_diorite_stonecutting.json ff4a8687bdff339a10e0b813788bca272332abd9 data/create/recipes/diorite_bricks_slab.json 7c49a389f9222fdfd6653d9fbcb1ca05bf207aa8 data/create/recipes/diorite_bricks_slab_from_diorite_bricks_stonecutting.json @@ -3134,6 +3152,7 @@ f764471aab017775e0d7a6d43a9e36b186db3ac2 data/create/recipes/diorite_cobblestone d3628d5ce836d3b9072be3d4cf30416146cccad2 data/create/recipes/diorite_cobblestone_wall_from_diorite_cobblestone_stonecutting.json d69d767a77ae62f8e53342dffda4c627906439d7 data/create/recipes/diorite_pillar.json 3019172274fdfcc606ad0f5569db433913231c28 data/create/recipes/diorite_pillar_from_diorite_stonecutting.json +2f1bf27611c640ec454be0e73ed75f596a4f1add data/create/recipes/dolomite.json 6ee0f10522f4acfe554e4743fa2ba1d8297a12f2 data/create/recipes/dolomite_bricks_from_dolomite_stonecutting.json 88a9b8e89e67455a9c4f1c3dbff813a3c3bd1609 data/create/recipes/dolomite_bricks_slab.json 3adfb9924ada35d58275533425802b4829f058ac data/create/recipes/dolomite_bricks_slab_from_dolomite_bricks_stonecutting.json @@ -3229,6 +3248,7 @@ c83e77a9799b6ca34dd73aa76b56159f2103c48c data/create/recipes/filling/milk_bucket fb8e4378cd2240644a4b5c0d06e27ad772ec7695 data/create/recipes/filling/sweet_roll.json 5b8bbde7f8b270ab75fac18d6858f2fadbc0efa3 data/create/recipes/framed_glass_from_glass_colorless_stonecutting.json d697de0c9b706ca4e18da7a2d769e7e5fe8d769d data/create/recipes/framed_glass_pane.json +147e7a160b82c8128f8fa7c3c6e7f7d652b89a36 data/create/recipes/gabbro.json a0dae50faaa1b7142bb4309675e3084c68daa547 data/create/recipes/gabbro_bricks_from_gabbro_stonecutting.json a19f047fa8507e994eb026795c86bc10ff5c373b data/create/recipes/gabbro_bricks_slab.json 84d83643f7987864eca0e2ca7cda4330ad9f1f86 data/create/recipes/gabbro_bricks_slab_from_gabbro_bricks_stonecutting.json @@ -3245,6 +3265,7 @@ f7407fd04cfe7558d53c44cb33dfd8ff8a736ae3 data/create/recipes/gabbro_cobblestone_ 8171880f4374f9102949b85e9a17e0b313caf3a6 data/create/recipes/gabbro_cobblestone_wall_from_gabbro_cobblestone_stonecutting.json 6e52667c2f9ec62a95ba27676fdc07a8222f1746 data/create/recipes/gabbro_pillar.json da3743119130ef0946b05b21a84c2fe5926dccd5 data/create/recipes/gabbro_pillar_from_gabbro_stonecutting.json +dc21523e591068eb5df7b287c9eef7b773b7d5d0 data/create/recipes/granite.json 5664bad03fce4a4724e8fd21c9c02ca6ae900df9 data/create/recipes/granite_bricks_from_granite_stonecutting.json 1c5265828318670a11bd1e439b6a6005edb37487 data/create/recipes/granite_bricks_slab.json 0f460bda24ff799a9ef948933cfb50ef038739d4 data/create/recipes/granite_bricks_slab_from_granite_bricks_stonecutting.json @@ -3274,6 +3295,7 @@ b49c314e171f31a39f38aabad767d8d3be613602 data/create/recipes/layered_gabbro_from 9712031277020c39e8e643690a6a968c5e275a75 data/create/recipes/layered_limestone_from_limestone_stonecutting.json fdfbe941eb56a98c3d28639154b7bcd4dcc66dfa data/create/recipes/layered_scoria_from_scoria_stonecutting.json cc070e83594b20cf697aa5dbb8c4e09dbf576d00 data/create/recipes/layered_weathered_limestone_from_weathered_limestone_stonecutting.json +90253fc317a2551c50da7693df4a60e8543d2d64 data/create/recipes/limestone.json 3b43347da62a69c6e76e6a0261f840f46ff90038 data/create/recipes/limestone_bricks_from_limestone_stonecutting.json aed4b037af6921e9337213dc09a215ab7a18adde data/create/recipes/limestone_bricks_slab.json 7222e1f13c6aec69ea37c84b4aca3e2322ef00d2 data/create/recipes/limestone_bricks_slab_from_limestone_bricks_stonecutting.json @@ -3443,7 +3465,7 @@ f2a140cbaddefd387fd94f0ce94df763a585dd4f data/create/recipes/paved_weathered_lim 9f02f552173ae1c85750bb16aa6bbbfb87a5a7f1 data/create/recipes/paved_weathered_limestone_stairs_from_paved_weathered_limestone_stonecutting.json cc4a5a893b10ffdfcc10085323d89d34a1b8f122 data/create/recipes/paved_weathered_limestone_wall.json d996f6505433a74cd8bdab04c0e0bac1b9a2da16 data/create/recipes/paved_weathered_limestone_wall_from_paved_weathered_limestone_stonecutting.json -c83e29f260eee9844c85995d45bedef6100cb91d data/create/recipes/polished_dark_scoria.json +c32e1418b17011c8c423d44ee20f2b86e82e7626 data/create/recipes/polished_dark_scoria.json 753c85bfb84a5d31f9670478042321702a589dc8 data/create/recipes/polished_dark_scoria_from_dark_scoria_stonecutting.json d3c78c504672fec3316b206505c2cb5fc8daf822 data/create/recipes/polished_dark_scoria_slab.json bcc5a7325b7f7110e6b382e7ad60fc547222d3ad data/create/recipes/polished_dark_scoria_slab_from_polished_dark_scoria_stonecutting.json @@ -3451,7 +3473,7 @@ c7d7e5f39099a71482cdfbebe1ef2dfd508ae768 data/create/recipes/polished_dark_scori 364d77f01b380bbb0036810f6e0df09773ea8e1c data/create/recipes/polished_dark_scoria_stairs_from_polished_dark_scoria_stonecutting.json 396b6c97b5e7f608b293dee51be97717c3430bc4 data/create/recipes/polished_dark_scoria_wall.json 62b0769e0208831db822f6d2b986fff6aee60729 data/create/recipes/polished_dark_scoria_wall_from_polished_dark_scoria_stonecutting.json -53930b3b32b076c9786e5c61d8cc7fe70a47fed7 data/create/recipes/polished_dolomite.json +a1561acc26948db5cffc041d85b1d26204754caf data/create/recipes/polished_dolomite.json da91fd1ccaac64f7ef9737f3c773490d0c0b10d1 data/create/recipes/polished_dolomite_from_dolomite_stonecutting.json 75288e75b604eacfbc19cb51cb4d4759bdeaafa5 data/create/recipes/polished_dolomite_slab.json 9a89eaf5f00d8fb10297de61248f8d11dded8c4b data/create/recipes/polished_dolomite_slab_from_polished_dolomite_stonecutting.json @@ -3459,7 +3481,7 @@ da91fd1ccaac64f7ef9737f3c773490d0c0b10d1 data/create/recipes/polished_dolomite_f e2dce404e4bcde076615ed0d0cf6fab769d441d5 data/create/recipes/polished_dolomite_stairs_from_polished_dolomite_stonecutting.json 8f2f4643886d166609b198704dcadb5e87b6323e data/create/recipes/polished_dolomite_wall.json 3b5d553e408a8b6385932e2a8082fcb5bdead0d1 data/create/recipes/polished_dolomite_wall_from_polished_dolomite_stonecutting.json -d9d2b6f6f4c8223c4cfc6258ba9013463691d88c data/create/recipes/polished_gabbro.json +5873547a8561849a73c0d2cca3faba3e8b65b33d data/create/recipes/polished_gabbro.json ba3e1444b9d1804411cc9c7536c657806dc37c1d data/create/recipes/polished_gabbro_from_gabbro_stonecutting.json b7d29a29fde4868b4ceef1437e5d00975068bc58 data/create/recipes/polished_gabbro_slab.json f7a62c1edc74e54fc0c747f23d7da182d49ef7b6 data/create/recipes/polished_gabbro_slab_from_polished_gabbro_stonecutting.json @@ -3467,7 +3489,7 @@ f7a62c1edc74e54fc0c747f23d7da182d49ef7b6 data/create/recipes/polished_gabbro_sla 7df6fd466badaa3cef5e2ad0e78bbb3b6429805e data/create/recipes/polished_gabbro_stairs_from_polished_gabbro_stonecutting.json ec70334e13e05cff7e04e7dc6b23be273c235e50 data/create/recipes/polished_gabbro_wall.json 5176a8fe5a48592c7b487518a57c962c24e3e751 data/create/recipes/polished_gabbro_wall_from_polished_gabbro_stonecutting.json -bb7d651a6c79bd97390c7b1743c4fe58c9973c39 data/create/recipes/polished_limestone.json +59a01eb264c302fe455639bcafa4afb97de2379e data/create/recipes/polished_limestone.json 0e88c98c9ef0d15523b23b00f8afde71d9d8e3e9 data/create/recipes/polished_limestone_from_limestone_stonecutting.json 135fd40e291c7cfdc73c14496654008da9dd797d data/create/recipes/polished_limestone_slab.json 4ce225832ab45daf6b5bc013c6f8762fdbe9ff0f data/create/recipes/polished_limestone_slab_from_polished_limestone_stonecutting.json @@ -3475,7 +3497,7 @@ fee3d0ec8d4f27d82acd5d0e3a2a142900e18be3 data/create/recipes/polished_limestone_ 6780c8bd8747ebb6db7e0adfc486ce00e7e2cf26 data/create/recipes/polished_limestone_stairs_from_polished_limestone_stonecutting.json 44b1f3873fe8150abbacab10ff3cc2033a01b4a0 data/create/recipes/polished_limestone_wall.json d68a27e463d31ba5eed19181c0335824601b9e68 data/create/recipes/polished_limestone_wall_from_polished_limestone_stonecutting.json -300b9c979ac848fb6ae69eeb6e89c9e22056c562 data/create/recipes/polished_scoria.json +82b5b5fc1d2f789b48a48a7dc846aeb505b0c3c1 data/create/recipes/polished_scoria.json 9d6926822ea6f2bb38ba55204278fe82fd453d16 data/create/recipes/polished_scoria_from_scoria_stonecutting.json 814efd67d3f061d0c0ba104993c868e075a4fd3e data/create/recipes/polished_scoria_slab.json 8696f262927ae55ce72af1a34cae68fd6ccc4050 data/create/recipes/polished_scoria_slab_from_polished_scoria_stonecutting.json @@ -3483,7 +3505,7 @@ efe648aa4fd0f22faa78c016dbe2d083462e1ad6 data/create/recipes/polished_scoria_sta ba6dd9ad0c69b088c1a9e33000bd5b9bcedb0ca0 data/create/recipes/polished_scoria_stairs_from_polished_scoria_stonecutting.json 8319042a131a9dcabae016009b807b91c491f8d3 data/create/recipes/polished_scoria_wall.json bc9a83e7793768723031ff14269e43c83687b9f3 data/create/recipes/polished_scoria_wall_from_polished_scoria_stonecutting.json -31a0826653da3e752da8507a46b16dc17334693b data/create/recipes/polished_weathered_limestone.json +d9d188d55d9bb94bceaad8de3ccb02532b021576 data/create/recipes/polished_weathered_limestone.json 73b468de08f3e0542b7020129faff3a40b3fee67 data/create/recipes/polished_weathered_limestone_from_weathered_limestone_stonecutting.json c0924d72a856c3182b89996a6ceaffd56930c455 data/create/recipes/polished_weathered_limestone_slab.json 1f5503d22859a08eef824d33f6ed48335f66c423 data/create/recipes/polished_weathered_limestone_slab_from_polished_weathered_limestone_stonecutting.json @@ -3496,9 +3518,10 @@ eae06580a0a5f486cde35426716d50fcb3ba5bb3 data/create/recipes/polished_weathered_ 0fa8386648398724f6fd373178b706c6b11ddefc data/create/recipes/pressing/gold_ingot.json a104ef6eb8872a40ea7b2ef67ae54cec943162f0 data/create/recipes/pressing/iron_ingot.json 7f9e72ec02a9926656744a95066f8aa304514565 data/create/recipes/pressing/lapis_block.json -654e274b07af172c22838d47e0974367c20101d4 data/create/recipes/pressing/path.json +b472136cdc8e87fa65a812a359542bdc484f27ec data/create/recipes/pressing/path.json bd57ccc8eb4357b4a5af021db7b806b514cd2558 data/create/recipes/pressing/sugar_cane.json 141173778757d87e7f2e9466bdab6ff1263c8e98 data/create/recipes/sandpaper_polishing/rose_quartz.json +5ab9c8271a9e1d4a863940aeafd1f8816cb37a29 data/create/recipes/scoria.json d59c68621c78ff5d2c51be4440dea603480efed8 data/create/recipes/scoria_bricks_from_scoria_stonecutting.json a7a28cf77955c2b4ed3687205dd24162e461aa30 data/create/recipes/scoria_bricks_slab.json 0577ffde98e7a027b21c430cd71cdafdd3cee3a3 data/create/recipes/scoria_bricks_slab_from_scoria_bricks_stonecutting.json @@ -3629,6 +3652,7 @@ e2c1774577aeb0756fb1d092245d9d77e40ba5f8 data/create/recipes/splashing/yellow_co dc6093427210bd7034a0e2184f6a1630c7b33b3e data/create/recipes/vertical_framed_glass_pane.json 40ec72d571002206c276aec5de72459155e043ce data/create/recipes/warped_window.json 8f4b0a3cfb0073f1414bf18c0d4e5e751c4a9185 data/create/recipes/warped_window_pane.json +e483f41ab4e959bda4d88c23817913843d0fbef6 data/create/recipes/weathered_limestone.json f75f25d3259dd51c29bee6ada2a4540a7a2bbeab data/create/recipes/weathered_limestone_bricks_from_weathered_limestone_stonecutting.json f58ef5eb552fc7dcd89f30aa4231286ecef5e00a data/create/recipes/weathered_limestone_bricks_slab.json ca9b163b3aaa526d6c3b070c2a7e50a56a38c6f4 data/create/recipes/weathered_limestone_bricks_slab_from_weathered_limestone_bricks_stonecutting.json @@ -3645,10 +3669,9 @@ d3fdb8ece6cb072a93ddb64a0baad5ac952117a4 data/create/recipes/weathered_limestone 0f3c993eb6dd3f37953f304b8fad15bf60469ef4 data/create/recipes/weathered_limestone_cobblestone_wall_from_weathered_limestone_cobblestone_stonecutting.json 6eceb25fabbb6b389ca35de3b829ad061c9c456a data/create/recipes/weathered_limestone_pillar.json 11667414f73bc2d00bda7c5c1a7d2934bf6e9165 data/create/recipes/weathered_limestone_pillar_from_weathered_limestone_stonecutting.json -eedf31af7134d03656c5fa57229982f9c5bed07c data/create/tags/blocks/brittle.json +20c20a12b0baff2ba493b1405db7d2d8a15b81af data/create/tags/blocks/brittle.json 330bfb3850ba3964b10b1bccbc3cbb9b012cae54 data/create/tags/blocks/fan_heaters.json 3bc64e3a1e7980237435b1770a9ba2102d57fcd4 data/create/tags/blocks/fan_transparent.json -74700d556ca80c7a1db5fd4efb09c3ddb26cad66 data/create/tags/blocks/non_movable.json c81ea194e808985847159b201140d4aa4cbcca65 data/create/tags/blocks/safe_nbt.json c9ac7e3e5ec18554e7184168d65e9b8e44ef5610 data/create/tags/blocks/sails.json 6cdeeac1689f7b5bfd9bc40b462143d8eaf3ad0b data/create/tags/blocks/seats.json @@ -3707,6 +3730,7 @@ f6c8f34ceb475546dba5cc6ff288863ea795d20b data/forge/tags/items/storage_blocks/co 0d188ad2c33d10ee8f0d455c4e63a4460a8302fb data/minecraft/tags/blocks/stairs.json 92584f914c53e00c111f9ff5e3894e2e3594946b data/minecraft/tags/blocks/walls.json 09d26bcd0f94459f945219997277c4fbf14adeb7 data/minecraft/tags/fluids/water.json +49cadea86f6b63d5065b859a0d0e7ad772cf51d6 data/minecraft/tags/items/piglin_loved.json 29e6f7e3d4be9a9b0af1fca5d32fa55e29905ce2 data/minecraft/tags/items/slabs.json 0d188ad2c33d10ee8f0d455c4e63a4460a8302fb data/minecraft/tags/items/stairs.json 92584f914c53e00c111f9ff5e3894e2e3594946b data/minecraft/tags/items/walls.json diff --git a/src/generated/resources/assets/create/lang/en_ud.json b/src/generated/resources/assets/create/lang/en_ud.json index 12c9bc03a..2428052fc 100644 --- a/src/generated/resources/assets/create/lang/en_ud.json +++ b/src/generated/resources/assets/create/lang/en_ud.json @@ -48,6 +48,7 @@ "block.create.chiseled_scoria": "\u0250\u0131\u0279o\u0254S p\u01DD\u05DF\u01DDs\u0131\u0265\u0186", "block.create.chiseled_weathered_limestone": "\u01DDuo\u0287s\u01DD\u026F\u0131\uA780 p\u01DD\u0279\u01DD\u0265\u0287\u0250\u01DDM p\u01DD\u05DF\u01DDs\u0131\u0265\u0186", "block.create.chocolate": "\u01DD\u0287\u0250\u05DFo\u0254o\u0265\u0186", + "block.create.chromatic_projector": "\u0279o\u0287\u0254\u01DD\u0638o\u0279\u0500 \u0254\u0131\u0287\u0250\u026Fo\u0279\u0265\u0186", "block.create.chute": "\u01DD\u0287n\u0265\u0186", "block.create.clockwork_bearing": "bu\u0131\u0279\u0250\u01DD\u15FA \u029E\u0279o\u028D\u029E\u0254o\u05DF\u0186", "block.create.clutch": "\u0265\u0254\u0287n\u05DF\u0186", @@ -409,6 +410,7 @@ "block.create.zinc_block": "\u0254u\u0131Z \u025Fo \u029E\u0254o\u05DF\u15FA", "block.create.zinc_ore": "\u01DD\u0279O \u0254u\u0131Z", "entity.create.contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186", + "entity.create.crafting_blueprint": "\u0287u\u0131\u0279d\u01DDn\u05DF\u15FA bu\u0131\u0287\u025F\u0250\u0279\u0186", "entity.create.gantry_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0287u\u0250\u2141", "entity.create.seat": "\u0287\u0250\u01DDS", "entity.create.stationary_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u028E\u0279\u0250uo\u0131\u0287\u0250\u0287S", @@ -437,6 +439,7 @@ "item.create.copper_nugget": "\u0287\u01DDbbnN \u0279\u01DDddo\u0186", "item.create.copper_sheet": "\u0287\u01DD\u01DD\u0265S \u0279\u01DDddo\u0186", "item.create.crafter_slot_cover": "\u0279\u01DD\u028Co\u0186 \u0287o\u05DFS \u0279\u01DD\u0287\u025F\u0250\u0279\u0186", + "item.create.crafting_blueprint": "\u0287u\u0131\u0279d\u01DDn\u05DF\u15FA bu\u0131\u0287\u025F\u0250\u0279\u0186", "item.create.crushed_aluminum_ore": "\u01DD\u0279O \u026Fnu\u0131\u026Fn\u05DF\u2C6F p\u01DD\u0265sn\u0279\u0186", "item.create.crushed_brass": "ss\u0250\u0279\u15FA p\u01DD\u0265sn\u0279\u0186", "item.create.crushed_copper_ore": "\u01DD\u0279O \u0279\u01DDddo\u0186 p\u01DD\u0265sn\u0279\u0186", @@ -468,6 +471,7 @@ "item.create.integrated_circuit": "\u0287\u0131n\u0254\u0279\u0131\u0186 p\u01DD\u0287\u0250\u0279b\u01DD\u0287uI", "item.create.iron_sheet": "\u0287\u01DD\u01DD\u0265S uo\u0279I", "item.create.lapis_sheet": "\u0287\u01DD\u01DD\u0265S s\u0131d\u0250\uA780", + "item.create.linked_controller": "\u0279\u01DD\u05DF\u05DFo\u0279\u0287uo\u0186 p\u01DD\u029Eu\u0131\uA780", "item.create.minecart_contraption": "uo\u0131\u0287d\u0250\u0279\u0287uo\u0186 \u0287\u0279\u0250\u0254\u01DDu\u0131W", "item.create.minecart_coupling": "bu\u0131\u05DFdno\u0186 \u0287\u0279\u0250\u0254\u01DDu\u0131W", "item.create.polished_rose_quartz": "z\u0287\u0279\u0250n\u1F49 \u01DDso\u1D1A p\u01DD\u0265s\u0131\u05DFo\u0500", diff --git a/src/generated/resources/assets/create/lang/en_us.json b/src/generated/resources/assets/create/lang/en_us.json index 427d2c658..144a7c6aa 100644 --- a/src/generated/resources/assets/create/lang/en_us.json +++ b/src/generated/resources/assets/create/lang/en_us.json @@ -51,6 +51,7 @@ "block.create.chiseled_scoria": "Chiseled Scoria", "block.create.chiseled_weathered_limestone": "Chiseled Weathered Limestone", "block.create.chocolate": "Chocolate", + "block.create.chromatic_projector": "Chromatic Projector", "block.create.chute": "Chute", "block.create.clockwork_bearing": "Clockwork Bearing", "block.create.clutch": "Clutch", @@ -413,6 +414,7 @@ "block.create.zinc_ore": "Zinc Ore", "entity.create.contraption": "Contraption", + "entity.create.crafting_blueprint": "Crafting Blueprint", "entity.create.gantry_contraption": "Gantry Contraption", "entity.create.seat": "Seat", "entity.create.stationary_contraption": "Stationary Contraption", @@ -443,6 +445,7 @@ "item.create.copper_nugget": "Copper Nugget", "item.create.copper_sheet": "Copper Sheet", "item.create.crafter_slot_cover": "Crafter Slot Cover", + "item.create.crafting_blueprint": "Crafting Blueprint", "item.create.crushed_aluminum_ore": "Crushed Aluminum Ore", "item.create.crushed_brass": "Crushed Brass", "item.create.crushed_copper_ore": "Crushed Copper Ore", @@ -474,6 +477,7 @@ "item.create.integrated_circuit": "Integrated Circuit", "item.create.iron_sheet": "Iron Sheet", "item.create.lapis_sheet": "Lapis Sheet", + "item.create.linked_controller": "Linked Controller", "item.create.minecart_contraption": "Minecart Contraption", "item.create.minecart_coupling": "Minecart Coupling", "item.create.polished_rose_quartz": "Polished Rose Quartz", @@ -671,6 +675,13 @@ "create.block.deployer.damage_source_name": "a rogue Deployer", "create.block.cart_assembler.invalid": "Place your Cart Assembler on a rail block", + "create.menu.return": "Return to Menu", + "create.menu.configure": "Configure...", + "create.menu.getting_started": "Getting Started", + "create.menu.project_page": "Project Page", + "create.menu.report_bugs": "Report Issues", + "create.menu.support": "Support Us", + "create.recipe.crushing": "Crushing", "create.recipe.milling": "Milling", "create.recipe.fan_washing": "Bulk Washing", @@ -1104,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "Fans pull from Below", "create.tooltip.chute.contains": "Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "Bind mode active", + "create.linked_controller.press_keybind": "Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "Display Slot", + "create.crafting_blueprint.inferred": "Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "Secondary Display Slot", + "create.crafting_blueprint.optional": "Optional", + "create.hint.hose_pulley.title": "Bottomless Supply", "create.hint.hose_pulley": "The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "No Targets", @@ -1131,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "Cogwheels rumble", - "create.subtitle.slime_added": "Slime squishes", + "create.subtitle.saw_idle": "Mechanical Saw turns", "create.subtitle.contraption_disassemble": "Contraption stops", - "create.subtitle.wrench_rotate": "Wrench used", "create.subtitle.mixing": "Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "Mechanical Press bonks", "create.subtitle.worldshaper_place": "Worldshaper zaps", - "create.subtitle.deployer_polish": "Deployer applies polish", "create.subtitle.depot_slide": "Item slides", - "create.subtitle.deny": "Declining boop", + "create.subtitle.saw_activate_stone": "Mechanical Saw activates", "create.subtitle.blaze_munch": "Blaze Burner munches", - "create.subtitle.schematicannon_launch_block": "Schematicannon fires", "create.subtitle.funnel_flap": "Funnel Flaps", - "create.subtitle.copper_armor_equip": "Diving equipment clinks", "create.subtitle.schematicannon_finish": "Schematicannon dings", "create.subtitle.scroll_value": "Scroll-input clicks", + "create.subtitle.crafter_craft": "Crafter crafts", + "create.subtitle.saw_process": "Mechanical Saw processes", + "create.subtitle.cranking": "Hand Crank turns", + "create.subtitle.wrench_remove": "Component breaks", + "create.subtitle.cogs": "Cogwheels rumble", + "create.subtitle.slime_added": "Slime squishes", + "create.subtitle.wrench_rotate": "Wrench used", + "create.subtitle.saw_activate_wood": "Mechanical Saw activates", + "create.subtitle.deployer_polish": "Deployer applies polish", + "create.subtitle.deny": "Declining boop", + "create.subtitle.controller_click": "Controller clicks", + "create.subtitle.schematicannon_launch_block": "Schematicannon fires", + "create.subtitle.copper_armor_equip": "Diving equipment clinks", "create.subtitle.mechanical_press_activation": "Mechanical Press clangs", "create.subtitle.contraption_assemble": "Contraption moves", - "create.subtitle.crafter_craft": "Crafter crafts", - "create.subtitle.cranking": "Hand Crank turns", "create.subtitle.crafter_click": "Crafter clicks", - "create.subtitle.wrench_remove": "Component breaks", "create.subtitle.depot_plop": "Item lands", "create.subtitle.confirm": "Affirmative ding", @@ -1397,9 +1428,46 @@ "item.create.refined_radiance.tooltip": "REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "A Chromatic material forged from _absorbed light_.", + "item.create.refined_radiance.tooltip.condition1": "Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "A Chromatic material forged _in the void_.", + "item.create.shadow_steel.tooltip.condition1": "Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "R-Click", + "item.create.linked_controller.tooltip.behaviour1": "_Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "_Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "When Worn", + "item.create.diving_boots.tooltip.behaviour1": "Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "_Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "_Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "_Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", @@ -1418,6 +1486,25 @@ "create.tooltip.randomWipDescription7": "This one maybe isn't for you. What about that one?", "create.tooltip.randomWipDescription8": "Use it and regret your decision immediately.", + "create.gui.chromatic_projector.title": "Chromatic Projector", + "create.gui.chromatic_projector.filter.invert": "Invert", + "create.gui.chromatic_projector.filter.sepia": "Sepia", + "create.gui.chromatic_projector.filter.grayscale": "Grayscale", + "create.gui.chromatic_projector.filter.saturate": "Saturate", + "create.gui.chromatic_projector.filter.hue_shift": "Hue shift", + "create.gui.chromatic_projector.filter.darken": "Darken", + "create.gui.chromatic_projector.filter.contrast": "Contrast", + "create.gui.chromatic_projector.filter.end": "End", + "create.gui.chromatic_projector.filter": "Filter", + "create.gui.chromatic_projector.surface": "Surface", + "create.gui.chromatic_projector.field": "Field", + "create.gui.chromatic_projector.strength": "Strength", + "create.gui.chromatic_projector.radius": "Radius", + "create.gui.chromatic_projector.feather": "Feather", + "create.gui.chromatic_projector.density": "Density", + "create.gui.chromatic_projector.fade": "Fade", + "create.gui.chromatic_projector.blend": "Blend", + "_": "->------------------------] Ponder Content [------------------------<-", @@ -1593,7 +1680,7 @@ "create.ponder.chain_drive.text_3": "Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1633,6 +1720,8 @@ "create.ponder.cogwheel.text_1": "Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "Creative Fluid Tanks", + "create.ponder.creative_motor.header": "Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1669,6 +1758,12 @@ "create.ponder.deployer_modes.text_1": "By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "Before stopping, the Deployer will finish any started cycles", @@ -1687,6 +1782,11 @@ "create.ponder.empty_blaze_burner.text_4": "For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "Strength and Direction of Flow depends on the Rotational Input", @@ -1705,6 +1805,26 @@ "create.ponder.fan_source.text_1": "Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "The provided Rotational Force has a very large stress capacity", @@ -1778,6 +1898,14 @@ "create.ponder.hand_crank.text_3": "Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "It will help relaying conveyed speed to other axes of rotation", @@ -1900,6 +2028,10 @@ "create.ponder.mechanical_press_compacting.text_3": "Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1930,6 +2062,10 @@ "create.ponder.piston_pole.text_1": "Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "Redstone Control", + "create.ponder.portable_storage_interface.header": "Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "This component can interact with storage without the need to stop the contraption.", @@ -2027,11 +2163,17 @@ "create.ponder.smart_chute.text_3": "Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "..they will attempt to keep themselves upright", @@ -2063,6 +2205,8 @@ "create.ponder.valve_handle.text_4": "Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "The more faces are powered, the faster the Water Wheel will rotate", 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 bffa0a121..d1e028884 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: 942", + "_": "Missing Localizations: 1039", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Zinkerz", "entity.create.contraption": "Vorrichtung", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "Portalkran Vorrichtung", "entity.create.seat": "Sitz", "entity.create.stationary_contraption": "Stationäre Vorrichtung", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Kupferklumpen", "item.create.copper_sheet": "Kupferblech", "item.create.crafter_slot_cover": "Handwerkseinheit Slot Abdeckung", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Zerkleinertes Aluminiumerz", "item.create.crushed_brass": "Zerkleinertes Messing", "item.create.crushed_copper_ore": "Zerkleinertes Kupfererz", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Integrierter Schaltkreis", "item.create.iron_sheet": "Eisenblech", "item.create.lapis_sheet": "Lapislazuliblech", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Loren Vorrichtung", "item.create.minecart_coupling": "Lorenkupplung", "item.create.polished_rose_quartz": "Polierter Rosenquarz", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "einem Finger", "create.block.cart_assembler.invalid": "Platziere deinen Lorenmonteur auf einer Schiene.", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Mahlen (Mahlwerk)", "create.recipe.milling": "Mahlen (Mahlstein)", "create.recipe.fan_washing": "Sammelwaschen", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "Propeller ziehen von unterhalb", "create.tooltip.chute.contains": "Enthält: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "Endlose Versorgung", "create.hint.hose_pulley": "Das angewählte Gewässer wird als unendlich betrachtet.", "create.hint.mechanical_arm_no_targets.title": "Keine Ziele", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Schleim matscht", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "Lohe kaut glücklich", - "create.subtitle.schematicannon_launch_block": "Bauplankanone schießt", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "Bauplankanone endet", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "Schleim matscht", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "Bauplankanone schießt", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "Mechanische Presse wird aktiviert", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "UNLOCALIZED: REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "UNLOCALIZED: A Chromatic material forged from _absorbed light_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "UNLOCALIZED: SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "UNLOCALIZED: A Chromatic material forged _in the void_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "UNLOCALIZED: MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart", "item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Work in progress!", - "create.tooltip.randomWipDescription0": "Bitte halte dies fern von Kindern", - "create.tooltip.randomWipDescription1": "Ein Babypanda stirbt jedes mal wenn du diesen Gegenstand benutzt. Jedes. Mal.", - "create.tooltip.randomWipDescription2": "Benutzung auf eigene Gefahr.", - "create.tooltip.randomWipDescription3": "Dies ist nicht der Gegenstand den du suchst, *wackelt mit Finger* bitte geht auseinander.", - "create.tooltip.randomWipDescription4": "Dieser Gegenstand wird sich in 10 Sekunden selbst zerstören. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Glaub mir, es ist nutzlos.", - "create.tooltip.randomWipDescription6": "Bei der Verwendung dieses Gegenstands stimmst du hiermit unserem Haftungsausschluss zu und nimmst dessen Bedingungen an.", - "create.tooltip.randomWipDescription7": "Dieser ist nicht für dich. Wie wäre es mit dem?", - "create.tooltip.randomWipDescription8": "Benutze es und bereue deine Entscheidung umgehend.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", diff --git a/src/generated/resources/assets/create/lang/unfinished/es_es.json b/src/generated/resources/assets/create/lang/unfinished/es_es.json index 12880cfef..56f7e7460 100644 --- a/src/generated/resources/assets/create/lang/unfinished/es_es.json +++ b/src/generated/resources/assets/create/lang/unfinished/es_es.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 643", + "_": "Missing Localizations: 740", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Mineral de zinc", "entity.create.contraption": "Artilugio", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "Artilugio de grúa", "entity.create.seat": "Asiento", "entity.create.stationary_contraption": "Artilugio estacionario", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Pepita de cobre", "item.create.copper_sheet": "Lámina de cobre", "item.create.crafter_slot_cover": "Tapa de ranura del Autoensamblador mecánico", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Mineral de aluminio molido", "item.create.crushed_brass": "Latón molido", "item.create.crushed_copper_ore": "Mineral de cobre molido", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Chip de circuito integrado", "item.create.iron_sheet": "Lámina de hierro", "item.create.lapis_sheet": "Lámina de lapislázuli", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Artilugio de vagoneta", "item.create.minecart_coupling": "Acoplamiento de vagoneta", "item.create.polished_rose_quartz": "Cuarzo rosado pulido", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "un Desplegador rebelde", "create.block.cart_assembler.invalid": "Coloque su Ensamblador de vagonetas en un bloque de Raíles", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Trituración", "create.recipe.milling": "Fresado", "create.recipe.fan_washing": "Lavado a granel", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "Los ventiladores tiran desde abajo", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "Suministro sin fondo", "create.hint.hose_pulley": "La masa de fluido objetivo se considera infinita", "create.hint.mechanical_arm_no_targets.title": "No hay objetivos", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Slime aplastado", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "Blaze mastica felizmente", - "create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "Acabados de Schematicannon", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "Slime aplastado", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "Disparos de Schematicannon", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "La Prensa Mecánica se activa", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "RESPLANDOR REFINADO", "item.create.refined_radiance.tooltip.summary": "Material cromático forjado a partir de _luz absorbida_", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "ACERO SOMBRÍO", "item.create.shadow_steel.tooltip.summary": "Un material cromático forjado _en el vacío_", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "ENSAMBLADOR DE VAGONETAS", "item.create.minecart_coupling.tooltip.summary": "_Encadena_ todas tus _Vagonetas_ o _Artilugios de vagoneta_ para formar un majestuoso Tren", "item.create.minecart_coupling.tooltip.condition1": "Cuando se utiliza en Vagonetas", "item.create.minecart_coupling.tooltip.behaviour1": "_Acopla_ dos Vagonetas, intentando mantenerlas a una _distancia constante_ mientras se mueven", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "¡Trabajo en curso!", - "create.tooltip.randomWipDescription0": "Por favor, mantenga este artículo fuera del alcance de los niños", - "create.tooltip.randomWipDescription1": "Un bebé panda muere cada vez que usas este objeto. Cada vez. Cada vez", - "create.tooltip.randomWipDescription2": "Úsalo bajo tu propio riesgo", - "create.tooltip.randomWipDescription3": "Este no es el objeto que buscas, *mueve los dedos* por favor, dispérsate", - "create.tooltip.randomWipDescription4": "Este objeto se autodestruirá en 10 segundos. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Créeme, es inútil", - "create.tooltip.randomWipDescription6": "Al utilizar este elemento, aceptas nuestra exención de responsabilidad y estás de acuerdo con sus términos", - "create.tooltip.randomWipDescription7": "Este quizás no es para ti. ¿Qué tal ese?", - "create.tooltip.randomWipDescription8": "Úsalo y arrepiéntete de tu decisión inmediatamente", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 f3de8dd15..208abfcf0 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: 1266", + "_": "Missing Localizations: 1352", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Mineral de Zinc", "entity.create.contraption": "Artefacto", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "Asiento", "entity.create.stationary_contraption": "Artefacto Estacionario", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Pepita de Cobre", "item.create.copper_sheet": "Lámina de Cobre", "item.create.crafter_slot_cover": "Cubierta de Ranura del Crafter", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Mineral de Aluminio Molido", "item.create.crushed_brass": "Latón Molido", "item.create.crushed_copper_ore": "Mineral de Cobre Molido", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Circuito Integrado", "item.create.iron_sheet": "Lámina de Hierro", "item.create.lapis_sheet": "Lámina de Lapislázuli", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Artefacto de Vagón", "item.create.minecart_coupling": "Acoplamiento de Vagonetas", "item.create.polished_rose_quartz": "Cuarzo Rosa Pulido", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer", "create.block.cart_assembler.invalid": "UNLOCALIZED: Place your Cart Assembler on a rail block", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "UNLOCALIZED: Crushing", "create.recipe.milling": "UNLOCALIZED: Milling", "create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "UNLOCALIZED: tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", - "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "UNLOCALIZED: REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "UNLOCALIZED: A Chromatic material forged from _absorbed light_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "UNLOCALIZED: SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "UNLOCALIZED: A Chromatic material forged _in the void_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "UNLOCALIZED: MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart", "item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", - "create.tooltip.wip": "UNLOCALIZED: WIP", - "create.tooltip.workInProgress": "UNLOCALIZED: Work in progress!", - "create.tooltip.randomWipDescription0": "UNLOCALIZED: Please keep this item away from children.", - "create.tooltip.randomWipDescription1": "UNLOCALIZED: A baby panda dies every time you use this item. Every. Time.", - "create.tooltip.randomWipDescription2": "UNLOCALIZED: Use at your own risk.", - "create.tooltip.randomWipDescription3": "UNLOCALIZED: This is not the item you are looking for, *finger-wiggles* please disperse.", - "create.tooltip.randomWipDescription4": "UNLOCALIZED: This item will self-destruct in 10 seconds. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "UNLOCALIZED: Believe me, it's useless.", - "create.tooltip.randomWipDescription6": "UNLOCALIZED: By using this item, you hereby consent to our disclaimer and agree to its terms.", - "create.tooltip.randomWipDescription7": "UNLOCALIZED: This one maybe isn't for you. What about that one?", - "create.tooltip.randomWipDescription8": "UNLOCALIZED: Use it and regret your decision immediately.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 558c2ff87..f852897b6 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: 1194", + "_": "Missing Localizations: 1291", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Minerai de zinc", "entity.create.contraption": "Engin", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "Siège", "entity.create.stationary_contraption": "Engin stationnaire", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Pépite de cuivre", "item.create.copper_sheet": "Plaques de cuivre", "item.create.crafter_slot_cover": "Couvercle", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Aluminium concassé", "item.create.crushed_brass": "Laiton concassé", "item.create.crushed_copper_ore": "Cuivre concassé", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Circuit intégré", "item.create.iron_sheet": "Plaque de Fer", "item.create.lapis_sheet": "Feuille de lapis", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Engin de wagonnet", "item.create.minecart_coupling": "Lien pour wagonnet", "item.create.polished_rose_quartz": "Quartz rose poli", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "un déployeur voyou", "create.block.cart_assembler.invalid": "UNLOCALIZED: Place your Cart Assembler on a rail block", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Ecrasement", "create.recipe.milling": "Mouture", "create.recipe.fan_washing": "Lavage", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Bruit de slime", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", - "create.subtitle.schematicannon_launch_block": "Tir de schémacanon", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "Fin de schémacanon", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "Bruit de slime", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "Tir de schémacanon", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "Activation de la presse mechanique", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "ÉCLAT RAFFINÉ", "item.create.refined_radiance.tooltip.summary": "Un matériau chromatique forgé à partir de _lumière_ _absorbée_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "ACIER SOMBRE", "item.create.shadow_steel.tooltip.summary": "Un matériau chromatique forgé _dans_ _le_ _néant_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "LIEN POUR WAGONS", "item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart", "item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", - "create.tooltip.wip": "En cours", - "create.tooltip.workInProgress": "En cours!", - "create.tooltip.randomWipDescription0": "Veuillez garder cet objet hors de portée des enfants.", - "create.tooltip.randomWipDescription1": "Un bébé panda meurt chaque fois que vous utilisez cet objet. Chaque. Fois.", - "create.tooltip.randomWipDescription2": "À utiliser à vos risques et périls.", - "create.tooltip.randomWipDescription3": "Ce n'est pas l'objet que vous recherchez, *agite les doigts* circulez.", - "create.tooltip.randomWipDescription4": "Cet objet s'autodétruit en 10 secondes. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Croyez-moi, c'est inutile.", - "create.tooltip.randomWipDescription6": "En utilisant cet article, vous êtes responsables et acceptez ses conditions.", - "create.tooltip.randomWipDescription7": "Celui-ci n'est peut-être pas pour vous. Que dire de celui-là?", - "create.tooltip.randomWipDescription8": "Utilisez-le et regrettez immédiatement votre décision.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 afa0b3942..4bb49e83f 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: 660", + "_": "Missing Localizations: 757", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Zinco grezzo", "entity.create.contraption": "Contrazione", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "Sedile", "entity.create.stationary_contraption": "Contrazione stazionaria", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Pepita di rame", "item.create.copper_sheet": "Lamiera di rame", "item.create.crafter_slot_cover": "Rivestimento per slot da costruzione", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Alluminio grezzo frantumato", "item.create.crushed_brass": "Ottone frantumato", "item.create.crushed_copper_ore": "Rame grezzo frantumato", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Circuito integrato", "item.create.iron_sheet": "Lamiera di ferro", "item.create.lapis_sheet": "Lamiera di lapislazzuli", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Contrazione per carrello da miniera", "item.create.minecart_coupling": "Aggancio per carrelli da miniera", "item.create.polished_rose_quartz": "Quarzo rosa levigato", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "un disadattato", "create.block.cart_assembler.invalid": "Piazza il tuo assemblatore di carrelli da miniera su un binario", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Frantumazione", "create.recipe.milling": "Macinatura", "create.recipe.fan_washing": "Lavaggio volumetrico", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "I ventilatori tirano da sotto", "create.tooltip.chute.contains": "Contiene: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "Buco senza fondo", "create.hint.hose_pulley": "Il corpo fluido selezionato è considerato infinito.", "create.hint.mechanical_arm_no_targets.title": "Nessun bersaglio", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Slime schiacciato", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "Il blaze lo gusta felicemente", - "create.subtitle.schematicannon_launch_block": "Tiri del cannoneschematico", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "Finiture cannoneschematico", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "Slime schiacciato", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "Tiri del cannoneschematico", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "Pressa meccanica attiva", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "RADIANCE RAFFINATA", "item.create.refined_radiance.tooltip.summary": "Un materiale cromatico forgiato dalla _luce_ _assorbita_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "ACCIAIO OSCURO", "item.create.shadow_steel.tooltip.summary": "Un materiale cromatico forgiato _nel_ _vuoto_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "AGGANCIO PER CARRELLI DA MINIERA", "item.create.minecart_coupling.tooltip.summary": "_Concatena_ i _carrelli da miniera_ le _macchine su carrello_ insieme per formare un treno maestoso.", "item.create.minecart_coupling.tooltip.condition1": "Quando usato su un carrello da miniera", "item.create.minecart_coupling.tooltip.behaviour1": "_Concatena_ due carrelli insieme, provando a tenerli uniti a una _distanza costante_ mentre si muovono.", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Work in progress!", - "create.tooltip.randomWipDescription0": "Si prega di tenere questo oggetto lontano dai bambini.", - "create.tooltip.randomWipDescription1": "Un cucciolo di panda muore ogni volta che usi questo oggetto. Ogni. Volta.", - "create.tooltip.randomWipDescription2": "Da utilizzare a proprio rischio.", - "create.tooltip.randomWipDescription3": "Questo non è l'oggetto che stai cercando, *le dita si muovono* per favore stai in disparte.", - "create.tooltip.randomWipDescription4": "Questo oggetto si autodistruggerà tra 10 secondi. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Credimi, è inutile.", - "create.tooltip.randomWipDescription6": "Utilizzando questo articolo, acconsenti al nostro disclaimer e accetti i suoi termini.", - "create.tooltip.randomWipDescription7": "Questo forse non fa per te. Che ne dici di quello?", - "create.tooltip.randomWipDescription8": "Usalo e rimpiangi immediatamente la tua decisione.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 9bf53aabf..5ca80c09d 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: 24", + "_": "Missing Localizations: 121", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "亜鉛鉱石", "entity.create.contraption": "からくり", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "ガントリーからくり", "entity.create.seat": "シート", "entity.create.stationary_contraption": "付設からくり", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "銅塊", "item.create.copper_sheet": "銅板", "item.create.crafter_slot_cover": "クラフタースロットカバー", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "砕いたアルミニウム鉱石", "item.create.crushed_brass": "砕いた真鍮", "item.create.crushed_copper_ore": "砕いた銅鉱石", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "集積回路", "item.create.iron_sheet": "鉄板", "item.create.lapis_sheet": "ラピスラズリ板", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "からくり付きトロッコ", "item.create.minecart_coupling": "トロッコ連結器", "item.create.polished_rose_quartz": "磨かれたローズクォーツ", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "悪いデプロイヤー", "create.block.cart_assembler.invalid": "トロッコアセンブラはレールの上にのみ設置できます", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "粉砕", "create.recipe.milling": "製粉", "create.recipe.fan_washing": "一括洗浄", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "ファンが下から吸い込んでいます", "create.tooltip.chute.contains": "内容物: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "底なし搬出", "create.hint.hose_pulley": "対象となる液体は無限とみなされています。", "create.hint.mechanical_arm_no_targets.title": "ターゲットが見つかりません", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "このからくりトロッコは大きすぎて拾えません。", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "歯車がゴロゴロと鳴る", - "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "からくりが止まる", - "create.subtitle.wrench_rotate": "レンチを使う", "create.subtitle.mixing": "混ぜる音", "create.subtitle.mechanical_press_activation_belt": "メカニカルプレスがボンと鳴る", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "アイテムが滑る", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "ブレイズの咀嚼音", - "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", "create.subtitle.funnel_flap": "ファンネルがはためく", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "概略図砲が作業を終える", "create.subtitle.scroll_value": "スクロールのカチカチ音", + "create.subtitle.crafter_craft": "メカニカルクラフターがクラフトする", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "ハンドクランクが回る", + "create.subtitle.wrench_remove": "機械を壊す", + "create.subtitle.cogs": "歯車がゴロゴロと鳴る", + "create.subtitle.slime_added": "スライムがぐしゃっとつぶれる", + "create.subtitle.wrench_rotate": "レンチを使う", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "概略図砲が発射する", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "メカニカルプレスがガーンと鳴る", "create.subtitle.contraption_assemble": "からくりが動く", - "create.subtitle.crafter_craft": "メカニカルクラフターがクラフトする", - "create.subtitle.cranking": "ハンドクランクが回る", "create.subtitle.crafter_click": "メカニカルクラフターのカチカチ音", - "create.subtitle.wrench_remove": "機械を壊す", "create.subtitle.depot_plop": "デプロイヤーにアイテムが入れられる", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "高貴な光輝", "item.create.refined_radiance.tooltip.summary": "_吸収した光輝_から鍛造した色彩素材。", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "シャドウスチール", "item.create.shadow_steel.tooltip.summary": "_奈落の虚無_から鍛造した色彩素材。", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "トロッコ連結器", "item.create.minecart_coupling.tooltip.summary": "壮大な列車を作るために_トロッコ_や_からくり車両_を_連結_しよう。", "item.create.minecart_coupling.tooltip.condition1": "トロッコに使ったとき", "item.create.minecart_coupling.tooltip.behaviour1": "_2台_のトロッコを連結します。それらは移動中に_一定_の_距離_を保とうします。", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "作業中です!", - "create.tooltip.randomWipDescription0": "お子様の手の届かないところに保管してください。", - "create.tooltip.randomWipDescription1": "赤ちゃんパンダは、このアイテムを使うたびに死にます。そう、いつでもね。", - "create.tooltip.randomWipDescription2": "自己責任。", - "create.tooltip.randomWipDescription3": "これはあなたが探しているアイテムではありません。*人差し指を振って*ちっちっちっ、解散!", - "create.tooltip.randomWipDescription4": "このアイテムは10秒で自爆します。10、9、8 ...", - "create.tooltip.randomWipDescription5": "私を信じて、それは無駄だ。", - "create.tooltip.randomWipDescription6": "このアイテムを使うことにより、お客様は免責事項に同意し、その条件を承諾するものとします。", - "create.tooltip.randomWipDescription7": "これは君に向いていないかもしれない。あれはどう??", - "create.tooltip.randomWipDescription8": "それを使ったことをすぐ後悔するだろう。", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "歯車は隣接する歯車へ回転力を伝達します", "create.ponder.cogwheel.text_2": "このように連結された隣のシャフトは、逆方向に回転します", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "クリエイティブモーターによる回転力の生成", "create.ponder.creative_motor.text_1": "クリエイティブモーターは、コンパクトで調整できる原動機です", "create.ponder.creative_motor.text_2": "背面パネルを見てスクロールすると、モーターの回転速度を変更できます", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "デフォルトでは、デプロイヤーは右クリックの動作を模倣します", "create.ponder.deployer_modes.text_2": "レンチを使えば、左クリックの動作を模倣するように設定できます", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "レッドストーン信号によるデプロイヤーの制御", "create.ponder.deployer_redstone.text_1": "レッドストーン信号を受けている間、デプロイヤーは稼働しません", "create.ponder.deployer_redstone.text_2": "デプロイヤーは停止する前に、開始したサイクルは終了させます", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "空のブレイズバーナーは火打石と打ち金を使って火を付ければ装飾にも使えます", "create.ponder.empty_blaze_burner.text_5": "しかし、これは加工用の熱源には適していません", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "ケース入りファンの気流", "create.ponder.fan_direction.text_1": "ケース入りファンは、回転力を利用して気流を生み出します", "create.ponder.fan_direction.text_2": "気流の強さと方向は、供給される回転力に依存します", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "ファンを熱源に向けて設置すると、回転力を生成できます", "create.ponder.fan_source.text_2": "レッドストーン信号を受けると、回転力が生成されます", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "勢車による回転力の生成", "create.ponder.flywheel.text_1": "かまどエンジンで回転力を生成するには、勢車が必要です", "create.ponder.flywheel.text_2": "これによって生成される回転力は、非常に大きな応力許容量を持っています", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "回転速度は比較的速めです", "create.ponder.hand_crank.text_4": "スニークしながら右クリックし続けると、時計回りに回転します", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "大きな歯車による回転力の伝達", "create.ponder.large_cogwheel.text_1": "大きな歯車は、直角に接続できます", "create.ponder.large_cogwheel.text_2": "回転力の回転軸を変えてに伝達するのに役立ちます", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "これらのレシピの中には、ブレイズバーナーの熱を必要とするものがあります", "create.ponder.mechanical_press_compacting.text_4": "フィルタースロットは、2つのレシピが競合する場合に使えます", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "メカニカルソーによる伐採", "create.ponder.mechanical_saw_breaker.text_1": "メカニカルソーは回転力を供給すると、目の前の木を伐採できます", "create.ponder.mechanical_saw_breaker.text_2": "木を完全に伐採するには、木と地面を繋ぐ最後の根本を伐採しなければなりません", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "ポールが無いとメカニカルピストンは動きません", "create.ponder.piston_pole.text_2": "後ろに付けたポールの長さによって、伸び縮みする長さが決まります", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "稼働中のからくりとの搬出入", "create.ponder.portable_storage_interface.text_1": "稼働中のからくりに組み込まれた収納ブロックは、プレイヤーが開くことはできません", "create.ponder.portable_storage_interface.text_2": "この装置は、からくりを停止することなく、収納ブロックと搬出入できます", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "マウスホイールで搬出するスタック量を指定できます", "create.ponder.smart_chute.text_4": "レッドストーン信号で、スマートシュートを停止させることもできます", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "速度メーターによる動力情報の監視", "create.ponder.speedometer.text_1": "速度メーターは、接続された機械の現在の回転速度を表示します", "create.ponder.speedometer.text_2": "エンジニアのゴーグルを装着していると、より詳細な情報を得られます", "create.ponder.speedometer.text_3": "コンパレータは、速度メーターの測定値に応じたレッドストーン信号を出力します", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "からくりの角度の固定", "create.ponder.stabilized_bearings.text_1": "メカニカルベアリングが動いている構造物に組み込まれているとき ...", "create.ponder.stabilized_bearings.text_2": "...自身の角度を真っ直ぐに保とうとします", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "スニーク状態で右クリックし続けると、時計回りに回転します", "create.ponder.valve_handle.text_5": "バルブハンドルは、染色できます", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "水車による回転力の生成", "create.ponder.water_wheel.text_1": "水車は隣接する水流から回転力を生み出します", "create.ponder.water_wheel.text_2": "水流を受ける面が多ければ多いほど、水車の回転速度は速くなります", 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 17289ec89..d10fc6a39 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: 713", + "_": "Missing Localizations: 810", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "아연 광석", "entity.create.contraption": "장치", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "좌석", "entity.create.stationary_contraption": "고정된 장치", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "구리 조각", "item.create.copper_sheet": "구리 판", "item.create.crafter_slot_cover": "조합기 슬롯 덮개", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore", "item.create.crushed_brass": "분쇄된 황동", "item.create.crushed_copper_ore": "분쇄된 구리 광석", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "집적 회로", "item.create.iron_sheet": "철 판", "item.create.lapis_sheet": "청금석 판", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "광산 수레 장치", "item.create.minecart_coupling": "광산 수레 커플링", "item.create.polished_rose_quartz": "윤나는 장밋빛 석영", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "배포기", "create.block.cart_assembler.invalid": "카트조립기를 레일 위에 설치하세요", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "분쇄", "create.recipe.milling": "맷돌질", "create.recipe.fan_washing": "세척", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "선풍기가 아래에서 당김", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "목표 없음", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "슬라임이 철퍽거림", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "블레이즈가 행복하게 섭취함", - "create.subtitle.schematicannon_launch_block": "청사진 대포가 발포함", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "청사진 대포가 끝남", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "슬라임이 철퍽거림", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "청사진 대포가 발포함", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "압착기가 가동됨", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "_흡수된_ _빛_으로 제련된 색채 혼합물입니다.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "_공허_에서 제련된 색채 혼합물입니다.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "당신의 모든 _수레들을 이어 _멋진 _기차_를 만들어보세요.", "item.create.minecart_coupling.tooltip.condition1": "광산 수레에 사용할 때", "item.create.minecart_coupling.tooltip.behaviour1": "_두 수레를 묶어_ 이동할 때 고정된 _거리를 유지하게_ 합니다.", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Work in progress!", - "create.tooltip.randomWipDescription0": "Please keep this item away from children.", - "create.tooltip.randomWipDescription1": "A baby panda dies every time you use this item. Every. Time.", - "create.tooltip.randomWipDescription2": "Use at your own risk.", - "create.tooltip.randomWipDescription3": "This is not the item you are looking for, *finger-wiggles* please disperse.", - "create.tooltip.randomWipDescription4": "This item will self-destruct in 10 seconds. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Believe me, it's useless.", - "create.tooltip.randomWipDescription6": "By using this item, you hereby consent to our disclaimer and agree to its terms.", - "create.tooltip.randomWipDescription7": "This one maybe isn't for you. What about that one?", - "create.tooltip.randomWipDescription8": "Use it and regret your decision immediately.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 acb783a8e..72b9df586 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: 1577", + "_": "Missing Localizations: 1674", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "UNLOCALIZED: Zinc Ore", "entity.create.contraption": "UNLOCALIZED: Contraption", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "UNLOCALIZED: Seat", "entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Koper klompje", "item.create.copper_sheet": "UNLOCALIZED: Copper Sheet", "item.create.crafter_slot_cover": "UNLOCALIZED: Crafter Slot Cover", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore", "item.create.crushed_brass": "Gemalen Brons", "item.create.crushed_copper_ore": "UNLOCALIZED: Crushed Copper Ore", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", "item.create.iron_sheet": "IJzeren Platen", "item.create.lapis_sheet": "UNLOCALIZED: Lapis Sheet", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "UNLOCALIZED: Minecart Contraption", "item.create.minecart_coupling": "UNLOCALIZED: Minecart Coupling", "item.create.polished_rose_quartz": "UNLOCALIZED: Polished Rose Quartz", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer", "create.block.cart_assembler.invalid": "UNLOCALIZED: Place your Cart Assembler on a rail block", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Verpulveren", "create.recipe.milling": "UNLOCALIZED: Milling", "create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "UNLOCALIZED: tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", - "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "UNLOCALIZED: REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "UNLOCALIZED: A Chromatic material forged from _absorbed light_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "UNLOCALIZED: SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "UNLOCALIZED: A Chromatic material forged _in the void_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "UNLOCALIZED: MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart", "item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Work in progress!", - "create.tooltip.randomWipDescription0": "Houdt dit object buiten bereik van kinderen.", - "create.tooltip.randomWipDescription1": "Een baby panda sterft elke keer als je dit object gebruikt.", - "create.tooltip.randomWipDescription2": "Gebruikt dit object op eigen risico.", - "create.tooltip.randomWipDescription3": "Niks te zien hier, vervolg uw weg.", - "create.tooltip.randomWipDescription4": "Dit object zal zichzelf vernietigen in 10 seconden.", - "create.tooltip.randomWipDescription5": "Geloof me, het is nuteloos.", - "create.tooltip.randomWipDescription6": "Door dit object te gebruiken stemt u in met onze disclaimer en gaat u akkoord met de algemene voorwaarden.", - "create.tooltip.randomWipDescription7": "Deze is misschien niet geschikt voor jou.", - "create.tooltip.randomWipDescription8": "Gebruikt het en je zal meteen spijt hebben.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", diff --git a/src/generated/resources/assets/create/lang/unfinished/pl_pl.json b/src/generated/resources/assets/create/lang/unfinished/pl_pl.json index 3b4dd77cd..18dc98c92 100644 --- a/src/generated/resources/assets/create/lang/unfinished/pl_pl.json +++ b/src/generated/resources/assets/create/lang/unfinished/pl_pl.json @@ -1,5 +1,5 @@ { - "_": "Missing Localizations: 38", + "_": "Missing Localizations: 97", "_": "->------------------------] Game Elements [------------------------<-", @@ -58,7 +58,7 @@ "block.create.cogwheel": "Koło zębate", "block.create.content_observer": "Detektor zawartości", "block.create.controller_rail": "Tory sterujące", - "block.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "block.create.copper_backtank": "Miedziany zbiornik w plecaku", "block.create.copper_block": "Blok miedzi", "block.create.copper_casing": "Miedziana Obudowa", "block.create.copper_ore": "Ruda miedzi", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Ruda cynku", "entity.create.contraption": "Maszyna", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "Maszyna suwnicowa", "entity.create.seat": "Siedzenie", "entity.create.stationary_contraption": "Maszyna stacjonarna", @@ -439,11 +440,12 @@ "item.create.chocolate_glazed_berries": "Jagody w czekoladzie", "item.create.chromatic_compound": "Związek chromatyczny", "item.create.cinder_flour": "Rozżarzona mąka", - "item.create.copper_backtank": "UNLOCALIZED: Copper Backtank", + "item.create.copper_backtank": "Miedziany zbiornik w plecaku", "item.create.copper_ingot": "Sztabka miedzi", "item.create.copper_nugget": "Bryłka miedzi", "item.create.copper_sheet": "Arkusz miedzi", "item.create.crafter_slot_cover": "Przykrywka na slot stołu rzemieślniczego", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Rozkruszona ruda żelaza", "item.create.crushed_brass": "Rozkruszony mosiądz", "item.create.crushed_copper_ore": "Rozkruszona ruda miedzi", @@ -458,8 +460,8 @@ "item.create.crushed_tin_ore": "Rozkruszona ruda cyny", "item.create.crushed_uranium_ore": "Rozkruszona ruda uranu", "item.create.crushed_zinc_ore": "Rozkruszona ruda cynku", - "item.create.diving_boots": "UNLOCALIZED: Diving Boots", - "item.create.diving_helmet": "UNLOCALIZED: Diving Helmet", + "item.create.diving_boots": "Buty do nurkowania", + "item.create.diving_helmet": "Hełm do nurkowania", "item.create.dough": "Ciasto", "item.create.electron_tube": "Lampa elektronowa", "item.create.empty_blaze_burner": "Pusty płomienny palnik", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Układ scalony", "item.create.iron_sheet": "Arkusz żelaza", "item.create.lapis_sheet": "Arkusz lazurytu", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Maszyna w wagoniku", "item.create.minecart_coupling": "Łącznik wagoników", "item.create.polished_rose_quartz": "Wypolerowany kwarc różowy", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "zbuntowany aplikator", "create.block.cart_assembler.invalid": "Postaw monter wagoników na torze", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Kruszenie", "create.recipe.milling": "Mielenie", "create.recipe.fan_washing": "Hurtowe płukanie", @@ -682,7 +692,7 @@ "create.recipe.fan_blasting.fan": "Wiatrak za lawą", "create.recipe.pressing": "Tłoczenie", "create.recipe.mixing": "Mieszanie", - "create.recipe.deploying": "UNLOCALIZED: Deploying", + "create.recipe.deploying": "Aplikowanie", "create.recipe.automatic_shapeless": "Zautomatyzowanie nieokreślone konstruowanie", "create.recipe.automatic_brewing": "Zautomatyzowane warzenie", "create.recipe.packing": "Prasowanie", @@ -749,15 +759,15 @@ "create.orientation.alongX": "Wzdłuż X", "create.gui.terrainzapper.title": "Ręczny kształter", - "create.gui.terrainzapper.searchDiagonal": "UNLOCALIZED: Follow Diagonals", - "create.gui.terrainzapper.searchFuzzy": "UNLOCALIZED: Ignore Material Borders", - "create.gui.terrainzapper.patternSection": "UNLOCALIZED: Pattern", - "create.gui.terrainzapper.pattern.solid": "UNLOCALIZED: Solid", - "create.gui.terrainzapper.pattern.checkered": "UNLOCALIZED: Checkerboard", - "create.gui.terrainzapper.pattern.inversecheckered": "UNLOCALIZED: Inverted Checkerboard", - "create.gui.terrainzapper.pattern.chance25": "UNLOCALIZED: 25% Roll", - "create.gui.terrainzapper.pattern.chance50": "UNLOCALIZED: 50% Roll", - "create.gui.terrainzapper.pattern.chance75": "UNLOCALIZED: 75% Roll", + "create.gui.terrainzapper.searchDiagonal": "Wzdłuż linii ukośnych", + "create.gui.terrainzapper.searchFuzzy": "Ignoruj krawędzie materiałów", + "create.gui.terrainzapper.patternSection": "Wzór", + "create.gui.terrainzapper.pattern.solid": "Ciągły", + "create.gui.terrainzapper.pattern.checkered": "Szachownica", + "create.gui.terrainzapper.pattern.inversecheckered": "Odrócona szachownica", + "create.gui.terrainzapper.pattern.chance25": "Obrót o 25%", + "create.gui.terrainzapper.pattern.chance50": "Obrót o 50%", + "create.gui.terrainzapper.pattern.chance75": "Obrót o 75%", "create.gui.terrainzapper.placement": "Położenie", "create.gui.terrainzapper.placement.merged": "Połączony", "create.gui.terrainzapper.placement.attached": "Przyłączony", @@ -766,8 +776,8 @@ "create.gui.terrainzapper.brush.cuboid": "Prostopadłościan", "create.gui.terrainzapper.brush.sphere": "Kula", "create.gui.terrainzapper.brush.cylinder": "Walec", - "create.gui.terrainzapper.brush.surface": "UNLOCALIZED: Surface", - "create.gui.terrainzapper.brush.cluster": "UNLOCALIZED: Cluster", + "create.gui.terrainzapper.brush.surface": "Powierzchnia", + "create.gui.terrainzapper.brush.cluster": "Grupa", "create.gui.terrainzapper.tool": "Narzędzie", "create.gui.terrainzapper.tool.fill": "Wypełnianie", "create.gui.terrainzapper.tool.place": "Stawianie", @@ -777,8 +787,8 @@ "create.gui.terrainzapper.tool.flatten": "Wypłaszczanie", "create.terrainzapper.shiftRightClickToSet": "Shift+Prawe kliknięcie, aby wybrać kształt", - "create.terrainzapper.usingBlock": "UNLOCALIZED: Using: %1$s", - "create.terrainzapper.leftClickToSet": "UNLOCALIZED: Left-Click a Block to set Material", + "create.terrainzapper.usingBlock": "Używając: %1$s", + "create.terrainzapper.leftClickToSet": "Kliknij LPM na blok aby ustawić materiał", "create.minecart_coupling.two_couplings_max": "Wagoniki nie mogą mieć więcej niż dwa łączniki każdy", "create.minecart_coupling.unloaded": "Część twojego pociągu wydaje się być w niezaładowanych Chunkach.", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "Wiatraki ciągną od dołu", "create.tooltip.chute.contains": "Zawiera: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "Niewyczerpany zapas", "create.hint.hose_pulley": "Wybrane zbiornik cieczy jest uznany za nieskończony", "create.hint.mechanical_arm_no_targets.title": "Brak celi", @@ -1131,35 +1155,41 @@ "create.command.killTPSCommand.status.usage.1": "[Create]: Użyj \"/killtps start\", aby sztucznie spowolnić serwer\n", "create.command.killTPSCommand.argument.tickTime": "tickTime", - "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_too_big": "Ta maszyna w wagoniku jest zbyt duża, aby ją podnieść", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Szlam plaska", - "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", - "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", - "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", - "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", - "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", + "create.subtitle.contraption_disassemble": "Maszyna staje", + "create.subtitle.mixing": "Dźwięki mieszania", + "create.subtitle.mechanical_press_activation_belt": "Mechaniczna prasa stuka", + "create.subtitle.worldshaper_place": "Kształter strzela", + "create.subtitle.depot_slide": "Przedmiot ślizga się", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "Płomyk szczęśliwie przeżuwa", - "create.subtitle.schematicannon_launch_block": "Schematoarmata strzela", - "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", + "create.subtitle.funnel_flap": "Lejek trzepocze", "create.subtitle.schematicannon_finish": "Schematoarmata skończyła", - "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.scroll_value": "Kliknięcie", + "create.subtitle.crafter_craft": "Mechaniczny stół rzemieślniczy konstruuje", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "Ręczna korba obraca się", + "create.subtitle.wrench_remove": "Komponent niszczy się", + "create.subtitle.cogs": "Koła zębate terkoczą", + "create.subtitle.slime_added": "Szlam plaska", + "create.subtitle.wrench_rotate": "Klucz skrzypi", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "Aplikator poleruje", + "create.subtitle.deny": "Dźwięk odmowy", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "Schematoarmata strzela", + "create.subtitle.copper_armor_equip": "Sprzęt do nurkowania pobrzękuje", "create.subtitle.mechanical_press_activation": "Mechaniczna prasa się uruchamia", - "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", - "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", - "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", - "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", + "create.subtitle.contraption_assemble": "Maszyna przesuwa się", + "create.subtitle.crafter_click": "Mechaniczny stół rzemieślniczy stuka", + "create.subtitle.depot_plop": "Przedmiot ląduje", + "create.subtitle.confirm": "Dźwięk potwierdzenia", "_": "->------------------------] Item Descriptions [------------------------<-", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "ŚWIETLISTY MATERIAŁ", "item.create.refined_radiance.tooltip.summary": "Chromatyczny materiał powstały z _absorbcji światła_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "MROCZNA STAL", "item.create.shadow_steel.tooltip.summary": "Chromatyczny materiał powstały w _otchłani_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "ŁĄCZNIK WAGONIKÓW", "item.create.minecart_coupling.tooltip.summary": "_Łączy_ wszystkie Twoje _wagoniki_ lub _maszyny torowe_, tworząc majestatyczny pociąg.", "item.create.minecart_coupling.tooltip.condition1": "Kiedy użyto na wagoniku", "item.create.minecart_coupling.tooltip.behaviour1": "_Łączy_ dwa wagoniki, próbując utrzymać je w stałej odległości od siebie.", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Praca w toku!", - "create.tooltip.randomWipDescription0": "Trzymać z dala od dzieci.", - "create.tooltip.randomWipDescription1": "Mała panda ginie za każdym razem, kiedy patrzysz na ten przedmiot. Za. Każdym. Razem.", - "create.tooltip.randomWipDescription2": "Używaj na własną odpowiedzialność.", - "create.tooltip.randomWipDescription3": "To nie ten przedmiot, którego szukasz, proszę się rozejść.", - "create.tooltip.randomWipDescription4": "Ten przedmiot ulegnie autodestrukcji za 10 sekund. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Uwierz mi, jest bezużyteczny.", - "create.tooltip.randomWipDescription6": "Używając tego przedmiotu, zgadzasz się na warunki umowy.", - "create.tooltip.randomWipDescription7": "Ten przedmiot chyba nie jest dla Ciebie. A może ten?", - "create.tooltip.randomWipDescription8": "Użyj tego i natychmiast będziesz tego żałował.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1538,11 +1593,11 @@ "create.ponder.blaze_burner.text_3": "Z użyciem płomiennego ciasta, palnik może uzyskać szczególnie wysoką temperaturę", "create.ponder.blaze_burner.text_4": "Dostarczanie płomykowi przedmiotów może zostać zautomatyzowane z użyciem aplikatorów lub mechanicznych ramion", - "create.ponder.brass_funnel.header": "Mosiężny lejek", - "create.ponder.brass_funnel.text_1": "Andezytowe lejki mogą pobierać jedynie pojedyncze przedmioty", - "create.ponder.brass_funnel.text_2": "Mosiężne lejki mogą pobierać nawet pełne stosy", + "create.ponder.brass_funnel.header": "Mosiężny lej", + "create.ponder.brass_funnel.text_1": "Andezytowe leje mogą pobierać jedynie pojedyncze przedmioty", + "create.ponder.brass_funnel.text_2": "Mosiężne leje mogą pobierać nawet pełne stosy", "create.ponder.brass_funnel.text_3": "Przewijanie na slocie filtrującym pozwala na precyzyjną kontrolę nad maksymalną wielkością stosu", - "create.ponder.brass_funnel.text_4": "Użycie przedmiotów patrząc na slot filtrujący spowoduje, że lejek będzie przesyłał tylko pasujące przedmioty", + "create.ponder.brass_funnel.text_4": "Użycie przedmiotu patrząc na slot filtrujący spowoduje, że lej będzie przesyłał tylko pasujące przedmioty", "create.ponder.brass_tunnel.header": "Używanie mosiężnych tuneli", "create.ponder.brass_tunnel.text_1": "Mosiężne tunele mogą być użyte do przykrycia Twoich taśmociągów", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "Koła zębate przekazują obrót do sąsiadujących kół", "create.ponder.cogwheel.text_2": "Koła połączone w ten sposób będą obracać się w przeciwnych kierunkach", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "Generowanie siły obrotowej z użyciem kreatywnego silnika", "create.ponder.creative_motor.text_1": "Kreatywny silnik to kompaktowe i regulowane źródło siły obrotowej", "create.ponder.creative_motor.text_2": "Przewijanie patrząc na tylny panel zmienia prędkość obrotu", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "Domyślnie, aplikator imituje prawe kliknięcie", "create.ponder.deployer_modes.text_2": "Może być przestawiony na lewe kliknięcie używając klucza", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "Kontrolowanie aplikatorów z użyciem Redstone'a", "create.ponder.deployer_redstone.text_1": "Zasilone przez Redstone, aplikatory nie aktywują się", "create.ponder.deployer_redstone.text_2": "Przed zatrzymaniem, aplikatory dokończą już zaczętą czynność", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "Dla celów dekoracyjnych, puste palniki można też zapalić krzesiwem", "create.ponder.empty_blaze_burner.text_5": "Nie będzie on dawał jednak ciepła", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "Przepływ powietrza przez izolowane wiatraki", "create.ponder.fan_direction.text_1": "Izolowane wiatraki używają siły obrotowej, aby wytworzyć przepływ powietrza", "create.ponder.fan_direction.text_2": "Siła i kierunek przepływu zależy od właściwości siły obrotu", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "Wiatraki skierowane w stronę źródła ciepła generują siłę obrotową", "create.ponder.fan_source.text_2": "Po zasileniu, wiatraki zaczną przesyłać siłę do przylegających komponentów", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "Generowanie siły obrotowej z użyciem koła zamachowego", "create.ponder.flywheel.text_1": "Koła zamachowe są wymagane, aby generować siłę obrotową przy pomocy silnika spalinowego", "create.ponder.flywheel.text_2": "Wyprodukowana w ten sposób siła ma bardzo dużą odporność na obciążenie", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "Wytwarzana prędkość jest dosyć duża!", "create.ponder.hand_crank.text_4": "Trzymaj PPM skradając się, aby obrócić ją zgodnie ze wskazówkami zegara", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "Przekazywanie siły obrotowej z użyciem dużych kół zębatych", "create.ponder.large_cogwheel.text_1": "Duże koła zębate mogą się łączyć ze sobą pod kątem prostym", "create.ponder.large_cogwheel.text_2": "Pomogą one w przekazywaniu siły obrotowej na inne osie obrotu", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "Niektóre z nich mogą wymagać użycia płomiennego palnika", "create.ponder.mechanical_press_compacting.text_4": "Slot filtrujący może być użyty w przypadku dwóch konfliktujących receptur", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "Ścinanie drzew z użyciem mechanicznej piły", "create.ponder.mechanical_saw_breaker.text_1": "Po otrzymaniu siły obrotowej, mechaniczna piła zetnie każde znajdujące się przed nią drzewo", "create.ponder.mechanical_saw_breaker.text_2": "Aby całkowicie ściąć drzewo, piła musi zniszczyć każdy blok łączący je z ziemią", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "Bez przyłączonych przedłużeń, mechaniczny tłok nie może się wysunąć", "create.ponder.piston_pole.text_2": "Długość przedłużenia z tyłu ustala maksymalny zasięg tłoka", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "Używanie przenośnych interfejsów magazynu", "create.ponder.portable_storage_interface.text_1": "Pojemniki na ruchomych maszynach nie mogą być otwarte przez gracza", "create.ponder.portable_storage_interface.text_2": "Ten komponent może współpracować z zawartością maszyny bez potrzeby jej zatrzymywania", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "Użyj rolki w myszce, aby sprecyzować maksymalną wielkość stosu", "create.ponder.smart_chute.text_4": "Sygnał Redstone zatrzyma działanie inteligentnych zsypów", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "Monitorowanie prędkości obrotu z użyciem prędkościomierza", "create.ponder.speedometer.text_1": "Prędkościomierz wyświetla obecną prędkość przyłączonych komponentów", "create.ponder.speedometer.text_2": "Mając na sobie gogle inżyniera, gracz może pozyskać dodatkowe informacje z miernika", "create.ponder.speedometer.text_3": "Komparatory mogą emitować sygnał Redstone bazując na pomiarach prędkościomierza", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "Stabilizowanie maszyn", "create.ponder.stabilized_bearings.text_1": "Kiedy łożyska mechaniczne są częścią ruchomej maszyny...", "create.ponder.stabilized_bearings.text_2": "...będą utrzymywać swoją obrotową część w pozycji wyjściowej", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "Trzymaj PPM skradając się, aby obrócić ją zgodnie ze wskazówkami zegara", "create.ponder.valve_handle.text_5": "Pokrętła mogą być zabarwione dla celów dekoracyjnych", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "Generowanie siły obrotowej z użyciem kół wodnych", "create.ponder.water_wheel.text_1": "Koła wodne pobierają energię z prądów wodnych", "create.ponder.water_wheel.text_2": "Im więcej stron ma dostęp do wody, tym szybciej koło się będzie obracać", 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 4d81d99bb..327048fc1 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: 1629", + "_": "Missing Localizations: 1715", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "UNLOCALIZED: Zinc Ore", "entity.create.contraption": "UNLOCALIZED: Contraption", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "UNLOCALIZED: Seat", "entity.create.stationary_contraption": "UNLOCALIZED: Stationary Contraption", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "UNLOCALIZED: Copper Nugget", "item.create.copper_sheet": "UNLOCALIZED: Copper Sheet", "item.create.crafter_slot_cover": "UNLOCALIZED: Crafter Slot Cover", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "UNLOCALIZED: Crushed Aluminum Ore", "item.create.crushed_brass": "UNLOCALIZED: Crushed Brass", "item.create.crushed_copper_ore": "UNLOCALIZED: Crushed Copper Ore", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "UNLOCALIZED: Integrated Circuit", "item.create.iron_sheet": "Placas de Ferro", "item.create.lapis_sheet": "UNLOCALIZED: Lapis Sheet", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "UNLOCALIZED: Minecart Contraption", "item.create.minecart_coupling": "UNLOCALIZED: Minecart Coupling", "item.create.polished_rose_quartz": "UNLOCALIZED: Polished Rose Quartz", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "UNLOCALIZED: a rogue Deployer", "create.block.cart_assembler.invalid": "UNLOCALIZED: Place your Cart Assembler on a rail block", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Moendo", "create.recipe.milling": "UNLOCALIZED: Milling", "create.recipe.fan_washing": "UNLOCALIZED: Bulk Washing", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "UNLOCALIZED: Fans pull from Below", "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "UNLOCALIZED: No Targets", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "UNLOCALIZED: tickTime", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "UNLOCALIZED: Blaze Burner munches", - "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "UNLOCALIZED: Schematicannon dings", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "UNLOCALIZED: Slime squishes", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "UNLOCALIZED: Schematicannon fires", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "UNLOCALIZED: Mechanical Press clangs", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "UNLOCALIZED: REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "UNLOCALIZED: A Chromatic material forged from _absorbed light_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "UNLOCALIZED: SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "UNLOCALIZED: A Chromatic material forged _in the void_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "UNLOCALIZED: MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "UNLOCALIZED: _Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.condition1": "UNLOCALIZED: When Used on Minecart", "item.create.minecart_coupling.tooltip.behaviour1": "UNLOCALIZED: _Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", - "create.tooltip.wip": "UNLOCALIZED: WIP", - "create.tooltip.workInProgress": "UNLOCALIZED: Work in progress!", - "create.tooltip.randomWipDescription0": "UNLOCALIZED: Please keep this item away from children.", - "create.tooltip.randomWipDescription1": "UNLOCALIZED: A baby panda dies every time you use this item. Every. Time.", - "create.tooltip.randomWipDescription2": "UNLOCALIZED: Use at your own risk.", - "create.tooltip.randomWipDescription3": "UNLOCALIZED: This is not the item you are looking for, *finger-wiggles* please disperse.", - "create.tooltip.randomWipDescription4": "UNLOCALIZED: This item will self-destruct in 10 seconds. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "UNLOCALIZED: Believe me, it's useless.", - "create.tooltip.randomWipDescription6": "UNLOCALIZED: By using this item, you hereby consent to our disclaimer and agree to its terms.", - "create.tooltip.randomWipDescription7": "UNLOCALIZED: This one maybe isn't for you. What about that one?", - "create.tooltip.randomWipDescription8": "UNLOCALIZED: Use it and regret your decision immediately.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 1f092d472..e9358caf7 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: 557", + "_": "Missing Localizations: 654", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "Цинковая руда", "entity.create.contraption": "Штуковина", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", "entity.create.seat": "Сиденье", "entity.create.stationary_contraption": "Стационарная штуковина", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "Кусочек меди", "item.create.copper_sheet": "Медный лист", "item.create.crafter_slot_cover": "Крышка на слот крафтера", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "Измельчённая алюминиевая руда", "item.create.crushed_brass": "Дроблёная латунь", "item.create.crushed_copper_ore": "Дроблёная медная руда", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "Интегральная схема", "item.create.iron_sheet": "Железный лист", "item.create.lapis_sheet": "Лазуритовый лист", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "Вагонеточная штуковина", "item.create.minecart_coupling": "Связыватель вагонеток", "item.create.polished_rose_quartz": "Полированный розовый кварц", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "автономным активатором", "create.block.cart_assembler.invalid": "Поместите сборщик вагонеток на блок рельс", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "Измельчение", "create.recipe.milling": "Помол", "create.recipe.fan_washing": "Массовая промывка", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "Вентилятор тянет снизу", "create.tooltip.chute.contains": "Содержит: %1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "Безграничное снабжение", "create.hint.hose_pulley": "Целевой водный резервуар считается бесконечным.", "create.hint.mechanical_arm_no_targets.title": "Нет целей", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "Время тика", "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "Намазывание слизи", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "Всполох радостно жуёт", - "create.subtitle.schematicannon_launch_block": "Выстрелы схематичной пушки", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "Схематичная пушка закончила работу", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "Намазывание слизи", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "Выстрелы схематичной пушки", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "Механический пресс активирован", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "Хроматический материал, _добытый_ _из_ _поглощенного_ _света_.", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "Хроматический материал, _добытый_ _в_ _пустоте_.", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "_Соединяет_ ваши _вагонетки_ или _Перевозочные устройства_ вместе, чтобы создать великолепный поезд.", "item.create.minecart_coupling.tooltip.condition1": "При использовании на вагонетке", "item.create.minecart_coupling.tooltip.behaviour1": "_Соединяет_ две вагонетки вместе, пытаясь держать их на _определенной дистанции_ при движении.", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Работа продолжается!", - "create.tooltip.randomWipDescription0": "Пожалуйста держите этот предмет подальше от детей!", - "create.tooltip.randomWipDescription1": "Маленькая панда умирает каждый раз, когда вы используете этот предмет. Каждый. Раз.", - "create.tooltip.randomWipDescription2": "Используйте на свой страх и риск.", - "create.tooltip.randomWipDescription3": "Это не тот предмет, который вы ищете, *шевелит пальцами* пожалуйста, ускорьтесь.", - "create.tooltip.randomWipDescription4": "Этот предмет самоуничтожится через 10 секунд. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Поверьте мне, это бесполезно.", - "create.tooltip.randomWipDescription6": "Используя этот пункт, вы тем самым соглашаетесь с нашим отказом от ответственности и соглашаетесь с его условиями.", - "create.tooltip.randomWipDescription7": "Этот, возможно, но не для тебя. Как насчет этого?", - "create.tooltip.randomWipDescription8": "Используя его, вы немедленно пожалеете о своем решении.", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1594,7 +1649,7 @@ "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", + "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exactly like Chain Drives", "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", 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 513325f0d..dd31aeb2c 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: 43", + "_": "Missing Localizations: 140", "_": "->------------------------] Game Elements [------------------------<-", @@ -414,6 +414,7 @@ "block.create.zinc_ore": "锌矿石", "entity.create.contraption": "装置", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "entity.create.gantry_contraption": "起重机装置", "entity.create.seat": "坐垫", "entity.create.stationary_contraption": "固定装置", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "铜粒", "item.create.copper_sheet": "铜板", "item.create.crafter_slot_cover": "合成器盖板", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "粉碎铝矿石", "item.create.crushed_brass": "粉碎黄铜", "item.create.crushed_copper_ore": "粉碎铜矿石", @@ -475,6 +477,7 @@ "item.create.integrated_circuit": "集成电路板", "item.create.iron_sheet": "铁板", "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "装配过的矿车", "item.create.minecart_coupling": "矿车连轴器", "item.create.polished_rose_quartz": "磨制玫瑰石英", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "二五仔机械手", "create.block.cart_assembler.invalid": "请将矿车装配器放置在铁轨上", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "粉碎", "create.recipe.milling": "研磨", "create.recipe.fan_washing": "批量洗涤", @@ -1105,6 +1115,20 @@ "create.tooltip.chute.fans_pull_down": "鼓风机从下方进行吸引", "create.tooltip.chute.contains": "内含物品:%1$s x%2$s", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + "create.hint.hose_pulley.title": "无限供应", "create.hint.hose_pulley": "目标液体对象被视为无限量的。", "create.hint.mechanical_arm_no_targets.title": "没有目标", @@ -1132,32 +1156,38 @@ "create.command.killTPSCommand.argument.tickTime": "tickTime", "create.contraption.minecart_contraption_too_big": "这一矿车装置似乎太大了,无法变为拾捡状态", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "粘液:挤碎声", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "烈焰人:咀嚼", - "create.subtitle.schematicannon_launch_block": "蓝图加农炮:发射", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "蓝图加农炮:叮", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "粘液:挤碎声", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "蓝图加农炮:发射", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "辊压机:工作中", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1398,27 +1428,52 @@ "item.create.refined_radiance.tooltip": "光辉石", "item.create.refined_radiance.tooltip.summary": "一种用_光辉_锻造的化合物材料。", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "暗影钢", "item.create.shadow_steel.tooltip.summary": "一种用_虚空_锻造的化合物材料。", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "矿车连轴器", "item.create.minecart_coupling.tooltip.summary": "将多个_矿车_或运输结构链接在一起,构成雄伟的火车。", "item.create.minecart_coupling.tooltip.condition1": "作用与矿车时", "item.create.minecart_coupling.tooltip.behaviour1": "将两个矿车耦合在一起,在移动时将它们保持_恒定的距离_。", - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "这东西还没有做完!", - "create.tooltip.randomWipDescription0": "别把这玩意给熊孩子", - "create.tooltip.randomWipDescription1": "每次你使用这个东西,都会让一只无辜的熊猫丢掉性命,每!一!次!", - "create.tooltip.randomWipDescription2": "使用后果自负", - "create.tooltip.randomWipDescription3": "(摇手指)这可不是你在找的物品,走开吧", - "create.tooltip.randomWipDescription4": "自爆模式已启动,10,9,8..。", - "create.tooltip.randomWipDescription5": "相信我,你现在已经没有回头路了。", - "create.tooltip.randomWipDescription6": "如果你使用这个东西,那么本作者与它造成的任何后果没有责任。", - "create.tooltip.randomWipDescription7": "这玩意不是给你用的,换个吧", - "create.tooltip.randomWipDescription8": "试试就逝世。", - "_": "->------------------------] Ponder Content [------------------------<-", @@ -1634,6 +1689,8 @@ "create.ponder.cogwheel.text_1": "齿轮会将动力传递至临近的齿轮", "create.ponder.cogwheel.text_2": "以此方式连接的齿轮,旋转方向相反", + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + "create.ponder.creative_motor.header": "使用创造马达发生旋转", "create.ponder.creative_motor.text_1": "创造马达不仅能够手动调配输出旋转力,而且体积相当小巧", "create.ponder.creative_motor.text_2": "对其背侧面板滚动滑轮,可以改变马达的输出旋转转速", @@ -1670,6 +1727,12 @@ "create.ponder.deployer_modes.text_1": "在默认情况下,机械手模仿玩家的右击交互", "create.ponder.deployer_modes.text_2": "使用扳手可以将模式调整为模仿玩家的左击交互", + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + "create.ponder.deployer_redstone.header": "使用红石控制机械手", "create.ponder.deployer_redstone.text_1": "当被红石充能时,机械手会停止工作", "create.ponder.deployer_redstone.text_2": "在停止工作前,机械手会完成当前正在进行的工作周期", @@ -1688,6 +1751,11 @@ "create.ponder.empty_blaze_burner.text_4": "如果是为了美观,空的烈焰人燃烧室也可以被打火石点燃", "create.ponder.empty_blaze_burner.text_5": "但是,这样的热源不足以给机器提加工供足够的热量", + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + "create.ponder.fan_direction.header": "鼓风机的气流", "create.ponder.fan_direction.text_1": "鼓风机使用旋转力来制造气流", "create.ponder.fan_direction.text_2": "流速以及方向由所接收旋转力的强弱以及方向而定", @@ -1706,6 +1774,26 @@ "create.ponder.fan_source.text_1": "如鼓风机的扇叶向下朝着热源放置,鼓风机可以借此产生旋转力", "create.ponder.fan_source.text_2": "当鼓风机接受红石信号后,它便会向外供给旋转力", + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + "create.ponder.flywheel.header": "使用飞轮来产生旋转力", "create.ponder.flywheel.text_1": "飞轮和熔炉引擎必须配套使用,方可产生旋转力", "create.ponder.flywheel.text_2": "如此产生的旋转力具有非常大的应力值", @@ -1779,6 +1867,14 @@ "create.ponder.hand_crank.text_3": "它产生的转速相对较高", "create.ponder.hand_crank.text_4": "潜行长按右键可以顺时针旋转它", + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + "create.ponder.large_cogwheel.header": "使用大齿轮传递旋转力", "create.ponder.large_cogwheel.text_1": "大齿轮可以以特定的角度相互连接", "create.ponder.large_cogwheel.text_2": "可以利用大齿轮变更旋转轴向", @@ -1901,6 +1997,10 @@ "create.ponder.mechanical_press_compacting.text_3": "一些配方可能需要烈焰人燃烧室提供热量", "create.ponder.mechanical_press_compacting.text_4": "过滤槽可用于解决两个配方相互冲突的情况", + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + "create.ponder.mechanical_saw_breaker.header": "使用动力锯伐木", "create.ponder.mechanical_saw_breaker.text_1": "向其通入旋转力后,动力锯可以直接砍伐掉它面前的树木", "create.ponder.mechanical_saw_breaker.text_2": "想要一次性砍掉整棵树,锯子必须破坏掉树与地面连接的最后一个方块", @@ -1931,6 +2031,10 @@ "create.ponder.piston_pole.text_1": "若无相接的延长杆,动力活塞无法移动其他方块", "create.ponder.piston_pole.text_2": "在其背面安装的延长杆长度,决定了活塞的推动范围", + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + "create.ponder.portable_storage_interface.header": "装置存储交换", "create.ponder.portable_storage_interface.text_1": "玩家无法与运动装置内的存储空间进行交互", "create.ponder.portable_storage_interface.text_2": "这一组件可以在不停止装置的情况下与装置内的存储空间进行交互", @@ -2028,11 +2132,17 @@ "create.ponder.smart_chute.text_3": "使用鼠标滚轮可以指定被过滤的物品数量", "create.ponder.smart_chute.text_4": "通入红石信号,智能溜槽将会完全暂停工作", + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + "create.ponder.speedometer.header": "使用速度表来监测转速", "create.ponder.speedometer.text_1": "速度表能显示相接组件的转速", "create.ponder.speedometer.text_2": "当佩戴工程师护目镜时,可以看到仪表所显示的更详细的数据", "create.ponder.speedometer.text_3": "红石比较器可以根据速度表的数值输出不同强弱的红石信号", + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + "create.ponder.stabilized_bearings.header": "装置固定朝向", "create.ponder.stabilized_bearings.text_1": "当动力轴承在结构被带动时...", "create.ponder.stabilized_bearings.text_2": "...它会确保它转盘的垂直朝向不变", @@ -2064,6 +2174,8 @@ "create.ponder.valve_handle.text_4": "潜行右击可使它顺时针旋转", "create.ponder.valve_handle.text_5": "可以通过染色来美化阀门手轮", + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + "create.ponder.water_wheel.header": "使用水车产生旋转力", "create.ponder.water_wheel.text_1": "水车利用临近的水流来进行应力发生", "create.ponder.water_wheel.text_2": "水车接触水流的面越多,它的转速越高", 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 8b3a4f40a..af9c043ad 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: 662", + "_": "Missing Localizations: 133", "_": "->------------------------] Game Elements [------------------------<-", @@ -165,8 +165,8 @@ "block.create.gabbro_cobblestone_stairs": "碎輝長岩樓梯", "block.create.gabbro_cobblestone_wall": "碎輝長岩牆", "block.create.gabbro_pillar": "豎紋輝長岩", - "block.create.gantry_carriage": "UNLOCALIZED: Gantry Carriage", - "block.create.gantry_shaft": "UNLOCALIZED: Gantry Shaft", + "block.create.gantry_carriage": "門式起重機", + "block.create.gantry_shaft": "門式起重機滑道", "block.create.gearbox": "齒輪箱", "block.create.gearshift": "變速箱", "block.create.glass_fluid_pipe": "玻璃液體管道", @@ -373,15 +373,15 @@ "block.create.sequenced_gearshift": "可程式化齒輪箱", "block.create.shadow_steel_casing": "暗影機殼", "block.create.shaft": "傳動軸", - "block.create.smart_chute": "UNLOCALIZED: Smart Chute", + "block.create.smart_chute": "智慧滑道", "block.create.smart_fluid_pipe": "智慧液體管道", "block.create.speedometer": "速度計", "block.create.spout": "液體灌注器", "block.create.spruce_window": "雲杉木窗戶", "block.create.spruce_window_pane": "雲杉木窗戶片", - "block.create.sticker": "UNLOCALIZED: Sticker", + "block.create.sticker": "方塊黏著器", "block.create.sticky_mechanical_piston": "黏性機械活塞", - "block.create.stockpile_switch": "存量檢測器", + "block.create.stockpile_switch": "存量偵測器", "block.create.stressometer": "動能錶", "block.create.tiled_glass": "十字玻璃窗", "block.create.tiled_glass_pane": "十字玻璃窗戶片", @@ -401,7 +401,7 @@ "block.create.weathered_limestone_cobblestone_stairs": "碎風化石灰岩樓梯", "block.create.weathered_limestone_cobblestone_wall": "碎風化石灰岩牆", "block.create.weathered_limestone_pillar": "豎紋風化石灰岩", - "block.create.weighted_ejector": "UNLOCALIZED: Weighted Ejector", + "block.create.weighted_ejector": "物品彈射器", "block.create.white_sail": "白色風帆", "block.create.white_seat": "白色坐墊", "block.create.white_valve_handle": "白色閥門開關", @@ -414,7 +414,8 @@ "block.create.zinc_ore": "鋅礦石", "entity.create.contraption": "結構", - "entity.create.gantry_contraption": "UNLOCALIZED: Gantry Contraption", + "entity.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", + "entity.create.gantry_contraption": "門式結構", "entity.create.seat": "坐墊", "entity.create.stationary_contraption": "固定結構", "entity.create.super_glue": "強力膠", @@ -436,7 +437,7 @@ "item.create.builders_tea": "工人茶", "item.create.chest_minecart_contraption": "裝修過的機械礦車", "item.create.chocolate_bucket": "巧克力桶", - "item.create.chocolate_glazed_berries": "UNLOCALIZED: Chocolate Glazed Berries", + "item.create.chocolate_glazed_berries": "巧克力甜莓", "item.create.chromatic_compound": "異彩化合物", "item.create.cinder_flour": "地獄麵粉", "item.create.copper_backtank": "UNLOCALIZED: Copper Backtank", @@ -444,6 +445,7 @@ "item.create.copper_nugget": "銅粒", "item.create.copper_sheet": "銅板", "item.create.crafter_slot_cover": "合成器蓋板", + "item.create.crafting_blueprint": "UNLOCALIZED: Crafting Blueprint", "item.create.crushed_aluminum_ore": "碎狀鋁礦石", "item.create.crushed_brass": "碎狀黃銅", "item.create.crushed_copper_ore": "碎狀銅礦石", @@ -471,10 +473,11 @@ "item.create.golden_sheet": "金板", "item.create.handheld_worldshaper": "地形雕塑器", "item.create.honey_bucket": "蜂蜜桶", - "item.create.honeyed_apple": "UNLOCALIZED: Honeyed Apple", + "item.create.honeyed_apple": "蜂蜜蘋果", "item.create.integrated_circuit": "IC板", "item.create.iron_sheet": "鐵板", "item.create.lapis_sheet": "青金石板", + "item.create.linked_controller": "UNLOCALIZED: Linked Controller", "item.create.minecart_contraption": "裝修過的礦車", "item.create.minecart_coupling": "礦車連結器", "item.create.polished_rose_quartz": "磨製玫瑰石英", @@ -488,13 +491,13 @@ "item.create.schematic_and_quill": "藍圖與筆", "item.create.shadow_steel": "暗影鋼", "item.create.super_glue": "強力膠", - "item.create.sweet_roll": "UNLOCALIZED: Sweet Roll", + "item.create.sweet_roll": "甜捲捲", "item.create.tree_fertilizer": "樹木肥料", "item.create.vertical_gearbox": "豎直齒輪箱", "item.create.wand_of_symmetry": "對稱杖", "item.create.wheat_flour": "小麥粉", "item.create.whisk": "攪拌器", - "item.create.wrench": "板手", + "item.create.wrench": "扳手", "item.create.zinc_ingot": "鋅錠", "item.create.zinc_nugget": "鋅粒", @@ -509,8 +512,8 @@ "advancement.create.its_alive.desc": "首次使齒輪結構的旋轉。", "advancement.create.shifting_gears": "換檔,加速,起飛!", "advancement.create.shifting_gears.desc": "將大齒輪連接到小齒輪上,機械結構的轉速將會翻倍", - "advancement.create.overstressed": "超載", - "advancement.create.overstressed.desc": "首次使動能網路超載。", + "advancement.create.overstressed": "過載", + "advancement.create.overstressed.desc": "首次使動能網路過載。", "advancement.create.belt": "流水線作業", "advancement.create.belt.desc": "用輸送帶連接兩個傳動軸", "advancement.create.tunnel": "尋找掩護!", @@ -536,11 +539,11 @@ "advancement.create.wrench": "細部調整", "advancement.create.wrench.desc": "做出一個方便調整方塊的板手", "advancement.create.goggles": "動能,一目了然", - "advancement.create.goggles.desc": "做出一個能看到機械動能訊息的MR護目鏡", + "advancement.create.goggles.desc": "做出一個能看到機械動能訊息的MR護目鏡", "advancement.create.speedometer": "精密的速度控制", - "advancement.create.speedometer.desc": "放置一個速度計,並且戴上MR護目鏡來讀取數據", + "advancement.create.speedometer.desc": "放置一個速度計,並且戴上MR護目鏡來讀取數據", "advancement.create.stressometer": "精密的動能控制", - "advancement.create.stressometer.desc": "放置一個動能計,並且戴上MR護目鏡來讀取數據", + "advancement.create.stressometer.desc": "放置一個動能錶,並且戴上MR護目鏡來讀取數據", "advancement.create.aesthetics": "繁榮與美學!", "advancement.create.aesthetics.desc": "將支架放在傳動軸,管道和齒輪上。", "advancement.create.reinforced": "超級加固!", @@ -632,8 +635,8 @@ "advancement.create.arm_many_targets": "你是要累死我?", "advancement.create.arm_many_targets.desc": "配置一隻有十個或更多輸出位置的機械手臂。", "advancement.create.arm_blaze_burner": "燃燒吧!烈焰使者!", - "advancement.create.arm_blaze_burner.desc": "指揮機械臂給烈焰使者動力爐投食。", - "advancement.create.fist_bump": "朋友,來碰個拳", + "advancement.create.arm_blaze_burner.desc": "指揮機械手臂給烈焰使者動力爐投食。", + "advancement.create.fist_bump": "朋友,來擊拳", "advancement.create.fist_bump.desc": "使兩個機械手互相碰拳", "advancement.create.crushing_wheel": "一對大傢伙", "advancement.create.crushing_wheel.desc": "製作一對能更快粉碎物品的粉碎輪", @@ -672,6 +675,13 @@ "create.block.deployer.damage_source_name": "機械手", "create.block.cart_assembler.invalid": "將您的礦車裝修站放在鐵軌上", + "create.menu.return": "UNLOCALIZED: Return to Menu", + "create.menu.configure": "UNLOCALIZED: Configure...", + "create.menu.getting_started": "UNLOCALIZED: Getting Started", + "create.menu.project_page": "UNLOCALIZED: Project Page", + "create.menu.report_bugs": "UNLOCALIZED: Report Issues", + "create.menu.support": "UNLOCALIZED: Support Us", + "create.recipe.crushing": "粉碎", "create.recipe.milling": "研磨", "create.recipe.fan_washing": "批次洗滌", @@ -691,14 +701,14 @@ "create.recipe.mechanical_crafting": "自動合成", "create.recipe.automatic_shaped": "自動合成", "create.recipe.block_cutting": "方塊切割", - "create.recipe.wood_cutting": "UNLOCALIZED: Wood Cutting", + "create.recipe.wood_cutting": "木材切割", "create.recipe.sandpaper_polishing": "砂紙打磨", "create.recipe.mystery_conversion": "神秘轉化", "create.recipe.spout_filling": "注液", "create.recipe.draining": "分液", "create.recipe.processing.chance": "%1$s%%概率", - "create.recipe.heat_requirement.none": "不需加熱", - "create.recipe.heat_requirement.heated": "加熱", + "create.recipe.heat_requirement.none": "不需要加熱", + "create.recipe.heat_requirement.heated": "普通加熱", "create.recipe.heat_requirement.superheated": "超級加熱", "create.generic.range": "範圍", @@ -712,8 +722,8 @@ "create.generic.unit.seconds": "秒", "create.generic.unit.minutes": "分", "create.generic.unit.rpm": "RPM", - "create.generic.unit.stress": "SU", - "create.generic.unit.degrees": "°", + "create.generic.unit.stress": "su", + "create.generic.unit.degrees": "度", "create.generic.unit.millibuckets": "%1$smB", "create.generic.clockwise": "順時鐘方向", "create.generic.counter_clockwise": "逆時鐘方向", @@ -813,18 +823,18 @@ "create.logistics.filter.apply_count": "使用提取計數過濾。", "create.gui.goggles.generator_stats": "產能器狀態:", - "create.gui.goggles.kinetic_stats": "機械學狀態:", - "create.gui.goggles.at_current_speed": "現在速度動能值", - "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", - "create.gui.goggles.fluid_container": "UNLOCALIZED: Fluid Container Info:", - "create.gui.goggles.fluid_container.capacity": "UNLOCALIZED: Capacity: ", - "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.assembly.exception.not_enough_sails": "UNLOCALIZED: Attached structure does not include enough sail-like blocks: %1$s\nA minimum of %2$s are required", + "create.gui.goggles.kinetic_stats": "機械狀態:", + "create.gui.goggles.at_current_speed": "目前動能值", + "create.gui.goggles.pole_length": "活塞桿長度:", + "create.gui.goggles.fluid_container": "液體容器資訊:", + "create.gui.goggles.fluid_container.capacity": "容量: ", + "create.gui.assembly.exception": "該結構無法組合:", + "create.gui.assembly.exception.unmovableBlock": "無法移動的方塊 (%4$s) 位於 [%1$s,%2$s,%3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "位於 [%1$s,%2$s,%3$s] 方塊屬未載入區塊", + "create.gui.assembly.exception.structureTooLarge": "結構中的方塊數量過多.\nThe 可放置的數量最大為: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "活塞的活塞桿數量過多\nThe 可放置的數量最大為: %1$s", + "create.gui.assembly.exception.noPistonPoles": "這個活塞遺失了一些活塞桿", + "create.gui.assembly.exception.not_enough_sails": "結構中所需的風帆類方塊數量不足: %1$s\n最少需要的數量為: %2$s", "create.gui.gauge.info_header": "儀表訊息:", "create.gui.speedometer.title": "旋轉速度", "create.gui.stressometer.title": "網路動能", @@ -841,19 +851,19 @@ "create.gui.stockpile_switch.move_to_upper_at": "移至上線%1$s%%", "create.gui.sequenced_gearshift.title": "可程式化齒輪箱", "create.gui.sequenced_gearshift.instruction": "指令", - "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "UNLOCALIZED: Turn by angle", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "以特定角度旋轉", "create.gui.sequenced_gearshift.instruction.turn_angle": "旋轉", "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "角度", - "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "UNLOCALIZED: Turn to move Piston/Pulley/Gantry", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "帶動 活塞/滑輪/門式起重機", "create.gui.sequenced_gearshift.instruction.turn_distance": "驅動活塞", "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "距離", - "create.gui.sequenced_gearshift.instruction.delay.descriptive": "UNLOCALIZED: Timed Delay", - "create.gui.sequenced_gearshift.instruction.delay": "UNLOCALIZED: Delay", - "create.gui.sequenced_gearshift.instruction.delay.duration": "UNLOCALIZED: Duration", - "create.gui.sequenced_gearshift.instruction.end.descriptive": "UNLOCALIZED: End", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "延遲時間", + "create.gui.sequenced_gearshift.instruction.delay": "延遲", + "create.gui.sequenced_gearshift.instruction.delay.duration": "間隔", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "結束", "create.gui.sequenced_gearshift.instruction.end": "停止", - "create.gui.sequenced_gearshift.instruction.await.descriptive": "UNLOCALIZED: Await new Redstone Pulse", - "create.gui.sequenced_gearshift.instruction.await": "UNLOCALIZED: Await", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "等待新的紅石脈衝", + "create.gui.sequenced_gearshift.instruction.await": "等待", "create.gui.sequenced_gearshift.speed": "速度,速度方向", "create.gui.sequenced_gearshift.speed.forward": "一倍速,正向", "create.gui.sequenced_gearshift.speed.forward_fast": "兩倍速,正向", @@ -1011,10 +1021,10 @@ "create.item_attributes.added_by.inverted": "不是由%1$s添加", "create.item_attributes.has_enchant": "有附魔效果%1$s", "create.item_attributes.has_enchant.inverted": "沒有附魔效果%1$s", - "create.item_attributes.color": "UNLOCALIZED: is dyed %1$s", - "create.item_attributes.color.inverted": "UNLOCALIZED: is not dyed %1$s", - "create.item_attributes.max_enchanted": "UNLOCALIZED: is enchanted at max level", - "create.item_attributes.max_enchanted.inverted": "UNLOCALIZED: is not enchanted at max level", + "create.item_attributes.color": "已被染色成 %1$s", + "create.item_attributes.color.inverted": "未被染色成 %1$s", + "create.item_attributes.max_enchanted": "已達到最高附魔等級", + "create.item_attributes.max_enchanted.inverted": "未達到最高附魔等級", "create.item_attributes.has_fluid": "包含%1$s", "create.item_attributes.has_fluid.inverted": "不包含%1$s", "create.item_attributes.has_name": "有自定義名稱%1$s", @@ -1050,8 +1060,8 @@ "create.gui.attribute_filter.deny_list.description": "只要沒有上述屬性,就可以通過", "create.gui.attribute_filter.add_reference_item": "添加參考物品", - "create.tooltip.holdForDescription": "UNLOCALIZED: Hold [%1$s] for Summary", - "create.tooltip.holdForControls": "UNLOCALIZED: Hold [%1$s] for Controls", + "create.tooltip.holdForDescription": "按住 [%1$s] 來讀取物品概要", + "create.tooltip.holdForControls": "按住 [%1$s] 來讀取控制方法", "create.tooltip.keyShift": "Shift", "create.tooltip.keyCtrl": "Ctrl", "create.tooltip.speedRequirement": "需求速度:%1$s", @@ -1075,11 +1085,11 @@ "create.mechanical_arm.summary": "機械手臂有%1$s 輸入以及 %2$s 輸出。", "create.mechanical_arm.points_outside_range": "%1$s 由於距離限制,選定的交互點被移除。", - "create.weighted_ejector.target_set": "UNLOCALIZED: Target Selected", - "create.weighted_ejector.target_not_valid": "UNLOCALIZED: Ejecting to Adjacent block (Target was not Valid)", - "create.weighted_ejector.no_target": "UNLOCALIZED: Ejecting to Adjacent block (No Target was Selected)", - "create.weighted_ejector.targeting": "UNLOCALIZED: Ejecting to [%1$s,%2$s,%3$s]", - "create.weighted_ejector.stack_size": "UNLOCALIZED: Ejected Stack Size", + "create.weighted_ejector.target_set": "已選取目的地", + "create.weighted_ejector.target_not_valid": "彈射到鄰近的方塊 (目的地無效)", + "create.weighted_ejector.no_target": "彈射到鄰近的方塊 (未選取目的地)", + "create.weighted_ejector.targeting": "彈射到 [%1$s,%2$s,%3$s]", + "create.weighted_ejector.stack_size": "彈射物品數量", "create.logistics.when_multiple_outputs_available": "當多個輸出可用時", @@ -1103,22 +1113,36 @@ "create.tooltip.chute.fans_push_down": "鼓風機從上方進行推動", "create.tooltip.chute.fans_pull_up": "鼓風機從下方進行吸引", "create.tooltip.chute.fans_pull_down": "鼓風機從上方進行吸引", - "create.tooltip.chute.contains": "UNLOCALIZED: Contains: %1$s x%2$s", + "create.tooltip.chute.contains": "物品: %1$s x%2$s", - "create.hint.hose_pulley.title": "UNLOCALIZED: Bottomless Supply", - "create.hint.hose_pulley": "UNLOCALIZED: The targeted body of fluid is considered infinite.", + "create.linked_controller.bind_mode": "UNLOCALIZED: Bind mode active", + "create.linked_controller.press_keybind": "UNLOCALIZED: Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "UNLOCALIZED: Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "UNLOCALIZED: Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "UNLOCALIZED: Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "UNLOCALIZED: Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "UNLOCALIZED: Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "UNLOCALIZED: Display Slot", + "create.crafting_blueprint.inferred": "UNLOCALIZED: Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "UNLOCALIZED: Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "UNLOCALIZED: Secondary Display Slot", + "create.crafting_blueprint.optional": "UNLOCALIZED: Optional", + + "create.hint.hose_pulley.title": "無限供應", + "create.hint.hose_pulley": "目標液體為無限供應", "create.hint.mechanical_arm_no_targets.title": "沒有目標", "create.hint.mechanical_arm_no_targets": "看起來這個_機械手臂_沒有被分配任何_目標_。在手持機械手臂的同時,右鍵選取輸送帶、置物臺、漏斗或其他設備來設定目標。", "create.hint.empty_bearing.title": "更新軸承", "create.hint.empty_bearing": "_空手右鍵_軸承來_添加_你新建造的結構。", "create.hint.full_deployer.title": "機械手物品溢出", - "create.hint.full_deployer": "_機械手_包含_過剩的物品_需要被_提取._使用_漏斗,__漏斗_或其他方法將溢出解決。", + "create.hint.full_deployer": "_機械手_包含_過剩的物品_需要被_取出._使用漏斗_或其他方法將溢出解決。", "create.gui.config.overlay1": "嗨 :)", "create.gui.config.overlay2": "這是一個實例層", "create.gui.config.overlay3": "點擊拖拽你的滑鼠", "create.gui.config.overlay4": "來將它移動到前方", - "create.gui.config.overlay5": "ESC退出目前界面", + "create.gui.config.overlay5": "ESC退出目前介面", "create.gui.config.overlay6": "並儲存新的位置", "create.gui.config.overlay7": "輸入/create overlay reset", "create.gui.config.overlay8": "重置到預設位置", @@ -1131,33 +1155,39 @@ "create.command.killTPSCommand.status.usage.1": "[Create]: 用 /killtps start 來手動降低伺服器TPS", "create.command.killTPSCommand.argument.tickTime": "tickTime", - "create.contraption.minecart_contraption_too_big": "UNLOCALIZED: This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_too_big": "這個礦車結構太大了而無法撿取", + "create.contraption.minecart_contraption_illegal_pickup": "UNLOCALIZED: A mystical force is binding this Cart Contraption to the world", "_": "->------------------------] Subtitles [------------------------<-", - "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", - "create.subtitle.slime_added": "黏液擠壓", + "create.subtitle.saw_idle": "UNLOCALIZED: Mechanical Saw turns", "create.subtitle.contraption_disassemble": "UNLOCALIZED: Contraption stops", - "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", "create.subtitle.mixing": "UNLOCALIZED: Mixing Noises", - "create.subtitle.mechanical_press_activation_belt": "UNLOCALIZED: Mechanical Press bonks", + "create.subtitle.mechanical_press_activation_belt": "液壓機工作", "create.subtitle.worldshaper_place": "UNLOCALIZED: Worldshaper zaps", - "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", "create.subtitle.depot_slide": "UNLOCALIZED: Item slides", - "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.saw_activate_stone": "UNLOCALIZED: Mechanical Saw activates", "create.subtitle.blaze_munch": "烈焰使者開心地吃著", - "create.subtitle.schematicannon_launch_block": "藍圖大炮發射", "create.subtitle.funnel_flap": "UNLOCALIZED: Funnel Flaps", - "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.schematicannon_finish": "藍圖大炮完成任務", "create.subtitle.scroll_value": "UNLOCALIZED: Scroll-input clicks", + "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", + "create.subtitle.saw_process": "UNLOCALIZED: Mechanical Saw processes", + "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", + "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", + "create.subtitle.cogs": "UNLOCALIZED: Cogwheels rumble", + "create.subtitle.slime_added": "黏液擠壓", + "create.subtitle.wrench_rotate": "UNLOCALIZED: Wrench used", + "create.subtitle.saw_activate_wood": "UNLOCALIZED: Mechanical Saw activates", + "create.subtitle.deployer_polish": "UNLOCALIZED: Deployer applies polish", + "create.subtitle.deny": "UNLOCALIZED: Declining boop", + "create.subtitle.controller_click": "UNLOCALIZED: Controller clicks", + "create.subtitle.schematicannon_launch_block": "藍圖大炮發射", + "create.subtitle.copper_armor_equip": "UNLOCALIZED: Diving equipment clinks", "create.subtitle.mechanical_press_activation": "液壓機工作", "create.subtitle.contraption_assemble": "UNLOCALIZED: Contraption moves", - "create.subtitle.crafter_craft": "UNLOCALIZED: Crafter crafts", - "create.subtitle.cranking": "UNLOCALIZED: Hand Crank turns", "create.subtitle.crafter_click": "UNLOCALIZED: Crafter clicks", - "create.subtitle.wrench_remove": "UNLOCALIZED: Component breaks", "create.subtitle.depot_plop": "UNLOCALIZED: Item lands", "create.subtitle.confirm": "UNLOCALIZED: Affirmative ding", @@ -1181,10 +1211,10 @@ "block.create.copper_casing.tooltip": "銅製機殼", "block.create.copper_casing.tooltip.summary": "具備多種用途的堅固機殼,也可用於裝飾。", - "block.create.copper_casing.tooltip.condition1": "對流體管道使用時", + "block.create.copper_casing.tooltip.condition1": "對液體管道使用時", "block.create.copper_casing.tooltip.behaviour1": "會把管道裝入機殼,裝進機殼的管道會與其他管道分開,以免它們自動相連。", - "block.create.encased_fluid_pipe.tooltip": "流體管道箱", + "block.create.encased_fluid_pipe.tooltip": "液體管道箱", "block.create.encased_fluid_pipe.tooltip.summary": "用銅機殼加固后的液體管道。", "block.create.seat.tooltip": "坐墊", @@ -1199,8 +1229,8 @@ "block.create.fluid_pipe.tooltip.summary": "用來傳輸_液體_。需要一個_機械泵_來提供壓強。", "block.create.fluid_pipe.tooltip.condition1": "轉移液體", "block.create.fluid_pipe.tooltip.behaviour1": "可以與_液體容器_如_儲存罐_或_作業盆_相連_。裸露的_管道_末端也可以排放或抽取液體。注意別漏水了!", - "block.create.fluid_pipe.tooltip.condition2": "UNLOCALIZED: Right-clicked with Wrench", - "block.create.fluid_pipe.tooltip.behaviour2": "UNLOCALIZED: Places a window on the pipe if available", + "block.create.fluid_pipe.tooltip.condition2": "使用扳手對其右鍵時", + "block.create.fluid_pipe.tooltip.behaviour2": "在狀況許可的情況下在管道上安裝透明窗", "block.create.hose_pulley.tooltip": "軟管滑輪", "block.create.hose_pulley.tooltip.summary": "用來在_世界_中放置或排放大量的液體。", @@ -1226,7 +1256,7 @@ "block.create.fluid_valve.tooltip": "液體閥門", "block.create.fluid_valve.tooltip.summary": "阻止液體沿管道向前流動。", "block.create.fluid_valve.tooltip.condition1": "控制流量", - "block.create.fluid_valve.tooltip.behaviour1": "施加的_旋轉力_將迫使閥門關閉,從而阻止液體流動。_逆轉旋轉方向_以重新打開閥門。", + "block.create.fluid_valve.tooltip.behaviour1": "施加的_動能_將迫使閥門關閉,從而阻止液體流動。_逆轉旋轉方向_以重新打開閥門。", "block.create.mechanical_pump.tooltip": "機械泵", "block.create.mechanical_pump.tooltip.summary": "_接入機械_,能迫使液體_沿管道指定方向移動_。在兩個方向上都有_最大的作用範圍_。(默認為16個方塊距離)", @@ -1263,7 +1293,7 @@ "item.create.wand_of_symmetry.tooltip.control2": "當右鍵空氣時", "item.create.wand_of_symmetry.tooltip.action2": "_刪除_鏡子", "item.create.wand_of_symmetry.tooltip.control3": "當潛行右鍵時", - "item.create.wand_of_symmetry.tooltip.action3": "打開_gui界面_", + "item.create.wand_of_symmetry.tooltip.action3": "打開_gui介面_", "item.create.handheld_worldshaper.tooltip": "環境塑形器", "item.create.handheld_worldshaper.tooltip.summary": "_大面積_更改地形的手持工具", @@ -1272,7 +1302,7 @@ "item.create.handheld_worldshaper.tooltip.control2": "當右鍵方塊時", "item.create.handheld_worldshaper.tooltip.action2": "_放置_或_替換_目標方塊", "item.create.handheld_worldshaper.tooltip.control3": "當潛行右鍵時", - "item.create.handheld_worldshaper.tooltip.action3": "打開工具的_gui界面_", + "item.create.handheld_worldshaper.tooltip.action3": "打開工具的_gui介面_", "item.create.tree_fertilizer.tooltip": "樹木肥料", "item.create.tree_fertilizer.tooltip.summary": "適用來常見樹木的快速肥料", @@ -1287,9 +1317,9 @@ "item.create.filter.tooltip": "過濾器", "item.create.filter.tooltip.summary": "將物品更精確地進行_篩選分類_,可以同時_篩選_多個物品或者將已標記的_過濾器_放在另一個_過濾器_里_嵌套_使用。", "item.create.filter.tooltip.condition1": "放置於過濾插槽中時", - "item.create.filter.tooltip.behaviour1": "根據_過濾器_的配置,來_決定_物品是否能夠通過", + "item.create.filter.tooltip.behaviour1": "根據_過濾器_的設定,來_決定_物品是否能夠通過", "item.create.filter.tooltip.condition2": "當右鍵時", - "item.create.filter.tooltip.behaviour2": "打開_配置面板_", + "item.create.filter.tooltip.behaviour2": "打開_設定面板_", "item.create.attribute_filter.tooltip": "屬性過濾器", "item.create.attribute_filter.tooltip.summary": "比起普通過濾器,_屬性過濾器_可以根據不同物品的_屬性_來進行過濾", @@ -1302,20 +1332,20 @@ "item.create.empty_schematic.tooltip.summary": "可作為合成材料或在_藍圖桌_使用", "item.create.schematic.tooltip": "藍圖", - "item.create.schematic.tooltip.summary": "將工程結構的_全息圖_放置於_世界中_,並使用_藍圖加農炮_進行構建。", - "item.create.schematic.tooltip.condition1": "當全息圖存在時", + "item.create.schematic.tooltip.summary": "將工程結構的_設計圖_放置於_世界中_,並使用_藍圖加農炮_進行構建。", + "item.create.schematic.tooltip.condition1": "當設計圖存在時", "item.create.schematic.tooltip.behaviour1": "可以使用屏幕上的工具調整位置", "item.create.schematic.tooltip.control1": "當潛行右鍵時", - "item.create.schematic.tooltip.action1": "打開一個用來輸入_精確坐標_的界面。", + "item.create.schematic.tooltip.action1": "打開一個用來輸入_精確坐標_的介面。", "item.create.schematic_and_quill.tooltip": "藍圖與筆", - "item.create.schematic_and_quill.tooltip.summary": "用來將世界中的結構保存到.nbt文件。", + "item.create.schematic_and_quill.tooltip.summary": "用來將世界中的結構存到.nbt文件。", "item.create.schematic_and_quill.tooltip.condition1": "第一步", "item.create.schematic_and_quill.tooltip.behaviour1": "手持藍圖與右鍵旋轉兩個點", "item.create.schematic_and_quill.tooltip.condition2": "第二步", - "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.action1": "選取點/確認存檔", "item.create.schematic_and_quill.tooltip.control2": "按住Ctrl滑鼠滾輪", "item.create.schematic_and_quill.tooltip.action2": "在_空中_選擇點滾動以調整距離。", "item.create.schematic_and_quill.tooltip.control3": "當潛行右鍵時", @@ -1323,8 +1353,8 @@ "block.create.schematicannon.tooltip": "藍圖加農炮", "block.create.schematicannon.tooltip.summary": "通過發射方塊以在世界中重新構建已部署的_全息圖_,使用相鄰箱子中的物品及_火藥_作為燃料。", - "block.create.schematicannon.tooltip.condition1": "UNLOCALIZED: When R-Clicked", - "block.create.schematicannon.tooltip.behaviour1": "UNLOCALIZED: Opens the _Interface_", + "block.create.schematicannon.tooltip.condition1": "當你對加農砲右鍵時", + "block.create.schematicannon.tooltip.behaviour1": "打開加農砲的設定介面", "block.create.schematic_table.tooltip": "藍圖桌", "block.create.schematic_table.tooltip.summary": "將保存的藍圖圖寫入_空白藍圖_", @@ -1334,11 +1364,11 @@ "item.create.goggles.tooltip": "MR護目鏡", "item.create.goggles.tooltip.summary": "一副特殊的眼鏡,能夠讓你看見_動能_的信息。", "item.create.goggles.tooltip.condition1": "當裝備後", - "item.create.goggles.tooltip.behaviour1": "將會展示該機械元件的_速度_、_動能_等數值", + "item.create.goggles.tooltip.behaviour1": "將會顯示該機械元件的_速度_、_動能_等數值。", "item.create.goggles.tooltip.condition2": "當裝備後看向儀表時", - "item.create.goggles.tooltip.behaviour2": "將會展示該儀表所連接網路的_速度_、_動能_等數值。", - "item.create.goggles.tooltip.condition3": "UNLOCALIZED: When looking at fluid containers", - "item.create.goggles.tooltip.behaviour3": "UNLOCALIZED: Shows detailed information about the _Capacity_ of the block and any _Fluids_ stored within.", + "item.create.goggles.tooltip.behaviour2": "將會顯示該儀表所連接網路的_速度_、_動能_等數值。", + "item.create.goggles.tooltip.condition3": "當裝備後看向液體容器時", + "item.create.goggles.tooltip.behaviour3": "將會顯示儲存在該容器內的 _液體_ 以及其 _容量_ 等資訊。", "item.create.wrench.tooltip": "板手", "item.create.wrench.tooltip.summary": "一種常用的工具,能夠調整_動能_的_方向_、_配置_等。", @@ -1365,18 +1395,18 @@ "block.create.portable_fluid_interface.tooltip.condition2": "被紅石激活時", "block.create.portable_fluid_interface.tooltip.behaviour2": "立即終止任何活動的連接。", - "block.create.stockpile_switch.tooltip": "存量檢測器", + "block.create.stockpile_switch.tooltip": "存量偵測器", "block.create.stockpile_switch.tooltip.summary": "根據連接的容器_儲存空間_的占用情況切換紅石訊號強度。", "block.create.stockpile_switch.tooltip.condition1": "低於_下線_或高於_上線_時", "block.create.stockpile_switch.tooltip.behaviour1": "提供紅石訊號", "block.create.content_observer.tooltip": "物品偵測器", - "block.create.content_observer.tooltip.summary": "檢測_容器_和_輸送帶_中過濾器匹配的物品。當觀察到包含匹配的物品時,此組件將發出_紅石訊號_。當觀察到的漏斗_轉移匹配的物品_時,此組件將發出_紅石脈沖_。", + "block.create.content_observer.tooltip.summary": "偵測_容器_和_輸送帶_中過濾器匹配的物品。當觀察到包含匹配的物品時,此組件將發出_紅石訊號_。當觀察到的漏斗_轉移匹配的物品_時,此組件將發出_紅石脈沖_。", "block.create.adjustable_crate.tooltip": "可調節板條箱", - "block.create.adjustable_crate.tooltip.summary": "該箱子支持玩家對其容量進行調整,最大可以容納_16組_物品。", - "block.create.adjustable_crate.tooltip.condition1": "UNLOCALIZED: When R-Clicked", - "block.create.adjustable_crate.tooltip.behaviour1": "UNLOCALIZED: Opens the _Interface_.", + "block.create.adjustable_crate.tooltip.summary": "這個箱子可以調整容量,最大可以收納_16組_物品。", + "block.create.adjustable_crate.tooltip.condition1": "當你對箱子按右鍵時", + "block.create.adjustable_crate.tooltip.behaviour1": "打開箱子的設定介面", "block.create.creative_crate.tooltip": "創造板條箱", "block.create.creative_crate.tooltip.summary": "這個容器可以給臨近的_藍圖大炮_提供無限物品以及燃料 (創造專用物品)", @@ -1393,717 +1423,799 @@ "item.create.sand_paper.tooltip.condition1": "使用時", "item.create.sand_paper.tooltip.behaviour1": "打磨_副手_上或者_準心所指_的物品。", - "item.create.builders_tea.tooltip": "建造工茶飲", + "item.create.builders_tea.tooltip": "工人茶", "item.create.builders_tea.tooltip.summary": "神清氣爽的一天,從這杯完美茶飲開始。恢復復_饑餓值_並獲得_加速_效果。", "item.create.refined_radiance.tooltip": "光輝石", "item.create.refined_radiance.tooltip.summary": "一種用_光輝_鍛造的化合物材料。", + "item.create.refined_radiance.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", "item.create.shadow_steel.tooltip": "暗影鋼", "item.create.shadow_steel.tooltip.summary": "一種用_虛空_鍛造的化合物材料。", + "item.create.shadow_steel.tooltip.condition1": "UNLOCALIZED: Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "UNLOCALIZED: Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "UNLOCALIZED: LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "UNLOCALIZED: Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "UNLOCALIZED: R-Click", + "item.create.linked_controller.tooltip.behaviour1": "UNLOCALIZED: _Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "UNLOCALIZED: R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "UNLOCALIZED: Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "UNLOCALIZED: R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "UNLOCALIZED: Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "UNLOCALIZED: DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "UNLOCALIZED: Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "UNLOCALIZED: Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "UNLOCALIZED: COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "UNLOCALIZED: A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "UNLOCALIZED: Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "UNLOCALIZED: When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "UNLOCALIZED: _Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "UNLOCALIZED: DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "UNLOCALIZED: A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "UNLOCALIZED: When Worn", + "item.create.diving_boots.tooltip.behaviour1": "UNLOCALIZED: Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "UNLOCALIZED: CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "UNLOCALIZED: _Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "UNLOCALIZED: R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "UNLOCALIZED: Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "UNLOCALIZED: R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "UNLOCALIZED: _Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", "item.create.minecart_coupling.tooltip": "礦車連軸器", "item.create.minecart_coupling.tooltip.summary": "將多個_礦車_或運輸結構鏈接在一起,構成雄偉的火車。", "item.create.minecart_coupling.tooltip.condition1": "作用與礦車時", "item.create.minecart_coupling.tooltip.behaviour1": "將兩個礦車耦合在一起,在移動時將它們保持_恒定的距離_。", - "create.tooltip.wip": "半成品", - "create.tooltip.workInProgress": "尚在製作中!", - "create.tooltip.randomWipDescription0": "禁止將此物品給兒童。", - "create.tooltip.randomWipDescription1": "每~一~次~你使用此物品時,就會使一隻小熊貓死亡。", - "create.tooltip.randomWipDescription2": "使用此物請自負後果。", - "create.tooltip.randomWipDescription3": "快走開,這不是你要找的東西(搖手指", - "create.tooltip.randomWipDescription4": "啟動自爆模式,10、9、8...。", - "create.tooltip.randomWipDescription5": "你已經沒有退路了。", - "create.tooltip.randomWipDescription6": "作者我將不負任何你使用此物所造成的責任。", - "create.tooltip.randomWipDescription7": "這東西不是給你用的,再找找吧!", - "create.tooltip.randomWipDescription8": "用了就死定了。", - "_": "->------------------------] Ponder Content [------------------------<-", - "create.ponder.hold_to_ponder": "UNLOCALIZED: Hold [%1$s] to Ponder", - "create.ponder.subject": "UNLOCALIZED: Subject of this scene", - "create.ponder.pondering": "UNLOCALIZED: Pondering about...", - "create.ponder.identify_mode": "UNLOCALIZED: Identify mode active.\nUnpause with [%1$s]", - "create.ponder.associated": "UNLOCALIZED: Associated Entries", - "create.ponder.close": "UNLOCALIZED: Close", - "create.ponder.identify": "UNLOCALIZED: Identify", - "create.ponder.next": "UNLOCALIZED: Next Scene", - "create.ponder.previous": "UNLOCALIZED: Previous Scene", - "create.ponder.replay": "UNLOCALIZED: Replay", - "create.ponder.think_back": "UNLOCALIZED: Think Back", - "create.ponder.slow_text": "UNLOCALIZED: Comfy Reading", - "create.ponder.shared.movement_anchors": "UNLOCALIZED: With the help of Chassis or Super Glue, larger structures can be moved.", - "create.ponder.shared.rpm32": "UNLOCALIZED: 32 RPM", - "create.ponder.shared.sneak_and": "UNLOCALIZED: Sneak +", - "create.ponder.shared.storage_on_contraption": "UNLOCALIZED: Inventories attached to the Contraption will pick up their drops automatically", - "create.ponder.shared.behaviour_modify_wrench": "UNLOCALIZED: This behaviour can be modified using a Wrench", - "create.ponder.shared.rpm8": "UNLOCALIZED: 8 RPM", - "create.ponder.shared.ctrl_and": "UNLOCALIZED: Ctrl +", - "create.ponder.shared.rpm16_source": "UNLOCALIZED: Source: 16 RPM", - "create.ponder.shared.rpm16": "UNLOCALIZED: 16 RPM", - "create.ponder.tag.kinetic_sources": "UNLOCALIZED: Kinetic Sources", - "create.ponder.tag.kinetic_sources.description": "UNLOCALIZED: Components which generate Rotational Force", - "create.ponder.tag.contraption_actor": "UNLOCALIZED: Contraption Actors", - "create.ponder.tag.contraption_actor.description": "UNLOCALIZED: Components which expose special behaviour when attached to a moving contraption", - "create.ponder.tag.arm_targets": "UNLOCALIZED: Targets for Mechanical Arms", - "create.ponder.tag.arm_targets.description": "UNLOCALIZED: Components which can be selected as inputs or outputs to the Mechanical Arm", - "create.ponder.tag.logistics": "UNLOCALIZED: Item Transportation", - "create.ponder.tag.logistics.description": "UNLOCALIZED: Components which help moving items around", - "create.ponder.tag.movement_anchor": "UNLOCALIZED: Movement Anchors", - "create.ponder.tag.movement_anchor.description": "UNLOCALIZED: Components which allow the creation of moving contraptions, animating an attached structure in a variety of ways", - "create.ponder.tag.creative": "UNLOCALIZED: Creative Mode", - "create.ponder.tag.creative.description": "UNLOCALIZED: Components not usually available for Survival Mode", - "create.ponder.tag.kinetic_relays": "UNLOCALIZED: Kinetic Blocks", - "create.ponder.tag.kinetic_relays.description": "UNLOCALIZED: Components which help relaying Rotational Force elsewhere", - "create.ponder.tag.windmill_sails": "UNLOCALIZED: Sails for Windmill Bearings", - "create.ponder.tag.windmill_sails.description": "UNLOCALIZED: Blocks that count towards the strength of a Windmill Contraption when assembled. Each of these have equal efficiency in doing so.", - "create.ponder.tag.contraption_assembly": "UNLOCALIZED: Block Attachment Utility", - "create.ponder.tag.contraption_assembly.description": "UNLOCALIZED: Tools and Components used to assemble structures moved as an animated Contraption", - "create.ponder.tag.decoration": "UNLOCALIZED: Aesthetics", - "create.ponder.tag.decoration.description": "UNLOCALIZED: Components used mostly for decorative purposes", - "create.ponder.tag.kinetic_appliances": "UNLOCALIZED: Kinetic Appliances", - "create.ponder.tag.kinetic_appliances.description": "UNLOCALIZED: Components which make use of Rotational Force", - "create.ponder.tag.redstone": "UNLOCALIZED: Logic Components", - "create.ponder.tag.redstone.description": "UNLOCALIZED: Components which help with redstone engineering", - "create.ponder.tag.fluids": "UNLOCALIZED: Fluid Manipulators", - "create.ponder.tag.fluids.description": "UNLOCALIZED: Components which help relaying and making use of Fluids", - - "create.ponder.adjustable_pulse_repeater.header": "UNLOCALIZED: Controlling signals using Adjustable Pulse Repeaters", - "create.ponder.adjustable_pulse_repeater.text_1": "UNLOCALIZED: Adjustable Pulse Repeaters emit a short pulse at a delay", - "create.ponder.adjustable_pulse_repeater.text_2": "UNLOCALIZED: Using the mouse wheel, the charge time can be configured", - "create.ponder.adjustable_pulse_repeater.text_3": "UNLOCALIZED: Configured delays can range up to 30 minutes", - - "create.ponder.adjustable_repeater.header": "UNLOCALIZED: Controlling signals using Adjustable Repeaters", - "create.ponder.adjustable_repeater.text_1": "UNLOCALIZED: Adjustable Repeaters behave similarly to regular Repeaters", - "create.ponder.adjustable_repeater.text_2": "UNLOCALIZED: They charge up for a set time...", - "create.ponder.adjustable_repeater.text_3": "UNLOCALIZED: ...and cool down for the same duration", - "create.ponder.adjustable_repeater.text_4": "UNLOCALIZED: Using the mouse wheel, the charge time can be configured", - "create.ponder.adjustable_repeater.text_5": "UNLOCALIZED: Configured delays can range up to 30 minutes", - - "create.ponder.analog_lever.header": "UNLOCALIZED: Controlling signals using the Analog Lever", - "create.ponder.analog_lever.text_1": "UNLOCALIZED: Analog Levers make for a compact and precise source of redstone power", - "create.ponder.analog_lever.text_2": "UNLOCALIZED: Right-click to increase its analog power output", - "create.ponder.analog_lever.text_3": "UNLOCALIZED: Right-click while Sneaking to decrease the power output again", - - "create.ponder.andesite_tunnel.header": "UNLOCALIZED: Using Andesite Tunnels", - "create.ponder.andesite_tunnel.text_1": "UNLOCALIZED: Andesite Tunnels can be used to cover up your belts", - "create.ponder.andesite_tunnel.text_2": "UNLOCALIZED: Whenever an Andesite Tunnel has connections to the sides...", - "create.ponder.andesite_tunnel.text_3": "UNLOCALIZED: ...they will split exactly one item off of any passing stacks", - "create.ponder.andesite_tunnel.text_4": "UNLOCALIZED: The remainder will continue on its path", - - "create.ponder.basin.header": "UNLOCALIZED: Processing Items in the Basin", - "create.ponder.basin.text_1": "UNLOCALIZED: A Basin can hold Items and Fluids for Processing", - "create.ponder.basin.text_2": "UNLOCALIZED: After a processing step, basins try to output below to the side of them", - "create.ponder.basin.text_3": "UNLOCALIZED: When a valid component is present, the Basin will show an output faucet", - "create.ponder.basin.text_4": "UNLOCALIZED: A number of options are applicable here", - "create.ponder.basin.text_5": "UNLOCALIZED: Outputs will be caught by the inventory below", - "create.ponder.basin.text_6": "UNLOCALIZED: Without output faucet, the Basin will retain items created in its processing", - "create.ponder.basin.text_7": "UNLOCALIZED: This can be useful if outputs should be re-used as ingredients", - "create.ponder.basin.text_8": "UNLOCALIZED: Desired outputs will then have to be extracted from the basin", - "create.ponder.basin.text_9": "UNLOCALIZED: A Filter might be necessary to avoid pulling out un-processed items", - - "create.ponder.bearing_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Bearing", - "create.ponder.bearing_modes.text_1": "UNLOCALIZED: When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle", - "create.ponder.bearing_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only near the angle it started at", - - "create.ponder.belt_casing.header": "UNLOCALIZED: Encasing Belts", - "create.ponder.belt_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Mechanical Belts", - "create.ponder.belt_casing.text_2": "UNLOCALIZED: A wrench can be used to remove the casing", - - "create.ponder.belt_connector.header": "UNLOCALIZED: Using Mechanical Belts", - "create.ponder.belt_connector.text_1": "UNLOCALIZED: Right-Clicking two shafts with a belt item will connect them together", - "create.ponder.belt_connector.text_2": "UNLOCALIZED: Accidental selections can be canceled with Right-Click while Sneaking", - "create.ponder.belt_connector.text_3": "UNLOCALIZED: Additional Shafts can be added throughout the Belt", - "create.ponder.belt_connector.text_4": "UNLOCALIZED: Shafts connected via Belts will rotate with Identical Speed and Direction", - "create.ponder.belt_connector.text_5": "UNLOCALIZED: Added shafts can be removed using the wrench", - "create.ponder.belt_connector.text_6": "UNLOCALIZED: Mechanical Belts can be dyed for aesthetic purposes", - - "create.ponder.belt_directions.header": "UNLOCALIZED: Valid Orientations for Mechanical Belts", - "create.ponder.belt_directions.text_1": "UNLOCALIZED: Belts cannot connect in arbitrary directions", - "create.ponder.belt_directions.text_2": "UNLOCALIZED: 1. They can connect horizontally", - "create.ponder.belt_directions.text_3": "UNLOCALIZED: 2. They can connect diagonally", - "create.ponder.belt_directions.text_4": "UNLOCALIZED: 3. They can connect vertically", - "create.ponder.belt_directions.text_5": "UNLOCALIZED: 4. And they can connect vertical shafts horizontally", - "create.ponder.belt_directions.text_6": "UNLOCALIZED: These are all possible directions. Belts can span any Length between 2 and 20 blocks", - - "create.ponder.belt_transport.header": "UNLOCALIZED: Using Mechanical Belts for Logistics", - "create.ponder.belt_transport.text_1": "UNLOCALIZED: Moving belts will transport Items and other Entities", - "create.ponder.belt_transport.text_2": "UNLOCALIZED: Right-Click with an empty hand to take items off a belt", - - "create.ponder.blaze_burner.header": "UNLOCALIZED: Feeding Blaze Burners", - "create.ponder.blaze_burner.text_1": "UNLOCALIZED: Blaze Burners can provide Heat to Items processed in a Basin", - "create.ponder.blaze_burner.text_2": "UNLOCALIZED: For this, the Blaze has to be fed with flammable items", - "create.ponder.blaze_burner.text_3": "UNLOCALIZED: With a Blaze Cake, the Burner can reach an even stronger level of heat", - "create.ponder.blaze_burner.text_4": "UNLOCALIZED: The feeding process can be automated using Deployers or Mechanical Arms", - - "create.ponder.brass_funnel.header": "UNLOCALIZED: The Brass Funnel", - "create.ponder.brass_funnel.text_1": "UNLOCALIZED: Andesite Funnels can only ever extract single items.", - "create.ponder.brass_funnel.text_2": "UNLOCALIZED: Brass Funnels can extract up to a full stack.", - "create.ponder.brass_funnel.text_3": "UNLOCALIZED: Scrolling on the filter slot allows for precise control over the extracted stack size.", - "create.ponder.brass_funnel.text_4": "UNLOCALIZED: Using items on the filter slot will restrict the funnel to only transfer matching stacks.", - - "create.ponder.brass_tunnel.header": "UNLOCALIZED: Using Brass Tunnels", - "create.ponder.brass_tunnel.text_1": "UNLOCALIZED: Brass Tunnels can be used to cover up your belts", - "create.ponder.brass_tunnel.text_2": "UNLOCALIZED: Brass Tunnels have filter slots on each open side", - "create.ponder.brass_tunnel.text_3": "UNLOCALIZED: Filters on inbound connections simply block non-matching items", - "create.ponder.brass_tunnel.text_4": "UNLOCALIZED: Filters on outbound connections can be used to sort items by type", - "create.ponder.brass_tunnel.text_5": "UNLOCALIZED: Whenever a passing item has multiple valid exits, the distribution mode will decide how to handle it", - "create.ponder.brass_tunnel.text_6": "UNLOCALIZED: Brass Tunnels on parallel belts will form a group", - "create.ponder.brass_tunnel.text_7": "UNLOCALIZED: Incoming Items will now be distributed across all connected exits", - "create.ponder.brass_tunnel.text_8": "UNLOCALIZED: For this, items can also be inserted into the Tunnel block directly", - - "create.ponder.brass_tunnel_modes.header": "UNLOCALIZED: Distribution Modes of the Brass Tunnel", - "create.ponder.brass_tunnel_modes.text_1": "UNLOCALIZED: Using a Wrench, the distribution behaviour of Brass Tunnels can be configured", - "create.ponder.brass_tunnel_modes.text_10": "UNLOCALIZED: 'Synchronize Inputs' is a unique setting for Brass Tunnels", - "create.ponder.brass_tunnel_modes.text_11": "UNLOCALIZED: Items are only allowed past if every tunnel in the group has one waiting", - "create.ponder.brass_tunnel_modes.text_12": "UNLOCALIZED: This ensures that all affected belts supply items at the same rate", - "create.ponder.brass_tunnel_modes.text_2": "UNLOCALIZED: 'Split' will attempt to distribute the stack evenly between available outputs", - "create.ponder.brass_tunnel_modes.text_3": "UNLOCALIZED: If an output is unable to take more items, it will be skipped", - "create.ponder.brass_tunnel_modes.text_4": "UNLOCALIZED: 'Forced Split' will never skip outputs, and instead wait until they are free", - "create.ponder.brass_tunnel_modes.text_5": "UNLOCALIZED: 'Round Robin' keeps stacks whole, and cycles through outputs iteratively", - "create.ponder.brass_tunnel_modes.text_6": "UNLOCALIZED: Once Again, if an output is unable to take more items, it will be skipped", - "create.ponder.brass_tunnel_modes.text_7": "UNLOCALIZED: 'Forced Round Robin' never skips outputs", - "create.ponder.brass_tunnel_modes.text_8": "UNLOCALIZED: 'Prefer Nearest' prioritizes the outputs closest to the items' input location", - "create.ponder.brass_tunnel_modes.text_9": "UNLOCALIZED: 'Randomize' will distribute whole stacks to randomly picked outputs", - - "create.ponder.cart_assembler.header": "UNLOCALIZED: Moving Structures using Cart Assemblers", - "create.ponder.cart_assembler.text_1": "UNLOCALIZED: Powered Cart Assemblers mount attached structures to passing Minecarts", - "create.ponder.cart_assembler.text_2": "UNLOCALIZED: Without a redstone signal, it disassembles passing cart contraptions back into blocks", - "create.ponder.cart_assembler.text_3": "UNLOCALIZED: Using a Wrench on the Minecart will let you carry the Contraption elsewhere", - - "create.ponder.cart_assembler_dual.header": "UNLOCALIZED: Assembling Carriage Contraptions", - "create.ponder.cart_assembler_dual.text_1": "UNLOCALIZED: Whenever two Cart Assembers share an attached structure...", - "create.ponder.cart_assembler_dual.text_2": "UNLOCALIZED: Powering either of them will create a Carriage Contraption", - "create.ponder.cart_assembler_dual.text_3": "UNLOCALIZED: The carts will behave like those connected via Minecart Coupling", - - "create.ponder.cart_assembler_modes.header": "UNLOCALIZED: Orientation Settings for Minecart Contraptions", - "create.ponder.cart_assembler_modes.text_1": "UNLOCALIZED: Cart Contraptions will rotate to face towards their carts' motion", - "create.ponder.cart_assembler_modes.text_2": "UNLOCALIZED: If the Assembler is set to Lock Rotation, the contraptions' orientation will never change", - - "create.ponder.cart_assembler_rails.header": "UNLOCALIZED: Other types of Minecarts and Rails", - "create.ponder.cart_assembler_rails.text_1": "UNLOCALIZED: Cart Assemblers on Regular Tracks will not affect the passing carts' motion", - "create.ponder.cart_assembler_rails.text_2": "UNLOCALIZED: When on Powered or Controller Rail, the carts will be held in place until it's Powered", - "create.ponder.cart_assembler_rails.text_3": "UNLOCALIZED: Other types of Minecarts can be used as the anchor", - "create.ponder.cart_assembler_rails.text_4": "UNLOCALIZED: Furnace Carts will keep themselves powered, pulling fuel from any attached inventories", - - "create.ponder.chain_drive.header": "UNLOCALIZED: Relaying rotational force with Chain Drives", - "create.ponder.chain_drive.text_1": "UNLOCALIZED: Chain Drives relay rotation to each other in a row", - "create.ponder.chain_drive.text_2": "UNLOCALIZED: All shafts connected like this will rotate in the same direction", - "create.ponder.chain_drive.text_3": "UNLOCALIZED: Any part of the row can be rotated by 90 degrees", - - "create.ponder.chain_gearshift.header": "UNLOCALIZED: Controlling rotational speed with Chain Gearshifts", - "create.ponder.chain_gearshift.text_1": "UNLOCALIZED: Unpowered Chain Gearshifts behave exacly like Chain Drives", - "create.ponder.chain_gearshift.text_2": "UNLOCALIZED: When Powered, the speed transmitted to other Chain Drives in the row is doubled", - "create.ponder.chain_gearshift.text_3": "UNLOCALIZED: Whenever the Powered Gearshift is not at the source, its speed will be halved instead", - "create.ponder.chain_gearshift.text_4": "UNLOCALIZED: In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift", - "create.ponder.chain_gearshift.text_5": "UNLOCALIZED: Using analog signals, the ratio can be adjusted more precisely between 1 and 2", - "create.ponder.chain_gearshift.text_6": "UNLOCALIZED: 12 RPM", - - "create.ponder.chute.header": "UNLOCALIZED: Transporting Items downward via Chutes", - "create.ponder.chute.text_1": "UNLOCALIZED: Chutes can transport items vertically from and to inventories", - "create.ponder.chute.text_2": "UNLOCALIZED: Using the Wrench, a window can be created", - "create.ponder.chute.text_3": "UNLOCALIZED: Placing chutes targeting the side faces of another will make it diagonal", - - "create.ponder.chute_upward.header": "UNLOCALIZED: Transporting Items upward via Chutes", - "create.ponder.chute_upward.text_1": "UNLOCALIZED: Using Encased Fans at the top or bottom, a Chute can move items upward", - "create.ponder.chute_upward.text_2": "UNLOCALIZED: Inspecting chutes with Engineers' Goggles reveals information about the movement direction", - "create.ponder.chute_upward.text_3": "UNLOCALIZED: On the 'blocked' end, items will have to be inserted/taken from the sides", - - "create.ponder.clockwork_bearing.header": "UNLOCALIZED: Animating Structures using Clockwork Bearings", - "create.ponder.clockwork_bearing.text_1": "UNLOCALIZED: Clockwork Bearings attach to blocks in front of them", - "create.ponder.clockwork_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, the structure will be rotated according to the hour of the day", - "create.ponder.clockwork_bearing.text_3": "UNLOCALIZED: 3:00", - "create.ponder.clockwork_bearing.text_4": "UNLOCALIZED: 4:00", - "create.ponder.clockwork_bearing.text_5": "UNLOCALIZED: Right-Click the bearing to start or stop animating the structure", - "create.ponder.clockwork_bearing.text_6": "UNLOCALIZED: In front of the Hour Hand, a second structure can be added", - "create.ponder.clockwork_bearing.text_7": "UNLOCALIZED: Ensure the two Structures are not attached to each other through super glue or similar", - "create.ponder.clockwork_bearing.text_8": "UNLOCALIZED: The Second Structure will now rotate as the Minute Hand", - - "create.ponder.clutch.header": "UNLOCALIZED: Controlling rotational force using a Clutch", - "create.ponder.clutch.text_1": "UNLOCALIZED: Clutches will relay rotation in a straight line", - "create.ponder.clutch.text_2": "UNLOCALIZED: When powered by Redstone, it breaks the connection", - - "create.ponder.cog_speedup.header": "UNLOCALIZED: Gearshifting with Cogs", - "create.ponder.cog_speedup.text_1": "UNLOCALIZED: Large and Small cogs can be connected diagonally", - "create.ponder.cog_speedup.text_2": "UNLOCALIZED: Shifting from large to small cogs, the conveyed speed will be doubled", - "create.ponder.cog_speedup.text_3": "UNLOCALIZED: Shifting the opposite way, the conveyed speed will be halved", - - "create.ponder.cogwheel.header": "UNLOCALIZED: Relaying rotational force using Cogwheels", - "create.ponder.cogwheel.text_1": "UNLOCALIZED: Cogwheels will relay rotation to other adjacent cogwheels", - "create.ponder.cogwheel.text_2": "UNLOCALIZED: Neighbouring shafts connected like this will rotate in opposite directions", - - "create.ponder.creative_motor.header": "UNLOCALIZED: Generating Rotational Force using Creative Motors", - "create.ponder.creative_motor.text_1": "UNLOCALIZED: Creative motors are a compact and configurable source of Rotational Force", - "create.ponder.creative_motor.text_2": "UNLOCALIZED: Scrolling on the back panel changes the RPM of the motors' rotational output", - - "create.ponder.crushing_wheels.header": "UNLOCALIZED: Processing Items with Crushing Wheels", - "create.ponder.crushing_wheels.text_1": "UNLOCALIZED: A pair of Crushing Wheels can grind items very effectively", - "create.ponder.crushing_wheels.text_2": "UNLOCALIZED: Their Rotational Input has to make them spin into each other", - "create.ponder.crushing_wheels.text_3": "UNLOCALIZED: Items thrown or inserted into the top will get processed", - "create.ponder.crushing_wheels.text_4": "UNLOCALIZED: Items can be inserted and picked up through automated means as well", - - "create.ponder.deployer.header": "UNLOCALIZED: Using the Deployer", - "create.ponder.deployer.text_1": "UNLOCALIZED: Given Rotational Force, a Deployer can imitate player interactions", - "create.ponder.deployer.text_10": "UNLOCALIZED: Right-click the front to give it an Item to use", - "create.ponder.deployer.text_11": "UNLOCALIZED: Items can also be inserted automatically", - "create.ponder.deployer.text_12": "UNLOCALIZED: Deployers carry a filter slot", - "create.ponder.deployer.text_13": "UNLOCALIZED: When a filter is set, it activates only while holding a matching item", - "create.ponder.deployer.text_14": "UNLOCALIZED: Only items matching the filter can now be inserted...", - "create.ponder.deployer.text_15": "UNLOCALIZED: ...and only non-matching items will be extracted", - "create.ponder.deployer.text_2": "UNLOCALIZED: It will always interact with the position 2 blocks in front of itself", - "create.ponder.deployer.text_3": "UNLOCALIZED: Blocks directly in front will not obstruct it", - "create.ponder.deployer.text_4": "UNLOCALIZED: Deployers can:", - "create.ponder.deployer.text_5": "UNLOCALIZED: Place Blocks,", - "create.ponder.deployer.text_6": "UNLOCALIZED: Use Items,", - "create.ponder.deployer.text_7": "UNLOCALIZED: Activate Blocks,", - "create.ponder.deployer.text_8": "UNLOCALIZED: Harvest blocks", - "create.ponder.deployer.text_9": "UNLOCALIZED: and Attack Mobs", - - "create.ponder.deployer_contraption.header": "UNLOCALIZED: Using Deployers on Contraptions", - "create.ponder.deployer_contraption.text_1": "UNLOCALIZED: Whenever Deployers are moved as part of an animated Contraption...", - "create.ponder.deployer_contraption.text_2": "UNLOCALIZED: They activate at each visited location, using items from inventories anywhere on the contraption", - "create.ponder.deployer_contraption.text_3": "UNLOCALIZED: The Filter slot can be used to specify which items to pull", - - "create.ponder.deployer_modes.header": "UNLOCALIZED: Modes of the Deployer", - "create.ponder.deployer_modes.text_1": "UNLOCALIZED: By default, a Deployer imitates a Right-click interaction", - "create.ponder.deployer_modes.text_2": "UNLOCALIZED: Using a Wrench, it can be set to imitate a Left-click instead", - - "create.ponder.deployer_redstone.header": "UNLOCALIZED: Controlling Deployers with Redstone", - "create.ponder.deployer_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Deployers will not activate", - "create.ponder.deployer_redstone.text_2": "UNLOCALIZED: Before stopping, the Deployer will finish any started cycles", - "create.ponder.deployer_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", - - "create.ponder.depot.header": "UNLOCALIZED: Using Depots", - "create.ponder.depot.text_1": "UNLOCALIZED: Depots can serve as 'stationary' belt elements", - "create.ponder.depot.text_2": "UNLOCALIZED: Right-Click to manually place or remove Items from it", - "create.ponder.depot.text_3": "UNLOCALIZED: Just like Mechanical Belts, it can provide items to processing", - "create.ponder.depot.text_4": "UNLOCALIZED: ...as well as provide Items to Mechanical Arms", - - "create.ponder.empty_blaze_burner.header": "UNLOCALIZED: Using Empty Blaze Burners", - "create.ponder.empty_blaze_burner.text_1": "UNLOCALIZED: Right-click a Blaze with the empty burner to capture it", - "create.ponder.empty_blaze_burner.text_2": "UNLOCALIZED: Alternatively, Blazes can be collected from their Spawners directly", - "create.ponder.empty_blaze_burner.text_3": "UNLOCALIZED: You now have an ideal heat source for various machines", - "create.ponder.empty_blaze_burner.text_4": "UNLOCALIZED: For Aesthetic purposes, Empty Blaze Burners can also be lit using Flint and Steel", - "create.ponder.empty_blaze_burner.text_5": "UNLOCALIZED: However, these are not suitable for industrial heating", - - "create.ponder.fan_direction.header": "UNLOCALIZED: Air flow of Encased Fans", - "create.ponder.fan_direction.text_1": "UNLOCALIZED: Encased Fans use Rotational Force to create an Air Current", - "create.ponder.fan_direction.text_2": "UNLOCALIZED: Strength and Direction of Flow depends on the Rotational Input", - - "create.ponder.fan_processing.header": "UNLOCALIZED: Processing Items using Encased Fans", - "create.ponder.fan_processing.text_1": "UNLOCALIZED: When passing through lava, the Air Flow becomes Heated", - "create.ponder.fan_processing.text_2": "UNLOCALIZED: Items caught in the area will be smelted", - "create.ponder.fan_processing.text_3": "UNLOCALIZED: Food items thrown here would be incinerated", - "create.ponder.fan_processing.text_4": "UNLOCALIZED: Instead, a setup for Smoking using Fire should be used for them", - "create.ponder.fan_processing.text_5": "UNLOCALIZED: Air Flows passing through water create a Washing Setup", - "create.ponder.fan_processing.text_6": "UNLOCALIZED: Some interesting new processing can be done with it", - "create.ponder.fan_processing.text_7": "UNLOCALIZED: The Speed of the Fan does NOT affect the processing speed, only its range", - "create.ponder.fan_processing.text_8": "UNLOCALIZED: Fan Processing can also be applied to Items on Depots and Belts", - - "create.ponder.fan_source.header": "UNLOCALIZED: Generating Rotational Force using Encased Fans", - "create.ponder.fan_source.text_1": "UNLOCALIZED: Fans facing down into a source of heat can provide Rotational Force", - "create.ponder.fan_source.text_2": "UNLOCALIZED: When given a Redstone Signal, the Fans will start providing power", - - "create.ponder.flywheel.header": "UNLOCALIZED: Generating Rotational Force using the Flywheel", - "create.ponder.flywheel.text_1": "UNLOCALIZED: Flywheels are required for generating rotational force with the Furnace Engine", - "create.ponder.flywheel.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", - "create.ponder.flywheel.text_3": "UNLOCALIZED: Using a Blast Furnace will double the efficiency of the Engine", - - "create.ponder.funnel_compat.header": "UNLOCALIZED: Funnel compatibility", - "create.ponder.funnel_compat.text_1": "UNLOCALIZED: Funnels should also interact nicely with a handful of other components.", - "create.ponder.funnel_compat.text_2": "UNLOCALIZED: Vertical Saws", - "create.ponder.funnel_compat.text_3": "UNLOCALIZED: Depots", - "create.ponder.funnel_compat.text_4": "UNLOCALIZED: Item Drains", - - "create.ponder.funnel_direction.header": "UNLOCALIZED: Direction of Transfer", - "create.ponder.funnel_direction.text_1": "UNLOCALIZED: Placed normally, it pulls items from the inventory.", - "create.ponder.funnel_direction.text_2": "UNLOCALIZED: Placed while sneaking, it puts items into the inventory.", - "create.ponder.funnel_direction.text_3": "UNLOCALIZED: Using a wrench, the funnel can be flipped after placement.", - "create.ponder.funnel_direction.text_4": "UNLOCALIZED: Same rules will apply for most orientations.", - "create.ponder.funnel_direction.text_5": "UNLOCALIZED: Funnels on belts will extract/insert depending on its movement direction.", - - "create.ponder.funnel_intro.header": "UNLOCALIZED: Using funnels", - "create.ponder.funnel_intro.text_1": "UNLOCALIZED: Funnels are ideal for transferring items from and to inventories.", - - "create.ponder.funnel_redstone.header": "UNLOCALIZED: Redstone control", - "create.ponder.funnel_redstone.text_1": "UNLOCALIZED: Redstone power will prevent any funnel from acting", - - "create.ponder.funnel_transfer.header": "UNLOCALIZED: Direct transfer", - "create.ponder.funnel_transfer.text_1": "UNLOCALIZED: Funnels cannot ever transfer between closed inventories directly.", - "create.ponder.funnel_transfer.text_2": "UNLOCALIZED: Chutes or Smart chutes might be more suitable for such purposes.", - "create.ponder.funnel_transfer.text_3": "UNLOCALIZED: Same applies for horizontal movement. A mechanical belt should help here.", - - "create.ponder.furnace_engine.header": "UNLOCALIZED: Generating Rotational Force using the Furnace Engine", - "create.ponder.furnace_engine.text_1": "UNLOCALIZED: Furnace Engines generate Rotational Force while their attached Furnace is running", - "create.ponder.furnace_engine.text_2": "UNLOCALIZED: The provided Rotational Force has a very large stress capacity", - "create.ponder.furnace_engine.text_3": "UNLOCALIZED: Using a Blast Furnace will double the efficiency of the Engine", - - "create.ponder.gantry_carriage.header": "UNLOCALIZED: Using Gantry Carriages", - "create.ponder.gantry_carriage.text_1": "UNLOCALIZED: Gantry Carriages can mount to and slide along a Gantry Shaft.", - "create.ponder.gantry_carriage.text_2": "UNLOCALIZED: Gantry setups can move attached Blocks.", - - "create.ponder.gantry_cascaded.header": "UNLOCALIZED: Cascaded Gantries", - "create.ponder.gantry_cascaded.text_1": "UNLOCALIZED: Gantry shafts attach to a carriage without the need of super glue", - "create.ponder.gantry_cascaded.text_2": "UNLOCALIZED: Same applies for carriages on moved Gantry Shafts", - "create.ponder.gantry_cascaded.text_3": "UNLOCALIZED: Thus, a gantry system can be cascaded to cover multiple axes of movement", - - "create.ponder.gantry_direction.header": "UNLOCALIZED: Gantry Movement Direction", - "create.ponder.gantry_direction.text_1": "UNLOCALIZED: Gantry Shafts can have opposite orientations", - "create.ponder.gantry_direction.text_2": "UNLOCALIZED: The movement direction of carriages depend on their shafts' orientation", - "create.ponder.gantry_direction.text_3": "UNLOCALIZED: ...as well as the rotation direction of the shaft", - "create.ponder.gantry_direction.text_4": "UNLOCALIZED: Same rules apply for the propagated rotation", - - "create.ponder.gantry_redstone.header": "UNLOCALIZED: Gantry Power Propagation", - "create.ponder.gantry_redstone.text_1": "UNLOCALIZED: Redstone-powered gantry shafts stop moving their carriages", - "create.ponder.gantry_redstone.text_2": "UNLOCALIZED: Instead, its rotational force is relayed to the carriages' output shaft", - - "create.ponder.gantry_shaft.header": "UNLOCALIZED: Using Gantry Shafts", - "create.ponder.gantry_shaft.text_1": "UNLOCALIZED: Gantry Shafts form the basis of a gantry setup. Attached Carriages will move along them.", - "create.ponder.gantry_shaft.text_2": "UNLOCALIZED: Gantry setups can move attached Blocks.", - - "create.ponder.gearbox.header": "UNLOCALIZED: Relaying rotational force using Gearboxes", - "create.ponder.gearbox.text_1": "UNLOCALIZED: Jumping between axes of rotation can get bulky quickly", - "create.ponder.gearbox.text_2": "UNLOCALIZED: A gearbox is the more compact equivalent of this setup", - "create.ponder.gearbox.text_3": "UNLOCALIZED: Shafts around corners rotate in mirrored directions", - "create.ponder.gearbox.text_4": "UNLOCALIZED: Straight connections will be reversed", - - "create.ponder.gearshift.header": "UNLOCALIZED: Controlling rotational force using a Gearshift", - "create.ponder.gearshift.text_1": "UNLOCALIZED: Gearshifts will relay rotation in a straight line", - "create.ponder.gearshift.text_2": "UNLOCALIZED: When powered by Redstone, it reverses the transmission", - - "create.ponder.hand_crank.header": "UNLOCALIZED: Generating Rotational Force using Hand Cranks", - "create.ponder.hand_crank.text_1": "UNLOCALIZED: Hand Cranks can be used by players to apply rotational force manually", - "create.ponder.hand_crank.text_2": "UNLOCALIZED: Hold Right-Click to rotate it Counter-Clockwise", - "create.ponder.hand_crank.text_3": "UNLOCALIZED: Its conveyed speed is relatively high", - "create.ponder.hand_crank.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", - - "create.ponder.large_cogwheel.header": "UNLOCALIZED: Relaying rotational force using Large Cogwheels", - "create.ponder.large_cogwheel.text_1": "UNLOCALIZED: Large cogwheels can connect to each other at right angles", - "create.ponder.large_cogwheel.text_2": "UNLOCALIZED: It will help relaying conveyed speed to other axes of rotation", - - "create.ponder.linear_chassis_attachment.header": "UNLOCALIZED: Attaching blocks using Linear Chassis", - "create.ponder.linear_chassis_attachment.text_1": "UNLOCALIZED: The open faces of a Linear Chassis can be made Sticky", - "create.ponder.linear_chassis_attachment.text_2": "UNLOCALIZED: Click again to make the opposite side sticky", - "create.ponder.linear_chassis_attachment.text_3": "UNLOCALIZED: Sneak and Right-Click with an empty hand to remove the slime", - "create.ponder.linear_chassis_attachment.text_4": "UNLOCALIZED: Stickied faces of the Linear Chassis will attach a line of blocks in front of it", - "create.ponder.linear_chassis_attachment.text_5": "UNLOCALIZED: Using a Wrench, a precise Range can be specified for this chassis", - "create.ponder.linear_chassis_attachment.text_6": "UNLOCALIZED: Holding CTRL and scrolling adjusts the range of all attached Chassis Blocks", - "create.ponder.linear_chassis_attachment.text_7": "UNLOCALIZED: Attaching blocks to any other side requires the use of Super Glue", - "create.ponder.linear_chassis_attachment.text_8": "UNLOCALIZED: Using these mechanics, structures of any shape can move as a Contraption", - - "create.ponder.linear_chassis_group.header": "UNLOCALIZED: Moving Linear Chassis in groups", - "create.ponder.linear_chassis_group.text_1": "UNLOCALIZED: Linear Chassis connect to identical Chassis blocks next to them", - "create.ponder.linear_chassis_group.text_2": "UNLOCALIZED: When one is moved by a Contraption, the others are dragged with it", - "create.ponder.linear_chassis_group.text_3": "UNLOCALIZED: Chassis of a different type or facing another direction will not attach", - - "create.ponder.mechanical_arm.header": "UNLOCALIZED: Setting up Mechanical Arms", - "create.ponder.mechanical_arm.text_1": "UNLOCALIZED: Mechanical Arms have to be assigned their in- and outputs before they are placed", - "create.ponder.mechanical_arm.text_2": "UNLOCALIZED: Right-Click inventories while holding the Arm to assign them as Targets", - "create.ponder.mechanical_arm.text_3": "UNLOCALIZED: Right-Click again to toggle between Input (Blue) and Output (Orange)", - "create.ponder.mechanical_arm.text_4": "UNLOCALIZED: Left-Click components to remove their Selection", - "create.ponder.mechanical_arm.text_5": "UNLOCALIZED: Once placed, the Mechanical Arm will target the blocks selected previously", - "create.ponder.mechanical_arm.text_6": "UNLOCALIZED: They can have any amount of in- and outputs within their range", - "create.ponder.mechanical_arm.text_7": "UNLOCALIZED: However, not every type of Inventory can be interacted with directly", - "create.ponder.mechanical_arm.text_8": "UNLOCALIZED: Funnels and Depots can help to Bridge that gap", - - "create.ponder.mechanical_arm_filtering.header": "UNLOCALIZED: Filtering Outputs of the Mechanical Arm", - "create.ponder.mechanical_arm_filtering.text_1": "UNLOCALIZED: Inputs", - "create.ponder.mechanical_arm_filtering.text_2": "UNLOCALIZED: Outputs", - "create.ponder.mechanical_arm_filtering.text_3": "UNLOCALIZED: Sometimes it is desirable to restrict targets of the Arm by matching a filter", - "create.ponder.mechanical_arm_filtering.text_4": "UNLOCALIZED: Mechanical Arms by themselves do not provide any options for filtering", - "create.ponder.mechanical_arm_filtering.text_5": "UNLOCALIZED: Brass Funnels as Targets do however communicate their own filter to the Arm", - "create.ponder.mechanical_arm_filtering.text_6": "UNLOCALIZED: The Arm is smart enough not to pick up items it couldn't distribute", - - "create.ponder.mechanical_arm_modes.header": "UNLOCALIZED: Distribution modes of the Mechanical Arm", - "create.ponder.mechanical_arm_modes.text_1": "UNLOCALIZED: Input", - "create.ponder.mechanical_arm_modes.text_2": "UNLOCALIZED: Outputs", - "create.ponder.mechanical_arm_modes.text_3": "UNLOCALIZED: Whenever an Arm has to choose between multiple valid outputs...", - "create.ponder.mechanical_arm_modes.text_4": "UNLOCALIZED: ...it will act according to its setting", - "create.ponder.mechanical_arm_modes.text_5": "UNLOCALIZED: Scrolling with a Wrench will allow you to configure it", - "create.ponder.mechanical_arm_modes.text_6": "UNLOCALIZED: Round Robin mode simply cycles through all outputs that are available", - "create.ponder.mechanical_arm_modes.text_7": "UNLOCALIZED: If an output is unable to take more items, it will be skipped", - "create.ponder.mechanical_arm_modes.text_8": "UNLOCALIZED: Forced Round Robin mode will never skip outputs, and instead wait until they are free", - "create.ponder.mechanical_arm_modes.text_9": "UNLOCALIZED: Prefer First prioritizes the outputs selected earliest when configuring this Arm", - - "create.ponder.mechanical_arm_redstone.header": "UNLOCALIZED: Controlling Mechanical Arms with Redstone", - "create.ponder.mechanical_arm_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Mechanical Arms will not activate", - "create.ponder.mechanical_arm_redstone.text_2": "UNLOCALIZED: Before stopping, it will finish any started cycles", - "create.ponder.mechanical_arm_redstone.text_3": "UNLOCALIZED: Thus, a negative pulse can be used to trigger exactly one activation cycle", - - "create.ponder.mechanical_bearing.header": "UNLOCALIZED: Movings Structures using the Mechanical Bearing", - "create.ponder.mechanical_bearing.text_1": "UNLOCALIZED: Mechanical Bearings attach to the block in front of them", - "create.ponder.mechanical_bearing.text_2": "UNLOCALIZED: Upon receiving Rotational Force, it will assemble it into a Rotating Contraption", - - "create.ponder.mechanical_crafter.header": "UNLOCALIZED: Setting up Mechanical Crafters", - "create.ponder.mechanical_crafter.text_1": "UNLOCALIZED: An array of Mechanical Crafters can be used to automate any Crafting Recipe", - "create.ponder.mechanical_crafter.text_2": "UNLOCALIZED: Using a Wrench, the Crafters' paths can be arranged", - "create.ponder.mechanical_crafter.text_3": "UNLOCALIZED: For a valid setup, all paths have to converge into one exit at any side", - "create.ponder.mechanical_crafter.text_4": "UNLOCALIZED: The outputs will be placed into the inventory at the exit", - "create.ponder.mechanical_crafter.text_5": "UNLOCALIZED: Mechanical Crafters require Rotational Force to operate", - "create.ponder.mechanical_crafter.text_6": "UNLOCALIZED: Right-Click the front to insert Items manually", - "create.ponder.mechanical_crafter.text_7": "UNLOCALIZED: Once every slot of a path contains an Item, the crafting process will begin", - "create.ponder.mechanical_crafter.text_8": "UNLOCALIZED: For recipes not fully occupying the crafter setup, the start can be forced using a Redstone Pulse", - - "create.ponder.mechanical_crafter_connect.header": "UNLOCALIZED: Connecting Inventories of Crafters", - "create.ponder.mechanical_crafter_connect.text_1": "UNLOCALIZED: Items can be inserted to Crafters automatically", - "create.ponder.mechanical_crafter_connect.text_2": "UNLOCALIZED: Using the Wrench at their backs, Mechanical Crafter inputs can be combined", - "create.ponder.mechanical_crafter_connect.text_3": "UNLOCALIZED: All connected Crafters can now be accessed by the same input location", - - "create.ponder.mechanical_crafter_covers.header": "UNLOCALIZED: Covering slots of Mechanical Crafters", - "create.ponder.mechanical_crafter_covers.text_1": "UNLOCALIZED: Some recipes will require additional Crafters to bridge gaps in the path", - "create.ponder.mechanical_crafter_covers.text_2": "UNLOCALIZED: Using Slot Covers, Crafters can be set to act as an Empty Slot in the arrangement", - "create.ponder.mechanical_crafter_covers.text_3": "UNLOCALIZED: Shared Inputs created with the Wrench at the back can also reach across covered Crafters", - - "create.ponder.mechanical_drill.header": "UNLOCALIZED: Breaking Blocks with the Mechanical Drill", - "create.ponder.mechanical_drill.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Drill will break blocks directly in front of it", - "create.ponder.mechanical_drill.text_2": "UNLOCALIZED: Its mining speed depends on the Rotational Input", - - "create.ponder.mechanical_drill_contraption.header": "UNLOCALIZED: Using Mechanical Drills on Contraptions", - "create.ponder.mechanical_drill_contraption.text_1": "UNLOCALIZED: Whenever Drills are moved as part of an animated Contraption...", - "create.ponder.mechanical_drill_contraption.text_2": "UNLOCALIZED: ...they will break blocks the contraption runs them into", - - "create.ponder.mechanical_harvester.header": "UNLOCALIZED: Using Mechanical Harvesters on Contraptions", - "create.ponder.mechanical_harvester.text_1": "UNLOCALIZED: Whenever Harvesters are moved as part of an animated Contraption...", - "create.ponder.mechanical_harvester.text_2": "UNLOCALIZED: They will harvest and reset any mature crops on their way", - - "create.ponder.mechanical_mixer.header": "UNLOCALIZED: Processing Items with the Mechanical Mixer", - "create.ponder.mechanical_mixer.text_1": "UNLOCALIZED: With a Mixer and Basin, some Crafting Recipes can be automated", - "create.ponder.mechanical_mixer.text_2": "UNLOCALIZED: Available recipes include any Shapeless Crafting Recipe, plus a couple extra ones", - "create.ponder.mechanical_mixer.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", - "create.ponder.mechanical_mixer.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", - - "create.ponder.mechanical_piston.header": "UNLOCALIZED: Moving Structures using Mechanical Pistons", - "create.ponder.mechanical_piston.text_1": "UNLOCALIZED: Mechanical Pistons can move blocks in front of them", - "create.ponder.mechanical_piston.text_2": "UNLOCALIZED: Speed and direction of movement depend on the Rotational Input", - "create.ponder.mechanical_piston.text_3": "UNLOCALIZED: Sticky Mechanical Pistons can pull the attached blocks back", - - "create.ponder.mechanical_piston_modes.header": "UNLOCALIZED: Movement Modes of the Mechanical Piston", - "create.ponder.mechanical_piston_modes.text_1": "UNLOCALIZED: Whenever Pistons stop moving, the moved structure reverts to blocks", - "create.ponder.mechanical_piston_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only at the location it started at", - - "create.ponder.mechanical_plough.header": "UNLOCALIZED: Using Mechanical Ploughs on Contraptions", - "create.ponder.mechanical_plough.text_1": "UNLOCALIZED: Whenever Ploughs are moved as part of an animated Contraption...", - "create.ponder.mechanical_plough.text_2": "UNLOCALIZED: ...they will break blocks without a solid collision hitbox", - "create.ponder.mechanical_plough.text_3": "UNLOCALIZED: Additionally, ploughs can create farmland", - "create.ponder.mechanical_plough.text_4": "UNLOCALIZED: ...they can also launch entities without hurting them", - - "create.ponder.mechanical_press.header": "UNLOCALIZED: Processing Items with the Mechanical Press", - "create.ponder.mechanical_press.text_1": "UNLOCALIZED: The Mechanical Press can process items provided beneath it", - "create.ponder.mechanical_press.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Press", - "create.ponder.mechanical_press.text_3": "UNLOCALIZED: When items are provided on a belt...", - "create.ponder.mechanical_press.text_4": "UNLOCALIZED: The Press will hold and process them automatically", - - "create.ponder.mechanical_press_compacting.header": "UNLOCALIZED: Compacting items with the Mechanical Press", - "create.ponder.mechanical_press_compacting.text_1": "UNLOCALIZED: Pressing items held in a Basin will cause them to be Compacted", - "create.ponder.mechanical_press_compacting.text_2": "UNLOCALIZED: Compacting includes any filled 2x2 or 3x3 Crafting Recipe, plus a couple extra ones", - "create.ponder.mechanical_press_compacting.text_3": "UNLOCALIZED: Some of those recipes may require the heat of a Blaze Burner", - "create.ponder.mechanical_press_compacting.text_4": "UNLOCALIZED: The filter slot can be used in case two recipes are conflicting.", - - "create.ponder.mechanical_saw_breaker.header": "UNLOCALIZED: Cutting Trees with the Mechanical Saw", - "create.ponder.mechanical_saw_breaker.text_1": "UNLOCALIZED: When given Rotational Force, a Mechanical Saw will cut trees directly in front of it", - "create.ponder.mechanical_saw_breaker.text_2": "UNLOCALIZED: In order to cut the tree fully, the Saw has to break the last block connecting it to the ground", - - "create.ponder.mechanical_saw_contraption.header": "UNLOCALIZED: Using Mechanical Saws on Contraptions", - "create.ponder.mechanical_saw_contraption.text_1": "UNLOCALIZED: Whenever Saws are moved as part of an animated Contraption...", - "create.ponder.mechanical_saw_contraption.text_2": "UNLOCALIZED: ...they will cut any trees the contraption runs them into", - - "create.ponder.mechanical_saw_processing.header": "UNLOCALIZED: Processing Items on the Mechanical Saw", - "create.ponder.mechanical_saw_processing.text_1": "UNLOCALIZED: Upward facing Mechanical Saws can process a variety of items", - "create.ponder.mechanical_saw_processing.text_2": "UNLOCALIZED: The processed item always moves against the rotational input to the saw", - "create.ponder.mechanical_saw_processing.text_3": "UNLOCALIZED: Saws can work in-line with Mechanical Belts", - "create.ponder.mechanical_saw_processing.text_4": "UNLOCALIZED: When an ingredient has multiple possible outcomes, the filter slot can specify it", - "create.ponder.mechanical_saw_processing.text_5": "UNLOCALIZED: Without filter, the Saw would cycle through all outcomes instead", - - "create.ponder.millstone.header": "UNLOCALIZED: Processing Items in the Millstone", - "create.ponder.millstone.text_1": "UNLOCALIZED: Millstones process items by grinding them", - "create.ponder.millstone.text_2": "UNLOCALIZED: They can be powered from the side using cogwheels", - "create.ponder.millstone.text_3": "UNLOCALIZED: Throw or Insert items at the top", - "create.ponder.millstone.text_4": "UNLOCALIZED: After some time, the result can be obtained via Right-click", - "create.ponder.millstone.text_5": "UNLOCALIZED: The outputs can also be extracted by automation", - - "create.ponder.nixie_tube.header": "UNLOCALIZED: Using Nixie Tubes", - "create.ponder.nixie_tube.text_1": "UNLOCALIZED: When powered by Redstone, Nixie Tubes will display the redstone signals' strength", - "create.ponder.nixie_tube.text_2": "UNLOCALIZED: Using name tags edited with an anvil, custom text can be displayed", - - "create.ponder.piston_pole.header": "UNLOCALIZED: Piston Extension Poles", - "create.ponder.piston_pole.text_1": "UNLOCALIZED: Without attached Poles, a Mechanical Piston cannot move", - "create.ponder.piston_pole.text_2": "UNLOCALIZED: The Length of pole added at its back determines the Extension Range", - - "create.ponder.portable_storage_interface.header": "UNLOCALIZED: Contraption Storage Exchange", - "create.ponder.portable_storage_interface.text_1": "UNLOCALIZED: Inventories on moving contraptions cannot be accessed by players.", - "create.ponder.portable_storage_interface.text_2": "UNLOCALIZED: This component can interact with storage without the need to stop the contraption.", - "create.ponder.portable_storage_interface.text_3": "UNLOCALIZED: Place a second one with a gap of 1 or 2 blocks inbetween", - "create.ponder.portable_storage_interface.text_4": "UNLOCALIZED: Whenever they pass by each other, they will engage in a connection", - "create.ponder.portable_storage_interface.text_5": "UNLOCALIZED: While engaged, the stationary interface will represent ALL inventories on the contraption", - "create.ponder.portable_storage_interface.text_6": "UNLOCALIZED: Items can now be inserted...", - "create.ponder.portable_storage_interface.text_7": "UNLOCALIZED: ...or extracted from the contraption", - "create.ponder.portable_storage_interface.text_8": "UNLOCALIZED: After no items have been exchanged for a while, the contraption will continue on its way", - - "create.ponder.portable_storage_interface_redstone.header": "UNLOCALIZED: Redstone Control", - "create.ponder.portable_storage_interface_redstone.text_1": "UNLOCALIZED: Redstone power will prevent the stationary interface from engaging", - - "create.ponder.powered_latch.header": "UNLOCALIZED: Controlling signals using the Powered Latch", - "create.ponder.powered_latch.text_1": "UNLOCALIZED: Powered Latches are redstone controllable Levers", - "create.ponder.powered_latch.text_2": "UNLOCALIZED: Signals at the back switch it on", - "create.ponder.powered_latch.text_3": "UNLOCALIZED: Signals from the side switch it back off", - "create.ponder.powered_latch.text_4": "UNLOCALIZED: Powered latches can also be toggled manually", - - "create.ponder.powered_toggle_latch.header": "UNLOCALIZED: Controlling signals using the Powered Toggle Latch", - "create.ponder.powered_toggle_latch.text_1": "UNLOCALIZED: Powered Toggle Latches are redstone controllable Levers", - "create.ponder.powered_toggle_latch.text_2": "UNLOCALIZED: Signals at the back will toggle its state", - "create.ponder.powered_toggle_latch.text_3": "UNLOCALIZED: ...on and back off", - "create.ponder.powered_toggle_latch.text_4": "UNLOCALIZED: Powered toggle latches can also be toggled manually", - - "create.ponder.pulse_repeater.header": "UNLOCALIZED: Controlling signals using Pulse Repeaters", - "create.ponder.pulse_repeater.text_1": "UNLOCALIZED: Pulse Repeaters will shorten any redstone signal to a single pulse", - - "create.ponder.radial_chassis.header": "UNLOCALIZED: Attaching blocks using Radial Chassis", - "create.ponder.radial_chassis.text_1": "UNLOCALIZED: Radial Chassis connect to identical Chassis blocks in a row", - "create.ponder.radial_chassis.text_2": "UNLOCALIZED: When one is moved by a Contraption, the others are dragged with it", - "create.ponder.radial_chassis.text_3": "UNLOCALIZED: The side faces of a Radial Chassis can be made Sticky", - "create.ponder.radial_chassis.text_4": "UNLOCALIZED: Click again to make all other sides sticky", - "create.ponder.radial_chassis.text_5": "UNLOCALIZED: Sneak and Right-Click with an empty hand to remove the slime", - "create.ponder.radial_chassis.text_6": "UNLOCALIZED: Whenever a Block is next to a sticky face...", - "create.ponder.radial_chassis.text_7": "UNLOCALIZED: ...it will attach all reachable blocks within a radius on that layer", - "create.ponder.radial_chassis.text_8": "UNLOCALIZED: Using a Wrench, a precise Radius can be specified for this chassis", - "create.ponder.radial_chassis.text_9": "UNLOCALIZED: Blocks not reachable by any sticky face will not attach", - - "create.ponder.redstone_contact.header": "UNLOCALIZED: Redstone Contacts", - "create.ponder.redstone_contact.text_1": "UNLOCALIZED: Redstone Contacts facing each other will emit a redstone signal", - "create.ponder.redstone_contact.text_2": "UNLOCALIZED: This still applies when one of them is part of a moving Contraption", - - "create.ponder.redstone_link.header": "UNLOCALIZED: Using Redstone Links", - "create.ponder.redstone_link.text_1": "UNLOCALIZED: Redstone Links can transmit redstone signals wirelessly", - "create.ponder.redstone_link.text_2": "UNLOCALIZED: Right-click while Sneaking to toggle receive mode", - "create.ponder.redstone_link.text_3": "UNLOCALIZED: A simple Right-click with a Wrench can do the same", - "create.ponder.redstone_link.text_4": "UNLOCALIZED: Receivers emit the redstone power of transmitters within 128 blocks", - "create.ponder.redstone_link.text_5": "UNLOCALIZED: Placing items in the two slots can specify a Frequency", - "create.ponder.redstone_link.text_6": "UNLOCALIZED: Only the links with matching Frequencies will communicate", - - "create.ponder.rope_pulley.header": "UNLOCALIZED: Moving Structures using Rope Pulleys", - "create.ponder.rope_pulley.text_1": "UNLOCALIZED: Rope Pulleys can move blocks vertically when given Rotational Force", - "create.ponder.rope_pulley.text_2": "UNLOCALIZED: Direction and Speed of movement depend on the Rotational Input", - - "create.ponder.rope_pulley_attachment.header": "UNLOCALIZED: Moving Pulleys as part of a Contraption", - "create.ponder.rope_pulley_attachment.text_1": "UNLOCALIZED: Whenever Pulleys are themselves being moved by a Contraption...", - "create.ponder.rope_pulley_attachment.text_2": "UNLOCALIZED: ...its attached structure will be dragged with it", - "create.ponder.rope_pulley_attachment.text_3": "UNLOCALIZED: Mind that pulleys are only movable while stopped", - - "create.ponder.rope_pulley_modes.header": "UNLOCALIZED: Movement Modes of the Rope Pulley", - "create.ponder.rope_pulley_modes.text_1": "UNLOCALIZED: Whenever Pulleys stop moving, the moved structure reverts to blocks", - "create.ponder.rope_pulley_modes.text_2": "UNLOCALIZED: It can be configured never to revert to solid blocks, or only at the location it started at", - - "create.ponder.rotation_speed_controller.header": "UNLOCALIZED: Using the Rotational Speed Controller", - "create.ponder.rotation_speed_controller.text_1": "UNLOCALIZED: Rot. Speed Controllers relay rotation from their axis to a Large Cogwheel above them", - "create.ponder.rotation_speed_controller.text_2": "UNLOCALIZED: Using the scroll input on its side, the conveyed speed can be configured", - - "create.ponder.sail.header": "UNLOCALIZED: Assembling Windmills using Sails", - "create.ponder.sail.text_1": "UNLOCALIZED: Sails are handy blocks to create Windmills with", - "create.ponder.sail.text_2": "UNLOCALIZED: They will attach to blocks and each other without the need of Super Glue or Chassis Blocks", - "create.ponder.sail.text_3": "UNLOCALIZED: Right-Click with Dye to paint them", - "create.ponder.sail.text_4": "UNLOCALIZED: Right-Click with Shears to turn them back into frames", - - "create.ponder.sail_frame.header": "UNLOCALIZED: Assembling Windmills using Sail Frames", - "create.ponder.sail_frame.text_1": "UNLOCALIZED: Sail Frames are handy blocks to create Windmills with", - "create.ponder.sail_frame.text_2": "UNLOCALIZED: They will attach to blocks and each other without the need of Super Glue or Chassis Blocks", - - "create.ponder.sequenced_gearshift.header": "UNLOCALIZED: Controlling Rotational Speed using Sequenced Gearshifts", - "create.ponder.sequenced_gearshift.text_1": "UNLOCALIZED: Seq. Gearshifts relay rotation by following a timed list of instructions", - "create.ponder.sequenced_gearshift.text_2": "UNLOCALIZED: Right-click it to open the Configuration UI", - "create.ponder.sequenced_gearshift.text_3": "UNLOCALIZED: Upon receiving a Redstone Signal, it will start running its configured sequence", - "create.ponder.sequenced_gearshift.text_4": "UNLOCALIZED: Once finished, it waits for the next Redstone Signal and starts over", - "create.ponder.sequenced_gearshift.text_5": "UNLOCALIZED: A redstone comparator can be used to read the current progress", - - "create.ponder.shaft.header": "UNLOCALIZED: Relaying rotational force using Shafts", - "create.ponder.shaft.text_1": "UNLOCALIZED: Shafts will relay rotation in a straight line.", - - "create.ponder.shaft_casing.header": "UNLOCALIZED: Encasing Shafts", - "create.ponder.shaft_casing.text_1": "UNLOCALIZED: Brass or Andesite Casing can be used to decorate Shafts", - - "create.ponder.smart_chute.header": "UNLOCALIZED: Filtering Items using Smart Chutes", - "create.ponder.smart_chute.text_1": "UNLOCALIZED: Smart Chutes are vertical chutes with additional control", - "create.ponder.smart_chute.text_2": "UNLOCALIZED: Items in the filter slot specify what exactly they can extract and transfer", - "create.ponder.smart_chute.text_3": "UNLOCALIZED: Use the Mouse Wheel to specify the extracted stack size", - "create.ponder.smart_chute.text_4": "UNLOCALIZED: Redstone power will prevent Smart Chutes from acting.", - - "create.ponder.speedometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Speedometer", - "create.ponder.speedometer.text_1": "UNLOCALIZED: The Speedometer displays the current Speed of the attached components", - "create.ponder.speedometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", - "create.ponder.speedometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Speedometer's measurements", - - "create.ponder.stabilized_bearings.header": "UNLOCALIZED: Stabilized Contraptions", - "create.ponder.stabilized_bearings.text_1": "UNLOCALIZED: Whenever Mechanical Bearings are themselves part of a moving Structure..", - "create.ponder.stabilized_bearings.text_2": "UNLOCALIZED: ..they will attempt to keep themselves upright", - "create.ponder.stabilized_bearings.text_3": "UNLOCALIZED: Once again, the bearing will attach to the block in front of it", - "create.ponder.stabilized_bearings.text_4": "UNLOCALIZED: As a result, the entire sub-Contraption will stay upright", - - "create.ponder.sticker.header": "UNLOCALIZED: Attaching blocks using the Sticker", - "create.ponder.sticker.text_1": "UNLOCALIZED: Stickers are ideal for Redstone-controlled block attachment", - "create.ponder.sticker.text_2": "UNLOCALIZED: Upon receiving a signal, it will toggle its state", - "create.ponder.sticker.text_3": "UNLOCALIZED: If it is now moved in a contraption, the block will move with it", - "create.ponder.sticker.text_4": "UNLOCALIZED: Toggled once again, the block is no longer attached", - - "create.ponder.stressometer.header": "UNLOCALIZED: Monitoring Kinetic information using the Stressometer", - "create.ponder.stressometer.text_1": "UNLOCALIZED: The Stressometer displays the current Stress Capacity of the attached kinetic network", - "create.ponder.stressometer.text_2": "UNLOCALIZED: When wearing Engineers' Goggles, the player can get more detailed information from the Gauge", - "create.ponder.stressometer.text_3": "UNLOCALIZED: Comparators can emit analog Restone Signals relative to the Stressometer's measurements", - - "create.ponder.super_glue.header": "UNLOCALIZED: Attaching blocks using Super Glue", - "create.ponder.super_glue.text_1": "UNLOCALIZED: Super Glue can be used between any two blocks", - "create.ponder.super_glue.text_2": "UNLOCALIZED: The attached blocks will move together when assembled into a Contraption", - "create.ponder.super_glue.text_3": "UNLOCALIZED: Whenever Super Glue is held in the off-hand...", - "create.ponder.super_glue.text_4": "UNLOCALIZED: ...added blocks will be glued to the face they were placed on automatically", - "create.ponder.super_glue.text_5": "UNLOCALIZED: Super Glue can be removed with Left-Click", - - "create.ponder.valve_handle.header": "UNLOCALIZED: Generating Rotational Force using Valve Handles", - "create.ponder.valve_handle.text_1": "UNLOCALIZED: Valve Handles can be used by players to apply rotational force manually", - "create.ponder.valve_handle.text_2": "UNLOCALIZED: Hold Right-Click to rotate it Counter-Clockwise", - "create.ponder.valve_handle.text_3": "UNLOCALIZED: Its conveyed speed is slow and precise", - "create.ponder.valve_handle.text_4": "UNLOCALIZED: Sneak and Hold Right-Click to rotate it Clockwise", - "create.ponder.valve_handle.text_5": "UNLOCALIZED: Valve handles can be dyed for aesthetic purposes", - - "create.ponder.water_wheel.header": "UNLOCALIZED: Generating Rotational Force using Water Wheels", - "create.ponder.water_wheel.text_1": "UNLOCALIZED: Water Wheels draw force from adjacent Water Currents", - "create.ponder.water_wheel.text_2": "UNLOCALIZED: The more faces are powered, the faster the Water Wheel will rotate", - "create.ponder.water_wheel.text_3": "UNLOCALIZED: The Wheels' blades should be oriented against the flow", - "create.ponder.water_wheel.text_4": "UNLOCALIZED: Facing the opposite way, they will not be as effective", - - "create.ponder.weighted_ejector.header": "UNLOCALIZED: Using Weighted Ejectors", - "create.ponder.weighted_ejector.text_1": "UNLOCALIZED: Sneak and Right-Click holding an Ejector to select its target location", - "create.ponder.weighted_ejector.text_10": "UNLOCALIZED: It is now limited to this stack size, and only activates when its held stack reaches this amount", - "create.ponder.weighted_ejector.text_11": "UNLOCALIZED: Other Entities will always trigger an Ejector when stepping on it", - "create.ponder.weighted_ejector.text_2": "UNLOCALIZED: The placed ejector will now launch objects to the marked location", - "create.ponder.weighted_ejector.text_3": "UNLOCALIZED: A valid target can be at any height or distance within range", - "create.ponder.weighted_ejector.text_4": "UNLOCALIZED: They cannot however be off to a side", - "create.ponder.weighted_ejector.text_5": "UNLOCALIZED: If no valid Target was selected, it will simply target the block directly in front", - "create.ponder.weighted_ejector.text_6": "UNLOCALIZED: Supply Rotational Force in order to charge it up", - "create.ponder.weighted_ejector.text_7": "UNLOCALIZED: Items placed on the ejector cause it to trigger", - "create.ponder.weighted_ejector.text_8": "UNLOCALIZED: If Inventories are targeted, the ejector will wait until there is space", - "create.ponder.weighted_ejector.text_9": "UNLOCALIZED: Using the Wrench, a required Stack Size can be configured", - - "create.ponder.weighted_ejector_redstone.header": "UNLOCALIZED: Controlling Weighted Ejectors with Redstone", - "create.ponder.weighted_ejector_redstone.text_1": "UNLOCALIZED: When powered by Redstone, Ejectors will not activate", - "create.ponder.weighted_ejector_redstone.text_2": "UNLOCALIZED: Furthermore, Observers can detect when Ejectors activate", - - "create.ponder.weighted_ejector_tunnel.header": "UNLOCALIZED: Splitting item stacks using Weighted Ejectors", - "create.ponder.weighted_ejector_tunnel.text_1": "UNLOCALIZED: Combined with Brass Tunnels, Ejectors can split item stacks by specific amounts", - "create.ponder.weighted_ejector_tunnel.text_2": "UNLOCALIZED: First, configure the Brass Tunnel to 'Prefer Nearest', in order to prioritize its side output", - "create.ponder.weighted_ejector_tunnel.text_3": "UNLOCALIZED: The Stack Size set on the Ejector now determines the amount to be split off", - "create.ponder.weighted_ejector_tunnel.text_4": "UNLOCALIZED: While a new stack of the configured size exits the side output...", - "create.ponder.weighted_ejector_tunnel.text_5": "UNLOCALIZED: ...the remainder will continue on its path", - - "create.ponder.windmill_source.header": "UNLOCALIZED: Generating Rotational Force using Windmill Bearings", - "create.ponder.windmill_source.text_1": "UNLOCALIZED: Windmill Bearings attach to the block in front of them", - "create.ponder.windmill_source.text_2": "UNLOCALIZED: If enough Sail-like blocks are attached to the block, it can act as a Windmill", - "create.ponder.windmill_source.text_3": "UNLOCALIZED: Activated with Right-Click, the Windmill Bearing will start providing Rotational Force", - "create.ponder.windmill_source.text_4": "UNLOCALIZED: The Amount of Sail Blocks determine its Rotation Speed", - "create.ponder.windmill_source.text_5": "UNLOCALIZED: Use a Wrench to configure its rotation direction", - "create.ponder.windmill_source.text_6": "UNLOCALIZED: Right-click the Bearing anytime to stop and edit the Structure again", - - "create.ponder.windmill_structure.header": "UNLOCALIZED: Windmill Contraptions", - "create.ponder.windmill_structure.text_1": "UNLOCALIZED: Any Structure can count as a valid Windmill, as long as it contains at least 8 sail-like Blocks.", + "create.ponder.hold_to_ponder": "按住 [%1$s] 來思考此物品", + "create.ponder.subject": "本場景的主題", + "create.ponder.pondering": "思考有關於...", + "create.ponder.identify_mode": "暫停模式已啟動\n按 [%1$s] 來取消暫停模式", + "create.ponder.associated": "相關物品", + "create.ponder.close": "關閉", + "create.ponder.identify": "暫停", + "create.ponder.next": "下個場景", + "create.ponder.previous": "上個場景", + "create.ponder.replay": "重放", + "create.ponder.think_back": "返回", + "create.ponder.slow_text": "降低文字顯示速度", + "create.ponder.shared.movement_anchors": "有了機殼底盤和強力膠就可以移動大型結構", + "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.sneak_and": "潛行 +", + "create.ponder.shared.storage_on_contraption": "與結構相連的儲物空間會自動撿取物品", + "create.ponder.shared.behaviour_modify_wrench": "使用扳手來調整這個動作", + "create.ponder.shared.rpm8": "8 RPM", + "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm16_source": "轉速: 16 RPM", + "create.ponder.shared.rpm16": "16 RPM", + "create.ponder.tag.kinetic_sources": "動能產生裝置", + "create.ponder.tag.kinetic_sources.description": "該裝置能夠產生動能", + "create.ponder.tag.contraption_actor": "Contraption Actors", + "create.ponder.tag.contraption_actor.description": "Components which expose special behaviour when attached to a moving contraption", + "create.ponder.tag.arm_targets": "機械手臂的目標物", + "create.ponder.tag.arm_targets.description": "該裝置可作為機械手臂的工作目標", + "create.ponder.tag.logistics": "傳輸物品", + "create.ponder.tag.logistics.description": "該裝置用於物品的傳輸", + "create.ponder.tag.movement_anchor": "Movement Anchors", + "create.ponder.tag.movement_anchor.description": "Components which allow the creation of moving contraptions, animating an attached structure in a variety of ways", + "create.ponder.tag.creative": "創造模式", + "create.ponder.tag.creative.description": "該裝置無法在生存模式中獲得", + "create.ponder.tag.kinetic_relays": "動能傳遞方塊", + "create.ponder.tag.kinetic_relays.description": "該裝置用於傳遞動能", + "create.ponder.tag.windmill_sails": "風車軸承的帆", + "create.ponder.tag.windmill_sails.description": "建造風車時用於產生動能的帆,每個帆對風車產生的效果都是同等的", + "create.ponder.tag.contraption_assembly": "方塊連接物件", + "create.ponder.tag.contraption_assembly.description": "此物件用於連接各個零件以便組成一個成品", + "create.ponder.tag.decoration": "裝飾", + "create.ponder.tag.decoration.description": "這些零件通常用於裝飾", + "create.ponder.tag.kinetic_appliances": "動能利用裝置", + "create.ponder.tag.kinetic_appliances.description": "這些裝置利用動能運作", + "create.ponder.tag.redstone": "邏輯控制裝置", + "create.ponder.tag.redstone.description": "這些裝置會在紅石電路中發揮用處", + "create.ponder.tag.fluids": "液體控制裝置", + "create.ponder.tag.fluids.description": "這些裝置可傳輸並利用液體", + + "create.ponder.adjustable_pulse_repeater.header": "使用可調式脈衝中繼器來控制訊號", + "create.ponder.adjustable_pulse_repeater.text_1": "可調式脈衝中繼器每次運作時會產生一個短脈衝", + "create.ponder.adjustable_pulse_repeater.text_2": "使用滑鼠滾輪來設定啟動後到產生脈衝的延遲", + "create.ponder.adjustable_pulse_repeater.text_3": "延遲可設定到最大30分鐘", + + "create.ponder.adjustable_repeater.header": "使用可調式中繼器來控制訊號", + "create.ponder.adjustable_repeater.text_1": "可調式中繼器就像一般的中繼器", + "create.ponder.adjustable_repeater.text_2": "收到訊號後在設定好的時間過後才啟動...", + "create.ponder.adjustable_repeater.text_3": "...訊號停止後也需要相隔同樣的時間過後才會停止", + "create.ponder.adjustable_repeater.text_4": "使用滑鼠滾輪來設定延遲", + "create.ponder.adjustable_repeater.text_5": "延遲可設定到最大30分鐘", + + "create.ponder.analog_lever.header": "使用可調式拉桿來控制訊號", + "create.ponder.analog_lever.text_1": "可調式拉桿是一種小巧而輕準的紅石能源", + "create.ponder.analog_lever.text_2": "右鍵來增加其紅石訊號輸出", + "create.ponder.analog_lever.text_3": "潛行並右鍵來減少其紅石訊號輸出", + + "create.ponder.andesite_tunnel.header": "使用安山岩物品隧道", + "create.ponder.andesite_tunnel.text_1": "安山岩物品隧道可以覆蓋在輸送帶上", + "create.ponder.andesite_tunnel.text_2": "當安山岩物品隧道側邊連接到另一條輸送帶時...", + "create.ponder.andesite_tunnel.text_3": "...隧道將會從經過的整組物品中拿出一個丟到另一條輸送帶上", + "create.ponder.andesite_tunnel.text_4": "剩餘物品則按照原路輸出", + + "create.ponder.basin.header": "在作業盆中處理物品", + "create.ponder.basin.text_1": "作業盆可以放入物品或液體來進行處理", + "create.ponder.basin.text_2": "在每次的處理完成後, 作業盆會試著輸出成品到他的側面下方", + "create.ponder.basin.text_3": "當側面下方有一個有效的容器或設備, 作業盆側面會出現一個輸出嘴", + "create.ponder.basin.text_4": "有很多的容器或設備可以觸發上述現象", + "create.ponder.basin.text_5": "作業盆輸出的成品會被儲存到該容器或設備內", + "create.ponder.basin.text_6": "如果側面沒有出現輸出嘴, 則作業盆內的成品則不會輸出", + "create.ponder.basin.text_7": "這個原理用在產生的成品為下一輪處理的原料時相當有用", + "create.ponder.basin.text_8": "期望的成品將會從作業盆中輸出", + "create.ponder.basin.text_9": "加裝過濾器可防止未被處理的物品輸出", + + "create.ponder.bearing_modes.header": "機械軸承的工作模式", + "create.ponder.bearing_modes.text_1": "當機械軸承停止時,它會控制整個結構停在最近的垂直線上並實體化", + "create.ponder.bearing_modes.text_2": "你可以控制它不要實體化,或是在結構起始位置才實體化", + + "create.ponder.belt_casing.header": "包裹住輸送帶", + "create.ponder.belt_casing.text_1": "安山岩機殼或黃銅機殼可以用來裝飾輸送帶", + "create.ponder.belt_casing.text_2": "使用扳手可以移除機殼", + + "create.ponder.belt_connector.header": "使用輸送帶", + "create.ponder.belt_connector.text_1": "手持輸送帶對兩根傳動軸右鍵以安裝輸送帶", + "create.ponder.belt_connector.text_2": "不小心點到傳動軸的話可以用潛行+右鍵來取消選取", + "create.ponder.belt_connector.text_3": "輸送帶間只要有空間就能安裝額外的傳動軸", + "create.ponder.belt_connector.text_4": "相同輸送帶接出來的傳動軸轉速及轉向會相同", + "create.ponder.belt_connector.text_5": "使用扳手可以移除已安裝的傳動軸", + "create.ponder.belt_connector.text_6": "輸送帶可以被各種染料染色", + + "create.ponder.belt_directions.header": "輸送帶正確的安裝方向", + "create.ponder.belt_directions.text_1": "輸送帶不可以隨意聯結", + "create.ponder.belt_directions.text_2": "1. 輸送帶可以水平連結", + "create.ponder.belt_directions.text_3": "2. 輸送帶可以對角連結", + "create.ponder.belt_directions.text_4": "3. 輸送帶可以垂直連結", + "create.ponder.belt_directions.text_5": "4. 也可以連結在垂直的傳動軸上", + "create.ponder.belt_directions.text_6": "這些都是可以使用的連接方式,輸送帶可以放置的長度為2~20格", + + "create.ponder.belt_transport.header": "將輸送帶用於後勤", + "create.ponder.belt_transport.text_1": "被啟動的輸送帶能運送物品及實體", + "create.ponder.belt_transport.text_2": "空手對輸送帶上的物品右鍵即可從輸送帶上取下物品", + + "create.ponder.blaze_burner.header": "餵食烈焰使者動力爐", + "create.ponder.blaze_burner.text_1": "烈焰使者動力爐可以用來加熱作業盆", + "create.ponder.blaze_burner.text_2": "你需要餵食可以燃燒的物品來加熱作業盆", + "create.ponder.blaze_burner.text_3": "餵食熔岩蛋糕可以讓烈焰使者動力爐加熱到另一個更高的境界", + "create.ponder.blaze_burner.text_4": "使用機械手或機械手臂來將餵食自動化", + + "create.ponder.brass_funnel.header": "黃銅漏斗", + "create.ponder.brass_funnel.text_1": "安山岩漏斗每次只能傳輸一個物品", + "create.ponder.brass_funnel.text_2": "但黃銅漏斗每次可以傳輸整組物品", + "create.ponder.brass_funnel.text_3": "對漏斗上的過濾格使用滾輪可以調整每次輸出物品的數量", + "create.ponder.brass_funnel.text_4": "手持物品對漏斗上的過濾格右鍵可以限制漏斗只輸出該物品", + + "create.ponder.brass_tunnel.header": "使用黃銅隧道", + "create.ponder.brass_tunnel.text_1": "黃銅隧道必須裝設在輸送帶上", + "create.ponder.brass_tunnel.text_2": "黃銅隧道輸出入口上都有過濾格", + "create.ponder.brass_tunnel.text_3": "在輸入口上的過濾器會阻擋不相符的物品", + "create.ponder.brass_tunnel.text_4": "在輸出口上的過濾器可依種類整理排列物品", + "create.ponder.brass_tunnel.text_5": "如果數種與過濾相符的物品通過隧道, 隧道的分配模式將決定如何處理這些物品", + "create.ponder.brass_tunnel.text_6": "在平行相鄰的輸送帶上,相鄰的黃銅隧道將會成為一組", + "create.ponder.brass_tunnel.text_7": "輸入該組內的物品將會採用該組隧道的分配模式輸送", + "create.ponder.brass_tunnel.text_8": "在這個情況下, 物品也能被直接輸入到隧道方塊", + + "create.ponder.brass_tunnel_modes.header": "黃銅隧道的分配模式", + "create.ponder.brass_tunnel_modes.text_1": "使用扳手來調整隧道的分配模式", + "create.ponder.brass_tunnel_modes.text_10": "'同步輸入' 是一種黃銅隧道的特殊設定", + "create.ponder.brass_tunnel_modes.text_11": "當同組內的所有隧道都有一個可通過的物品時,所有隧道才可輸出物品", + "create.ponder.brass_tunnel_modes.text_12": "這確保了同組隧道所在的輸送帶都能以同一速率輸出物品", + "create.ponder.brass_tunnel_modes.text_2": "'分流輸出' 此模式會將物品輸出到該組隧道可用的輸出口", + "create.ponder.brass_tunnel_modes.text_3": "如果該組隧道內某個輸出口無法再輸出物品,則該輸出口會被跳過", + "create.ponder.brass_tunnel_modes.text_4": "'強制分流輸出' 模式不會跳過某個無法輸出物品的輸出口, 直到該輸出口可以輸出物品", + "create.ponder.brass_tunnel_modes.text_5": "'輪詢輸入' 模式將會保持整組物品完整性, 然後在有輸出口可以輸出時才輸入物品", + "create.ponder.brass_tunnel_modes.text_6": "如果該組隧道內某個輸出口無法再輸出物品,則該輸出口會被跳過", + "create.ponder.brass_tunnel_modes.text_7": "'強制輪詢輸入' 模式不會跳過某個無法輸出物品的輸出口, 直到該輸出口可以輸出物品", + "create.ponder.brass_tunnel_modes.text_8": "'鄰近優先' 模式會將物品輸出到該組隧道離物品輸入口最近的出口", + "create.ponder.brass_tunnel_modes.text_9": "'隨機輸出' 模式會隨機選擇同組隧道的一個輸出口輸出", + + "create.ponder.cart_assembler.header": "使用礦車裝修站裝修礦車來移動結構", + "create.ponder.cart_assembler.text_1": "礦車裝修站會將所有連接到礦車的結構裝在礦車上", + "create.ponder.cart_assembler.text_2": "如果沒有紅時訊號,它會將礦車結構分解成方塊", + "create.ponder.cart_assembler.text_3": "對礦車結構使用扳手可以將礦車變成物品", + + "create.ponder.cart_assembler_dual.header": "雙礦車結構", + "create.ponder.cart_assembler_dual.text_1": "當兩台礦車在同一礦車結構上", + "create.ponder.cart_assembler_dual.text_2": "任一礦車裝修站收到紅石訊號時,會形成完整的一個礦車結構", + "create.ponder.cart_assembler_dual.text_3": "整個礦車結構會類似於用礦車連結器連接兩個礦車結構", + + "create.ponder.cart_assembler_modes.header": "礦車結構的方向設定", + "create.ponder.cart_assembler_modes.text_1": "礦車結構會隨著礦車方向改變", + "create.ponder.cart_assembler_modes.text_2": "如果在裝修站鎖定其方向,則結構方向不會隨礦車方向改變", + + "create.ponder.cart_assembler_rails.header": "其他種類的礦車和鐵軌", + "create.ponder.cart_assembler_rails.text_1": "放在普通鐵軌上的礦車裝修站不會影響礦車的動作", + "create.ponder.cart_assembler_rails.text_2": "如果裝修站在沒有紅石訊號的動力鐵軌或控制鐵軌上,則礦車會停下直到鐵軌收到紅石訊號", + "create.ponder.cart_assembler_rails.text_3": "有幾種礦車可以當作錨來使用", + "create.ponder.cart_assembler_rails.text_4": "熔爐礦車會盡可能維持熔煉狀態,並會拿取鄰近儲存結構上的燃料", + + "create.ponder.chain_drive.header": "使用鏈式傳動箱傳遞動能", + "create.ponder.chain_drive.text_1": "同一排上的鏈式傳動箱會互相傳遞動能", + "create.ponder.chain_drive.text_2": "所有傳動軸此時會朝相同方向旋轉", + "create.ponder.chain_drive.text_3": "任一個鏈式傳動箱被旋轉90度時所有鏈式傳動箱仍可正常運作", + + "create.ponder.chain_gearshift.header": "使用可調式鏈式變速箱來調整轉速", + "create.ponder.chain_gearshift.text_1": "未被控制的可調式鏈式變速箱與鏈式傳動箱無異", + "create.ponder.chain_gearshift.text_2": "當可調式鏈式變速箱被啟動後,它會把轉速提升兩倍傳至其他鏈式傳動箱", + "create.ponder.chain_gearshift.text_3": "當被啟動的可調式鏈式變速箱並不是動能輸入端,則它會把轉速減半", + "create.ponder.chain_gearshift.text_4": "上述兩種狀況中,其他鏈式傳動箱都會被可調式鏈式變速箱提升兩倍的轉速", + "create.ponder.chain_gearshift.text_5": "利用紅石訊號的強弱可以調整轉速倍率為x1或x2", + "create.ponder.chain_gearshift.text_6": "12 RPM", + + "create.ponder.chute.header": "使用滑道向下輸送物品", + "create.ponder.chute.text_1": "滑道可以在兩個垂直的儲物空間中輸送物品", + "create.ponder.chute.text_2": "使用扳手可以讓它產生一個觀景窗", + "create.ponder.chute.text_3": "在滑道的側面放置另一個滑道,會產生一個斜狀的滑道", + + "create.ponder.chute_upward.header": "使用滑道向上輸送物品", + "create.ponder.chute_upward.text_1": "在滑道上方或下方使用鼓風機時,物品會根據被向上或向下吹", + "create.ponder.chute_upward.text_2": "裝備MR護目鏡以觀測物品的傳輸方向", + "create.ponder.chute_upward.text_3": "如滑道底端被擋住,則物品只能由側邊進行輸出入", + + "create.ponder.clockwork_bearing.header": "使用時鐘軸承來建造時鐘結構", + "create.ponder.clockwork_bearing.text_1": "時鐘軸承會黏住其前方方塊產生一個時針結構", + "create.ponder.clockwork_bearing.text_2": "在輸入動能後,該結構會依照遊戲時間來旋轉", + "create.ponder.clockwork_bearing.text_3": "3:00", + "create.ponder.clockwork_bearing.text_4": "4:00", + "create.ponder.clockwork_bearing.text_5": "對軸承右鍵會使結構啟動或停止", + "create.ponder.clockwork_bearing.text_6": "在時針結構的前方可再增加一組分針結構", + "create.ponder.clockwork_bearing.text_7": "你必須確保時針分針結構間未被使用強力膠之類的相連零件", + "create.ponder.clockwork_bearing.text_8": "分針結構此時將正常運作", + + "create.ponder.clutch.header": "使用離合器控制動能", + "create.ponder.clutch.text_1": "離合器能將動能直線傳遞", + "create.ponder.clutch.text_2": "當離合器被啟動,離合器會中斷動能傳遞", + + "create.ponder.cog_speedup.header": "使用大小齒輪來變速", + "create.ponder.cog_speedup.text_1": "大齒輪與小齒輪可以斜向傳遞動能", + "create.ponder.cog_speedup.text_2": "從大齒輪傳遞動能至小齒輪時,轉速加倍", + "create.ponder.cog_speedup.text_3": "從小齒輪傳遞動能至大齒輪時,轉速減半", + + "create.ponder.cogwheel.header": "使用齒輪來傳遞動能", + "create.ponder.cogwheel.text_1": "齒輪會將動力傳遞至臨近的齒輪", + "create.ponder.cogwheel.text_2": "以此方式連接的齒輪,旋轉方向相反", + + "create.ponder.creative_fluid_tank.header": "UNLOCALIZED: Creative Fluid Tanks", + + "create.ponder.creative_motor.header": "使用創造馬達產生動能", + "create.ponder.creative_motor.text_1": "創造馬達不僅能夠手動設定輸出動能,而且體積相當小巧", + "create.ponder.creative_motor.text_2": "對其背後面板滾動滾輪,可以改變馬達的轉速", + + "create.ponder.crushing_wheels.header": "使用粉碎輪處理物品", + "create.ponder.crushing_wheels.text_1": "一對粉碎輪,磨物快又準", + "create.ponder.crushing_wheels.text_2": "接入的動能必須使這兩個輪子契合轉動", + "create.ponder.crushing_wheels.text_3": "扔入或者放入的物品都會被粉碎處理", + "create.ponder.crushing_wheels.text_4": "你也可以使用自動化進行物品的輸入以及撿取", + + "create.ponder.deployer.header": "使用機械手", + "create.ponder.deployer.text_1": "在機械手獲得動能後能夠模仿玩家的各種行為", + "create.ponder.deployer.text_10": "對機械手手部右鍵,即可將手上的物品給它使用", + "create.ponder.deployer.text_11": "物品也可以自動化輸入到機械手內", + "create.ponder.deployer.text_12": "機械手附帶一個過濾格", + "create.ponder.deployer.text_13": "當設定了過濾後,只有當它的手中物品與過濾格相符時,它才會工作", + "create.ponder.deployer.text_14": "只有與過濾格相符的物品才可輸入...", + "create.ponder.deployer.text_15": "...不符的物品可被取出來", + "create.ponder.deployer.text_2": "它只會與它正前方兩格處的位置進行互動", + "create.ponder.deployer.text_3": "放在在它面前的方塊不會阻攔它的工作", + "create.ponder.deployer.text_4": "機械手可以:", + "create.ponder.deployer.text_5": "放置方塊", + "create.ponder.deployer.text_6": "使用物品", + "create.ponder.deployer.text_7": "啟動方塊", + "create.ponder.deployer.text_8": "採收方塊", + "create.ponder.deployer.text_9": "以及攻擊生物", + + "create.ponder.deployer_contraption.header": "在裝置上使用機械手", + "create.ponder.deployer_contraption.text_1": "當機械手在移動的結構上時...", + "create.ponder.deployer_contraption.text_2": "機械手會對每一個經過的方塊使用裝置中任意容器內的物品", + "create.ponder.deployer_contraption.text_3": "可以透過過濾格來指定其從存儲空間中抽取的物品", + + "create.ponder.deployer_modes.header": "機械手的工作模式", + "create.ponder.deployer_modes.text_1": "在設設情況下,機械手模仿玩家的右鍵", + "create.ponder.deployer_modes.text_2": "使用扳手可以將模式調整為模仿玩家的左鍵", + + "create.ponder.deployer_processing.header": "UNLOCALIZED: Processing Items using Deployers", + "create.ponder.deployer_processing.text_1": "UNLOCALIZED: With a fitting held item, Deployers can process items provided beneath them", + "create.ponder.deployer_processing.text_2": "UNLOCALIZED: The Input items can be dropped or placed on a Depot under the Deployer", + "create.ponder.deployer_processing.text_3": "UNLOCALIZED: When items are provided on a belt...", + "create.ponder.deployer_processing.text_4": "UNLOCALIZED: The Deployer will hold and process them automatically", + + "create.ponder.deployer_redstone.header": "使用紅石控制機械手", + "create.ponder.deployer_redstone.text_1": "當機械手收到紅時訊號時會停止工作", + "create.ponder.deployer_redstone.text_2": "在停止工作前,機械手會完成目前手頭上的工作", + "create.ponder.deployer_redstone.text_3": "因此,輸入脈衝訊號可以使其每次只進行一個週期的工作", + + "create.ponder.depot.header": "使用置物台", + "create.ponder.depot.text_1": "置物台可以被當成一個“靜止的”傳送帶原件使用", + "create.ponder.depot.text_2": "右擊可以手動放置或取下物品", + "create.ponder.depot.text_3": "與傳送帶一樣,它也可以將其內的物品轉送到其他設備中進行加工...", + "create.ponder.depot.text_4": "...同時物品也可以被機械手存取", + + "create.ponder.empty_blaze_burner.header": "使用空的烈焰人燃燒室", + "create.ponder.empty_blaze_burner.text_1": "手持空的烈焰人燃燒室右擊烈焰人來抓取烈焰人", + "create.ponder.empty_blaze_burner.text_2": "或者,也可以透過右擊烈焰人刷怪籠來填充啟動烈焰人燃燒室", + "create.ponder.empty_blaze_burner.text_3": "這樣,你便有了一個可供部分機器加工的熱源", + "create.ponder.empty_blaze_burner.text_4": "如果是為了美觀,空的烈焰人燃燒室也可以被打火石點燃", + "create.ponder.empty_blaze_burner.text_5": "但是,這樣的熱源不足以給機器提加工供足夠的熱量", + + "create.ponder.encased_fluid_pipe.header": "UNLOCALIZED: Encasing Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_1": "UNLOCALIZED: Copper Casing can be used to decorate Fluid Pipes", + "create.ponder.encased_fluid_pipe.text_2": "UNLOCALIZED: Aside from being conceiled, Encased Pipes are locked into their connectivity state", + "create.ponder.encased_fluid_pipe.text_3": "UNLOCALIZED: It will no longer react to any neighbouring blocks being added or removed", + + "create.ponder.fan_direction.header": "鼓風機的氣流", + "create.ponder.fan_direction.text_1": "鼓風機使用動能來製造氣流", + "create.ponder.fan_direction.text_2": "流速以及方向由所接收動能的強弱以及方向而定", + + "create.ponder.fan_processing.header": "使用鼓風機加工物品", + "create.ponder.fan_processing.text_1": "當氣流吹過熔岩時,氣流會被加熱", + "create.ponder.fan_processing.text_2": "熱氣流中的物品會被冶煉", + "create.ponder.fan_processing.text_3": "但在氣流中的食物會被直接燒成灰", + "create.ponder.fan_processing.text_4": "而想要烹飪食物,必須要透過吹過火焰的氣流來煙燻食物", + "create.ponder.fan_processing.text_5": "當氣流吹過水後,便可用於洗滌物品", + "create.ponder.fan_processing.text_6": "這種加工方法可以做到不少有趣的事情", + "create.ponder.fan_processing.text_7": "鼓風機的轉速對加工的速度沒有影響,只影響氣流的吹拂距離", + "create.ponder.fan_processing.text_8": "而那些放置在置物台或者傳送帶上的物品,鼓風機也是可以處理的", + + "create.ponder.fan_source.header": "使用鼓風機來產生動能", + "create.ponder.fan_source.text_1": "如鼓風機的扇葉向下朝著熱源放置,鼓風機可以藉此產生動能", + "create.ponder.fan_source.text_2": "當鼓風機接受紅石訊號後,它便會向外供給動能", + + "create.ponder.fluid_pipe_flow.header": "UNLOCALIZED: Moving Fluids using Copper Pipes", + "create.ponder.fluid_pipe_flow.text_1": "UNLOCALIZED: Fluid Pipes can connect two or more fluid sources and targets", + "create.ponder.fluid_pipe_flow.text_2": "UNLOCALIZED: Using a wrench, a straight pipe segment can be given a window", + "create.ponder.fluid_pipe_flow.text_3": "UNLOCALIZED: Windowed pipes will not connect to any other adjacent pipe segments", + "create.ponder.fluid_pipe_flow.text_4": "UNLOCALIZED: Powered by Mechanical Pumps, the Pipes can transport Fluids", + "create.ponder.fluid_pipe_flow.text_5": "UNLOCALIZED: No fluid is being extracted at first", + "create.ponder.fluid_pipe_flow.text_6": "UNLOCALIZED: Once the flow connects them, the endpoints gradually transfer their contents", + "create.ponder.fluid_pipe_flow.text_7": "UNLOCALIZED: Thus, the Pipe blocks themselves never 'physically' contain any fluid", + + "create.ponder.fluid_pipe_interaction.header": "UNLOCALIZED: Draining and Filling fluid containers", + "create.ponder.fluid_pipe_interaction.text_1": "UNLOCALIZED: Endpoints of a pipe network can interact with a variety of blocks", + "create.ponder.fluid_pipe_interaction.text_2": "UNLOCALIZED: Any block with fluid storage capabilities can be filled or drained", + "create.ponder.fluid_pipe_interaction.text_3": "UNLOCALIZED: Source blocks right in front of an open end can be picked up...", + "create.ponder.fluid_pipe_interaction.text_4": "UNLOCALIZED: ...while spilling into empty spaces can create fluid sources", + "create.ponder.fluid_pipe_interaction.text_5": "UNLOCALIZED: Pipes can also extract fluids from a handful of other blocks directly", + + "create.ponder.fluid_tank_sizes.header": "UNLOCALIZED: Dimensions of a Fluid tank", + + "create.ponder.fluid_tank_storage.header": "UNLOCALIZED: Storing Fluids in Fluid Tanks", + + "create.ponder.flywheel.header": "使用飛輪來產生動能", + "create.ponder.flywheel.text_1": "飛輪和熔爐引擎必須配套使用,方可產生動能", + "create.ponder.flywheel.text_2": "如此產生的動能具有非常大的應力值", + "create.ponder.flywheel.text_3": "使用高爐會使得引擎的效率翻倍", + + "create.ponder.funnel_compat.header": "漏斗的相容性", + "create.ponder.funnel_compat.text_1": "漏斗可以與一些其他組件互動", + "create.ponder.funnel_compat.text_2": "動力鋸", + "create.ponder.funnel_compat.text_3": "置物台", + "create.ponder.funnel_compat.text_4": "分液池", + + "create.ponder.funnel_direction.header": "物流方向", + "create.ponder.funnel_direction.text_1": "直接放置時,漏斗會將物品從容器中取出", + "create.ponder.funnel_direction.text_2": "潛行時放置時,漏斗會將物品置入容器中", + "create.ponder.funnel_direction.text_3": "使用扳手可以改變漏斗的存/取模式", + "create.ponder.funnel_direction.text_4": "對大多數朝向放置的漏斗都具有此特性", + "create.ponder.funnel_direction.text_5": "在傳送帶末端放置的漏斗會根據傳送帶的傳動方向存/取物品", + + "create.ponder.funnel_intro.header": "使用漏斗", + "create.ponder.funnel_intro.text_1": "用漏斗來存取物品欄內的物品,可謂又快又好", + + "create.ponder.funnel_redstone.header": "紅石訊號控制", + "create.ponder.funnel_redstone.text_1": "紅石訊號會使漏斗停止工作", + + "create.ponder.funnel_transfer.header": "直接運輸", + "create.ponder.funnel_transfer.text_1": "漏斗無法將物品傳輸到非開放式的物品欄中", + "create.ponder.funnel_transfer.text_2": "溜槽和智慧溜槽更適用於這樣的場景", + "create.ponder.funnel_transfer.text_3": "水平傳輸也是如此,也許傳送帶更方便快捷", + + "create.ponder.furnace_engine.header": "使用熔爐引擎生產動能", + "create.ponder.furnace_engine.text_1": "熔爐引擎會在與其相連熔爐工作時生產動能", + "create.ponder.furnace_engine.text_2": "如此產生的動能具有非常大的應力值", + "create.ponder.furnace_engine.text_3": "使用高爐會使得引擎的效率翻倍", + + "create.ponder.gantry_carriage.header": "使用起重機取物器", + "create.ponder.gantry_carriage.text_1": "起重機取物器可以被放置在起重機杆上,並且可以沿著起重機杆運動", + "create.ponder.gantry_carriage.text_2": "起重機可以移動其黏附的方塊", + + "create.ponder.gantry_cascaded.header": "串聯起重機", + "create.ponder.gantry_cascaded.text_1": "無需強力膠,取物器便可與起重機杆相連", + "create.ponder.gantry_cascaded.text_2": "即使是在移動的起重機杆上也是如此", + "create.ponder.gantry_cascaded.text_3": "因此,起重機系統可以串聯起來,如此可以影響到多軸向的運動", + + "create.ponder.gantry_direction.header": "起重機移動方向", + "create.ponder.gantry_direction.text_1": "起重機杆可以有相反的方向", + "create.ponder.gantry_direction.text_2": "取物器的移動方向取決於起重機杆的方向", + "create.ponder.gantry_direction.text_3": "......以及起重機杆的旋轉方向", + "create.ponder.gantry_direction.text_4": "在旋轉傳遞中,此規則同樣適用", + + "create.ponder.gantry_redstone.header": "起重機的力傳遞", + "create.ponder.gantry_redstone.text_1": "被紅石訊號啟動的起重機,將不會移動其上的取物器", + "create.ponder.gantry_redstone.text_2": "作為替代,杆上的動能會傳遞到取物器的輸出杆上", + + "create.ponder.gantry_shaft.header": "使用起重機杆", + "create.ponder.gantry_shaft.text_1": "起重機杆組成了起重機結構的基礎。與其相接的載物器可以沿著杆進行移動。", + "create.ponder.gantry_shaft.text_2": "起重機結構可以移動與其相接的方塊。", + + "create.ponder.gearbox.header": "使用十字齒輪箱傳遞動能", + "create.ponder.gearbox.text_1": "更改旋轉軸,很容易使得整個旋轉體系變得臃腫不堪", + "create.ponder.gearbox.text_2": "十字齒輪箱則是替代方案,它的體積更為小巧緊", + "create.ponder.gearbox.text_3": "側邊連接的傳動桿,旋轉方向與輸入端一致", + "create.ponder.gearbox.text_4": "直線連接的傳動桿,旋轉方向會被反轉", + + "create.ponder.gearshift.header": "使用反轉齒輪箱控制動能", + "create.ponder.gearshift.text_1": "反轉齒輪箱可以直線傳輸旋轉", + "create.ponder.gearshift.text_2": "通入紅石訊號後,輸出端的旋轉方向會被反轉", + + "create.ponder.hand_crank.header": "使用手搖把手產生動能", + "create.ponder.hand_crank.text_1": "玩家可以使用手搖把手來手動產生動能", + "create.ponder.hand_crank.text_2": "按住右鍵可以逆時針旋轉它", + "create.ponder.hand_crank.text_3": "它產生的轉速相對較高", + "create.ponder.hand_crank.text_4": "潛行長按右鍵可以順時針旋轉它", + + "create.ponder.hose_pulley.header": "UNLOCALIZED: Source Filling and Draining using Hose Pulleys", + + "create.ponder.hose_pulley_infinite.header": "UNLOCALIZED: Passively Filling and Draining large bodies of Fluid", + + "create.ponder.hose_pulley_level.header": "UNLOCALIZED: Fill and Drain level of Hose Pulleys", + + "create.ponder.item_drain.header": "UNLOCALIZED: Emptying Fluid Containers using Item Drains", + + "create.ponder.large_cogwheel.header": "使用大齒輪傳遞動能", + "create.ponder.large_cogwheel.text_1": "大齒輪可以以特定的角度相互連接", + "create.ponder.large_cogwheel.text_2": "可以利用大齒輪變更旋轉軸向", + + "create.ponder.linear_chassis_attachment.header": "使用機殼底盤黏合方塊", + "create.ponder.linear_chassis_attachment.text_1": "它的開放面可以變為黏性面", + "create.ponder.linear_chassis_attachment.text_2": "再次點擊黏性面,可以將它的相反面也變得具有黏性", + "create.ponder.linear_chassis_attachment.text_3": "空手潛行右擊可以移除此面的黏性物", + "create.ponder.linear_chassis_attachment.text_4": "黏性面可以將此面前方的一長條方塊黏住", + "create.ponder.linear_chassis_attachment.text_5": "使用扳手可以精確控制底盤的影響範圍", + "create.ponder.linear_chassis_attachment.text_6": "按住 Ctrl 滑動滾輪,你可以一次性調節所有底盤的影響範圍", + "create.ponder.linear_chassis_attachment.text_7": "若想讓底盤的其他面也能黏方塊,你需要用到強力膠", + "create.ponder.linear_chassis_attachment.text_8": "利用這些機制,任何形狀的機制都可以像裝置那樣移動", + + "create.ponder.linear_chassis_group.header": "成組移動機殼底盤", + "create.ponder.linear_chassis_group.text_1": "相鄰的機殼底盤可以相互連接在一起", + "create.ponder.linear_chassis_group.text_2": "其中的一個底盤若被移動,其餘的底盤也會跟著移動", + "create.ponder.linear_chassis_group.text_3": "不同種類的底盤,或者是朝向不一致的底盤,將不會相連", + + "create.ponder.mechanical_arm.header": "設定動力臂", + "create.ponder.mechanical_arm.text_1": "你得在放置動力臂之前就設定好它的輸入以及輸出端", + "create.ponder.mechanical_arm.text_2": "手持動力臂右擊某個存儲空間,可以將其指定為目標", + "create.ponder.mechanical_arm.text_3": "再次右擊可以將其在輸入端(藍色)以及輸出端(橙色)之間切換", + "create.ponder.mechanical_arm.text_4": "左擊此組件可以移除選擇", + "create.ponder.mechanical_arm.text_5": "將動力臂放下來後,它會將此前選擇的方塊作為目標", + "create.ponder.mechanical_arm.text_6": "在有效範圍內,機械手臂可以有任意數量的輸出以及輸入端", + "create.ponder.mechanical_arm.text_7": "然而,並不是所有的存儲空間可以被直接互動", + "create.ponder.mechanical_arm.text_8": "在此情況下,漏斗和置物台可以解決此問題", + + "create.ponder.mechanical_arm_filtering.header": "過濾動力臂的輸出端", + "create.ponder.mechanical_arm_filtering.text_1": "輸入", + "create.ponder.mechanical_arm_filtering.text_2": "輸出", + "create.ponder.mechanical_arm_filtering.text_3": "有時,你會想著利用某種過濾限煞車力臂的目標", + "create.ponder.mechanical_arm_filtering.text_4": "動力臂自身並不提供任何過濾選項", + "create.ponder.mechanical_arm_filtering.text_5": "然而,若將黃銅漏斗作為目標,則漏斗的過濾槽則可以應用至動力臂上", + "create.ponder.mechanical_arm_filtering.text_6": "動力臂足夠智慧,它不會去拿取那些它無法分配的物品", + + "create.ponder.mechanical_arm_modes.header": "動力臂的分配模式", + "create.ponder.mechanical_arm_modes.text_1": "輸入", + "create.ponder.mechanical_arm_modes.text_2": "輸出", + "create.ponder.mechanical_arm_modes.text_3": "若動力臂必須在數個有效的輸出端之間作出選擇...", + "create.ponder.mechanical_arm_modes.text_4": "...它會依照自己的設定選擇特定的行為", + "create.ponder.mechanical_arm_modes.text_5": "手持扳手對其滑動滾輪,可以改變其設定", + "create.ponder.mechanical_arm_modes.text_6": "輪詢調度模式很好理解,即循環輸出至所有有效的輸出端", + "create.ponder.mechanical_arm_modes.text_7": "如果某個輸出端無法容納更多物品,則它會被跳過", + "create.ponder.mechanical_arm_modes.text_8": "強制輪詢調度不會跳過任何輸出端,動力臂會一直等待,直到輸出端有空位容納物品輸入", + "create.ponder.mechanical_arm_modes.text_9": "最近優先模式會使得動力臂先將物品輸出至更早被選擇的輸出端", + + "create.ponder.mechanical_arm_redstone.header": "利用紅石訊號控制動力臂", + "create.ponder.mechanical_arm_redstone.text_1": "通入紅石訊號後,動力臂會停止工作", + "create.ponder.mechanical_arm_redstone.text_2": "在停止工作前,它會完成目前正在進行的工作週期", + "create.ponder.mechanical_arm_redstone.text_3": "因此,通入單次負紅石脈衝可以精確控制動力臂,使其每次只進行單個週期的工作", + + "create.ponder.mechanical_bearing.header": "使用動力軸承移動結構", + "create.ponder.mechanical_bearing.text_1": "動力軸承會與其前方的方塊黏合在一起", + "create.ponder.mechanical_bearing.text_2": "接收到動能後,它會將這一黏合結構組裝為旋轉裝置", + + "create.ponder.mechanical_crafter.header": "設置動力合成器", + "create.ponder.mechanical_crafter.text_1": "動力合成器陣列可用於自動化任何合成配方的製作", + "create.ponder.mechanical_crafter.text_2": "使用扳手可以調控合成器的合成通路", + "create.ponder.mechanical_crafter.text_3": "所有的合成通路必須匯集到任意一側的一個出口,整套合成器方可算是設置正確", + "create.ponder.mechanical_crafter.text_4": "輸出產物會被放入位於出口的存儲空間中", + "create.ponder.mechanical_crafter.text_5": "動力合成器的運轉需要動能的供應", + "create.ponder.mechanical_crafter.text_6": "右擊合成器正面,可以手動放入物品", + "create.ponder.mechanical_crafter.text_7": "一旦合成通路上的所有合成槽位都有了物品,合成就會開始", + "create.ponder.mechanical_crafter.text_8": "而對於那些沒有完全占滿所有合成器槽位的配方,你可以通入紅石訊號強制開啟合成", + + "create.ponder.mechanical_crafter_connect.header": "為合成器連接物品欄", + "create.ponder.mechanical_crafter_connect.text_1": "合成器可以自動接受向其輸入的物品", + "create.ponder.mechanical_crafter_connect.text_2": "對其背面使用扳手,可以連接合成器", + "create.ponder.mechanical_crafter_connect.text_3": "所有相連的合成器可以訪問同一個位置的輸入", + + "create.ponder.mechanical_crafter_covers.header": "蓋住動力合成器的合成槽", + "create.ponder.mechanical_crafter_covers.text_1": "有些配方需要額外的合成器,來補足合成通路上的間隙", + "create.ponder.mechanical_crafter_covers.text_2": "使用合成槽蓋板,合成器會在合成進行時的行為就如同一個空的合成槽位", + "create.ponder.mechanical_crafter_covers.text_3": "被蓋住的合成器並不會阻斷共享輸入端的影響", + + "create.ponder.mechanical_drill.header": "使用機械鑽頭破壞方塊", + "create.ponder.mechanical_drill.text_1": "當向其通入動能後,機械鑽頭會破壞它面前的方塊", + "create.ponder.mechanical_drill.text_2": "它的挖掘速度取決於通入的動能轉速", + + "create.ponder.mechanical_drill_contraption.header": "在裝置中使用機械鑽頭", + "create.ponder.mechanical_drill_contraption.text_1": "在運動裝置中使用機械鑽頭時...", + "create.ponder.mechanical_drill_contraption.text_2": "...它會破壞掉它撞上的方塊", + + "create.ponder.mechanical_harvester.header": "在裝置中使用動力收割機", + "create.ponder.mechanical_harvester.text_1": "在運動裝置中使用動力收割機時...", + "create.ponder.mechanical_harvester.text_2": "它會採收其路徑上的作物,並重設這些作物的生長進度", + + "create.ponder.mechanical_mixer.header": "使用動力攪拌器處理物品", + "create.ponder.mechanical_mixer.text_1": "使用攪拌器和工作盆,你可以自動化某些合成配方", + "create.ponder.mechanical_mixer.text_2": "有效配方包括各種無序合成配方,以及一些額外的配方", + "create.ponder.mechanical_mixer.text_3": "一些配方可能需要使用烈焰人燃燒室提供熱量", + "create.ponder.mechanical_mixer.text_4": "過濾槽可用於解決兩個配方相互衝突的情況", + + "create.ponder.mechanical_piston.header": "使用動力活塞移動結構", + "create.ponder.mechanical_piston.text_1": "動力活塞可以移動它前方的方塊", + "create.ponder.mechanical_piston.text_2": "移動速度和方向取決於通入活塞的動能", + "create.ponder.mechanical_piston.text_3": "黏性動力活塞可以將相接的方塊拉回來", + + "create.ponder.mechanical_piston_modes.header": "動力活塞的移動模式", + "create.ponder.mechanical_piston_modes.text_1": "一旦活塞停下,被移動的結構就會回退到方塊狀態", + "create.ponder.mechanical_piston_modes.text_2": "你也可以將其設定為從不方塊化,或者只在起始位置方塊化", + + "create.ponder.mechanical_plough.header": "在裝置中使用動力犁", + "create.ponder.mechanical_plough.text_1": "在運動裝置中使用動力犁時...", + "create.ponder.mechanical_plough.text_2": "...它會破壞掉那些不具有固體碰撞箱的方塊", + "create.ponder.mechanical_plough.text_3": "此外,動力犁可以耕地", + "create.ponder.mechanical_plough.text_4": "...它也可以在不傷害實體的情況下推動它們", + + "create.ponder.mechanical_press.header": "使用機械液壓機處理物品", + "create.ponder.mechanical_press.text_1": "機械液壓機可以處理位於其下方的物品", + "create.ponder.mechanical_press.text_2": "在其下方丟入物品,或者將物品放在置物台上,都算作有效的物品輸入", + "create.ponder.mechanical_press.text_3": "若物品被輸入時正位於傳送帶上...", + "create.ponder.mechanical_press.text_4": "輥軋機會使物品停下,然後自動處理這一物品", + + "create.ponder.mechanical_press_compacting.header": "使用機械液壓機壓縮物品", + "create.ponder.mechanical_press_compacting.text_1": "對放置於工作盆內的物品進行輥軋,可以將這些物品壓縮在一起", + "create.ponder.mechanical_press_compacting.text_2": "壓縮意指任何同種物品填滿了 2x2 或者 3x3 網格的配方,以及一些額外的配方", + "create.ponder.mechanical_press_compacting.text_3": "一些配方可能需要烈焰人燃燒室提供熱量", + "create.ponder.mechanical_press_compacting.text_4": "過濾槽可用於解決兩個配方相互衝突的情況", + + "create.ponder.mechanical_pump_flow.header": "UNLOCALIZED: Fluid Transportation using Mechanical Pumps", + + "create.ponder.mechanical_pump_speed.header": "UNLOCALIZED: Throughput of Mechanical Pumps", + + "create.ponder.mechanical_saw_breaker.header": "使用動力鋸伐木", + "create.ponder.mechanical_saw_breaker.text_1": "向其通入動能後,動力鋸可以直接砍伐掉它面前的樹木", + "create.ponder.mechanical_saw_breaker.text_2": "想要一次性砍掉整棵樹,鋸子必須破壞掉樹與地面連接的最後一個方塊", + + "create.ponder.mechanical_saw_contraption.header": "在裝置中使用動力鋸", + "create.ponder.mechanical_saw_contraption.text_1": "若在運動裝置中使用動力鋸...", + "create.ponder.mechanical_saw_contraption.text_2": "...它會將撞到它的樹木破壞掉", + + "create.ponder.mechanical_saw_processing.header": "使用動力鋸處理物品", + "create.ponder.mechanical_saw_processing.text_1": "面向朝上的動力鋸可以將物品處理為其變種", + "create.ponder.mechanical_saw_processing.text_2": "處理過後的物品的彈出方向始終與通入鋸中的旋轉轉向相反", + "create.ponder.mechanical_saw_processing.text_3": "鋸子可以", + "create.ponder.mechanical_saw_processing.text_4": "若輸入原料有多種可能產物,你可以用動力鋸上的過濾槽指定只產出某種產物", + "create.ponder.mechanical_saw_processing.text_5": "若沒有使用過濾槽,動力鋸會在各產物中按順序循環輸出", + + "create.ponder.millstone.header": "使用石磨處理物品", + "create.ponder.millstone.text_1": "石磨會對輸入的物品進行磨製", + "create.ponder.millstone.text_2": "在其側邊使用齒輪與其相耦合,方可為其通入動力", + "create.ponder.millstone.text_3": "頂部可以丟入或者塞入物品", + "create.ponder.millstone.text_4": "一段時間過後,右擊石磨可以拿出其中的產物", + "create.ponder.millstone.text_5": "產物的提取也是可以自動化的", + + "create.ponder.nixie_tube.header": "使用真空管顯示器", + "create.ponder.nixie_tube.text_1": "通入紅石訊號後,真空管顯示器會顯示出紅石訊號的強度", + "create.ponder.nixie_tube.text_2": "使用命名牌在鐵砧上為其命名,可以自訂它的顯示文本", + + "create.ponder.piston_pole.header": "活塞延長杆", + "create.ponder.piston_pole.text_1": "若無相接的延長杆,動力活塞無法移動其他方塊", + "create.ponder.piston_pole.text_2": "在其背面安裝的延長杆長度,決定了活塞的推動範圍", + + "create.ponder.portable_fluid_interface.header": "UNLOCALIZED: Contraption Fluid Exchange", + + "create.ponder.portable_fluid_interface_redstone.header": "UNLOCALIZED: Redstone Control", + + "create.ponder.portable_storage_interface.header": "裝置存儲交換", + "create.ponder.portable_storage_interface.text_1": "玩家無法與運動裝置內的存儲空間進行互動", + "create.ponder.portable_storage_interface.text_2": "這一組件可以在不停止裝置的情況下與裝置內的存儲空間進行互動", + "create.ponder.portable_storage_interface.text_3": "放置第二個介面時,記得要與裝置介面相隔 1 格或者 2 格的距離", + "create.ponder.portable_storage_interface.text_4": "當它們彼此經過時,它們會連接在一起", + "create.ponder.portable_storage_interface.text_5": "連接狀態下,固定側介面便會作為整個裝置的存儲空間代理", + "create.ponder.portable_storage_interface.text_6": "物品會被輸入到裝置內...", + "create.ponder.portable_storage_interface.text_7": "...或是從裝置中提取出來", + "create.ponder.portable_storage_interface.text_8": "物品交換完畢後,裝置仍然會停留在原地一小會,然後才會繼續前行", + + "create.ponder.portable_storage_interface_redstone.header": "紅石控制", + "create.ponder.portable_storage_interface_redstone.text_1": "通入紅石訊號可以阻止固定側介面的連接行為", + + "create.ponder.powered_latch.header": "使用閂鎖器控制訊號", + "create.ponder.powered_latch.text_1": "閂鎖器是一種可以用紅石訊號控制的拉杆", + "create.ponder.powered_latch.text_2": "後方輸入的訊號會將其設為開啟狀態", + "create.ponder.powered_latch.text_3": "側邊輸入的訊號會將其設為關閉狀態", + "create.ponder.powered_latch.text_4": "你也可以手動切換其狀態", + + "create.ponder.powered_toggle_latch.header": "使用T型正反器控制訊號", + "create.ponder.powered_toggle_latch.text_1": "T型正反器是一種可以用紅石訊號控制的拉杆", + "create.ponder.powered_toggle_latch.text_2": "後方訊號輸入可以改變它的狀態", + "create.ponder.powered_toggle_latch.text_3": "...開啟或者是關閉", + "create.ponder.powered_toggle_latch.text_4": "你也可以手動切換其狀態", + + "create.ponder.pulse_repeater.header": "使用脈衝中繼器控制訊號", + "create.ponder.pulse_repeater.text_1": "脈衝中繼器會將所有通入的紅石訊號縮減為一次脈衝", + + "create.ponder.radial_chassis.header": "使用旋轉底盤黏著方塊", + "create.ponder.radial_chassis.text_1": "同一行上的旋轉底盤會相互連接在一起", + "create.ponder.radial_chassis.text_2": "當其中的一個底盤被裝置帶動時,其餘的底盤也會被帶動", + "create.ponder.radial_chassis.text_3": "底盤的側邊可以變為黏性面", + "create.ponder.radial_chassis.text_4": "再次點擊黏性面,可以讓其所有面都變得帶黏性", + "create.ponder.radial_chassis.text_5": "空手潛行右擊可以移除其上的黏性物", + "create.ponder.radial_chassis.text_6": "若有物品與底盤的黏性面相接觸...", + "create.ponder.radial_chassis.text_7": "...底盤便會與同層且位於半徑內的所有可及方塊黏著在一起", + "create.ponder.radial_chassis.text_8": "使用扳手可以精確指定底盤的影響範圍", + "create.ponder.radial_chassis.text_9": "黏性面一側的不可及方塊不會被黏著", + + "create.ponder.redstone_contact.header": "接觸式紅石訊號發生器", + "create.ponder.redstone_contact.text_1": "當兩個接觸式紅石訊號發生器面對面時,它們會發出紅石訊號", + "create.ponder.redstone_contact.text_2": "並且,若有一方位於運動裝置上,此特性也能正常生效", + + "create.ponder.redstone_link.header": "使用無線紅石訊號機", + "create.ponder.redstone_link.text_1": "無線紅石訊號機可以無線傳輸紅石訊號", + "create.ponder.redstone_link.text_2": "潛行右擊可以改變其接收模式", + "create.ponder.redstone_link.text_3": "手持扳手右擊也可以", + "create.ponder.redstone_link.text_4": "接收端會發出由傳輸端發來的訊號,有效距離為 128 格", + "create.ponder.redstone_link.text_5": "在它們所帶的槽位中放上物品,可以為它們指定頻道", + "create.ponder.redstone_link.text_6": "只有頻道相互匹配的機方可互通", + + "create.ponder.rope_pulley.header": "使用繩索滑輪移動結構", + "create.ponder.rope_pulley.text_1": "繩索滑輪在接受動能時可以垂直移動方塊結構", + "create.ponder.rope_pulley.text_2": "移動的方向及速度取決於提供的轉速", + + "create.ponder.rope_pulley_attachment.header": "繩索滑輪與裝置一同運動", + "create.ponder.rope_pulley_attachment.text_1": "當繩索滑輪本身在裝置中被帶動時...", + "create.ponder.rope_pulley_attachment.text_2": "...它附著在滑輪上的結構會被滑輪拉著一同移動", + "create.ponder.rope_pulley_attachment.text_3": "注意,只有繩索滑輪停止工作時才能被移動", + + "create.ponder.rope_pulley_modes.header": "繩索滑輪的運動模式", + "create.ponder.rope_pulley_modes.text_1": "當繩索滑輪停止運動時,它所附屬的移動結構便會方塊化", + "create.ponder.rope_pulley_modes.text_2": "你可以調整整個結構永不方塊化,或者僅在結構的初始位置方塊化", + + "create.ponder.rotation_speed_controller.header": "使用轉速控制器", + "create.ponder.rotation_speed_controller.text_1": "轉速控制器將動能從其轉軸傳遞至它上方的大齒輪", + "create.ponder.rotation_speed_controller.text_2": "在其側面滾動滑鼠滾輪,可以調節輸出轉速", + + "create.ponder.sail.header": "使用風帆來組裝風車", + "create.ponder.sail.text_1": "風帆是製作風車的趁手材料", + "create.ponder.sail.text_2": "無需強力膠等黏附手段,它們便可自行互相連結", + "create.ponder.sail.text_3": "手持染料右擊可對其染色", + "create.ponder.sail.text_4": "手持剪刀右擊可剪除帆布,使其變迴風帆框架", + + "create.ponder.sail_frame.header": "使用風帆框架來組裝風車", + "create.ponder.sail_frame.text_1": "風帆框架是製作風車的趁手材料", + "create.ponder.sail_frame.text_2": "無需強力膠等黏附手段,它們便可自行互相連結", + + "create.ponder.sequenced_gearshift.header": "使用可編程齒輪箱來控制轉速", + "create.ponder.sequenced_gearshift.text_1": "可編程齒輪箱能夠根據玩家設置的預設時序表來傳遞旋轉", + "create.ponder.sequenced_gearshift.text_2": "對其右擊可以打開設置面板", + "create.ponder.sequenced_gearshift.text_3": "接受紅石訊號時,它會開始執行其內部已設定好的時序指令表", + "create.ponder.sequenced_gearshift.text_4": "當完成時序指令表後,它會進入待機狀態,再次接受紅石訊號後,它才會再次執行時序指令表內容", + "create.ponder.sequenced_gearshift.text_5": "紅石比較器可以讀取目前時序指令表完成進度", + + "create.ponder.shaft.header": "使用傳動軸來傳送動能", + "create.ponder.shaft.text_1": "傳動軸可以直線傳送動能", + + "create.ponder.shaft_casing.header": "包裹傳動軸", + "create.ponder.shaft_casing.text_1": "黃銅及安山岩機殼可以用來裝飾傳動軸", + + "create.ponder.smart_chute.header": "使用智慧滑道來過濾物品", + "create.ponder.smart_chute.text_1": "智慧滑道是一種可以被控制的滑道", + "create.ponder.smart_chute.text_2": "當在其過濾槽內指定了物品後,溜槽只會傳輸這一指定標記的物品", + "create.ponder.smart_chute.text_3": "使用滑鼠滾輪可以指定被過濾的物品數量", + "create.ponder.smart_chute.text_4": "通入紅石訊號,智慧溜槽將會完全暫停工作", + + "create.ponder.smart_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Smart Pipes", + + "create.ponder.speedometer.header": "使用速度計來監測轉速", + "create.ponder.speedometer.text_1": "速度計能顯示相接組件的轉速", + "create.ponder.speedometer.text_2": "當佩戴MR護目鏡時,可以看到儀表所顯示的更詳細的數據", + "create.ponder.speedometer.text_3": "紅石比較器可以根據速度計的數值輸出不同強弱的紅石訊號", + + "create.ponder.spout_access.header": "UNLOCALIZED: Moving fluids into Spouts", + + "create.ponder.spout_filling.header": "UNLOCALIZED: Filling Items using a Spout", + + "create.ponder.stabilized_bearings.header": "裝置固定朝向", + "create.ponder.stabilized_bearings.text_1": "當動力軸承在結構被帶動時...", + "create.ponder.stabilized_bearings.text_2": "...它會確保它轉盤的垂直朝向不變", + "create.ponder.stabilized_bearings.text_3": "跟預設的一樣,動力軸承會黏著它前方的方塊", + "create.ponder.stabilized_bearings.text_4": "這種情況下,它所黏著的子結構的垂直朝向也不會改變", + + "create.ponder.sticker.header": "使用方塊黏著器來黏取方塊", + "create.ponder.sticker.text_1": "方塊黏著器是一個很棒的裝置,他受控於紅石訊號", + "create.ponder.sticker.text_2": "當接收到訊號時,他會黏起面前的一個方塊", + "create.ponder.sticker.text_3": "如果此時方塊黏著器被移動,被黏到的方塊會跟著移動", + "create.ponder.sticker.text_4": "再次接收到訊號後,黏著器會放下它面前的方塊", + + "create.ponder.stressometer.header": "使用動能錶來監測應力", + "create.ponder.stressometer.text_1": "動能錶能顯示目前動能網路內的應力訊息", + "create.ponder.stressometer.text_2": "當佩戴MR護目鏡時,可以看到儀表所顯示的更詳細的數據", + "create.ponder.stressometer.text_3": "紅石比較器可以根據動能錶的數值輸出不同強弱的紅石訊號", + + "create.ponder.super_glue.header": "使用強力膠來黏附方塊", + "create.ponder.super_glue.text_1": "強力膠可以在任意兩個方塊間使用", + "create.ponder.super_glue.text_2": "當被黏合的方塊被組裝為裝置時,他們會一起運動", + "create.ponder.super_glue.text_3": "當強力膠在副手時...", + "create.ponder.super_glue.text_4": "...新放置的方塊會自動被黏附在所放置方塊的面上", + "create.ponder.super_glue.text_5": "左擊可以清除強力膠", + + "create.ponder.valve_handle.header": "使用閥門手輪產生動能", + "create.ponder.valve_handle.text_1": "玩家可以手動使用閥門手輪來產生動能", + "create.ponder.valve_handle.text_2": "右擊可使它逆時針旋轉", + "create.ponder.valve_handle.text_3": "它的轉速慢而精確", + "create.ponder.valve_handle.text_4": "潛行右擊可使它順時針旋轉", + "create.ponder.valve_handle.text_5": "可以透過染色來美化閥門手輪", + + "create.ponder.valve_pipe.header": "UNLOCALIZED: Controlling Fluid flow using Valves", + + "create.ponder.water_wheel.header": "使用水車產生動能", + "create.ponder.water_wheel.text_1": "水車利用臨近的水流來進行應力發生", + "create.ponder.water_wheel.text_2": "水車接觸水流的麵越多,它的轉速越高", + "create.ponder.water_wheel.text_3": "水車葉片應逆著水流方向擺放", + "create.ponder.water_wheel.text_4": "如果順著水流擺放,它的效率則會降低", + + "create.ponder.weighted_ejector.header": "使用彈射置物台", + "create.ponder.weighted_ejector.text_1": "手持彈射置物台時,潛行時右擊可以設置彈射目標位置", + "create.ponder.weighted_ejector.text_10": "現在,只有等被放置的物品數量等於所設定數量時,彈射置物台才會彈射物品", + "create.ponder.weighted_ejector.text_11": "當其他實體站在彈射置物台上時會被直接彈射", + "create.ponder.weighted_ejector.text_2": "現在,放置下的彈射置物台會將物品彈射至目標位置", + "create.ponder.weighted_ejector.text_3": "限制範圍內的任意距離和高度均可作為有效目標地點", + "create.ponder.weighted_ejector.text_4": "但是,目標位置與置物台的連線,必須垂直於置物台的側面", + "create.ponder.weighted_ejector.text_5": "如果沒有設置有效目標位置,彈射置物台會直接將其前方一格設為默認目標位置", + "create.ponder.weighted_ejector.text_6": "提供動能可為其蓄力", + "create.ponder.weighted_ejector.text_7": "蓄力完畢後,放置在它上方的物品會被立刻彈射出去", + "create.ponder.weighted_ejector.text_8": "如果目標為容器,則彈射置物台會等待容器有位置後再彈射物品", + "create.ponder.weighted_ejector.text_9": "使用扳手可以調整彈射所要求的物品數量", + + "create.ponder.weighted_ejector_redstone.header": "使用紅石控制彈射置物台", + "create.ponder.weighted_ejector_redstone.text_1": "當被紅石充能時,彈射置物台停止工作", + "create.ponder.weighted_ejector_redstone.text_2": "此外,置物台彈射的瞬間可以被偵測器偵測", + + "create.ponder.weighted_ejector_tunnel.header": "使用彈射置物台來分流物品", + "create.ponder.weighted_ejector_tunnel.text_1": "與黃銅隧道搭配使用時,彈射置物台可以將物品以特定數量進行分流", + "create.ponder.weighted_ejector_tunnel.text_2": "首先,將黃銅隧道調整為“最近優先”模式,從而讓它優先側面輸出", + "create.ponder.weighted_ejector_tunnel.text_3": "置物台上所設置的物品數量則為被分流出去的物品數量", + "create.ponder.weighted_ejector_tunnel.text_4": "當所設置的物品數量被分流出去後...", + "create.ponder.weighted_ejector_tunnel.text_5": "...剩餘的物品則會繼續前進", + + "create.ponder.windmill_source.header": "使用風車軸承產生動能", + "create.ponder.windmill_source.text_1": "風車軸承會黏著它面前的方塊結構", + "create.ponder.windmill_source.text_2": "如果黏著的方塊結構包含足夠的風帆方塊即為風車", + "create.ponder.windmill_source.text_3": "右鍵啟動風車後,風車開始提供動能", + "create.ponder.windmill_source.text_4": "產生的動能將取決於所黏風帆方塊之數量", + "create.ponder.windmill_source.text_5": "使用扳手來調整其旋轉方向", + "create.ponder.windmill_source.text_6": "對風車軸承右鍵可使其停止方便你維修風車", + + "create.ponder.windmill_structure.header": "風車結構", + "create.ponder.windmill_structure.text_1": "任一包含至少8個風帆方塊的結構即為有效的風車", "_": "Thank you for translating Create!" diff --git a/src/generated/resources/assets/create/models/item/crafting_blueprint.json b/src/generated/resources/assets/create/models/item/crafting_blueprint.json new file mode 100644 index 000000000..94ec8d07a --- /dev/null +++ b/src/generated/resources/assets/create/models/item/crafting_blueprint.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "create:item/crafting_blueprint" + } +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/models/item/linked_controller.json b/src/generated/resources/assets/create/models/item/linked_controller.json new file mode 100644 index 000000000..6bf114f21 --- /dev/null +++ b/src/generated/resources/assets/create/models/item/linked_controller.json @@ -0,0 +1,3 @@ +{ + "parent": "create:item/linked_controller/item" +} \ No newline at end of file diff --git a/src/generated/resources/assets/create/sounds.json b/src/generated/resources/assets/create/sounds.json index 61a42d76f..1052dd3a7 100644 --- a/src/generated/resources/assets/create/sounds.json +++ b/src/generated/resources/assets/create/sounds.json @@ -49,6 +49,15 @@ ], "subtitle": "create.subtitle.contraption_disassemble" }, + "controller_click": { + "sounds": [ + { + "name": "minecraft:entity.item_frame.add_item", + "type": "event" + } + ], + "subtitle": "create.subtitle.controller_click" + }, "copper_armor_equip": { "sounds": [ { @@ -205,6 +214,42 @@ } ] }, + "saw_activate_stone": { + "sounds": [ + { + "name": "minecraft:ui.stonecutter.take_result", + "type": "event" + } + ], + "subtitle": "create.subtitle.saw_activate_stone" + }, + "saw_activate_wood": { + "sounds": [ + { + "name": "minecraft:entity.boat.paddle_land", + "type": "event" + } + ], + "subtitle": "create.subtitle.saw_activate_wood" + }, + "saw_idle": { + "sounds": [ + { + "name": "minecraft:entity.boat.paddle_land", + "type": "event" + } + ], + "subtitle": "create.subtitle.saw_idle" + }, + "saw_process": { + "sounds": [ + { + "name": "minecraft:block.sand.place", + "type": "event" + } + ], + "subtitle": "create.subtitle.saw_process" + }, "schematicannon_finish": { "sounds": [ { diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite.json new file mode 100644 index 000000000..344f964cc --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/andesite.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:andesite" + ] + }, + "criteria": { + "has_andesite_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:andesite_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:andesite" + } + } + }, + "requirements": [ + [ + "has_andesite_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite.json new file mode 100644 index 000000000..df09f4529 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/diorite.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:diorite" + ] + }, + "criteria": { + "has_diorite_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:diorite_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:diorite" + } + } + }, + "requirements": [ + [ + "has_diorite_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/building_blocks/granite.json b/src/generated/resources/data/create/advancements/recipes/building_blocks/granite.json new file mode 100644 index 000000000..f0a2adf3f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/building_blocks/granite.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:granite" + ] + }, + "criteria": { + "has_granite_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:granite_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:granite" + } + } + }, + "requirements": [ + [ + "has_granite_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json new file mode 100644 index 000000000..e1d2038ea --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/crafting_blueprint.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/appliances/crafting_blueprint" + ] + }, + "criteria": { + "has_item": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "minecraft:crafting_table" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/appliances/crafting_blueprint" + } + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/linked_controller.json b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/linked_controller.json new file mode 100644 index 000000000..ef2c10afb --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.base/crafting/appliances/linked_controller.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:crafting/appliances/linked_controller" + ] + }, + "criteria": { + "has_item": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:redstone_link" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:crafting/appliances/linked_controller" + } + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/andesite_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/andesite_pillar.json index f8b57edb6..7c9df9388 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/andesite_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/andesite_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_andesite": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_andesite", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria.json new file mode 100644 index 000000000..48a14dd4b --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:dark_scoria" + ] + }, + "criteria": { + "has_dark_scoria_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:dark_scoria_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:dark_scoria" + } + } + }, + "requirements": [ + [ + "has_dark_scoria_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria_pillar.json index 351c3e02c..dc1bc8e5e 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/dark_scoria_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_dark_scoria": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_dark_scoria", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/diorite_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/diorite_pillar.json index fea456f6c..846e74a19 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/diorite_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/diorite_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_diorite": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_diorite", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite.json new file mode 100644 index 000000000..2ee623acf --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:dolomite" + ] + }, + "criteria": { + "has_dolomite_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:dolomite_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:dolomite" + } + } + }, + "requirements": [ + [ + "has_dolomite_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite_pillar.json index ec49ae69a..d82162c4d 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/dolomite_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_dolomite": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_dolomite", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro.json new file mode 100644 index 000000000..85c5c99b3 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:gabbro" + ] + }, + "criteria": { + "has_gabbro_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:gabbro_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:gabbro" + } + } + }, + "requirements": [ + [ + "has_gabbro_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro_pillar.json index f6ec9691f..d33f4e3f3 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/gabbro_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_gabbro": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_gabbro", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/granite_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/granite_pillar.json index 38443374f..884b1e38c 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/granite_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/granite_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_granite": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_granite", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone.json new file mode 100644 index 000000000..1b38ab26f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:limestone" + ] + }, + "criteria": { + "has_limestone_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:limestone_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:limestone" + } + } + }, + "requirements": [ + [ + "has_limestone_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone_pillar.json index 8150f5a59..2690c0cfc 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/limestone_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_limestone": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_limestone", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria.json new file mode 100644 index 000000000..fc94ffc6f --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:scoria" + ] + }, + "criteria": { + "has_scoria_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:scoria_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:scoria" + } + } + }, + "requirements": [ + [ + "has_scoria_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria_pillar.json index 7d8e33863..e21ba1a34 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/scoria_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_scoria": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_scoria", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone.json new file mode 100644 index 000000000..2b7672332 --- /dev/null +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone.json @@ -0,0 +1,32 @@ +{ + "parent": "minecraft:recipes/root", + "rewards": { + "recipes": [ + "create:weathered_limestone" + ] + }, + "criteria": { + "has_weathered_limestone_cobblestone": { + "trigger": "minecraft:inventory_changed", + "conditions": { + "items": [ + { + "item": "create:weathered_limestone_cobblestone" + } + ] + } + }, + "has_the_recipe": { + "trigger": "minecraft:recipe_unlocked", + "conditions": { + "recipe": "create:weathered_limestone" + } + } + }, + "requirements": [ + [ + "has_weathered_limestone_cobblestone", + "has_the_recipe" + ] + ] +} \ No newline at end of file diff --git a/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json b/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json index e9b129e93..6acc03c00 100644 --- a/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json +++ b/src/generated/resources/data/create/advancements/recipes/create.palettes/weathered_limestone_pillar.json @@ -6,7 +6,7 @@ ] }, "criteria": { - "has_ingredient": { + "has_weathered_limestone": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ @@ -25,7 +25,7 @@ }, "requirements": [ [ - "has_ingredient", + "has_weathered_limestone", "has_the_recipe" ] ] diff --git a/src/generated/resources/data/create/loot_tables/blocks/dark_scoria.json b/src/generated/resources/data/create/loot_tables/blocks/dark_scoria.json index c26589bf5..912caa5f7 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/dark_scoria.json +++ b/src/generated/resources/data/create/loot_tables/blocks/dark_scoria.json @@ -5,13 +5,37 @@ "rolls": 1, "entries": [ { - "type": "minecraft:item", - "name": "create:dark_scoria" - } - ], - "conditions": [ - { - "condition": "minecraft:survives_explosion" + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "create:dark_scoria" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "name": "create:dark_scoria_cobblestone" + } + ] } ] } diff --git a/src/generated/resources/data/create/loot_tables/blocks/dolomite.json b/src/generated/resources/data/create/loot_tables/blocks/dolomite.json index d97bb3322..4085d60be 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/dolomite.json +++ b/src/generated/resources/data/create/loot_tables/blocks/dolomite.json @@ -5,13 +5,37 @@ "rolls": 1, "entries": [ { - "type": "minecraft:item", - "name": "create:dolomite" - } - ], - "conditions": [ - { - "condition": "minecraft:survives_explosion" + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "create:dolomite" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "name": "create:dolomite_cobblestone" + } + ] } ] } diff --git a/src/generated/resources/data/create/loot_tables/blocks/gabbro.json b/src/generated/resources/data/create/loot_tables/blocks/gabbro.json index 8446b845e..2f477a53e 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/gabbro.json +++ b/src/generated/resources/data/create/loot_tables/blocks/gabbro.json @@ -5,13 +5,37 @@ "rolls": 1, "entries": [ { - "type": "minecraft:item", - "name": "create:gabbro" - } - ], - "conditions": [ - { - "condition": "minecraft:survives_explosion" + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "create:gabbro" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "name": "create:gabbro_cobblestone" + } + ] } ] } diff --git a/src/generated/resources/data/create/loot_tables/blocks/limestone.json b/src/generated/resources/data/create/loot_tables/blocks/limestone.json index acec889d0..e5b513a61 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/limestone.json +++ b/src/generated/resources/data/create/loot_tables/blocks/limestone.json @@ -5,13 +5,37 @@ "rolls": 1, "entries": [ { - "type": "minecraft:item", - "name": "create:limestone" - } - ], - "conditions": [ - { - "condition": "minecraft:survives_explosion" + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "create:limestone" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "name": "create:limestone_cobblestone" + } + ] } ] } diff --git a/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json b/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json index 255327042..16d2e3ed1 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json +++ b/src/generated/resources/data/create/loot_tables/blocks/schematicannon.json @@ -6,6 +6,19 @@ "entries": [ { "type": "minecraft:item", + "functions": [ + { + "function": "minecraft:copy_nbt", + "source": "block_entity", + "ops": [ + { + "source": "Options", + "target": "BlockEntityTag.Options", + "op": "replace" + } + ] + } + ], "name": "create:schematicannon" } ], diff --git a/src/generated/resources/data/create/loot_tables/blocks/scoria.json b/src/generated/resources/data/create/loot_tables/blocks/scoria.json index 0025a35ae..a119016fa 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/scoria.json +++ b/src/generated/resources/data/create/loot_tables/blocks/scoria.json @@ -5,13 +5,37 @@ "rolls": 1, "entries": [ { - "type": "minecraft:item", - "name": "create:scoria" - } - ], - "conditions": [ - { - "condition": "minecraft:survives_explosion" + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "create:scoria" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "name": "create:scoria_cobblestone" + } + ] } ] } diff --git a/src/generated/resources/data/create/loot_tables/blocks/weathered_limestone.json b/src/generated/resources/data/create/loot_tables/blocks/weathered_limestone.json index 9a11fe4be..e2f779734 100644 --- a/src/generated/resources/data/create/loot_tables/blocks/weathered_limestone.json +++ b/src/generated/resources/data/create/loot_tables/blocks/weathered_limestone.json @@ -5,13 +5,37 @@ "rolls": 1, "entries": [ { - "type": "minecraft:item", - "name": "create:weathered_limestone" - } - ], - "conditions": [ - { - "condition": "minecraft:survives_explosion" + "type": "minecraft:alternatives", + "children": [ + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:match_tool", + "predicate": { + "enchantments": [ + { + "enchantment": "minecraft:silk_touch", + "levels": { + "min": 1 + } + } + ] + } + } + ], + "name": "create:weathered_limestone" + }, + { + "type": "minecraft:item", + "conditions": [ + { + "condition": "minecraft:survives_explosion" + } + ], + "name": "create:weathered_limestone_cobblestone" + } + ] } ] } diff --git a/src/generated/resources/data/create/recipes/andesite.json b/src/generated/resources/data/create/recipes/andesite.json new file mode 100644 index 000000000..1a8a89094 --- /dev/null +++ b/src/generated/resources/data/create/recipes/andesite.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:andesite_cobblestone" + }, + "result": "minecraft:andesite", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/copper_backtank.json b/src/generated/resources/data/create/recipes/crafting/appliances/copper_backtank.json index a99c83f9d..66a29e031 100644 --- a/src/generated/resources/data/create/recipes/crafting/appliances/copper_backtank.json +++ b/src/generated/resources/data/create/recipes/crafting/appliances/copper_backtank.json @@ -2,7 +2,7 @@ "type": "minecraft:crafting_shaped", "pattern": [ "AGA", - "PPP", + "PBP", " P " ], "key": { @@ -12,6 +12,9 @@ "A": { "item": "create:andesite_alloy" }, + "B": { + "tag": "forge:storage_blocks/copper" + }, "P": { "tag": "forge:ingots/copper" } diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json b/src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json new file mode 100644 index 000000000..880a71332 --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/crafting_blueprint.json @@ -0,0 +1,14 @@ +{ + "type": "minecraft:crafting_shapeless", + "ingredients": [ + { + "item": "minecraft:painting" + }, + { + "item": "minecraft:crafting_table" + } + ], + "result": { + "item": "create:crafting_blueprint" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/crafting/appliances/linked_controller.json b/src/generated/resources/data/create/recipes/crafting/appliances/linked_controller.json new file mode 100644 index 000000000..62b2fef8e --- /dev/null +++ b/src/generated/resources/data/create/recipes/crafting/appliances/linked_controller.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "SSS", + " P ", + "SSS" + ], + "key": { + "S": { + "tag": "minecraft:wooden_buttons" + }, + "P": { + "item": "create:redstone_link" + } + }, + "result": { + "item": "create:linked_controller" + } +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/dark_scoria.json b/src/generated/resources/data/create/recipes/dark_scoria.json new file mode 100644 index 000000000..e8677d0a9 --- /dev/null +++ b/src/generated/resources/data/create/recipes/dark_scoria.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:dark_scoria_cobblestone" + }, + "result": "create:dark_scoria", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/diorite.json b/src/generated/resources/data/create/recipes/diorite.json new file mode 100644 index 000000000..a9dc4b737 --- /dev/null +++ b/src/generated/resources/data/create/recipes/diorite.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:diorite_cobblestone" + }, + "result": "minecraft:diorite", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/dolomite.json b/src/generated/resources/data/create/recipes/dolomite.json new file mode 100644 index 000000000..c59ecebbb --- /dev/null +++ b/src/generated/resources/data/create/recipes/dolomite.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:dolomite_cobblestone" + }, + "result": "create:dolomite", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/gabbro.json b/src/generated/resources/data/create/recipes/gabbro.json new file mode 100644 index 000000000..6d05576cb --- /dev/null +++ b/src/generated/resources/data/create/recipes/gabbro.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:gabbro_cobblestone" + }, + "result": "create:gabbro", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/granite.json b/src/generated/resources/data/create/recipes/granite.json new file mode 100644 index 000000000..2a6e30e9b --- /dev/null +++ b/src/generated/resources/data/create/recipes/granite.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:granite_cobblestone" + }, + "result": "minecraft:granite", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/limestone.json b/src/generated/resources/data/create/recipes/limestone.json new file mode 100644 index 000000000..90c360ab1 --- /dev/null +++ b/src/generated/resources/data/create/recipes/limestone.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:limestone_cobblestone" + }, + "result": "create:limestone", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/polished_dark_scoria.json b/src/generated/resources/data/create/recipes/polished_dark_scoria.json index 1dcca3f52..5a9cfcde0 100644 --- a/src/generated/resources/data/create/recipes/polished_dark_scoria.json +++ b/src/generated/resources/data/create/recipes/polished_dark_scoria.json @@ -1,11 +1,11 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "XX", - "XX" + "##", + "##" ], "key": { - "X": { + "#": { "item": "create:dark_scoria" } }, diff --git a/src/generated/resources/data/create/recipes/polished_dolomite.json b/src/generated/resources/data/create/recipes/polished_dolomite.json index 16fbd2463..4fcd09891 100644 --- a/src/generated/resources/data/create/recipes/polished_dolomite.json +++ b/src/generated/resources/data/create/recipes/polished_dolomite.json @@ -1,11 +1,11 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "XX", - "XX" + "##", + "##" ], "key": { - "X": { + "#": { "item": "create:dolomite" } }, diff --git a/src/generated/resources/data/create/recipes/polished_gabbro.json b/src/generated/resources/data/create/recipes/polished_gabbro.json index c9fb7b71a..5c9cfe964 100644 --- a/src/generated/resources/data/create/recipes/polished_gabbro.json +++ b/src/generated/resources/data/create/recipes/polished_gabbro.json @@ -1,11 +1,11 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "XX", - "XX" + "##", + "##" ], "key": { - "X": { + "#": { "item": "create:gabbro" } }, diff --git a/src/generated/resources/data/create/recipes/polished_limestone.json b/src/generated/resources/data/create/recipes/polished_limestone.json index e07df319b..13556fd93 100644 --- a/src/generated/resources/data/create/recipes/polished_limestone.json +++ b/src/generated/resources/data/create/recipes/polished_limestone.json @@ -1,11 +1,11 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "XX", - "XX" + "##", + "##" ], "key": { - "X": { + "#": { "item": "create:limestone" } }, diff --git a/src/generated/resources/data/create/recipes/polished_scoria.json b/src/generated/resources/data/create/recipes/polished_scoria.json index 796ad769a..4ccbf5c05 100644 --- a/src/generated/resources/data/create/recipes/polished_scoria.json +++ b/src/generated/resources/data/create/recipes/polished_scoria.json @@ -1,11 +1,11 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "XX", - "XX" + "##", + "##" ], "key": { - "X": { + "#": { "item": "create:scoria" } }, diff --git a/src/generated/resources/data/create/recipes/polished_weathered_limestone.json b/src/generated/resources/data/create/recipes/polished_weathered_limestone.json index 3d29b1740..cd0a57df5 100644 --- a/src/generated/resources/data/create/recipes/polished_weathered_limestone.json +++ b/src/generated/resources/data/create/recipes/polished_weathered_limestone.json @@ -1,11 +1,11 @@ { "type": "minecraft:crafting_shaped", "pattern": [ - "XX", - "XX" + "##", + "##" ], "key": { - "X": { + "#": { "item": "create:weathered_limestone" } }, diff --git a/src/generated/resources/data/create/recipes/pressing/path.json b/src/generated/resources/data/create/recipes/pressing/path.json index b9a17c39f..7c98111e3 100644 --- a/src/generated/resources/data/create/recipes/pressing/path.json +++ b/src/generated/resources/data/create/recipes/pressing/path.json @@ -7,9 +7,6 @@ }, { "item": "minecraft:dirt" - }, - { - "item": "minecraft:podzol" } ] ], diff --git a/src/generated/resources/data/create/recipes/scoria.json b/src/generated/resources/data/create/recipes/scoria.json new file mode 100644 index 000000000..d63cf40bf --- /dev/null +++ b/src/generated/resources/data/create/recipes/scoria.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:scoria_cobblestone" + }, + "result": "create:scoria", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/recipes/weathered_limestone.json b/src/generated/resources/data/create/recipes/weathered_limestone.json new file mode 100644 index 000000000..93ce442c8 --- /dev/null +++ b/src/generated/resources/data/create/recipes/weathered_limestone.json @@ -0,0 +1,9 @@ +{ + "type": "minecraft:smelting", + "ingredient": { + "item": "create:weathered_limestone_cobblestone" + }, + "result": "create:weathered_limestone", + "experience": 0.1, + "cookingtime": 200 +} \ No newline at end of file diff --git a/src/generated/resources/data/create/tags/blocks/brittle.json b/src/generated/resources/data/create/tags/blocks/brittle.json index c028ad70c..7970c3bf9 100644 --- a/src/generated/resources/data/create/tags/blocks/brittle.json +++ b/src/generated/resources/data/create/tags/blocks/brittle.json @@ -25,6 +25,7 @@ "create:furnace_engine", "create:redstone_link", "#minecraft:doors", + "#minecraft:beds", "minecraft:flower_pot", "minecraft:bell", "minecraft:cocoa" diff --git a/src/generated/resources/data/create/tags/blocks/non_movable.json b/src/generated/resources/data/create/tags/blocks/non_movable.json deleted file mode 100644 index 5e8aecc98..000000000 --- a/src/generated/resources/data/create/tags/blocks/non_movable.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "replace": false, - "values": [] -} \ No newline at end of file diff --git a/src/generated/resources/data/minecraft/tags/items/piglin_loved.json b/src/generated/resources/data/minecraft/tags/items/piglin_loved.json new file mode 100644 index 000000000..478bada69 --- /dev/null +++ b/src/generated/resources/data/minecraft/tags/items/piglin_loved.json @@ -0,0 +1,7 @@ +{ + "replace": false, + "values": [ + "create:golden_sheet", + "create:crushed_gold_ore" + ] +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/AllBlockPartials.java b/src/main/java/com/simibubi/create/AllBlockPartials.java index 046ca169d..25d9e0ddb 100644 --- a/src/main/java/com/simibubi/create/AllBlockPartials.java +++ b/src/main/java/com/simibubi/create/AllBlockPartials.java @@ -3,9 +3,9 @@ package com.simibubi.create; import java.util.HashMap; import java.util.Map; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; @@ -93,20 +93,22 @@ public class AllBlockPartials { SPOUT_TOP = get("spout/top"), SPOUT_MIDDLE = get("spout/middle"), SPOUT_BOTTOM = get("spout/bottom"), - SPEED_CONTROLLER_BRACKET = get("rotation_speed_controller/bracket"), + SPEED_CONTROLLER_BRACKET = get("rotation_speed_controller/bracket"), - GOGGLES = get("goggles"), + GOGGLES = get("goggles"), - EJECTOR_TOP = get("weighted_ejector/top"), - - COPPER_BACKTANK_SHAFT = get("copper_backtank/block_shaft_input"), - COPPER_BACKTANK_COGS = get("copper_backtank/block_cogs"), + EJECTOR_TOP = get("weighted_ejector/top"), - COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"), - COUPLING_RING = getEntity("minecart_coupling/ring"), - COUPLING_CONNECTOR = getEntity("minecart_coupling/connector") + COPPER_BACKTANK_SHAFT = get("copper_backtank/block_shaft_input"), + COPPER_BACKTANK_COGS = get("copper_backtank/block_cogs"), - ; + CRAFTING_BLUEPRINT_1x1 = getEntity("crafting_blueprint_small"), + CRAFTING_BLUEPRINT_2x2 = getEntity("crafting_blueprint_medium"), + CRAFTING_BLUEPRINT_3x3 = getEntity("crafting_blueprint_large"), + + COUPLING_ATTACHMENT = getEntity("minecart_coupling/attachment"), + COUPLING_RING = getEntity("minecart_coupling/ring"), + COUPLING_CONNECTOR = getEntity("minecart_coupling/connector"); public static final Map> PIPE_ATTACHMENTS = new HashMap<>(); public static final Map BLAZES = new HashMap<>(); diff --git a/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java index 472b8e8a2..13af7d571 100644 --- a/src/main/java/com/simibubi/create/AllBlocks.java +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -9,8 +9,6 @@ import static com.simibubi.create.foundation.data.CreateRegistrate.connectedText import static com.simibubi.create.foundation.data.ModelGen.customItemModel; import static com.simibubi.create.foundation.data.ModelGen.oxidizedItemModel; -import java.util.Vector; - import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllItemTags; import com.simibubi.create.content.AllSections; @@ -116,6 +114,7 @@ import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock; import com.simibubi.create.content.contraptions.relays.gauge.GaugeGenerator; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock; import com.simibubi.create.content.curiosities.armor.CopperBacktankBlock; +import com.simibubi.create.content.curiosities.projector.ChromaticProjectorBlock; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock; import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock; import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelCTBehaviour; @@ -157,6 +156,7 @@ import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkGenerato import com.simibubi.create.content.logistics.block.redstone.StockpileSwitchBlock; import com.simibubi.create.content.schematics.block.SchematicTableBlock; import com.simibubi.create.content.schematics.block.SchematicannonBlock; +import com.simibubi.create.foundation.block.DyedBlockList; import com.simibubi.create.foundation.block.ItemUseOverrides; import com.simibubi.create.foundation.config.StressConfigDefaults; import com.simibubi.create.foundation.data.AssetLookup; @@ -166,6 +166,7 @@ import com.simibubi.create.foundation.data.CreateRegistrate; import com.simibubi.create.foundation.data.ModelGen; import com.simibubi.create.foundation.data.SharedProperties; import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.ColorHandlers; import com.simibubi.create.foundation.utility.DyeHelper; import com.simibubi.create.foundation.worldgen.OxidizingBlock; import com.tterrag.registrate.providers.RegistrateRecipeProvider; @@ -203,7 +204,7 @@ import net.minecraftforge.common.ToolType; public class AllBlocks { private static final CreateRegistrate REGISTRATE = Create.registrate() - .itemGroup(() -> Create.baseCreativeTab); + .itemGroup(() -> Create.BASE_CREATIVE_TAB); // Schematics @@ -215,6 +216,16 @@ public class AllBlocks { REGISTRATE.block("schematicannon", SchematicannonBlock::new) .initialProperties(() -> Blocks.DISPENSER) .blockstate((ctx, prov) -> prov.simpleBlock(ctx.getEntry(), AssetLookup.partialBaseModel(ctx, prov))) + .loot((lt, block) -> { + Builder builder = LootTable.builder(); + IBuilder survivesExplosion = SurvivesExplosion.builder(); + lt.registerLootTable(block, builder.addLootPool(LootPool.builder() + .acceptCondition(survivesExplosion) + .rolls(ConstantRange.of(1)) + .addEntry(ItemLootEntry.builder(AllBlocks.SCHEMATICANNON.get().asItem()) + .acceptFunction(CopyNbt.func_215881_a(CopyNbt.Source.BLOCK_ENTITY) + .func_216056_a("Options", "BlockEntityTag.Options"))))); + }) .item() .transform(customItemModel()) .register(); @@ -607,44 +618,39 @@ public class AllBlocks { .blockstate((c, p) -> BlockStateGen.directionalAxisBlock(c, p, (state, vertical) -> AssetLookup.partialBaseModel(c, p, vertical ? "vertical" : "horizontal", state.get(FluidValveBlock.ENABLED) ? "open" : "closed"))) - .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) - .item() - .transform(customItemModel()) - .register(); - - public static final BlockEntry COPPER_VALVE_HANDLE = - REGISTRATE.block("copper_valve_handle", ValveHandleBlock::copper) - .transform(BuilderTransformers.valveHandle(null)) + .onRegister(CreateRegistrate.blockModel(() -> PipeAttachmentModel::new)) + .item() + .transform(customItemModel()) .register(); - public static final Vector> DYED_VALVE_HANDLES = - new Vector<>(DyeColor.values().length); + public static final BlockEntry COPPER_VALVE_HANDLE = + REGISTRATE.block("copper_valve_handle", ValveHandleBlock::copper) + .transform(BuilderTransformers.valveHandle(null)) + .register(); - static { - for (DyeColor colour : DyeColor.values()) { - String colourName = colour.getString(); - DYED_VALVE_HANDLES.add(REGISTRATE.block(colourName + "_valve_handle", ValveHandleBlock::dyed) + public static final DyedBlockList DYED_VALVE_HANDLES = new DyedBlockList<>(colour -> { + String colourName = colour.getString(); + return REGISTRATE.block(colourName + "_valve_handle", ValveHandleBlock::dyed) .transform(BuilderTransformers.valveHandle(colour)) .recipe((c, p) -> ShapedRecipeBuilder.shapedRecipe(c.get()) - .patternLine("#") - .patternLine("-") - .key('#', DyeHelper.getTagOfDye(colour)) - .key('-', AllItemTags.VALVE_HANDLES.tag) - .addCriterion("has_valve", RegistrateRecipeProvider.hasItem(AllItemTags.VALVE_HANDLES.tag)) - .build(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_valve_handle"))) - .register()); - } - } + .patternLine("#") + .patternLine("-") + .key('#', DyeHelper.getTagOfDye(colour)) + .key('-', AllItemTags.VALVE_HANDLES.tag) + .addCriterion("has_valve", RegistrateRecipeProvider.hasItem(AllItemTags.VALVE_HANDLES.tag)) + .build(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_valve_handle"))) + .register(); + }); public static final BlockEntry FLUID_TANK = REGISTRATE.block("fluid_tank", FluidTankBlock::regular) - .initialProperties(SharedProperties::softMetal) - .properties(AbstractBlock.Properties::nonOpaque) - .blockstate(new FluidTankGenerator()::generate) - .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard)) - .addLayer(() -> RenderType::getCutoutMipped) - .item(FluidTankItem::new) - .model(AssetLookup.customBlockItemModel("_", "block_single_window")) - .build() + .initialProperties(SharedProperties::softMetal) + .properties(AbstractBlock.Properties::nonOpaque) + .blockstate(new FluidTankGenerator()::generate) + .onRegister(CreateRegistrate.blockModel(() -> FluidTankModel::standard)) + .addLayer(() -> RenderType::getCutoutMipped) + .item(FluidTankItem::new) + .model(AssetLookup.customBlockItemModel("_", "block_single_window")) + .build() .register(); public static final BlockEntry CREATIVE_FLUID_TANK = @@ -830,11 +836,11 @@ public class AllBlocks { .register(); public static final BlockEntry CONTROLLER_RAIL = - REGISTRATE.block("controller_rail", ControllerRailBlock::new) - .initialProperties(() -> Blocks.POWERED_RAIL) - .blockstate(new ControllerRailGenerator()::generate) - .addLayer(() -> RenderType::getCutoutMipped) - .onRegister(CreateRegistrate.blockColors(() -> AllColorHandlers::getRedstonePower)) + REGISTRATE.block("controller_rail", ControllerRailBlock::new) + .initialProperties(() -> Blocks.POWERED_RAIL) + .blockstate(new ControllerRailGenerator()::generate) + .addLayer(() -> RenderType::getCutoutMipped) + .color(() -> ColorHandlers::getRedstonePower) .tag(BlockTags.RAILS) .item() .model((c, p) -> p.generated(c, Create.asResource("block/" + c.getName()))) @@ -943,105 +949,93 @@ public class AllBlocks { .addLayer(() -> RenderType::getCutoutMipped) .item() .transform(customItemModel()) - .register(); + .register(); public static final BlockEntry MECHANICAL_PLOUGH = - REGISTRATE.block("mechanical_plough", PloughBlock::new) - .initialProperties(SharedProperties::stone) - .onRegister(addMovementBehaviour(new PloughMovementBehaviour())) - .blockstate(BlockStateGen.horizontalBlockProvider(false)) - .simpleItem() - .register(); + REGISTRATE.block("mechanical_plough", PloughBlock::new) + .initialProperties(SharedProperties::stone) + .onRegister(addMovementBehaviour(new PloughMovementBehaviour())) + .blockstate(BlockStateGen.horizontalBlockProvider(false)) + .simpleItem() + .register(); - public static final BlockEntry[] SEATS = new BlockEntry[DyeColor.values().length]; - - static { - // SEATS - for (DyeColor colour : DyeColor.values()) { - String colourName = colour.getString(); - SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour(); - SEATS[colour.ordinal()] = - REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour == DyeColor.RED)) - .initialProperties(SharedProperties::wooden) - .onRegister(addMovementBehaviour(movementBehaviour)) - .blockstate((c, p) -> { - p.simpleBlock(c.get(), p.models() + public static final DyedBlockList SEATS = new DyedBlockList<>(colour -> { + String colourName = colour.getString(); + SeatMovementBehaviour movementBehaviour = new SeatMovementBehaviour(); + return REGISTRATE.block(colourName + "_seat", p -> new SeatBlock(p, colour == DyeColor.RED)) + .initialProperties(SharedProperties::wooden) + .onRegister(addMovementBehaviour(movementBehaviour)) + .blockstate((c, p) -> { + p.simpleBlock(c.get(), p.models() .withExistingParent(colourName + "_seat", p.modLoc("block/seat")) .texture("1", p.modLoc("block/seat/top_" + colourName)) .texture("2", p.modLoc("block/seat/side_" + colourName))); - }) - .recipe((c, p) -> { - ShapedRecipeBuilder.shapedRecipe(c.get()) + }) + .recipe((c, p) -> { + ShapedRecipeBuilder.shapedRecipe(c.get()) .patternLine("#") .patternLine("-") .key('#', DyeHelper.getWoolOfDye(colour)) .key('-', ItemTags.WOODEN_SLABS) .addCriterion("has_wool", RegistrateRecipeProvider.hasItem(ItemTags.WOOL)) .build(p, Create.asResource("crafting/kinetics/" + c.getName())); - ShapedRecipeBuilder.shapedRecipe(c.get()) + ShapedRecipeBuilder.shapedRecipe(c.get()) .patternLine("#") .patternLine("-") .key('#', DyeHelper.getTagOfDye(colour)) .key('-', AllItemTags.SEATS.tag) .addCriterion("has_seat", RegistrateRecipeProvider.hasItem(AllItemTags.SEATS.tag)) .build(p, Create.asResource("crafting/kinetics/" + c.getName() + "_from_other_seat")); - }) - .onRegisterAfter(Item.class, v -> TooltipHelper.referTo(v, "block.create.seat")) - .tag(AllBlockTags.SEATS.tag) - .item() - .tag(AllItemTags.SEATS.tag) - .build() - .register(); - } - } + }) + .onRegisterAfter(Item.class, v -> TooltipHelper.referTo(v, "block.create.seat")) + .tag(AllBlockTags.SEATS.tag) + .item() + .tag(AllItemTags.SEATS.tag) + .build() + .register(); + }); public static final BlockEntry SAIL_FRAME = REGISTRATE.block("sail_frame", p -> SailBlock.frame(p)) - .initialProperties(SharedProperties::wooden) - .properties(Block.Properties::nonOpaque) - .blockstate(BlockStateGen.directionalBlockProvider(false)) - .tag(AllBlockTags.WINDMILL_SAILS.tag) - .tag(AllBlockTags.FAN_TRANSPARENT.tag) - .simpleItem() - .register(); - - public static final BlockEntry[] DYED_SAILS = new BlockEntry[DyeColor.values().length]; + .initialProperties(SharedProperties::wooden) + .properties(Block.Properties::nonOpaque) + .blockstate(BlockStateGen.directionalBlockProvider(false)) + .tag(AllBlockTags.WINDMILL_SAILS.tag) + .tag(AllBlockTags.FAN_TRANSPARENT.tag) + .simpleItem() + .register(); public static final BlockEntry SAIL = REGISTRATE.block("white_sail", p -> SailBlock.withCanvas(p)) - .initialProperties(SharedProperties::wooden) - .properties(Block.Properties::nonOpaque) - .blockstate(BlockStateGen.directionalBlockProvider(false)) - .tag(AllBlockTags.WINDMILL_SAILS.tag) - .simpleItem() - .register(); + .initialProperties(SharedProperties::wooden) + .properties(Block.Properties::nonOpaque) + .blockstate(BlockStateGen.directionalBlockProvider(false)) + .tag(AllBlockTags.WINDMILL_SAILS.tag) + .simpleItem() + .register(); - static { - // DYED SAILS - for (DyeColor colour : DyeColor.values()) { - if (colour == DyeColor.WHITE) { - DYED_SAILS[colour.ordinal()] = SAIL; - continue; - } - String colourName = colour.getString(); - DYED_SAILS[colour.ordinal()] = REGISTRATE.block(colourName + "_sail", p -> SailBlock.withCanvas(p)) + public static final DyedBlockList DYED_SAILS = new DyedBlockList<>(colour -> { + if (colour == DyeColor.WHITE) { + return SAIL; + } + String colourName = colour.getString(); + return REGISTRATE.block(colourName + "_sail", p -> SailBlock.withCanvas(p)) .properties(Block.Properties::nonOpaque) .initialProperties(SharedProperties::wooden) .blockstate((c, p) -> p.directionalBlock(c.get(), p.models() - .withExistingParent(colourName + "_sail", p.modLoc("block/white_sail")) - .texture("0", p.modLoc("block/sail/canvas_" + colourName)))) + .withExistingParent(colourName + "_sail", p.modLoc("block/white_sail")) + .texture("0", p.modLoc("block/sail/canvas_" + colourName)))) .tag(AllBlockTags.WINDMILL_SAILS.tag) .tag(AllBlockTags.SAILS.tag) .loot((p, b) -> p.registerDropping(b, SAIL.get())) .register(); - } - } + }); public static final BlockEntry ANDESITE_CASING = REGISTRATE.block("andesite_casing", CasingBlock::new) - .transform(BuilderTransformers.casing(AllSpriteShifts.ANDESITE_CASING)) - .register(); + .transform(BuilderTransformers.casing(AllSpriteShifts.ANDESITE_CASING)) + .register(); public static final BlockEntry BRASS_CASING = REGISTRATE.block("brass_casing", CasingBlock::new) - .transform(BuilderTransformers.casing(AllSpriteShifts.BRASS_CASING)) - .register(); + .transform(BuilderTransformers.casing(AllSpriteShifts.BRASS_CASING)) + .register(); public static final BlockEntry COPPER_CASING = REGISTRATE.block("copper_casing", CasingBlock::new) .transform(BuilderTransformers.casing(AllSpriteShifts.COPPER_CASING)) diff --git a/src/main/java/com/simibubi/create/AllColorHandlers.java b/src/main/java/com/simibubi/create/AllColorHandlers.java index f8d86596d..e69de29bb 100644 --- a/src/main/java/com/simibubi/create/AllColorHandlers.java +++ b/src/main/java/com/simibubi/create/AllColorHandlers.java @@ -1,116 +0,0 @@ -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; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.color.BlockColors; -import net.minecraft.client.renderer.color.IBlockColor; -import net.minecraft.client.renderer.color.IItemColor; -import net.minecraft.client.renderer.color.ItemColors; -import net.minecraft.item.ItemStack; -import net.minecraft.state.properties.BlockStateProperties; -import net.minecraft.util.IItemProvider; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.GrassColors; -import net.minecraft.world.IBlockDisplayReader; -import net.minecraft.world.biome.BiomeColors; - -public class AllColorHandlers { - - private final Map coloredVertexBlocks = new HashMap<>(); - private final Map coloredBlocks = new HashMap<>(); - private final Map coloredItems = new HashMap<>(); - - // - - public static IBlockColor getGrassyBlock() { - return new BlockColor( - (state, world, pos, layer) -> pos != null && world != null ? BiomeColors.getGrassColor(world, pos) - : GrassColors.get(0.5D, 1.0D)); - } - - public static IItemColor getGrassyItem() { - return new ItemColor((stack, layer) -> GrassColors.get(0.5D, 1.0D)); - } - - public static IBlockColor getRedstonePower() { - return new BlockColor((state, world, pos, layer) -> RedstoneWireBlock - .getWireColor(pos != null && world != null ? state.get(BlockStateProperties.POWER_0_15) : 0)); - } - - // - - public void register(Block block, IBlockColor color) { - coloredBlocks.put(block, color); - } - - public void register(Block block, IBlockVertexColor color) { - coloredVertexBlocks.put(block, color); - } - - public void register(IItemProvider item, IItemColor color) { - coloredItems.put(item, color); - } - - public void init() { - BlockColors blockColors = Minecraft.getInstance() - .getBlockColors(); - ItemColors itemColors = Minecraft.getInstance() - .getItemColors(); - - coloredBlocks.forEach((block, color) -> blockColors.register(color, block)); - coloredItems.forEach((item, color) -> itemColors.register(color, item)); - coloredVertexBlocks.forEach((block, color) -> CreateClient.getCustomBlockModels() - .register(() -> block, model -> new ColoredVertexModel(model, color))); - } - - // - - private static class ItemColor implements IItemColor { - - private Function function; - - @FunctionalInterface - interface Function { - int apply(ItemStack stack, int layer); - } - - public ItemColor(Function function) { - this.function = function; - } - - @Override - public int getColor(ItemStack stack, int layer) { - return function.apply(stack, layer); - } - - } - - private static class BlockColor implements IBlockColor { - - private Function function; - - @FunctionalInterface - interface Function { - int apply(BlockState state, IBlockDisplayReader world, BlockPos pos, int layer); - } - - public BlockColor(Function function) { - this.function = function; - } - - @Override - public int getColor(BlockState state, IBlockDisplayReader world, BlockPos pos, int layer) { - return function.apply(state, world, pos, layer); - } - - } - -} diff --git a/src/main/java/com/simibubi/create/AllContainerTypes.java b/src/main/java/com/simibubi/create/AllContainerTypes.java index f7ea37a0c..14d498753 100644 --- a/src/main/java/com/simibubi/create/AllContainerTypes.java +++ b/src/main/java/com/simibubi/create/AllContainerTypes.java @@ -1,7 +1,11 @@ package com.simibubi.create; +import com.simibubi.create.content.curiosities.tools.BlueprintContainer; +import com.simibubi.create.content.curiosities.tools.BlueprintScreen; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateContainer; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateScreen; +import com.simibubi.create.content.logistics.item.LinkedControllerContainer; +import com.simibubi.create.content.logistics.item.LinkedControllerScreen; import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer; import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen; import com.simibubi.create.content.logistics.item.filter.FilterContainer; @@ -10,61 +14,42 @@ import com.simibubi.create.content.schematics.block.SchematicTableContainer; import com.simibubi.create.content.schematics.block.SchematicTableScreen; import com.simibubi.create.content.schematics.block.SchematicannonContainer; import com.simibubi.create.content.schematics.block.SchematicannonScreen; -import com.simibubi.create.foundation.utility.Lang; +import com.tterrag.registrate.builders.ContainerBuilder.ForgeContainerFactory; +import com.tterrag.registrate.builders.ContainerBuilder.ScreenFactory; +import com.tterrag.registrate.util.entry.ContainerEntry; +import com.tterrag.registrate.util.nullness.NonNullSupplier; import net.minecraft.client.gui.IHasContainer; -import net.minecraft.client.gui.ScreenManager; -import net.minecraft.client.gui.ScreenManager.IScreenFactory; import net.minecraft.client.gui.screen.Screen; import net.minecraft.inventory.container.Container; -import net.minecraft.inventory.container.ContainerType; -import net.minecraft.inventory.container.ContainerType.IFactory; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.fml.network.IContainerFactory; -public enum AllContainerTypes { +public class AllContainerTypes { - SCHEMATIC_TABLE(SchematicTableContainer::new), - SCHEMATICANNON(SchematicannonContainer::new), - FLEXCRATE(AdjustableCrateContainer::new), - FILTER(FilterContainer::new), - ATTRIBUTE_FILTER(AttributeFilterContainer::new), + public static final ContainerEntry SCHEMATIC_TABLE = + register("schematic_table", SchematicTableContainer::new, () -> SchematicTableScreen::new); - ; + public static final ContainerEntry SCHEMATICANNON = + register("schematicannon", SchematicannonContainer::new, () -> SchematicannonScreen::new); - public ContainerType type; - private IFactory factory; + public static final ContainerEntry FLEXCRATE = + register("flexcrate", AdjustableCrateContainer::new, () -> AdjustableCrateScreen::new); - private AllContainerTypes(IContainerFactory factory) { - this.factory = factory; + public static final ContainerEntry FILTER = + register("filter", FilterContainer::new, () -> FilterScreen::new); + + public static final ContainerEntry ATTRIBUTE_FILTER = + register("attribute_filter", AttributeFilterContainer::new, () -> AttributeFilterScreen::new); + + public static final ContainerEntry CRAFTING_BLUEPRINT = + register("crafting_blueprint", BlueprintContainer::new, () -> BlueprintScreen::new); + + public static final ContainerEntry LINKED_CONTROLLER = + register("linked_controller", LinkedControllerContainer::new, () -> LinkedControllerScreen::new); + + private static > ContainerEntry register(String name, ForgeContainerFactory factory, NonNullSupplier> screenFactory) { + return Create.registrate().container(name, factory, screenFactory).register(); } - public static void register(RegistryEvent.Register> event) { - for (AllContainerTypes container : values()) { - container.type = new ContainerType<>(container.factory) - .setRegistryName(new ResourceLocation(Create.ID, Lang.asId(container.name()))); - event.getRegistry() - .register(container.type); - } - } - - @OnlyIn(Dist.CLIENT) - public static void registerScreenFactories() { - bind(SCHEMATIC_TABLE, SchematicTableScreen::new); - bind(SCHEMATICANNON, SchematicannonScreen::new); - bind(FLEXCRATE, AdjustableCrateScreen::new); - bind(FILTER, FilterScreen::new); - bind(ATTRIBUTE_FILTER, AttributeFilterScreen::new); - } - - @OnlyIn(Dist.CLIENT) - @SuppressWarnings("unchecked") - private static > void bind(AllContainerTypes c, - IScreenFactory factory) { - ScreenManager.registerFactory((ContainerType) c.type, factory); - } + public static void register() {} } diff --git a/src/main/java/com/simibubi/create/AllEntityTypes.java b/src/main/java/com/simibubi/create/AllEntityTypes.java index 32afec7fa..5873de910 100644 --- a/src/main/java/com/simibubi/create/AllEntityTypes.java +++ b/src/main/java/com/simibubi/create/AllEntityTypes.java @@ -1,5 +1,6 @@ package com.simibubi.create; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; 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; @@ -7,68 +8,77 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Con 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.glue.GlueInstance; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueRenderer; +import com.simibubi.create.content.curiosities.tools.BlueprintEntity; +import com.simibubi.create.content.curiosities.tools.BlueprintRenderer; +import com.simibubi.create.foundation.data.CreateEntityBuilder; import com.simibubi.create.foundation.utility.Lang; -import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.builders.EntityBuilder; +import com.tterrag.registrate.util.entry.EntityEntry; import com.tterrag.registrate.util.nullness.NonNullConsumer; +import com.tterrag.registrate.util.nullness.NonNullSupplier; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityClassification; import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType.IFactory; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.client.registry.RenderingRegistry; +import net.minecraftforge.fml.client.registry.IRenderFactory; public class AllEntityTypes { - public static final RegistryEntry> ORIENTED_CONTRAPTION = - contraption("contraption", OrientedContraptionEntity::new, 5, 3, true); - public static final RegistryEntry> CONTROLLED_CONTRAPTION = - contraption("stationary_contraption", ControlledContraptionEntity::new, 20, 40, false); - public static final RegistryEntry> GANTRY_CONTRAPTION = - contraption("gantry_contraption", GantryContraptionEntity::new, 10, 40, false); + public static final EntityEntry ORIENTED_CONTRAPTION = + contraption("contraption", OrientedContraptionEntity::new, () -> OrientedContraptionEntityRenderer::new, + 5, 3, true); + public static final EntityEntry CONTROLLED_CONTRAPTION = + contraption("stationary_contraption", ControlledContraptionEntity::new, () -> ContraptionEntityRenderer::new, + 20, 40, false); + public static final EntityEntry GANTRY_CONTRAPTION = + contraption("gantry_contraption", GantryContraptionEntity::new, () -> ContraptionEntityRenderer::new, + 10, 40, false); - public static final RegistryEntry> SUPER_GLUE = register("super_glue", - SuperGlueEntity::new, EntityClassification.MISC, 10, Integer.MAX_VALUE, false, true, SuperGlueEntity::build); - public static final RegistryEntry> SEAT = register("seat", SeatEntity::new, - EntityClassification.MISC, 0, Integer.MAX_VALUE, false, true, SeatEntity::build); + public static final EntityEntry SUPER_GLUE = + register("super_glue", SuperGlueEntity::new, () -> SuperGlueRenderer::new, + EntityClassification.MISC, 10, Integer.MAX_VALUE, false, true, SuperGlueEntity::build) + .instance(() -> GlueInstance::new) + .register(); + + public static final EntityEntry CRAFTING_BLUEPRINT = + register("crafting_blueprint", BlueprintEntity::new, () -> BlueprintRenderer::new, + EntityClassification.MISC, 10, Integer.MAX_VALUE, false, true, BlueprintEntity::build).register(); + + public static final EntityEntry SEAT = + register("seat", SeatEntity::new, () -> SeatEntity.Render::new, + EntityClassification.MISC, 0, Integer.MAX_VALUE, false, true, SeatEntity::build).register(); // - public static void register() {} - - private static RegistryEntry> contraption(String name, IFactory factory, - int range, int updateFrequency, boolean sendVelocity) { - return register(name, factory, EntityClassification.MISC, range, updateFrequency, sendVelocity, true, - AbstractContraptionEntity::build); + private static EntityEntry contraption(String name, IFactory factory, + NonNullSupplier> renderer, int range, int updateFrequency, + boolean sendVelocity) { + return register(name, factory, renderer, EntityClassification.MISC, range, updateFrequency, + sendVelocity, true, AbstractContraptionEntity::build).register(); } - private static RegistryEntry> register(String name, IFactory factory, - EntityClassification group, int range, int updateFrequency, boolean sendVelocity, boolean immuneToFire, - NonNullConsumer> propertyBuilder) { + private static CreateEntityBuilder register(String name, IFactory factory, + NonNullSupplier> renderer, EntityClassification group, int range, + int updateFrequency, boolean sendVelocity, boolean immuneToFire, + NonNullConsumer> propertyBuilder) { String id = Lang.asId(name); - return Create.registrate() - .entity(id, factory, group) - .properties(b -> b.setTrackingRange(range) - .setUpdateInterval(updateFrequency) - .setShouldReceiveVelocityUpdates(sendVelocity)) - .properties(propertyBuilder) - .properties(b -> { - if (immuneToFire) - b.immuneToFire(); - }) - .register(); + return (CreateEntityBuilder) Create.registrate() + .entity(id, factory, group) + .properties(b -> b.setTrackingRange(range) + .setUpdateInterval(updateFrequency) + .setShouldReceiveVelocityUpdates(sendVelocity)) + .properties(propertyBuilder) + .properties(b -> { + if (immuneToFire) + b.immuneToFire(); + }) + .renderer(renderer); } - @OnlyIn(value = Dist.CLIENT) - public static void registerRenderers() { - RenderingRegistry.registerEntityRenderingHandler(CONTROLLED_CONTRAPTION.get(), ContraptionEntityRenderer::new); - RenderingRegistry.registerEntityRenderingHandler(ORIENTED_CONTRAPTION.get(), - OrientedContraptionEntityRenderer::new); - RenderingRegistry.registerEntityRenderingHandler(GANTRY_CONTRAPTION.get(), ContraptionEntityRenderer::new); - RenderingRegistry.registerEntityRenderingHandler(SUPER_GLUE.get(), SuperGlueRenderer::new); - RenderingRegistry.registerEntityRenderingHandler(SEAT.get(), SeatEntity.Render::new); + public static void register() { } } diff --git a/src/main/java/com/simibubi/create/AllFluids.java b/src/main/java/com/simibubi/create/AllFluids.java index 5a7b92355..854aab1f1 100644 --- a/src/main/java/com/simibubi/create/AllFluids.java +++ b/src/main/java/com/simibubi/create/AllFluids.java @@ -7,7 +7,7 @@ import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid; import com.simibubi.create.content.contraptions.fluids.potion.PotionFluid.PotionFluidAttributes; import com.simibubi.create.content.palettes.AllPaletteBlocks; import com.simibubi.create.foundation.data.CreateRegistrate; -import com.tterrag.registrate.util.entry.RegistryEntry; +import com.tterrag.registrate.util.entry.FluidEntry; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.RenderType; @@ -25,47 +25,47 @@ public class AllFluids { private static final CreateRegistrate REGISTRATE = Create.registrate(); - public static RegistryEntry POTION = - REGISTRATE.virtualFluid("potion", PotionFluidAttributes::new, PotionFluid::new) - .lang(f -> "fluid.create.potion", "Potion") + public static FluidEntry POTION = + REGISTRATE.virtualFluid("potion", PotionFluidAttributes::new, PotionFluid::new) + .lang(f -> "fluid.create.potion", "Potion") + .register(); + + public static FluidEntry TEA = REGISTRATE.virtualFluid("tea") + .lang(f -> "fluid.create.tea", "Builder's Tea") + .tag(AllTags.forgeFluidTag("tea")) .register(); - public static RegistryEntry TEA = REGISTRATE.virtualFluid("tea") - .lang(f -> "fluid.create.tea", "Builder's Tea") - .tag(AllTags.forgeFluidTag("tea")) - .register(); - - public static RegistryEntry MILK = REGISTRATE.virtualFluid("milk") - .lang(f -> "fluid.create.milk", "Milk") - .tag(AllTags.forgeFluidTag("milk")) - .register(); - - public static RegistryEntry HONEY = - REGISTRATE.standardFluid("honey", NoColorFluidAttributes::new) - .lang(f -> "fluid.create.honey", "Honey") - .attributes(b -> b.viscosity(500) - .density(1400)) - .properties(p -> p.levelDecreasePerBlock(2) - .tickRate(25) - .slopeFindDistance(3) - .explosionResistance(100f)) - .tag(AllTags.forgeFluidTag("honey")) - .bucket() - .properties(p -> p.maxStackSize(1)) - .build() + public static FluidEntry MILK = REGISTRATE.virtualFluid("milk") + .lang(f -> "fluid.create.milk", "Milk") + .tag(AllTags.forgeFluidTag("milk")) .register(); - public static RegistryEntry CHOCOLATE = - REGISTRATE.standardFluid("chocolate", NoColorFluidAttributes::new) - .lang(f -> "fluid.create.chocolate", "Chocolate") - .tag(AllTags.forgeFluidTag("chocolate")) - .attributes(b -> b.viscosity(500) - .density(1400)) - .properties(p -> p.levelDecreasePerBlock(2) - .tickRate(25) - .slopeFindDistance(3) - .explosionResistance(100f)) - .bucket() + public static FluidEntry HONEY = + REGISTRATE.standardFluid("honey", NoColorFluidAttributes::new) + .lang(f -> "fluid.create.honey", "Honey") + .attributes(b -> b.viscosity(500) + .density(1400)) + .properties(p -> p.levelDecreasePerBlock(2) + .tickRate(25) + .slopeFindDistance(3) + .explosionResistance(100f)) + .tag(AllTags.forgeFluidTag("honey")) + .bucket() + .properties(p -> p.maxStackSize(1)) + .build() + .register(); + + public static FluidEntry CHOCOLATE = + REGISTRATE.standardFluid("chocolate", NoColorFluidAttributes::new) + .lang(f -> "fluid.create.chocolate", "Chocolate") + .tag(AllTags.forgeFluidTag("chocolate")) + .attributes(b -> b.viscosity(500) + .density(1400)) + .properties(p -> p.levelDecreasePerBlock(2) + .tickRate(25) + .slopeFindDistance(3) + .explosionResistance(100f)) + .bucket() .properties(p -> p.maxStackSize(1)) .build() .register(); @@ -78,7 +78,7 @@ public class AllFluids { public static void assignRenderLayers() {} @OnlyIn(Dist.CLIENT) - private static void makeTranslucent(RegistryEntry entry) { + private static void makeTranslucent(FluidEntry entry) { ForgeFlowingFluid fluid = entry.get(); RenderTypeLookup.setRenderLayer(fluid, RenderType.getTranslucent()); RenderTypeLookup.setRenderLayer(fluid.getStillFluid(), RenderType.getTranslucent()); diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java index 2d13ad744..e926eaa33 100644 --- a/src/main/java/com/simibubi/create/AllItems.java +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -1,10 +1,10 @@ package com.simibubi.create; -import static com.simibubi.create.AllTags.forgeItemTag; import static com.simibubi.create.AllTags.AllItemTags.CREATE_INGOTS; import static com.simibubi.create.AllTags.AllItemTags.CRUSHED_ORES; import static com.simibubi.create.AllTags.AllItemTags.NUGGETS; import static com.simibubi.create.AllTags.AllItemTags.PLATES; +import static com.simibubi.create.AllTags.forgeItemTag; import static com.simibubi.create.content.AllSections.CURIOSITIES; import static com.simibubi.create.content.AllSections.KINETICS; import static com.simibubi.create.content.AllSections.LOGISTICS; @@ -35,12 +35,15 @@ import com.simibubi.create.content.curiosities.armor.DivingBootsItem; import com.simibubi.create.content.curiosities.armor.DivingHelmetItem; import com.simibubi.create.content.curiosities.symmetry.SymmetryWandItem; import com.simibubi.create.content.curiosities.symmetry.client.SymmetryWandModel; +import com.simibubi.create.content.curiosities.tools.BlueprintItem; import com.simibubi.create.content.curiosities.tools.ExtendoGripItem; import com.simibubi.create.content.curiosities.tools.ExtendoGripModel; import com.simibubi.create.content.curiosities.tools.SandPaperItem; import com.simibubi.create.content.curiosities.tools.SandPaperItemRenderer.SandPaperModel; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperItem; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperModel; +import com.simibubi.create.content.logistics.item.LinkedControllerItem; +import com.simibubi.create.content.logistics.item.LinkedControllerModel; import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.schematics.item.SchematicAndQuillItem; import com.simibubi.create.content.schematics.item.SchematicItem; @@ -56,12 +59,13 @@ import net.minecraft.item.Food; import net.minecraft.item.Item; import net.minecraft.item.Rarity; import net.minecraft.tags.ITag; +import net.minecraft.tags.ItemTags; import net.minecraft.util.ResourceLocation; public class AllItems { private static final CreateRegistrate REGISTRATE = Create.registrate() - .itemGroup(() -> Create.baseCreativeTab); + .itemGroup(() -> Create.BASE_CREATIVE_TAB); // Schematics @@ -122,10 +126,10 @@ public class AllItems { BRASS_INGOT = taggedIngredient("brass_ingot", forgeItemTag("ingots/brass"), CREATE_INGOTS.tag); public static final ItemEntry CHROMATIC_COMPOUND = - REGISTRATE.item("chromatic_compound", ChromaticCompoundItem::new) - .properties(p -> p.rarity(Rarity.UNCOMMON)) - .model(AssetLookup.existingItemModel()) - .onRegister(CreateRegistrate.itemColors(() -> ChromaticCompoundColor::new)) + REGISTRATE.item("chromatic_compound", ChromaticCompoundItem::new) + .properties(p -> p.rarity(Rarity.UNCOMMON)) + .model(AssetLookup.existingItemModel()) + .color(() -> ChromaticCompoundColor::new) .register(); public static final ItemEntry SHADOW_STEEL = REGISTRATE.item("shadow_steel", ShadowSteelItem::new) @@ -145,11 +149,11 @@ public class AllItems { COPPER_SHEET = taggedIngredient("copper_sheet", forgeItemTag("plates/copper"), PLATES.tag), BRASS_SHEET = taggedIngredient("brass_sheet", forgeItemTag("plates/brass"), PLATES.tag), IRON_SHEET = taggedIngredient("iron_sheet", forgeItemTag("plates/iron"), PLATES.tag), - GOLDEN_SHEET = taggedIngredient("golden_sheet", forgeItemTag("plates/gold"), PLATES.tag), + GOLDEN_SHEET = taggedIngredient("golden_sheet", forgeItemTag("plates/gold"), PLATES.tag, ItemTags.PIGLIN_LOVED), LAPIS_SHEET = taggedIngredient("lapis_sheet", forgeItemTag("plates/lapis_lazuli"), PLATES.tag), CRUSHED_IRON = taggedIngredient("crushed_iron_ore", CRUSHED_ORES.tag), - CRUSHED_GOLD = taggedIngredient("crushed_gold_ore", CRUSHED_ORES.tag), + CRUSHED_GOLD = taggedIngredient("crushed_gold_ore", CRUSHED_ORES.tag, ItemTags.PIGLIN_LOVED), CRUSHED_COPPER = taggedIngredient("crushed_copper_ore", CRUSHED_ORES.tag), CRUSHED_ZINC = taggedIngredient("crushed_zinc_ore", CRUSHED_ORES.tag), CRUSHED_BRASS = taggedIngredient("crushed_brass", CRUSHED_ORES.tag); @@ -183,25 +187,29 @@ public class AllItems { public static final ItemEntry GOGGLES = REGISTRATE.item("goggles", GogglesItem::new) .properties(p -> p.maxStackSize(1)) - .onRegister(CreateRegistrate.itemModel(() -> GogglesModel::new)) - .lang("Engineer's Goggles") - .register(); - - public static final ItemEntry SUPER_GLUE = REGISTRATE.item("super_glue", SuperGlueItem::new) - .register(); - - public static final ItemEntry MINECART_COUPLING = - REGISTRATE.item("minecart_coupling", MinecartCouplingItem::new) + .onRegister(CreateRegistrate.itemModel(() -> GogglesModel::new)) + .lang("Engineer's Goggles") .register(); + public static final ItemEntry SUPER_GLUE = REGISTRATE.item("super_glue", SuperGlueItem::new) + .register(); + + public static final ItemEntry MINECART_COUPLING = + REGISTRATE.item("minecart_coupling", MinecartCouplingItem::new) + .register(); + + public static final ItemEntry CRAFTING_BLUEPRINT = + REGISTRATE.item("crafting_blueprint", BlueprintItem::new) + .register(); + public static final ItemEntry SAND_PAPER = REGISTRATE.item("sand_paper", SandPaperItem::new) - .transform(CreateRegistrate.customRenderedItem(() -> SandPaperModel::new)) - .register(); + .transform(CreateRegistrate.customRenderedItem(() -> SandPaperModel::new)) + .register(); public static final ItemEntry RED_SAND_PAPER = REGISTRATE.item("red_sand_paper", SandPaperItem::new) - .transform(CreateRegistrate.customRenderedItem(() -> SandPaperModel::new)) - .onRegister(s -> TooltipHelper.referTo(s, SAND_PAPER)) - .register(); + .transform(CreateRegistrate.customRenderedItem(() -> SandPaperModel::new)) + .onRegister(s -> TooltipHelper.referTo(s, SAND_PAPER)) + .register(); public static final ItemEntry WRENCH = REGISTRATE.item("wrench", WrenchItem::new) .properties(p -> p.maxStackSize(1)) @@ -214,6 +222,12 @@ public class AllItems { .model(AssetLookup.itemModelWithPartials()) .register(); + public static final ItemEntry LINKED_CONTROLLER = + REGISTRATE.item("linked_controller", LinkedControllerItem::new) + .transform(CreateRegistrate.customRenderedItem(() -> LinkedControllerModel::new)) + .model(AssetLookup.itemModelWithPartials()) + .register(); + public static final ItemEntry WAND_OF_SYMMETRY = REGISTRATE.item("wand_of_symmetry", SymmetryWandItem::new) .transform(CreateRegistrate.customRenderedItem(() -> SymmetryWandModel::new)) diff --git a/src/main/java/com/simibubi/create/AllKeys.java b/src/main/java/com/simibubi/create/AllKeys.java index d997811b2..3877f1026 100644 --- a/src/main/java/com/simibubi/create/AllKeys.java +++ b/src/main/java/com/simibubi/create/AllKeys.java @@ -9,7 +9,8 @@ import net.minecraftforge.fml.client.registry.ClientRegistry; public enum AllKeys { - TOOL_MENU("toolmenu", GLFW.GLFW_KEY_LEFT_ALT), ACTIVATE_TOOL("", GLFW.GLFW_KEY_LEFT_CONTROL), + TOOL_MENU("toolmenu", GLFW.GLFW_KEY_LEFT_ALT), + ACTIVATE_TOOL("", GLFW.GLFW_KEY_LEFT_CONTROL), ; diff --git a/src/main/java/com/simibubi/create/AllMovementBehaviours.java b/src/main/java/com/simibubi/create/AllMovementBehaviours.java index 0d306ddaf..ece2e1f65 100644 --- a/src/main/java/com/simibubi/create/AllMovementBehaviours.java +++ b/src/main/java/com/simibubi/create/AllMovementBehaviours.java @@ -17,12 +17,12 @@ import net.minecraft.block.Blocks; import net.minecraft.util.ResourceLocation; public class AllMovementBehaviours { - private static final HashMap movementBehaviours = new HashMap<>(); + private static final HashMap MOVEMENT_BEHAVIOURS = new HashMap<>(); public static void addMovementBehaviour(ResourceLocation resourceLocation, MovementBehaviour movementBehaviour) { - if (movementBehaviours.containsKey(resourceLocation)) - Create.logger.warn("Movement behaviour for " + resourceLocation.toString() + " was overridden"); - movementBehaviours.put(resourceLocation, movementBehaviour); + if (MOVEMENT_BEHAVIOURS.containsKey(resourceLocation)) + Create.LOGGER.warn("Movement behaviour for " + resourceLocation.toString() + " was overridden"); + MOVEMENT_BEHAVIOURS.put(resourceLocation, movementBehaviour); } public static void addMovementBehaviour(Block block, MovementBehaviour movementBehaviour) { @@ -31,7 +31,7 @@ public class AllMovementBehaviours { @Nullable public static MovementBehaviour of(ResourceLocation resourceLocation) { - return movementBehaviours.getOrDefault(resourceLocation, null); + return MOVEMENT_BEHAVIOURS.getOrDefault(resourceLocation, null); } @Nullable @@ -45,7 +45,7 @@ public class AllMovementBehaviours { } public static boolean contains(Block block) { - return movementBehaviours.containsKey(block.getRegistryName()); + return MOVEMENT_BEHAVIOURS.containsKey(block.getRegistryName()); } public static NonNullConsumer addMovementBehaviour( diff --git a/src/main/java/com/simibubi/create/AllSoundEvents.java b/src/main/java/com/simibubi/create/AllSoundEvents.java index bec9744d2..dc2b0f0c0 100644 --- a/src/main/java/com/simibubi/create/AllSoundEvents.java +++ b/src/main/java/com/simibubi/create/AllSoundEvents.java @@ -152,12 +152,37 @@ public class AllSoundEvents { .playExisting(SoundEvents.ITEM_ARMOR_EQUIP_GOLD, 1f, 1f) .category(SoundCategory.PLAYERS) .build(), - + AUTO_POLISH = create("deployer_polish").subtitle("Deployer applies polish") .playExisting(SoundEvents.UI_STONECUTTER_TAKE_RESULT, 1f, 1f) .category(SoundCategory.BLOCKS) .build(), + CONTROLLER_CLICK = create("controller_click").subtitle("Controller clicks") + .playExisting(SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, .35f, 1f) + .category(SoundCategory.BLOCKS) + .build(), + + SAW_ACTIVATE_WOOD = create("saw_activate_wood").subtitle("Mechanical Saw activates") + .playExisting(SoundEvents.ENTITY_BOAT_PADDLE_LAND, .75f, 1.5f) + .category(SoundCategory.BLOCKS) + .build(), + + SAW_ACTIVATE_STONE = create("saw_activate_stone").subtitle("Mechanical Saw activates") + .playExisting(SoundEvents.UI_STONECUTTER_TAKE_RESULT, .125f, 1.25f) + .category(SoundCategory.BLOCKS) + .build(), + + SAW_PROCESS = create("saw_process").subtitle("Mechanical Saw processes") + .playExisting(SoundEvents.BLOCK_SAND_PLACE, .075f, .75f) + .category(SoundCategory.BLOCKS) + .build(), + + SAW_IDLE = create("saw_idle").subtitle("Mechanical Saw turns") + .playExisting(SoundEvents.ENTITY_BOAT_PADDLE_LAND) + .category(SoundCategory.BLOCKS) + .build(), + BLAZE_MUNCH = create("blaze_munch").subtitle("Blaze Burner munches") .playExisting(SoundEvents.ENTITY_GENERIC_EAT, .5f, 1f) .category(SoundCategory.BLOCKS) @@ -172,7 +197,7 @@ public class AllSoundEvents { for (SoundEntry entry : entries.values()) entry.register(registry); } - + public static void prepare() { for (SoundEntry entry : entries.values()) entry.prepare(); @@ -363,7 +388,7 @@ public class AllSoundEvents { this.wrappedEvents = wrappedEvents; compiledEvents = Lists.newArrayList(); } - + @Override public void prepare() { for (int i = 0; i < wrappedEvents.size(); i++) { @@ -376,7 +401,7 @@ public class AllSoundEvents { @Override public void register(IForgeRegistry registry) { - for (Pair> pair : compiledEvents) + for (Pair> pair : compiledEvents) registry.register(pair.getFirst()); } @@ -435,7 +460,7 @@ public class AllSoundEvents { public CustomSoundEntry(String id, String subtitle, SoundCategory category) { super(id, subtitle, category); } - + @Override public void prepare() { ResourceLocation location = getLocation(); diff --git a/src/main/java/com/simibubi/create/AllSpecialTextures.java b/src/main/java/com/simibubi/create/AllSpecialTextures.java index d3b95fe85..786dde9be 100644 --- a/src/main/java/com/simibubi/create/AllSpecialTextures.java +++ b/src/main/java/com/simibubi/create/AllSpecialTextures.java @@ -2,10 +2,7 @@ package com.simibubi.create; import net.minecraft.client.Minecraft; import net.minecraft.util.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -@EventBusSubscriber(value = Dist.CLIENT) public enum AllSpecialTextures { BLANK("blank.png"), diff --git a/src/main/java/com/simibubi/create/AllSpriteShifts.java b/src/main/java/com/simibubi/create/AllSpriteShifts.java index 224d852a7..e2c943f9f 100644 --- a/src/main/java/com/simibubi/create/AllSpriteShifts.java +++ b/src/main/java/com/simibubi/create/AllSpriteShifts.java @@ -5,11 +5,12 @@ import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTT import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType.OMNIDIRECTIONAL; import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType.VERTICAL; +import java.util.Arrays; import java.util.IdentityHashMap; import java.util.Map; -import com.simibubi.create.content.palettes.PaletteBlockPatterns; -import com.simibubi.create.content.palettes.PaletteBlockPatterns.CTs; +import com.simibubi.create.content.palettes.PaletteBlockPattern; +import com.simibubi.create.content.palettes.PaletteBlockPattern.CTs; import com.simibubi.create.content.palettes.PaletteStoneVariants; import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry; import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType; @@ -23,7 +24,7 @@ import net.minecraft.item.DyeColor; public class AllSpriteShifts { static final Map WOODEN_WINDOWS = new IdentityHashMap<>(); - static final Map> PALETTE_VARIANT_PATTERNS = + static final Map> PALETTE_VARIANT_PATTERNS = new IdentityHashMap<>(); public static final Map DYED_BELTS = new IdentityHashMap<>(), @@ -69,7 +70,7 @@ public class AllSpriteShifts { return WOODEN_WINDOWS.get(woodType); } - public static CTSpriteShiftEntry getVariantPattern(PaletteStoneVariants variant, PaletteBlockPatterns.CTs texture) { + public static CTSpriteShiftEntry getVariantPattern(PaletteStoneVariants variant, PaletteBlockPattern.CTs texture) { return PALETTE_VARIANT_PATTERNS.get(variant) .get(texture); } @@ -77,7 +78,11 @@ public class AllSpriteShifts { // private static void populateMaps() { - WoodType.stream() + WoodType[] supportedWoodTypes = new WoodType[]{ + WoodType.OAK, WoodType.SPRUCE, WoodType.BIRCH, WoodType.ACACIA, WoodType.JUNGLE, WoodType.DARK_OAK, + WoodType.CRIMSON, WoodType.WARPED + }; + Arrays.stream(supportedWoodTypes) .forEach(woodType -> WOODEN_WINDOWS.put(woodType, vertical("palettes/" + woodType.getName() + "_window"))); for (PaletteStoneVariants paletteStoneVariants : PaletteStoneVariants.values()) { @@ -85,7 +90,7 @@ public class AllSpriteShifts { IdentityHashMap map = new IdentityHashMap<>(); PALETTE_VARIANT_PATTERNS.put(paletteStoneVariants, map); - for (PaletteBlockPatterns.CTs texture : PaletteBlockPatterns.CTs.values()) { + for (PaletteBlockPattern.CTs texture : PaletteBlockPattern.CTs.values()) { String textureName = Lang.asId(texture.name()); String target = "palettes/" + variantName + "/" + textureName; map.put(texture, getCT(texture.type, target)); diff --git a/src/main/java/com/simibubi/create/AllStitchedTextures.java b/src/main/java/com/simibubi/create/AllStitchedTextures.java new file mode 100644 index 000000000..30482c457 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllStitchedTextures.java @@ -0,0 +1,15 @@ +package com.simibubi.create; + +import com.jozufozu.flywheel.core.AtlasStitcher; +import com.jozufozu.flywheel.core.StitchedSprite; + +import net.minecraft.util.ResourceLocation; + +public class AllStitchedTextures { + + public static final StitchedSprite SUPER_GLUE = AtlasStitcher.getInstance().get(new ResourceLocation(Create.ID, "entity/super_glue/slime")); + + public static void init() { + + } +} diff --git a/src/main/java/com/simibubi/create/AllTags.java b/src/main/java/com/simibubi/create/AllTags.java index b42cdf120..e8a93844b 100644 --- a/src/main/java/com/simibubi/create/AllTags.java +++ b/src/main/java/com/simibubi/create/AllTags.java @@ -31,7 +31,7 @@ import net.minecraftforge.fml.ModList; public class AllTags { private static final CreateRegistrate REGISTRATE = Create.registrate() - .itemGroup(() -> Create.baseCreativeTab); + .itemGroup(() -> Create.BASE_CREATIVE_TAB); public static NonNullFunction, ItemBuilder>> tagBlockAndItem( String tagName) { @@ -146,7 +146,6 @@ public class AllTags { WINDMILL_SAILS, FAN_HEATERS, WINDOWABLE, - NON_MOVABLE, BRITTLE, SEATS, SAILS, @@ -179,6 +178,7 @@ public class AllTags { } } + public boolean matches(BlockState block) { return tag.contains(block.getBlock()); } @@ -209,6 +209,7 @@ public class AllTags { AllBlockTags.WINDMILL_SAILS.includeAll(BlockTags.WOOL); AllBlockTags.BRITTLE.includeAll(BlockTags.DOORS); + AllBlockTags.BRITTLE.includeAll(BlockTags.BEDS); AllBlockTags.BRITTLE.add(Blocks.FLOWER_POT, Blocks.BELL, Blocks.COCOA); AllBlockTags.FAN_TRANSPARENT.includeAll(BlockTags.FENCES); diff --git a/src/main/java/com/simibubi/create/AllTileEntities.java b/src/main/java/com/simibubi/create/AllTileEntities.java index 329786289..e0455c9c2 100644 --- a/src/main/java/com/simibubi/create/AllTileEntities.java +++ b/src/main/java/com/simibubi/create/AllTileEntities.java @@ -119,6 +119,8 @@ import com.simibubi.create.content.contraptions.relays.gearbox.GearshiftTileEnti import com.simibubi.create.content.curiosities.armor.CopperBacktankInstance; import com.simibubi.create.content.curiosities.armor.CopperBacktankRenderer; import com.simibubi.create.content.curiosities.armor.CopperBacktankTileEntity; +import com.simibubi.create.content.curiosities.projector.ChromaticProjectorInstance; +import com.simibubi.create.content.curiosities.projector.ChromaticProjectorTileEntity; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelInstance; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelRenderer; import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity; @@ -157,7 +159,6 @@ import com.simibubi.create.content.schematics.block.SchematicannonInstance; import com.simibubi.create.content.schematics.block.SchematicannonRenderer; import com.simibubi.create.content.schematics.block.SchematicannonTileEntity; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; -import com.tterrag.registrate.util.entry.BlockEntry; import com.tterrag.registrate.util.entry.TileEntityEntry; public class AllTileEntities { @@ -246,10 +247,10 @@ public class AllTileEntities { .register(); public static final TileEntityEntry HAND_CRANK = Create.registrate() - .tileEntity("hand_crank", HandCrankTileEntity::new) - .instance(() -> HandCrankInstance::new) - .validBlocks(AllBlocks.HAND_CRANK, AllBlocks.COPPER_VALVE_HANDLE) - .validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray(new BlockEntry[AllBlocks.DYED_VALVE_HANDLES.size()])) + .tileEntity("hand_crank", HandCrankTileEntity::new) + .instance(() -> HandCrankInstance::new) + .validBlocks(AllBlocks.HAND_CRANK, AllBlocks.COPPER_VALVE_HANDLE) + .validBlocks(AllBlocks.DYED_VALVE_HANDLES.toArray()) .renderer(() -> HandCrankRenderer::new) .register(); @@ -657,7 +658,6 @@ public class AllTileEntities { .validBlocks(AllBlocks.ADJUSTABLE_PULSE_REPEATER) .renderer(() -> AdjustableRepeaterRenderer::new) .register(); - public static final TileEntityEntry COPPER_BACKTANK = Create.registrate() .tileEntity("copper_backtank", CopperBacktankTileEntity::new) .instance(() -> CopperBacktankInstance::new) diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java index c62a11acb..d86dea882 100644 --- a/src/main/java/com/simibubi/create/Create.java +++ b/src/main/java/com/simibubi/create/Create.java @@ -31,7 +31,6 @@ import com.simibubi.create.foundation.worldgen.AllWorldFeatures; import com.tterrag.registrate.util.NonNullLazyValue; import net.minecraft.data.DataGenerator; -import net.minecraft.inventory.container.ContainerType; import net.minecraft.item.ItemGroup; import net.minecraft.item.crafting.IRecipeSerializer; import net.minecraft.particles.ParticleType; @@ -55,54 +54,54 @@ public class Create { public static final String ID = "create"; public static final String NAME = "Create"; - public static final String VERSION = "0.3.1c"; + public static final String VERSION = "0.3.2"; - public static Logger logger = LogManager.getLogger(); - public static ItemGroup baseCreativeTab = new CreateItemGroup(); - public static ItemGroup palettesCreativeTab = new PalettesItemGroup(); + public static final Logger LOGGER = LogManager.getLogger(); - public static Gson GSON = new GsonBuilder().setPrettyPrinting() - .disableHtmlEscaping() - .create(); + public static final Gson GSON = new GsonBuilder().setPrettyPrinting() + .disableHtmlEscaping() + .create(); - public static ServerSchematicLoader schematicReceiver; - public static RedstoneLinkNetworkHandler redstoneLinkNetworkHandler; - public static TorquePropagator torquePropagator; - public static ServerLagger lagger; - public static ChunkUtil chunkUtil; - public static Random random; + public static final ItemGroup BASE_CREATIVE_TAB = new CreateItemGroup(); + public static final ItemGroup PALETTES_CREATIVE_TAB = new PalettesItemGroup(); - private static final NonNullLazyValue registrate = CreateRegistrate.lazy(ID); + public static final ServerSchematicLoader SCHEMATIC_RECEIVER = new ServerSchematicLoader(); + public static final RedstoneLinkNetworkHandler REDSTONE_LINK_NETWORK_HANDLER = new RedstoneLinkNetworkHandler(); + public static final TorquePropagator TORQUE_PROPAGATOR = new TorquePropagator(); + public static final ServerLagger LAGGER = new ServerLagger(); + public static final ChunkUtil CHUNK_UTIL = new ChunkUtil(); + public static final Random RANDOM = new Random(); + + private static final NonNullLazyValue REGISTRATE = CreateRegistrate.lazy(ID); public Create() { - IEventBus modEventBus = FMLJavaModLoadingContext.get() - .getModEventBus(); - AllSoundEvents.prepare(); AllBlocks.register(); AllItems.register(); AllFluids.register(); AllTags.register(); AllPaletteBlocks.register(); + AllContainerTypes.register(); AllEntityTypes.register(); AllTileEntities.register(); AllMovementBehaviours.register(); AllWorldFeatures.register(); + AllConfigs.register(); + + IEventBus modEventBus = FMLJavaModLoadingContext.get() + .getModEventBus(); + IEventBus forgeEventBus = MinecraftForge.EVENT_BUS; modEventBus.addListener(Create::init); - MinecraftForge.EVENT_BUS.addListener(EventPriority.HIGH, Create::onBiomeLoad); modEventBus.addGenericListener(Feature.class, AllWorldFeatures::registerOreFeatures); modEventBus.addGenericListener(Placement.class, AllWorldFeatures::registerDecoratorFeatures); modEventBus.addGenericListener(IRecipeSerializer.class, AllRecipeTypes::register); - modEventBus.addGenericListener(ContainerType.class, AllContainerTypes::register); modEventBus.addGenericListener(ParticleType.class, AllParticleTypes::register); modEventBus.addGenericListener(SoundEvent.class, AllSoundEvents::register); modEventBus.addListener(AllConfigs::onLoad); modEventBus.addListener(AllConfigs::onReload); modEventBus.addListener(EventPriority.LOWEST, this::gatherData); - - AllConfigs.register(); - random = new Random(); + forgeEventBus.addListener(EventPriority.HIGH, Create::onBiomeLoad); DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> CreateClient.addClientListeners(modEventBus)); } @@ -110,14 +109,9 @@ public class Create { public static void init(final FMLCommonSetupEvent event) { CapabilityMinecartController.register(); SchematicInstances.register(); - schematicReceiver = new ServerSchematicLoader(); - redstoneLinkNetworkHandler = new RedstoneLinkNetworkHandler(); - torquePropagator = new TorquePropagator(); - lagger = new ServerLagger(); - chunkUtil = new ChunkUtil(); - chunkUtil.init(); - MinecraftForge.EVENT_BUS.register(chunkUtil); + CHUNK_UTIL.init(); + MinecraftForge.EVENT_BUS.register(CHUNK_UTIL); AllPackets.registerPackets(); AllTriggers.register(); @@ -128,18 +122,6 @@ public class Create { }); } - public static void onBiomeLoad(BiomeLoadingEvent event) { - AllWorldFeatures.reload(event); - } - - public static CreateRegistrate registrate() { - return registrate.get(); - } - - public static ResourceLocation asResource(String path) { - return new ResourceLocation(ID, path); - } - public void gatherData(GatherDataEvent event) { DataGenerator gen = event.getGenerator(); gen.addProvider(new AllAdvancements(gen)); @@ -150,4 +132,16 @@ public class Create { ProcessingRecipeGen.registerAll(gen); } + public static void onBiomeLoad(BiomeLoadingEvent event) { + AllWorldFeatures.reload(event); + } + + public static CreateRegistrate registrate() { + return REGISTRATE.get(); + } + + public static ResourceLocation asResource(String path) { + return new ResourceLocation(ID, path); + } + } diff --git a/src/main/java/com/simibubi/create/CreateClient.java b/src/main/java/com/simibubi/create/CreateClient.java index 635998c39..f0b2f45ee 100644 --- a/src/main/java/com/simibubi/create/CreateClient.java +++ b/src/main/java/com/simibubi/create/CreateClient.java @@ -5,8 +5,9 @@ import java.util.List; import java.util.Map; import java.util.function.Function; -import javax.annotation.Nullable; - +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.AtlasStitcher; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; @@ -20,18 +21,11 @@ import com.simibubi.create.foundation.block.render.CustomBlockModels; import com.simibubi.create.foundation.block.render.SpriteShifter; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.UIRenderHelper; -import com.simibubi.create.foundation.item.CustomItemModels; -import com.simibubi.create.foundation.item.CustomRenderedItems; +import com.simibubi.create.foundation.item.render.CustomItemModels; +import com.simibubi.create.foundation.item.render.CustomRenderedItems; import com.simibubi.create.foundation.ponder.content.PonderIndex; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; -import com.simibubi.create.foundation.render.AllProgramSpecs; -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.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.utility.WorldAttached; import com.simibubi.create.foundation.utility.ghost.GhostBlocks; import com.simibubi.create.foundation.utility.outliner.Outliner; @@ -53,7 +47,6 @@ import net.minecraft.util.text.TextComponentUtils; import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.HoverEvent; -import net.minecraft.world.IWorld; import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.event.TextureStitchEvent; @@ -63,66 +56,47 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; public class CreateClient { - public static ClientSchematicLoader schematicSender; - public static SchematicHandler schematicHandler; - public static SchematicAndQuillHandler schematicAndQuillHandler; - public static SuperByteBufferCache bufferCache; - public static WorldAttached kineticRenderer; - public static final Outliner outliner = new Outliner(); - public static GhostBlocks ghostBlocks; + public static final ClientSchematicLoader SCHEMATIC_SENDER = new ClientSchematicLoader(); + public static final SchematicHandler SCHEMATIC_HANDLER = new SchematicHandler(); + public static final SchematicAndQuillHandler SCHEMATIC_AND_QUILL_HANDLER = new SchematicAndQuillHandler(); + public static final SuperByteBufferCache BUFFER_CACHE = new SuperByteBufferCache(); + public static final Outliner OUTLINER = new Outliner(); + public static final GhostBlocks GHOST_BLOCKS = new GhostBlocks(); private static CustomBlockModels customBlockModels; private static CustomItemModels customItemModels; private static CustomRenderedItems customRenderedItems; - private static AllColorHandlers colorHandlers; private static CasingConnectivity casingConnectivity; public static void addClientListeners(IEventBus modEventBus) { modEventBus.addListener(CreateClient::clientInit); - modEventBus.addListener(CreateClient::onModelBake); - modEventBus.addListener(CreateClient::onModelRegistry); modEventBus.addListener(CreateClient::onTextureStitch); + modEventBus.addListener(CreateClient::onModelRegistry); + modEventBus.addListener(CreateClient::onModelBake); modEventBus.addListener(AllParticleTypes::registerFactories); modEventBus.addListener(ClientEvents::loadCompleted); - - Backend.init(); - OptifineHandler.init(); } public static void clientInit(FMLClientSetupEvent event) { - AllProgramSpecs.init(); - kineticRenderer = new WorldAttached<>(KineticRenderer::new); - - schematicSender = new ClientSchematicLoader(); - schematicHandler = new SchematicHandler(); - schematicAndQuillHandler = new SchematicAndQuillHandler(); - - bufferCache = new SuperByteBufferCache(); - bufferCache.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); - bufferCache.registerCompartment(ContraptionRenderDispatcher.CONTRAPTION, 20); - bufferCache.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20); - - ghostBlocks = new GhostBlocks(); + BUFFER_CACHE.registerCompartment(KineticTileEntityRenderer.KINETIC_TILE); + BUFFER_CACHE.registerCompartment(ContraptionRenderDispatcher.CONTRAPTION, 20); + BUFFER_CACHE.registerCompartment(WorldSectionElement.DOC_WORLD_SECTION, 20); AllKeys.register(); - AllContainerTypes.registerScreenFactories(); - // AllTileEntities.registerRenderers(); - AllEntityTypes.registerRenderers(); - getColorHandler().init(); - AllFluids.assignRenderLayers(); + // AllFluids.assignRenderLayers(); + AllBlockPartials.clientInit(); + AllStitchedTextures.init(); + PonderIndex.register(); PonderIndex.registerTags(); UIRenderHelper.init(); - UIRenderHelper.enableStencil(); IResourceManager resourceManager = Minecraft.getInstance() - .getResourceManager(); + .getResourceManager(); if (resourceManager instanceof IReloadableResourceManager) ((IReloadableResourceManager) resourceManager).addReloadListener(new ResourceReloadHandler()); - AllBlockPartials.clientInit(); - event.enqueueWork(() -> { CopperBacktankArmorLayer.register(); }); @@ -130,11 +104,19 @@ public class CreateClient { public static void onTextureStitch(TextureStitchEvent.Pre event) { if (!event.getMap() - .getId() - .equals(PlayerContainer.BLOCK_ATLAS_TEXTURE)) + .getId() + .equals(PlayerContainer.BLOCK_ATLAS_TEXTURE)) return; SpriteShifter.getAllTargetSprites() - .forEach(event::addSprite); + .forEach(event::addSprite); + } + + public static void onModelRegistry(ModelRegistryEvent event) { + PartialModel.onModelRegistry(event); + + getCustomRenderedItems().foreach((item, modelFunc) -> modelFunc.apply(null) + .getModelLocations() + .forEach(ModelLoader::addSpecialModel)); } public static void onModelBake(ModelBakeEvent event) { @@ -142,23 +124,15 @@ public class CreateClient { PartialModel.onModelBake(event); getCustomBlockModels() - .foreach((block, modelFunc) -> swapModels(modelRegistry, getAllBlockStateModelLocations(block), modelFunc)); + .foreach((block, modelFunc) -> swapModels(modelRegistry, getAllBlockStateModelLocations(block), modelFunc)); getCustomItemModels() - .foreach((item, modelFunc) -> swapModels(modelRegistry, getItemModelLocation(item), modelFunc)); + .foreach((item, modelFunc) -> swapModels(modelRegistry, getItemModelLocation(item), modelFunc)); getCustomRenderedItems().foreach((item, modelFunc) -> { swapModels(modelRegistry, getItemModelLocation(item), m -> modelFunc.apply(m) .loadPartials(event)); }); } - public static void onModelRegistry(ModelRegistryEvent event) { - PartialModel.onModelRegistry(event); - - getCustomRenderedItems().foreach((item, modelFunc) -> modelFunc.apply(null) - .getModelLocations() - .forEach(ModelLoader::addSpecialModel)); - } - protected static ModelResourceLocation getItemModelLocation(Item item) { return new ModelResourceLocation(item.getRegistryName(), "inventory"); } @@ -207,12 +181,6 @@ public class CreateClient { return customBlockModels; } - public static AllColorHandlers getColorHandler() { - if (colorHandlers == null) - colorHandlers = new AllColorHandlers(); - return colorHandlers; - } - public static CasingConnectivity getCasingConnectivity() { if (casingConnectivity == null) casingConnectivity = new CasingConnectivity(); @@ -220,18 +188,7 @@ public class CreateClient { } public static void invalidateRenderers() { - invalidateRenderers(null); - } - - public static void invalidateRenderers(@Nullable IWorld world) { - bufferCache.invalidate(); - - if (world != null) { - kineticRenderer.get(world) - .invalidate(); - } else { - kineticRenderer.forEach(InstancedTileRenderer::invalidate); - } + BUFFER_CACHE.invalidate(); ContraptionRenderDispatcher.invalidateAll(); } diff --git a/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java b/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java new file mode 100644 index 000000000..d4d4facd0 --- /dev/null +++ b/src/main/java/com/simibubi/create/compat/jei/BlueprintTransferHandler.java @@ -0,0 +1,33 @@ +package com.simibubi.create.compat.jei; + +import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket; +import com.simibubi.create.content.curiosities.tools.BlueprintContainer; +import com.simibubi.create.foundation.networking.AllPackets; + +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.recipe.transfer.IRecipeTransferError; +import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.crafting.IRecipe; + +public class BlueprintTransferHandler implements IRecipeTransferHandler { + + @Override + public Class getContainerClass() { + return BlueprintContainer.class; + } + + @Override + public IRecipeTransferError transferRecipe(BlueprintContainer container, Object recipe, IRecipeLayout recipeLayout, + PlayerEntity player, boolean maxTransfer, boolean doTransfer) { + if (!(recipe instanceof IRecipe)) + return null; + if (!doTransfer) + return null; + IRecipe iRecipe = (IRecipe) recipe; + // Continued server-side in BlueprintItem.assignCompleteRecipe() + AllPackets.channel.sendToServer(new BlueprintAssignCompleteRecipePacket(iRecipe.getId())); + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index 5d545b40f..9e34f5f0f 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -1,8 +1,8 @@ package com.simibubi.create.compat.jei; import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -39,7 +39,9 @@ import com.simibubi.create.content.contraptions.components.press.MechanicalPress import com.simibubi.create.content.contraptions.components.saw.SawTileEntity; import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipeManager; import com.simibubi.create.content.contraptions.processing.BasinRecipe; +import com.simibubi.create.content.curiosities.tools.BlueprintScreen; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateScreen; +import com.simibubi.create.content.logistics.item.LinkedControllerScreen; import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen; import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen; import com.simibubi.create.content.logistics.item.filter.FilterScreen; @@ -51,10 +53,12 @@ import com.simibubi.create.foundation.config.ConfigBase.ConfigBool; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; +import mezz.jei.api.constants.VanillaRecipeCategoryUid; import mezz.jei.api.registration.IGuiHandlerRegistration; import mezz.jei.api.registration.IRecipeCatalystRegistration; import mezz.jei.api.registration.IRecipeCategoryRegistration; import mezz.jei.api.registration.IRecipeRegistration; +import mezz.jei.api.registration.IRecipeTransferRegistration; import mezz.jei.api.runtime.IIngredientManager; import net.minecraft.client.Minecraft; import net.minecraft.item.ItemStack; @@ -81,19 +85,19 @@ public class CreateJEI implements IModPlugin { } public IIngredientManager ingredientManager; - final List> ALL = new ArrayList<>(); - final CreateRecipeCategory + private final List> allCategories = new ArrayList<>(); + private final CreateRecipeCategory - milling = register("milling", MillingCategory::new).recipes(AllRecipeTypes.MILLING) - .catalyst(AllBlocks.MILLSTONE::get) - .build(), + milling = register("milling", MillingCategory::new).recipes(AllRecipeTypes.MILLING) + .catalyst(AllBlocks.MILLSTONE::get) + .build(), - crushing = register("crushing", CrushingCategory::new).recipes(AllRecipeTypes.CRUSHING) + crushing = register("crushing", CrushingCategory::new).recipes(AllRecipeTypes.CRUSHING) .recipesExcluding(AllRecipeTypes.MILLING::getType, AllRecipeTypes.CRUSHING::getType) .catalyst(AllBlocks.CRUSHING_WHEEL::get) .build(), - pressing = register("pressing", PressingCategory::new).recipes(AllRecipeTypes.PRESSING) + pressing = register("pressing", PressingCategory::new).recipes(AllRecipeTypes.PRESSING) .catalyst(AllBlocks.MECHANICAL_PRESS::get) .build(), @@ -106,7 +110,9 @@ public class CreateJEI implements IModPlugin { .build(), blasting = register("fan_blasting", FanBlastingCategory::new) - .recipesExcluding(() -> IRecipeType.SMELTING, () -> IRecipeType.SMOKING) + .recipesExcluding(() -> IRecipeType.SMELTING, () -> IRecipeType.BLASTING) + .recipes(() -> IRecipeType.BLASTING) + .removeRecipes(() -> IRecipeType.SMOKING) .catalystStack(ProcessingViaFanCategory.getFan("fan_blasting")) .build(), @@ -165,9 +171,10 @@ public class CreateJEI implements IModPlugin { .catalyst(AllItems.SAND_PAPER::get) .catalyst(AllItems.RED_SAND_PAPER::get) .build(), - + deploying = register("deploying", DeployingCategory::new) - .recipeList(() -> DeployerApplicationRecipe.convert(findRecipesByType(AllRecipeTypes.SANDPAPER_POLISHING.type))) + .recipeList( + () -> DeployerApplicationRecipe.convert(findRecipesByType(AllRecipeTypes.SANDPAPER_POLISHING.type))) .recipes(AllRecipeTypes.DEPLOYING) .catalyst(AllBlocks.DEPLOYER::get) .catalyst(AllBlocks.DEPOT::get) @@ -201,136 +208,152 @@ public class CreateJEI implements IModPlugin { mechanicalCrafting = register("mechanical_crafting", MechanicalCraftingCategory::new).recipes(AllRecipeTypes.MECHANICAL_CRAFTING) - .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) - .build() - - ; + .catalyst(AllBlocks.MECHANICAL_CRAFTER::get) + .build(); private > CategoryBuilder register(String name, - Supplier> supplier) { + Supplier> supplier) { return new CategoryBuilder(name, supplier); } + @Override + public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { + registration.addRecipeTransferHandler(new BlueprintTransferHandler(), VanillaRecipeCategoryUid.CRAFTING); + } + @Override public void registerCategories(IRecipeCategoryRegistration registration) { - ALL.forEach(registration::addRecipeCategories); + allCategories.forEach(registration::addRecipeCategories); } @Override public void registerRecipes(IRecipeRegistration registration) { ingredientManager = registration.getIngredientManager(); - ALL.forEach(c -> c.recipes.forEach(s -> registration.addRecipes(s.get(), c.getUid()))); + allCategories.forEach(c -> c.recipes.forEach(s -> registration.addRecipes(s.get(), c.getUid()))); } @Override public void registerRecipeCatalysts(IRecipeCatalystRegistration registration) { - ALL.forEach(c -> c.recipeCatalysts.forEach(s -> registration.addRecipeCatalyst(s.get(), c.getUid()))); + allCategories.forEach(c -> c.recipeCatalysts.forEach(s -> registration.addRecipeCatalyst(s.get(), c.getUid()))); } + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public void registerGuiHandlers(IGuiHandlerRegistration registration) { SlotMover slotMover = new SlotMover(); - registration.addGuiContainerHandler(AdjustableCrateScreen.class, slotMover); - registration.addGuiContainerHandler(SchematicannonScreen.class, slotMover); registration.addGuiContainerHandler(SchematicTableScreen.class, slotMover); + registration.addGuiContainerHandler(SchematicannonScreen.class, slotMover); + registration.addGuiContainerHandler(AdjustableCrateScreen.class, slotMover); registration.addGuiContainerHandler(FilterScreen.class, slotMover); registration.addGuiContainerHandler(AttributeFilterScreen.class, slotMover); - registration.addGhostIngredientHandler(AbstractFilterScreen.class, new FilterGhostIngredientHandler()); + registration.addGuiContainerHandler(BlueprintScreen.class, slotMover); + registration.addGuiContainerHandler(LinkedControllerScreen.class, slotMover); + + registration.addGhostIngredientHandler(AbstractFilterScreen.class, new GhostIngredientHandler()); + registration.addGhostIngredientHandler(BlueprintScreen.class, new GhostIngredientHandler()); } private class CategoryBuilder> { - CreateRecipeCategory category; + private CreateRecipeCategory category; + private List>>> recipeListConsumers = new ArrayList<>(); private Predicate pred; - CategoryBuilder(String name, Supplier> category) { + public CategoryBuilder(String name, Supplier> category) { this.category = category.get(); this.category.setCategoryId(name); - this.pred = Predicates.alwaysTrue(); + pred = Predicates.alwaysTrue(); } - CategoryBuilder catalyst(Supplier supplier) { - return catalystStack(() -> new ItemStack(supplier.get() - .asItem())); - } - - CategoryBuilder catalystStack(Supplier supplier) { - category.recipeCatalysts.add(supplier); - return this; - } - - CategoryBuilder recipes(AllRecipeTypes recipeTypeEntry) { + public CategoryBuilder recipes(AllRecipeTypes recipeTypeEntry) { return recipes(recipeTypeEntry::getType); } - CategoryBuilder recipes(Supplier> recipeType) { + public CategoryBuilder recipes(Supplier> recipeType) { return recipes(r -> r.getType() == recipeType.get()); } - CategoryBuilder recipes(ResourceLocation serializer) { + public CategoryBuilder recipes(ResourceLocation serializer) { return recipes(r -> r.getSerializer() .getRegistryName() .equals(serializer)); } - CategoryBuilder recipes(Predicate> pred) { + public CategoryBuilder recipes(Predicate> pred) { return recipeList(() -> findRecipes(pred)); } - CategoryBuilder recipes(Predicate> pred, Function, T> converter) { + public CategoryBuilder recipes(Predicate> pred, Function, T> converter) { return recipeList(() -> findRecipes(pred), converter); } - CategoryBuilder recipeList(Supplier>> list) { + public CategoryBuilder recipeList(Supplier>> list) { return recipeList(list, null); } - CategoryBuilder recipeList(Supplier>> list, Function, T> converter) { - category.recipes.add(() -> { - if (!this.pred.test(AllConfigs.SERVER.recipes)) - return Collections.emptyList(); + public CategoryBuilder recipeList(Supplier>> list, + Function, T> converter) { + recipeListConsumers.add(recipes -> { + List> toAdd = list.get(); if (converter != null) - return list.get() - .stream() - .map(converter) - .collect(Collectors.toList()); - return list.get(); + toAdd = toAdd.stream() + .map(converter) + .collect(Collectors.toList()); + recipes.addAll(toAdd); }); return this; } - CategoryBuilder recipesExcluding(Supplier> recipeType, + public CategoryBuilder recipesExcluding(Supplier> recipeType, Supplier> excluded) { - category.recipes.add(() -> { - if (!this.pred.test(AllConfigs.SERVER.recipes)) - return Collections.emptyList(); - return findRecipesByTypeExcluding(recipeType.get(), excluded.get()); + recipeListConsumers.add(recipes -> { + recipes.addAll(findRecipesByTypeExcluding(recipeType.get(), excluded.get())); }); return this; } - CategoryBuilder enableWhen(Function configValue) { - this.pred = c -> configValue.apply(c) + public CategoryBuilder removeRecipes(Supplier> recipeType) { + recipeListConsumers.add(recipes -> { + removeRecipesByType(recipes, recipeType.get()); + }); + return this; + } + + public CategoryBuilder catalyst(Supplier supplier) { + return catalystStack(() -> new ItemStack(supplier.get() + .asItem())); + } + + public CategoryBuilder catalystStack(Supplier supplier) { + category.recipeCatalysts.add(supplier); + return this; + } + + public CategoryBuilder enableWhen(Function configValue) { + pred = c -> configValue.apply(c) .get(); return this; } - CategoryBuilder enableWhenBool(Function configValue) { - this.pred = configValue::apply; + public CategoryBuilder enableWhenBool(Function configValue) { + pred = configValue::apply; return this; } - CreateRecipeCategory build() { - ALL.add(category); + public CreateRecipeCategory build() { + if (pred.test(AllConfigs.SERVER.recipes)) + category.recipes.add(() -> { + List> recipes = new ArrayList<>(); + for (Consumer>> consumer : recipeListConsumers) + consumer.accept(recipes); + return recipes; + }); + allCategories.add(category); return category; } } - static List> findRecipesByType(IRecipeType type) { - return findRecipes(r -> r.getType() == type); - } - - static List> findRecipes(Predicate> predicate) { + public static List> findRecipes(Predicate> predicate) { return Minecraft.getInstance().world.getRecipeManager() .getRecipes() .stream() @@ -338,24 +361,44 @@ public class CreateJEI implements IModPlugin { .collect(Collectors.toList()); } - static List> findRecipesByTypeExcluding(IRecipeType type, IRecipeType excludingType) { - List> byType = findRecipes(r -> r.getType() == type); - List> byExcludingType = findRecipes(r -> r.getType() == excludingType); - byType.removeIf(recipe -> { - for (IRecipe r : byExcludingType) { - ItemStack[] matchingStacks = recipe.getIngredients() - .get(0) - .getMatchingStacks(); - if (matchingStacks.length == 0) - return true; - if (r.getIngredients() - .get(0) - .test(matchingStacks[0])) - return true; - } - return false; - }); + public static List> findRecipesByType(IRecipeType type) { + return findRecipes(recipe -> recipe.getType() == type); + } + + public static List> findRecipesByTypeExcluding(IRecipeType type, IRecipeType excludingType) { + List> byType = findRecipesByType(type); + removeRecipesByType(byType, excludingType); return byType; } + public static List> findRecipesByTypeExcluding(IRecipeType type, IRecipeType... excludingTypes) { + List> byType = findRecipesByType(type); + for (IRecipeType excludingType : excludingTypes) + removeRecipesByType(byType, excludingType); + return byType; + } + + public static void removeRecipesByType(List> recipes, IRecipeType type) { + List> byType = findRecipesByType(type); + recipes.removeIf(recipe -> { + for (IRecipe r : byType) + if (doInputsMatch(recipe, r)) + return true; + return false; + }); + } + + public static boolean doInputsMatch(IRecipe recipe1, IRecipe recipe2) { + ItemStack[] matchingStacks = recipe1.getIngredients() + .get(0) + .getMatchingStacks(); + if (matchingStacks.length == 0) + return true; + if (recipe2.getIngredients() + .get(0) + .test(matchingStacks[0])) + return true; + return false; + } + } diff --git a/src/main/java/com/simibubi/create/compat/jei/FilterGhostIngredientHandler.java b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java similarity index 59% rename from src/main/java/com/simibubi/create/compat/jei/FilterGhostIngredientHandler.java rename to src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java index c5ee188cd..7a1644dda 100644 --- a/src/main/java/com/simibubi/create/compat/jei/FilterGhostIngredientHandler.java +++ b/src/main/java/com/simibubi/create/compat/jei/GhostIngredientHandler.java @@ -5,12 +5,10 @@ import java.util.List; import javax.annotation.ParametersAreNonnullByDefault; -import org.apache.logging.log4j.LogManager; - -import com.simibubi.create.content.logistics.item.filter.AbstractFilterContainer; -import com.simibubi.create.content.logistics.item.filter.AbstractFilterScreen; import com.simibubi.create.content.logistics.item.filter.AttributeFilterScreen; -import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; +import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.GhostItemContainer; +import com.simibubi.create.foundation.gui.GhostItemSubmitPacket; import com.simibubi.create.foundation.networking.AllPackets; import mcp.MethodsReturnNonnullByDefault; @@ -18,21 +16,20 @@ import mezz.jei.api.gui.handlers.IGhostIngredientHandler; import net.minecraft.client.renderer.Rectangle2d; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; @MethodsReturnNonnullByDefault @ParametersAreNonnullByDefault -public class FilterGhostIngredientHandler - implements IGhostIngredientHandler> { +public class GhostIngredientHandler> + implements IGhostIngredientHandler> { @Override - public List> getTargets(AbstractFilterScreen gui, I ingredient, boolean doStart) { + public List> getTargets(AbstractSimiContainerScreen gui, I ingredient, boolean doStart) { List> targets = new ArrayList<>(); boolean isAttributeFilter = gui instanceof AttributeFilterScreen; if (ingredient instanceof ItemStack) { for (int i = 36; i < gui.getContainer().inventorySlots.size(); i++) { - targets.add(new FilterGhostTarget<>(gui, i - 36, isAttributeFilter)); + targets.add(new GhostTarget<>(gui, i - 36, isAttributeFilter)); // Only accept items in 1st slot. 2nd is used for functionality, don't wanna override that one if (isAttributeFilter) @@ -44,7 +41,8 @@ public class FilterGhostIngredientHandler } @Override - public void onComplete() {} + public void onComplete() { + } @Override public boolean shouldHighlightTargets() { @@ -52,14 +50,14 @@ public class FilterGhostIngredientHandler return true; } - private static class FilterGhostTarget implements Target { + private static class GhostTarget> implements Target { private final Rectangle2d area; - private final AbstractFilterScreen gui; + private final AbstractSimiContainerScreen gui; private final int slotIndex; private final boolean isAttributeFilter; - public FilterGhostTarget(AbstractFilterScreen gui, int slotIndex, boolean isAttributeFilter) { + public GhostTarget(AbstractSimiContainerScreen gui, int slotIndex, boolean isAttributeFilter) { this.gui = gui; this.slotIndex = slotIndex; this.isAttributeFilter = isAttributeFilter; @@ -75,19 +73,14 @@ public class FilterGhostIngredientHandler @Override public void accept(I ingredient) { ItemStack stack = ((ItemStack) ingredient).copy(); - LogManager.getLogger() - .info(stack); stack.setCount(1); - gui.getContainer().filterInventory.setStackInSlot(slotIndex, stack); + gui.getContainer().ghostInventory.setStackInSlot(slotIndex, stack); if (isAttributeFilter) return; // sync new filter contents with server - CompoundNBT data = new CompoundNBT(); - data.putInt("Slot", slotIndex); - data.put("Item", stack.serializeNBT()); - AllPackets.channel.sendToServer(new FilterScreenPacket(FilterScreenPacket.Option.UPDATE_FILTER_ITEM, data)); + AllPackets.channel.sendToServer(new GhostItemSubmitPacket(stack, slotIndex)); } } } diff --git a/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java index 84543da40..55bfbdab2 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/CreateRecipeCategory.java @@ -31,13 +31,13 @@ import net.minecraftforge.fluids.FluidStack; public abstract class CreateRecipeCategory> implements IRecipeCategory { - public List> recipeCatalysts = new ArrayList<>(); - public List>>> recipes = new ArrayList<>(); - public ResourceLocation uid; + public final List>>> recipes = new ArrayList<>(); + public final List> recipeCatalysts = new ArrayList<>(); + protected ResourceLocation uid; protected String name; - private IDrawable icon; private IDrawable background; + private IDrawable icon; public CreateRecipeCategory(IDrawable icon, IDrawable background) { this.background = background; @@ -49,11 +49,6 @@ public abstract class CreateRecipeCategory> implements IRec this.name = name; } - @Override - public IDrawable getIcon() { - return icon; - } - @Override public ResourceLocation getUid() { return uid; @@ -70,6 +65,11 @@ public abstract class CreateRecipeCategory> implements IRec return background; } + @Override + public IDrawable getIcon() { + return icon; + } + protected static AllGuiTextures getRenderedSlot(IRecipe recipe, int index) { AllGuiTextures jeiSlot = AllGuiTextures.JEI_SLOT; if (!(recipe instanceof ProcessingRecipe)) diff --git a/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java index 2f03d2056..69b2292d8 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/ProcessingViaFanCategory.java @@ -21,7 +21,6 @@ import mezz.jei.api.ingredients.IIngredients; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.util.text.TextFormatting; public abstract class ProcessingViaFanCategory> extends CreateRecipeCategory { @@ -41,7 +40,7 @@ public abstract class ProcessingViaFanCategory> extends Cre public static Supplier getFan(String name) { return () -> AllBlocks.ENCASED_FAN.asStack() - .setDisplayName(Lang.translate("recipe." + name + ".fan").formatted(TextFormatting.RESET)); + .setDisplayName(Lang.translate("recipe." + name + ".fan").styled(style -> style.withItalic(false))); } @Override diff --git a/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java b/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java index 9bc30ce82..0c965b5c6 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/SpoutCategory.java @@ -12,6 +12,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.Create; import com.simibubi.create.compat.jei.category.animations.AnimatedSpout; import com.simibubi.create.content.contraptions.fluids.actors.FillingRecipe; +import com.simibubi.create.content.contraptions.fluids.actors.GenericItemFilling; import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder; import com.simibubi.create.foundation.fluid.FluidIngredient; @@ -71,6 +72,8 @@ public class SpoutCategory extends CreateRecipeCategory { ItemStack copy = stack.copy(); copy.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY) .ifPresent(fhi -> { + if (!GenericItemFilling.isFluidHandlerValid(copy, fhi)) + return; FluidStack fluidCopy = fluidStack.copy(); fluidCopy.setAmount(1000); fhi.fill(fluidCopy, FluidAction.EXECUTE); diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java index 920ab0bf3..8d448783d 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedBlazeBurner.java @@ -1,11 +1,11 @@ package com.simibubi.create.compat.jei.category.animations; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; import com.simibubi.create.foundation.gui.GuiGameElement; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import mezz.jei.api.gui.drawable.IDrawable; import net.minecraft.util.math.vector.Vector3f; diff --git a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java index 0459efd33..263add564 100644 --- a/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java +++ b/src/main/java/com/simibubi/create/compat/jei/category/animations/AnimatedCrushingWheels.java @@ -1,7 +1,6 @@ package com.simibubi.create.compat.jei.category.animations; import com.mojang.blaze3d.matrix.MatrixStack; -import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllBlocks; import com.simibubi.create.foundation.gui.GuiGameElement; @@ -14,11 +13,11 @@ public class AnimatedCrushingWheels extends AnimatedKinetics { @Override public void draw(MatrixStack matrixStack, int xOffset, int yOffset) { - RenderSystem.enableDepthTest(); + matrixStack.push(); matrixStack.translate(xOffset, yOffset, 100); matrixStack.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(-22.5f)); int scale = 22; - + BlockState wheel = AllBlocks.CRUSHING_WHEEL.get() .getDefaultState() .with(BlockStateProperties.AXIS, Axis.X); @@ -33,6 +32,8 @@ public class AnimatedCrushingWheels extends AnimatedKinetics { .atLocal(2, 0, 0) .scale(scale) .render(matrixStack); + + matrixStack.pop(); } } 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 fb0e5a880..fe8a3c37f 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 @@ -1,8 +1,8 @@ package com.simibubi.create.compat.jei.category.animations; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AnimationTickHolder; import mezz.jei.api.gui.drawable.IDrawable; diff --git a/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java b/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java index f62c174bc..6876dd717 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java +++ b/src/main/java/com/simibubi/create/content/contraptions/KineticDebugger.java @@ -28,11 +28,11 @@ public class KineticDebugger { if (!isActive()) { if (KineticTileEntityRenderer.rainbowMode) { KineticTileEntityRenderer.rainbowMode = false; - CreateClient.bufferCache.invalidate(); - } + CreateClient.BUFFER_CACHE.invalidate(); + } return; } - + KineticTileEntity te = getSelectedTE(); if (te == null) return; @@ -44,18 +44,18 @@ public class KineticDebugger { .getRenderShape(world, toOutline); if (te.getTheoreticalSpeed() != 0 && !shape.isEmpty()) - CreateClient.outliner.chaseAABB("kineticSource", shape.getBoundingBox() - .offset(toOutline)) - .lineWidth(1 / 16f) - .colored(te.hasSource() ? ColorHelper.colorFromLong(te.network) : 0xffcc00); + CreateClient.OUTLINER.chaseAABB("kineticSource", shape.getBoundingBox() + .offset(toOutline)) + .lineWidth(1 / 16f) + .colored(te.hasSource() ? ColorHelper.colorFromLong(te.network) : 0xffcc00); if (state.getBlock() instanceof IRotate) { Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); Vector3d vec = Vector3d.of(Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis) - .getDirectionVec()); + .getDirectionVec()); Vector3d center = VecHelper.getCenterOf(te.getPos()); - CreateClient.outliner.showLine("rotationAxis", center.add(vec), center.subtract(vec)) - .lineWidth(1 / 16f); + CreateClient.OUTLINER.showLine("rotationAxis", center.add(vec), center.subtract(vec)) + .lineWidth(1 / 16f); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java b/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java index 6dfae6185..3d169a6ef 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java +++ b/src/main/java/com/simibubi/create/content/contraptions/TorquePropagator.java @@ -15,12 +15,12 @@ public class TorquePropagator { public void onLoadWorld(IWorld world) { networks.put(world, new HashMap<>()); - Create.logger.debug("Prepared Kinetic Network Space for " + WorldHelper.getDimensionID(world)); + Create.LOGGER.debug("Prepared Kinetic Network Space for " + WorldHelper.getDimensionID(world)); } public void onUnloadWorld(IWorld world) { networks.remove(world); - Create.logger.debug("Removed Kinetic Network Space for " + WorldHelper.getDimensionID(world)); + Create.LOGGER.debug("Removed Kinetic Network Space for " + WorldHelper.getDimensionID(world)); } public KineticNetwork getOrCreateNetworkFor(KineticTileEntity te) { 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 index 738155141..592db77bf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/BackHalfShaftInstance.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; public class BackHalfShaftInstance extends HalfShaftInstance { - public BackHalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public BackHalfShaftInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java index 6d3664988..cd06bf1a4 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HalfShaftInstance.java @@ -1,19 +1,19 @@ package com.simibubi.create.content.contraptions.base; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; public class HalfShaftInstance extends SingleRotatingInstance { - public HalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public HalfShaftInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { Direction dir = getShaftDirection(); return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, dir); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java index d5a21d468..c7298995f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/HorizontalHalfShaftInstance.java @@ -1,13 +1,13 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.util.Direction; public class HorizontalHalfShaftInstance extends HalfShaftInstance { - public HorizontalHalfShaftInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public HorizontalHalfShaftInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticAttributes.java deleted file mode 100644 index 8f7b9b15b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticAttributes.java +++ /dev/null @@ -1,41 +0,0 @@ -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.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; - -public enum KineticAttributes implements IVertexAttrib { - INSTANCE_POSITION("aInstancePos", CommonAttributes.VEC3), - SPEED("aSpeed", CommonAttributes.FLOAT), - OFFSET("aOffset", CommonAttributes.FLOAT), - ; - - private final String name; - private final VertexAttribSpec spec; - - KineticAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 1; - } - - @Override - public int getBufferIndex() { - return 1; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java index b259c89aa..6eb292670 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/KineticData.java @@ -1,9 +1,8 @@ package com.simibubi.create.content.contraptions.base; -import java.nio.ByteBuffer; - -import com.simibubi.create.foundation.render.backend.core.BasicData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.core.materials.BasicData; import com.simibubi.create.foundation.utility.ColorHelper; import net.minecraft.util.math.BlockPos; @@ -16,7 +15,7 @@ public class KineticData extends BasicData { private float rotationalSpeed; private float rotationOffset; - protected KineticData(InstancedModel owner) { + protected KineticData(Instancer owner) { super(owner); } @@ -73,28 +72,25 @@ public class KineticData extends BasicData { } public KineticData setRotationalSpeed(float rotationalSpeed) { - this.rotationalSpeed = rotationalSpeed; - return this; - } + this.rotationalSpeed = rotationalSpeed; + return this; + } - public KineticData setRotationOffset(float rotationOffset) { - this.rotationOffset = rotationOffset; - return this; - } + public KineticData setRotationOffset(float rotationOffset) { + this.rotationOffset = rotationOffset; + return this; + } + @Override + public void write(MappedBuffer buf) { + super.write(buf); - @Override - public void write(ByteBuffer buf) { - super.write(buf); - - buf.asFloatBuffer().put(new float[] { - x, - y, - z, - rotationalSpeed, - rotationOffset - }); - - buf.position(buf.position() + 5 * 4); - } + buf.putFloatArray(new float[]{ + x, + y, + z, + rotationalSpeed, + 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 deleted file mode 100644 index 29ee62162..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/KineticRenderMaterials.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.simibubi.create.content.contraptions.components.actors.ActorData; -import com.simibubi.create.content.contraptions.relays.belt.BeltData; -import com.simibubi.create.content.logistics.block.FlapData; -import com.simibubi.create.foundation.render.backend.MaterialType; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class KineticRenderMaterials { - public static final MaterialType> ROTATING = new MaterialType<>(); - public static final MaterialType> BELTS = new MaterialType<>(); - - public static final MaterialType> ACTORS = new MaterialType<>(); - - public static final MaterialType> FLAPS = 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 93058fb64..6878a5167 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 @@ -7,6 +7,8 @@ import java.util.List; import javax.annotation.Nullable; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.KineticNetwork; import com.simibubi.create.content.contraptions.RotationPropagator; @@ -18,9 +20,8 @@ import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; import com.simibubi.create.content.contraptions.relays.gearbox.GearboxBlock; 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.sound.SoundScapes; +import com.simibubi.create.foundation.sound.SoundScapes.AmbienceGroup; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.Lang; @@ -257,7 +258,7 @@ public abstract class KineticTileEntity extends SmartTileEntity effects.triggerOverStressedEffect(); if (clientPacket) - FastRenderDispatcher.enqueueUpdate(this); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public float getGeneratedSpeed() { @@ -329,7 +330,7 @@ public abstract class KineticTileEntity extends SmartTileEntity } public KineticNetwork getOrCreateNetwork() { - return Create.torquePropagator.getOrCreateNetworkFor(this); + return Create.TORQUE_PROPAGATOR.getOrCreateNetworkFor(this); } public boolean hasNetwork() { @@ -476,6 +477,14 @@ public abstract class KineticTileEntity extends SmartTileEntity return d.getAxisDirection() == AxisDirection.POSITIVE ? axisSpeed : -axisSpeed; } + public static float convertToLinear(float speed) { + return speed / 512f; + } + + public static float convertToAngular(float speed) { + return speed * 3 / 10f; + } + public boolean isOverStressed() { return overStressed; } @@ -551,9 +560,8 @@ public abstract class KineticTileEntity extends SmartTileEntity @Override public void requestModelDataUpdate() { super.requestModelDataUpdate(); - if (!this.removed) { - FastRenderDispatcher.enqueueUpdate(this); - } + if (!this.removed) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } protected AxisAlignedBB cachedBoundingBox; @@ -575,14 +583,14 @@ public abstract class KineticTileEntity extends SmartTileEntity float componentSpeed = Math.abs(getSpeed()); if (componentSpeed == 0) return; - float pitch = MathHelper.clamp((componentSpeed / 256f) + .45f, .5f, 1.25f); + float pitch = MathHelper.clamp((componentSpeed / 256f) + .45f, .85f, 1f); if (isNoisy()) - SoundScapes.playGeneralKineticAmbience(pos, pitch); + SoundScapes.play(AmbienceGroup.KINETIC, pos, pitch); Block block = getBlockState().getBlock(); if (ICogWheel.isSmallCog(block) || ICogWheel.isLargeCog(block) || block instanceof GearboxBlock) - SoundScapes.playCogwheelAmbience(pos, pitch); + SoundScapes.play(AmbienceGroup.COG, pos, pitch); } protected boolean isNoisy() { 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 dcefcadfe..bea28ca27 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 @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.base; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlocks; @@ -8,7 +9,6 @@ import com.simibubi.create.content.contraptions.KineticDebugger; import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel; 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; @@ -39,7 +39,7 @@ public class KineticTileEntityRenderer extends SafeTileEntityRenderer extends T protected final Direction.Axis axis; - public KineticTileInstance(InstancedTileRenderer modelManager, T tile) { + public KineticTileInstance(MaterialManager modelManager, T tile) { super(modelManager, tile); axis = ((IRotate) blockState.getBlock()).getRotationAxis(blockState); @@ -84,9 +84,9 @@ public abstract class KineticTileInstance extends T return shaft(getRotationAxis()); } - protected final RenderMaterial> getRotatingMaterial() { - return renderer.getMaterial(KineticRenderMaterials.ROTATING); - } + protected final InstanceMaterial getRotatingMaterial() { + return materialManager.getMaterial(AllMaterialSpecs.ROTATING); + } public static BlockState shaft(Direction.Axis axis) { return AllBlocks.SHAFT.getDefaultState() diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingAttributes.java deleted file mode 100644 index ef0e1122c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingAttributes.java +++ /dev/null @@ -1,39 +0,0 @@ -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.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; - -public enum RotatingAttributes implements IVertexAttrib { - AXIS("aAxis", CommonAttributes.NORMAL), - ; - - private final String name; - private final VertexAttribSpec spec; - - RotatingAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 1; - } - - @Override - public int getBufferIndex() { - return 1; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java index 1ca50d3e8..443168be0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingData.java @@ -1,8 +1,7 @@ package com.simibubi.create.content.contraptions.base; -import java.nio.ByteBuffer; - -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.backend.instancing.Instancer; import net.minecraft.util.Direction; import net.minecraft.util.math.vector.Vector3f; @@ -12,9 +11,9 @@ public class RotatingData extends KineticData { private byte rotationAxisY; private byte rotationAxisZ; - protected RotatingData(InstancedModel owner) { - super(owner); - } + public RotatingData(Instancer owner) { + super(owner); + } public RotatingData setRotationAxis(Direction.Axis axis) { Direction orientation = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis); @@ -25,20 +24,20 @@ public class RotatingData extends KineticData { 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); - markDirty(); - 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); + markDirty(); + return this; + } - @Override - public void write(ByteBuffer buf) { - super.write(buf); + @Override + public void write(MappedBuffer buf) { + super.write(buf); - putVec3(buf, rotationAxisX, rotationAxisY, rotationAxisZ); - } + buf.putVec3(rotationAxisX, rotationAxisY, rotationAxisZ); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingModel.java b/src/main/java/com/simibubi/create/content/contraptions/base/RotatingModel.java deleted file mode 100644 index 81582c35b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/base/RotatingModel.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.simibubi.create.content.contraptions.base; - -import com.simibubi.create.foundation.render.backend.core.BasicAttributes; -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 RotatingModel extends InstancedModel { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(BasicAttributes.class) - .addAttributes(KineticAttributes.class) - .addAttributes(RotatingAttributes.class) - .build(); - - public RotatingModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected RotatingData newInstance() { - return new RotatingData(this); - } - - @Override - protected VertexFormat getInstanceFormat() { - return FORMAT; - } - -} 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 index 16f85ab32..415882390 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/ShaftlessCogInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/ShaftlessCogInstance.java @@ -1,17 +1,18 @@ package com.simibubi.create.content.contraptions.base; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.AllMaterialSpecs; public class ShaftlessCogInstance extends SingleRotatingInstance { - public ShaftlessCogInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public ShaftlessCogInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { - return renderer.getMaterial(KineticRenderMaterials.ROTATING).getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, tile.getBlockState()); + protected Instancer getModel() { + return materialManager.getMaterial(AllMaterialSpecs.ROTATING).getModel(AllBlockPartials.SHAFTLESS_COGWHEEL, 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 index 1749e308f..17ba2884d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/base/SingleRotatingInstance.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.contraptions.base; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import net.minecraft.block.BlockState; @@ -9,7 +9,7 @@ public class SingleRotatingInstance extends KineticTileInstance modelManager, KineticTileEntity tile) { + public SingleRotatingInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); rotatingModel = setup(getModel().createInstance()); @@ -34,7 +34,7 @@ public class SingleRotatingInstance extends KineticTileInstance getModel() { + protected Instancer getModel() { return getRotatingMaterial().getModel(getRenderedBlockState()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java index 191e3ebc0..dd8c01e8e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorData.java @@ -1,9 +1,8 @@ package com.simibubi.create.content.contraptions.components.actors; -import java.nio.ByteBuffer; - -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Quaternion; @@ -29,9 +28,9 @@ public class ActorData extends InstanceData { private float speed; - protected ActorData(InstancedModel owner) { - super(owner); - } + public ActorData(Instancer owner) { + super(owner); + } public ActorData setPosition(BlockPos pos) { @@ -92,24 +91,24 @@ public class ActorData extends InstanceData { return this; } - public ActorData setLocalRotation(Quaternion q) { - this.qX = q.getX(); - this.qY = q.getY(); - this.qZ = q.getZ(); - this.qW = q.getW(); - markDirty(); - return this; - } + public ActorData setLocalRotation(Quaternion q) { + this.qX = q.getX(); + this.qY = q.getY(); + this.qZ = q.getZ(); + this.qW = q.getW(); + markDirty(); + 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); - putVec4(buf, qX, qY, qZ, qW); - putVec3(buf, rotationCenterX, rotationCenterY, rotationCenterZ); - put(buf, speed); + @Override + public void write(MappedBuffer buf) { + buf.putVec3(x, y, z); + buf.putVec2(blockLight, skyLight); + buf.putFloat(rotationOffset); + buf.putVec3(rotationAxisX, rotationAxisY, rotationAxisZ); + buf.putVec4(qX, qY, qZ, qW); + buf.putVec3(rotationCenterX, rotationCenterY, rotationCenterZ); + buf.putFloat(speed); - } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorModel.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorModel.java deleted file mode 100644 index a8fdeac6c..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorModel.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.contraptions.components.actors; - -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; - -import net.minecraft.client.renderer.BufferBuilder; - -public class ActorModel extends InstancedModel { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(ActorVertexAttributes.class) - .build(); - - public ActorModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected VertexFormat getInstanceFormat() { - return FORMAT; - } - - @Override - protected ActorData newInstance() { - return new ActorData(this); - } -} 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 deleted file mode 100644 index ff633d817..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/ActorVertexAttributes.java +++ /dev/null @@ -1,45 +0,0 @@ -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.IAttribSpec; -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.QUATERNION), - ROTATION_CENTER("aRotationCenter", CommonAttributes.NORMAL), - SPEED("aSpeed", CommonAttributes.FLOAT), - ; - - 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 IAttribSpec 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/DrillActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java index 40df1e591..316d7eed2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/DrillActorInstance.java @@ -1,13 +1,14 @@ package com.simibubi.create.content.contraptions.components.actors; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; @@ -16,12 +17,12 @@ import net.minecraft.util.math.vector.Quaternion; public class DrillActorInstance extends ActorInstance { ActorData drillHead; - private Direction facing; + private final Direction facing; - public DrillActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { - super(modelManager, context); + public DrillActorInstance(MaterialManager materialManager, PlacementSimulationWorld contraption, MovementContext context) { + super(materialManager, contraption, context); - RenderMaterial> renderMaterial = modelManager.getActorMaterial(); + InstanceMaterial instanceMaterial = materialManager.getMaterial(AllMaterialSpecs.ACTORS); BlockState state = context.state; @@ -36,7 +37,7 @@ public class DrillActorInstance extends ActorInstance { else eulerY = facing.getHorizontalAngle() + ((axis == Direction.Axis.X) ? 180 : 0); - drillHead = renderMaterial.getModel(AllBlockPartials.DRILL_HEAD, state).createInstance(); + drillHead = instanceMaterial.getModel(AllBlockPartials.DRILL_HEAD, state).createInstance(); drillHead.setPosition(context.localPos) .setBlockLight(localBlockLight()) 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 index 7d1bdd735..1df84bd4e 100644 --- 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 @@ -2,24 +2,24 @@ package com.simibubi.create.content.contraptions.components.actors; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; public class DrillInstance extends SingleRotatingInstance { - public DrillInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public DrillInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { BlockState referenceState = tile.getBlockState(); Direction facing = referenceState.get(FACING); return getRotatingMaterial().getModel(AllBlockPartials.DRILL_HEAD, referenceState, facing); 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 8232772f3..cda9e9a75 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,12 +2,13 @@ package com.simibubi.create.content.contraptions.components.actors; import javax.annotation.Nullable; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -34,10 +35,10 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @Override @OnlyIn(value = Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - if (!FastRenderDispatcher.available()) - DrillRenderer.renderInContraption(context, ms, msLocal, buffer); + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + if (!Backend.getInstance().canUseInstancing()) + DrillRenderer.renderInContraption(context, renderWorld, matrices, buffer); } @Override @@ -47,8 +48,8 @@ public class DrillMovementBehaviour extends BlockBreakingMovementBehaviour { @Nullable @Override - public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { - return new DrillActorInstance(kr, context); + public ActorInstance createInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + return new DrillActorInstance(materialManager, simulationWorld, 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 3734c3509..df1e668d9 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 @@ -5,12 +5,15 @@ 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.content.contraptions.components.structureMovement.render.ContraptionMatrices; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; 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.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -29,9 +32,8 @@ public class DrillRenderer extends KineticTileEntityRenderer { return PartialBufferer.getFacing(AllBlockPartials.DRILL_HEAD, te.getBlockState()); } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { BlockState state = context.state; SuperByteBuffer superBuffer = PartialBufferer.get(AllBlockPartials.DRILL_HEAD, state); Direction facing = state.get(DrillBlock.FACING); @@ -42,18 +44,22 @@ public class DrillRenderer extends KineticTileEntityRenderer { float time = AnimationTickHolder.getRenderTime() / 20; float angle = (float) (((time * speed) % 360)); - for (MatrixStack m : matrixStacks) - MatrixStacker.of(m) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)) - .rotateZ(angle) - .unCentre(); + MatrixStack m = matrices.contraptionStack; + m.push(); + MatrixStacker.of(m) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)) + .rotateZ(angle) + .unCentre(); superBuffer - .light(msLocal.peek() - .getModel()) - .renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + .transform(m) + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getSolid())); + + m.pop(); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java index 83f516058..fafd7c7e2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/HarvesterActorInstance.java @@ -2,18 +2,18 @@ package com.simibubi.create.content.contraptions.components.actors; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; @@ -33,16 +33,16 @@ public class HarvesterActorInstance extends ActorInstance { private double rotation; private double previousRotation; - public HarvesterActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { - super(modelManager, context); + public HarvesterActorInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + super(materialManager, simulationWorld, context); - RenderMaterial> renderMaterial = modelManager.getTransformMaterial(); + InstanceMaterial instanceMaterial = materialManager.getTransformMaterial(); BlockState state = context.state; facing = state.get(HORIZONTAL_FACING); - harvester = renderMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance(); + harvester = instanceMaterial.getModel(AllBlockPartials.HARVESTER_BLADE, state).createInstance(); horizontalAngle = facing.getHorizontalAngle() + ((facing.getAxis() == Direction.Axis.X) ? 180 : 0); 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 6472d23d4..0aed0b128 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 @@ -6,15 +6,17 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableBoolean; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.CocoaBlock; @@ -47,15 +49,15 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { @Nullable @Override - public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { - return new HarvesterActorInstance(kr, context); + public ActorInstance createInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + return new HarvesterActorInstance(materialManager, simulationWorld, context); } @Override - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffers) { - if (!FastRenderDispatcher.available()) - HarvesterRenderer.renderInContraption(context, ms, msLocal, buffers); + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffers) { + if (!Backend.getInstance().canUseInstancing()) + HarvesterRenderer.renderInContraption(context, renderWorld, matrices, buffers); } @Override @@ -150,24 +152,28 @@ public class HarvesterMovementBehaviour extends MovementBehaviour { } private BlockState cutCrop(World world, BlockPos pos, BlockState state) { - if (state.getBlock() instanceof CropsBlock) { - CropsBlock crop = (CropsBlock) state.getBlock(); + Block block = state.getBlock(); + if (block instanceof CropsBlock) { + CropsBlock crop = (CropsBlock) block; return crop.withAge(0); } - if (state.getBlock() == Blocks.SUGAR_CANE || state.getBlock() == Blocks.KELP) { + if (block == Blocks.SWEET_BERRY_BUSH) { + return state.with(BlockStateProperties.AGE_0_3, Integer.valueOf(1)); + } + if (block == Blocks.SUGAR_CANE || block == Blocks.KELP) { if (state.getFluidState() - .isEmpty()) + .isEmpty()) return Blocks.AIR.getDefaultState(); return state.getFluidState() - .getBlockState(); + .getBlockState(); } if (state.getCollisionShape(world, pos) - .isEmpty() || state.getBlock() instanceof CocoaBlock) { + .isEmpty() || block instanceof CocoaBlock) { for (Property property : state.getProperties()) { if (!(property instanceof IntegerProperty)) continue; if (!property.getName() - .equals(BlockStateProperties.AGE_0_1.getName())) + .equals(BlockStateProperties.AGE_0_1.getName())) continue; return state.with((IntegerProperty) property, Integer.valueOf(0)); } 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 44cf29765..3ab34b532 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,6 +5,7 @@ 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.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; @@ -12,6 +13,7 @@ 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.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -39,8 +41,8 @@ public class HarvesterRenderer extends SafeTileEntityRenderer 0 && action.execute()) - onContentTransferred(); + keepAlive(); return fill; } @@ -95,7 +95,7 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi return FluidStack.EMPTY; FluidStack drain = wrapped.drain(resource, action); if (!drain.isEmpty() && action.execute()) - onContentTransferred(); + keepAlive(); return drain; } @@ -104,10 +104,14 @@ public class PortableFluidInterfaceTileEntity extends PortableStorageInterfaceTi if (!canTransfer()) return FluidStack.EMPTY; FluidStack drain = wrapped.drain(maxDrain, action); - if (!drain.isEmpty() && (action.execute() || drain.getAmount() == 1)) - onContentTransferred(); + if (!drain.isEmpty() && action.execute()) + keepAlive(); return drain; } + + public void keepAlive() { + onContentTransferred(); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java index a29066465..6bd6b8f13 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceMovement.java @@ -2,10 +2,11 @@ package com.simibubi.create.content.contraptions.components.actors; import java.util.Optional; -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.ContraptionMatrices; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -31,9 +32,9 @@ public class PortableStorageInterfaceMovement extends MovementBehaviour { @Override @OnlyIn(Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - PortableStorageInterfaceRenderer.renderInContraption(context, ms, msLocal, buffer); + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + PortableStorageInterfaceRenderer.renderInContraption(context, renderWorld, matrices, buffer); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java index 01c3d4d6f..287b2314f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/PortableStorageInterfaceRenderer.java @@ -2,19 +2,20 @@ package com.simibubi.create.content.contraptions.components.actors; import java.util.function.Consumer; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; 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.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -37,12 +38,12 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer sbb.light(light) - .renderInto(ms, vb), ms); + render(blockState, te.isConnected(), progress, null, sbb -> sbb.light(light) + .renderInto(ms, vb)); } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { BlockState blockState = context.state; PortableStorageInterfaceTileEntity te = getTargetPSI(context); IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); @@ -55,44 +56,36 @@ public class PortableStorageInterfaceRenderer extends SafeTileEntityRenderer sbb.light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, vb), ms, msLocal); + render(blockState, lit, progress, matrices.contraptionStack, sbb -> sbb.light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, vb)); } - private static void render(BlockState blockState, float progress, boolean lit, - Consumer drawCallback, MatrixStack... matrixStacks) { - for (MatrixStack ms : matrixStacks) - ms.push(); - + private static void render(BlockState blockState, boolean lit, float progress, + MatrixStack local, Consumer drawCallback) { SuperByteBuffer middle = PartialBufferer.get(getMiddleForState(blockState, lit), blockState); SuperByteBuffer top = PartialBufferer.get(getTopForState(blockState), blockState); - Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING); - for (MatrixStack ms : matrixStacks) - MatrixStacker.of(ms) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) - .unCentre(); - - for (MatrixStack ms : matrixStacks) { - ms.translate(0, progress / 2f, 0); - ms.push(); - ms.translate(0, 6 / 16f, 0); + if (local != null) { + middle.transform(local); + top.transform(local); } + Direction facing = blockState.get(PortableStorageInterfaceBlock.FACING); + rotateToFacing(middle, facing); + rotateToFacing(top, facing); + middle.translate(0, progress * 0.5f + 0.375f, 0); + top.translate(0, progress, 0); drawCallback.accept(middle); - - for (MatrixStack ms : matrixStacks) { - ms.pop(); - ms.translate(0, progress / 2f, 0); - } - drawCallback.accept(top); + } - for (MatrixStack ms : matrixStacks) - ms.pop(); + private static void rotateToFacing(SuperByteBuffer buffer, Direction facing) { + buffer.matrixStacker() + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(facing == Direction.UP ? 0 : facing == Direction.DOWN ? 180 : 90) + .unCentre(); } protected static PortableStorageInterfaceTileEntity getTargetPSI(MovementContext context) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java index a24d69459..77aebb0c3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SawMovementBehaviour.java @@ -1,13 +1,14 @@ package com.simibubi.create.content.contraptions.components.actors; -import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.components.saw.SawBlock; 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.MovementContext; import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.foundation.utility.TreeCutter; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -85,9 +86,9 @@ public class SawMovementBehaviour extends BlockBreakingMovementBehaviour { @Override @OnlyIn(value = Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - SawRenderer.renderInContraption(context, ms, msLocal, buffer); + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + SawRenderer.renderInContraption(context, renderWorld, matrices, buffer); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java index 3cccce364..bd2f0001c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/actors/SeatBlock.java @@ -96,12 +96,12 @@ public class SeatBlock extends Block { ItemStack heldItem = player.getHeldItem(hand); for (DyeColor color : DyeColor.values()) { if (!heldItem.getItem() - .isIn(DyeHelper.getTagOfDye(color))) + .isIn(DyeHelper.getTagOfDye(color))) continue; if (world.isRemote) return ActionResultType.SUCCESS; - BlockState newState = AllBlocks.SEATS[color.ordinal()].getDefaultState(); + BlockState newState = AllBlocks.SEATS.get(color).getDefaultState(); if (newState != state) world.setBlockState(pos, newState); return ActionResultType.SUCCESS; @@ -148,5 +148,5 @@ public class SeatBlock extends Block { public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + } 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 412cd349b..03f8fa982 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 @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.components.clock; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -8,7 +9,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.clock.CuckooClockTileEntity.Animation; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.block.BlockState; 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 7ee30f4d6..9b3aefbd8 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 @@ -41,7 +41,7 @@ public class CuckooClockTileEntity extends KineticTileEntity { super(type); animationType = Animation.NONE; } - + @Override protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { super.fromTag(state, compound, clientPacket); @@ -51,7 +51,7 @@ public class CuckooClockTileEntity extends KineticTileEntity { animationProgress.value = 0; } } - + @Override public void write(CompoundNBT compound, boolean clientPacket) { if (clientPacket && sendAnimationUpdate) @@ -66,10 +66,24 @@ public class CuckooClockTileEntity extends KineticTileEntity { if (getSpeed() == 0) return; - int dayTime = (int) (world.getDayTime() % 24000); + + boolean isNatural = world.getDimension().isNatural(); + int dayTime = (int) ((world.getDayTime() * (isNatural ? 1 : 24)) % 24000); int hours = (dayTime / 1000 + 6) % 24; int minutes = (dayTime % 1000) * 60 / 1000; + if (!isNatural) { + if (world.isRemote) { + moveHands(hours, minutes); + + if (AnimationTickHolder.getTicks() % 6 == 0) + playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 2f); + else if (AnimationTickHolder.getTicks() % 3 == 0) + playSound(SoundEvents.BLOCK_NOTE_BLOCK_HAT, 1 / 16f, 1.5f); + } + return; + } + if (!world.isRemote) { if (animationType == Animation.NONE) { if (hours == 12 && minutes < 5) @@ -150,10 +164,10 @@ public class CuckooClockTileEntity extends KineticTileEntity { animationProgress.lastValue = 0; animationProgress.value = 0; sendAnimationUpdate = true; - + if (animation == Animation.CREEPER) AllTriggers.triggerForNearbyPlayers(AllTriggers.CUCKOO, world, pos, 10); - + sendData(); } @@ -174,7 +188,7 @@ public class CuckooClockTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { 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 index 2d88b431c..4ca256adf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/MechanicalCrafterInstance.java @@ -2,25 +2,25 @@ package com.simibubi.create.content.contraptions.components.crafter; import java.util.function.Supplier; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.util.Direction; public class MechanicalCrafterInstance extends SingleRotatingInstance { - public MechanicalCrafterInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public MechanicalCrafterInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { Direction facing = blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING); Supplier 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 4e0e9bc73..a4575de82 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 @@ -3,6 +3,8 @@ package com.simibubi.create.content.contraptions.components.crafter; import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; import static com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer.standardKineticRotationTransform; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -11,8 +13,6 @@ import com.simibubi.create.content.contraptions.components.crafter.MechanicalCra import com.simibubi.create.content.contraptions.components.crafter.RecipeGridHandler.GroupedItems; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -156,7 +156,7 @@ public class MechanicalCrafterRenderer extends SafeTileEntityRenderer= 1000) { AllSoundEvents.CRAFTER_CLICK.playOnServer(world, pos, 1, 2); AllSoundEvents.CRAFTER_CRAFT.playOnServer(world, pos); } - + if (countDown < 0) { countDown = 0; if (!runLogic) @@ -513,7 +513,7 @@ public class MechanicalCrafterTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java index 3f32854de..0dd0d5991 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crafter/RecipeGridHandler.java @@ -9,6 +9,10 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.IntStream; + +import net.minecraft.item.crafting.FireworkRocketRecipe; +import net.minecraft.item.crafting.ICraftingRecipe; import org.apache.commons.lang3.tuple.Pair; @@ -145,6 +149,7 @@ public class RecipeGridHandler { if (AllConfigs.SERVER.recipes.allowRegularCraftingInCrafter.get()) result = world.getRecipeManager() .getRecipe(IRecipeType.CRAFTING, craftinginventory, world) + .filter(r -> isRecipeAllowed(r, craftinginventory)) .map(r -> r.getCraftingResult(craftinginventory)) .orElse(null); if (result == null) @@ -154,6 +159,17 @@ public class RecipeGridHandler { return result; } + public static boolean isRecipeAllowed(ICraftingRecipe recipe, CraftingInventory inventory) { + if (!AllConfigs.SERVER.recipes.allowBiggerFireworksInCrafter.get() && recipe instanceof FireworkRocketRecipe) { + int numItems = IntStream.range(0, inventory.getSizeInventory()) + .map(i -> inventory.getStackInSlot(i).isEmpty() ? 0 : 1) + .sum(); + if (numItems > 9) + return false; + } + return true; + } + public static class GroupedItems { Map, ItemStack> grid = new HashMap<>(); int minX, minY, maxX, maxY, width, height; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java index 2b2bda8d6..bef299a96 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankBlock.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.crank; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.foundation.block.ITE; import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import net.minecraft.block.Block; import net.minecraft.block.BlockRenderType; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java index 843882dce..b353c463b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankInstance.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.crank; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -20,7 +20,7 @@ public class HandCrankInstance extends SingleRotatingInstance implements IDynami private ModelData crank; private Direction facing; - public HandCrankInstance(InstancedTileRenderer modelManager, HandCrankTileEntity tile) { + public HandCrankInstance(MaterialManager modelManager, HandCrankTileEntity tile) { super(modelManager, tile); this.tile = tile; @@ -33,7 +33,7 @@ public class HandCrankInstance extends SingleRotatingInstance implements IDynami facing = blockState.get(BlockStateProperties.FACING); Direction opposite = facing.getOpposite(); - InstancedModel model = getTransformMaterial().getModel(renderedHandle, blockState, opposite); + Instancer model = getTransformMaterial().getModel(renderedHandle, blockState, opposite); crank = model.createInstance(); rotateCrank(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java index 7db258093..586f0ea90 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankRenderer.java @@ -2,13 +2,13 @@ package com.simibubi.create.content.contraptions.components.crank; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -28,7 +28,7 @@ public class HandCrankRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockState state = te.getBlockState(); Block block = state.getBlock(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java index a058b740c..259a89b10 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/HandCrankTileEntity.java @@ -77,7 +77,7 @@ public class HandCrankTileEntity extends GeneratingKineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java index e9e8c32d7..8b0b71e91 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crank/ValveHandleBlock.java @@ -2,8 +2,8 @@ package com.simibubi.create.content.contraptions.components.crank; import javax.annotation.ParametersAreNonnullByDefault; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlocks; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.DyeHelper; import net.minecraft.block.BlockState; @@ -43,14 +43,14 @@ public class ValveHandleBlock extends HandCrankBlock { ItemStack heldItem = player.getHeldItem(handIn); for (DyeColor color : DyeColor.values()) { if (!heldItem.getItem() - .isIn(DyeHelper.getTagOfDye(color))) + .isIn(DyeHelper.getTagOfDye(color))) continue; if (worldIn.isRemote) return ActionResultType.SUCCESS; - BlockState newState = AllBlocks.DYED_VALVE_HANDLES.get(color.ordinal()) - .getDefaultState() - .with(FACING, state.get(FACING)); + BlockState newState = AllBlocks.DYED_VALVE_HANDLES.get(color) + .getDefaultState() + .with(FACING, state.get(FACING)); if (newState != state) worldIn.setBlockState(pos, newState); return ActionResultType.SUCCESS; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java index 127ed6923..34e587985 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelBlock.java @@ -92,34 +92,29 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE if (AllBlocks.CRUSHING_WHEEL.has(otherState)) { controllerShouldExist = true; - try { - CrushingWheelTileEntity te = getTileEntity(world, pos); - CrushingWheelTileEntity otherTe = getTileEntity(world, otherWheelPos); + CrushingWheelTileEntity te = getTileEntity(world, pos); + CrushingWheelTileEntity otherTe = getTileEntity(world, otherWheelPos); - if (te != null && otherTe != null && (te.getSpeed() > 0) != (otherTe.getSpeed() > 0) - && te.getSpeed() != 0) { - Axis wheelAxis = state.get(AXIS); - Axis sideAxis = side.getAxis(); - int controllerADO = Math.round(Math.signum(te.getSpeed())) * side.getAxisDirection().getOffset(); - Vector3d controllerDirVec = new Vector3d(wheelAxis == Axis.X ? 1 : 0 - , wheelAxis == Axis.Y ? 1 : 0 - , wheelAxis == Axis.Z ? 1 : 0) - .crossProduct(new Vector3d(sideAxis == Axis.X ? 1 : 0 - , sideAxis == Axis.Y ? 1 : 0 - , sideAxis == Axis.Z ? 1 : 0)); + if (te != null && otherTe != null && (te.getSpeed() > 0) != (otherTe.getSpeed() > 0) + && te.getSpeed() != 0) { + Axis wheelAxis = state.get(AXIS); + Axis sideAxis = side.getAxis(); + int controllerADO = Math.round(Math.signum(te.getSpeed())) * side.getAxisDirection().getOffset(); + Vector3d controllerDirVec = new Vector3d(wheelAxis == Axis.X ? 1 : 0 + , wheelAxis == Axis.Y ? 1 : 0 + , wheelAxis == Axis.Z ? 1 : 0) + .crossProduct(new Vector3d(sideAxis == Axis.X ? 1 : 0 + , sideAxis == Axis.Y ? 1 : 0 + , sideAxis == Axis.Z ? 1 : 0)); - controllerNewDirection = Direction.getFacingFromVector(controllerDirVec.x * controllerADO - , controllerDirVec.y * controllerADO - , controllerDirVec.z * controllerADO); + controllerNewDirection = Direction.getFacingFromVector(controllerDirVec.x * controllerADO + , controllerDirVec.y * controllerADO + , controllerDirVec.z * controllerADO); - controllerShouldBeValid = true; - } - if (otherState.get(AXIS) != state.get(AXIS)) - controllerShouldExist = false; - - } catch (TileEntityException e) { - controllerShouldExist = false; + controllerShouldBeValid = true; } + if (otherState.get(AXIS) != state.get(AXIS)) + controllerShouldExist = false; } if (!controllerShouldExist) { @@ -149,27 +144,25 @@ public class CrushingWheelBlock extends RotatedPillarKineticBlock implements ITE @Override public void onEntityCollision(BlockState state, World worldIn, BlockPos pos, Entity entityIn) { - try { - CrushingWheelTileEntity te = getTileEntity(worldIn, pos); - if (entityIn.getY() < pos.getY() + 1.25f || !entityIn.isOnGround()) - return; + if (entityIn.getY() < pos.getY() + 1.25f || !entityIn.isOnGround()) + return; - double x = 0; - double z = 0; + float speed = getTileEntityOptional(worldIn, pos).map(CrushingWheelTileEntity::getSpeed) + .orElse(0f); - if (state.get(AXIS) == Axis.X) { - z = te.getSpeed() / 20f; - x += (pos.getX() + .5f - entityIn.getX()) * .1f; - } - if (state.get(AXIS) == Axis.Z) { - x = te.getSpeed() / -20f; - z += (pos.getZ() + .5f - entityIn.getZ()) * .1f; - } - entityIn.setMotion(entityIn.getMotion() - .add(x, 0, z)); + double x = 0; + double z = 0; - } catch (TileEntityException e) { + if (state.get(AXIS) == Axis.X) { + z = speed / 20f; + x += (pos.getX() + .5f - entityIn.getX()) * .1f; } + if (state.get(AXIS) == Axis.Z) { + x = speed / -20f; + z += (pos.getZ() + .5f - entityIn.getZ()) * .1f; + } + entityIn.setMotion(entityIn.getMotion() + .add(x, 0, z)); } @Override diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java index e1175feba..944b8e073 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/crusher/CrushingWheelControllerBlock.java @@ -91,28 +91,28 @@ public class CrushingWheelControllerBlock extends DirectionalBlock }); } - public void checkEntityForProcessing(World worldIn, BlockPos pos, Entity entityIn){ - try { - CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); - if (te.crushingspeed == 0) - return; - if (entityIn instanceof ItemEntity) - ((ItemEntity) entityIn).setPickupDelay(10); - CompoundNBT data = entityIn.getPersistentData(); - if (data.contains("BypassCrushingWheel")) { - if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) - return; - } - if (te.isOccupied()) - return; - boolean isPlayer = entityIn instanceof PlayerEntity; - if (isPlayer && ((PlayerEntity) entityIn).isCreative()) - return; - if (isPlayer && entityIn.world.getDifficulty() == Difficulty.PEACEFUL) + public void checkEntityForProcessing(World worldIn, BlockPos pos, Entity entityIn) { + CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); + if (te == null) + return; + if (te.crushingspeed == 0) + return; + if (entityIn instanceof ItemEntity) + ((ItemEntity) entityIn).setPickupDelay(10); + CompoundNBT data = entityIn.getPersistentData(); + if (data.contains("BypassCrushingWheel")) { + if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) return; + } + if (te.isOccupied()) + return; + boolean isPlayer = entityIn instanceof PlayerEntity; + if (isPlayer && ((PlayerEntity) entityIn).isCreative()) + return; + if (isPlayer && entityIn.world.getDifficulty() == Difficulty.PEACEFUL) + return; - te.startCrushing(entityIn); - } catch (TileEntityException e) {} + te.startCrushing(entityIn); } @Override @@ -167,26 +167,26 @@ public class CrushingWheelControllerBlock extends DirectionalBlock @Override public VoxelShape getCollisionShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) { + VoxelShape standardShape = AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING)); + if (!state.get(VALID)) - return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING)); + return standardShape; Entity entity = context.getEntity(); - if (entity != null) { + if (entity == null) + return standardShape; - CompoundNBT data = entity.getPersistentData(); - if (data.contains("BypassCrushingWheel")) { - if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) - if (state.get(FACING) != Direction.UP) //Allow output items to land on top of the block rather than falling back through. - return VoxelShapes.empty(); - } - - try { - CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); - if (te.processingEntity == entity) + CompoundNBT data = entity.getPersistentData(); + if (data.contains("BypassCrushingWheel")) + if (pos.equals(NBTUtil.readBlockPos(data.getCompound("BypassCrushingWheel")))) + if (state.get(FACING) != Direction.UP) // Allow output items to land on top of the block rather than falling back through. return VoxelShapes.empty(); - } catch (TileEntityException e) {} - } - return AllShapes.CRUSHING_WHEEL_CONTROLLER_COLLISION.get(state.get(FACING)); + + CrushingWheelControllerTileEntity te = getTileEntity(worldIn, pos); + if (te != null && te.processingEntity == entity) + return VoxelShapes.empty(); + + return standardShape; } @Override @@ -202,7 +202,7 @@ public class CrushingWheelControllerBlock extends DirectionalBlock public Class getTileEntityClass() { return CrushingWheelControllerTileEntity.class; } - + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java index 7daf5b76d..7d007d11e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/BeltDeployerCallbacks.java @@ -9,10 +9,10 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.State; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe; -import com.simibubi.create.content.logistics.InWorldProcessing; import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; @@ -89,7 +89,7 @@ public class BeltDeployerCallbacks { boolean centered = BeltHelper.isItemUpright(stack); copy.stack = stack; copy.locked = true; - copy.angle = centered ? 180 : Create.random.nextInt(360); + copy.angle = centered ? 180 : Create.RANDOM.nextInt(360); return copy; }) .collect(Collectors.toList()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java index e91bc8a0d..437ac1686 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerActorInstance.java @@ -3,25 +3,24 @@ package com.simibubi.create.content.contraptions.components.deployer; import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; -import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; import com.simibubi.create.content.contraptions.base.KineticTileInstance; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionProgram; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; +import com.simibubi.create.foundation.render.AllMaterialSpecs; 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.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; @@ -42,10 +41,10 @@ public class DeployerActorInstance extends ActorInstance { ModelData hand; RotatingData shaft; - public DeployerActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { - super(modelManager, context); + public DeployerActorInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + super(materialManager, simulationWorld, context); - RenderMaterial> mat = modelManager.getTransformMaterial(); + InstanceMaterial mat = materialManager.getTransformMaterial(); BlockState state = context.state; DeployerTileEntity.Mode mode = NBTHelper.readEnum(context.tileData, "Mode", DeployerTileEntity.Mode.class); @@ -63,9 +62,9 @@ public class DeployerActorInstance extends ActorInstance { hand = mat.getModel(handPose, state).createInstance(); Direction.Axis axis = ((IRotate) state.getBlock()).getRotationAxis(state); - shaft = modelManager.getMaterial(KineticRenderMaterials.ROTATING) - .getModel(KineticTileInstance.shaft(axis)) - .createInstance(); + shaft = materialManager.getMaterial(AllMaterialSpecs.ROTATING) + .getModel(KineticTileInstance.shaft(axis)) + .createInstance(); int blockLight = localBlockLight(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java index 55f3a928d..b15e827a9 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerHandler.java @@ -5,9 +5,19 @@ import static net.minecraftforge.eventbus.api.Event.Result.DENY; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import javax.annotation.Nullable; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlockItem; + +import net.minecraft.block.DoublePlantBlock; + +import net.minecraft.entity.merchant.villager.AbstractVillagerEntity; +import net.minecraft.entity.merchant.villager.VillagerEntity; +import net.minecraft.state.properties.DoubleBlockHalf; + import org.apache.commons.lang3.tuple.Pair; import com.google.common.collect.Multimap; @@ -142,7 +152,9 @@ public class DeployerHandler { // Check for entities final ServerWorld world = player.getServerWorld(); - List entities = world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(clickedPos)); + List entities = world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(clickedPos)).stream() + .filter(e -> !(e instanceof AbstractContraptionEntity)) + .collect(Collectors.toList()); Hand hand = Hand.MAIN_HAND; if (!entities.isEmpty()) { Entity entity = entities.get(world.rand.nextInt(entities.size())); @@ -159,8 +171,14 @@ public class DeployerHandler { } if (cancelResult == null) { if (entity.processInitialInteract(player, hand) - .isAccepted()) + .isAccepted()){ + if (entity instanceof AbstractVillagerEntity) { + AbstractVillagerEntity villager = ((AbstractVillagerEntity) entity); + if (villager.getCustomer() instanceof DeployerFakePlayer) + villager.setCustomer(null); + } success = true; + } else if (entity instanceof LivingEntity && stack.useOnEntity(player, (LivingEntity) entity, hand) .isAccepted()) success = true; @@ -271,13 +289,15 @@ public class DeployerHandler { // Use on block if (useBlock != DENY && flag1 - && safeOnUse(clickedState, world, clickedPos, player, hand, result) == ActionResultType.SUCCESS) + && safeOnUse(clickedState, world, clickedPos, player, hand, result).isAccepted()) return; if (stack.isEmpty()) return; if (useItem == DENY) return; - if (item instanceof BlockItem && !clickedState.isReplaceable(new BlockItemUseContext(itemusecontext))) + if (item instanceof BlockItem + && !(item instanceof CartAssemblerBlockItem) + && !clickedState.isReplaceable(new BlockItemUseContext(itemusecontext))) return; // Reposition fire placement for convenience @@ -294,7 +314,7 @@ public class DeployerHandler { // 'Inert' item use behaviour & block placement ActionResultType onItemUse = stack.onItemUse(itemusecontext); - if (onItemUse == ActionResultType.SUCCESS) + if (onItemUse.isAccepted()) return; if (item == Items.ENDER_PEARL) return; @@ -349,8 +369,22 @@ public class DeployerHandler { prevHeldItem.onBlockDestroyed(world, blockstate, pos, player); if (prevHeldItem.isEmpty() && !heldItem.isEmpty()) net.minecraftforge.event.ForgeEventFactory.onPlayerDestroyItem(player, heldItem, Hand.MAIN_HAND); - if (!blockstate.removedByPlayer(world, pos, player, canHarvest, world.getFluidState(pos))) - return true; + + + BlockPos posUp = pos.up(); + BlockState stateUp = world.getBlockState(posUp); + if (blockstate.getBlock() instanceof DoublePlantBlock + && blockstate.get(DoublePlantBlock.HALF) == DoubleBlockHalf.LOWER + && stateUp.getBlock() == blockstate.getBlock() + && stateUp.get(DoublePlantBlock.HALF) == DoubleBlockHalf.UPPER + ) { + // hack to prevent DoublePlantBlock from dropping a duplicate item + world.setBlockState(pos, Blocks.AIR.getDefaultState(), 35); + world.setBlockState(posUp, Blocks.AIR.getDefaultState(), 35); + } else { + if (!blockstate.removedByPlayer(world, pos, player, canHarvest, world.getFluidState(pos))) + return true; + } blockstate.getBlock() .onPlayerDestroy(world, pos, blockstate); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java index 31b1d7665..5981b32d8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerInstance.java @@ -3,14 +3,14 @@ package com.simibubi.create.content.contraptions.components.deployer; import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.ITickableInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -36,7 +36,7 @@ public class DeployerInstance extends ShaftInstance implements IDynamicInstance, float progress; private boolean newHand = false; - public DeployerInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public DeployerInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); this.tile = (DeployerTileEntity) super.tile; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java index ab152a5f5..4243f024a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerMovementBehaviour.java @@ -7,7 +7,8 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.Pair; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.AllTags.AllBlockTags; @@ -16,17 +17,17 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Abs 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.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.logistics.item.filter.FilterItem; import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.SchematicWorld; import com.simibubi.create.content.schematics.filtering.SchematicInstances; import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.item.ItemHelper.ExtractionCountMode; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.BlockHelper; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTProcessors; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -104,31 +105,31 @@ public class DeployerMovementBehaviour extends MovementBehaviour { if (schematicWorld == null) return; if (!schematicWorld.getBounds() - .isVecInside(pos.subtract(schematicWorld.anchor))) + .isVecInside(pos.subtract(schematicWorld.anchor))) return; BlockState blockState = schematicWorld.getBlockState(pos); - ItemRequirement requirement = ItemRequirement.of(blockState); + ItemRequirement requirement = ItemRequirement.of(blockState, schematicWorld.getTileEntity(pos)); if (requirement.isInvalid() || requirement.isEmpty()) return; if (AllBlocks.BELT.has(blockState)) return; - List requiredItems = requirement.getRequiredItems(); - ItemStack firstRequired = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0); + List requiredItems = requirement.getRequiredItems(); + ItemStack firstRequired = requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item; if (!context.contraption.hasUniversalCreativeCrate) { IItemHandler iItemHandler = context.contraption.inventory; - for (ItemStack required : requiredItems) { + for (ItemRequirement.StackRequirement required : requiredItems) { int amountFound = ItemHelper - .extract(iItemHandler, s -> ItemRequirement.validate(required, s), ExtractionCountMode.UPTO, - required.getCount(), true) - .getCount(); - if (amountFound < required.getCount()) + .extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO, + required.item.getCount(), true) + .getCount(); + if (amountFound < required.item.getCount()) return; } - for (ItemStack required : requiredItems) - ItemHelper.extract(iItemHandler, s -> ItemRequirement.validate(required, s), ExtractionCountMode.UPTO, - required.getCount(), false); + for (ItemRequirement.StackRequirement required : requiredItems) + ItemHelper.extract(iItemHandler, s -> ItemRequirement.validate(required.item, s), ExtractionCountMode.UPTO, + required.item.getCount(), false); } CompoundNBT data = null; @@ -254,10 +255,10 @@ public class DeployerMovementBehaviour extends MovementBehaviour { } @Override - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffers) { - if (!FastRenderDispatcher.available()) - DeployerRenderer.renderInContraption(context, ms, msLocal, buffers); + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffers) { + if (!Backend.getInstance().canUseInstancing()) + DeployerRenderer.renderInContraption(context, renderWorld, matrices, buffers); } @Override @@ -267,7 +268,7 @@ public class DeployerMovementBehaviour extends MovementBehaviour { @Nullable @Override - public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { - return new DeployerActorInstance(kr, context); + public ActorInstance createInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + return new DeployerActorInstance(materialManager, simulationWorld, context); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java index 0261f9651..9eee73565 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/deployer/DeployerRenderer.java @@ -3,6 +3,8 @@ package com.simibubi.create.content.contraptions.components.deployer; import static com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock.AXIS_ALONG_FIRST_COORDINATE; import static com.simibubi.create.content.contraptions.base.DirectionalKineticBlock.FACING; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -10,17 +12,17 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity.Mode; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringRenderer; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -35,7 +37,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 net.minecraft.util.math.vector.Matrix4f; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraft.world.World; @@ -52,7 +53,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer renderItem(te, partialTicks, ms, buffer, light, overlay); FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; renderComponents(te, partialTicks, ms, buffer, light, overlay); } @@ -111,7 +112,7 @@ public class DeployerRenderer extends SafeTileEntityRenderer protected void renderComponents(DeployerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { IVertexBuilder vb = buffer.getBuffer(RenderType.getSolid()); - if (!FastRenderDispatcher.available(te.getWorld())) { + if (!Backend.getInstance().canUseInstancing(te.getWorld())) { KineticTileEntityRenderer.renderRotatingKineticBlock(te, getRenderedBlockState(te), ms, vb, light); } @@ -154,9 +155,8 @@ public class DeployerRenderer extends SafeTileEntityRenderer return buffer; } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { IVertexBuilder builder = buffer.getBuffer(RenderType.getSolid()); BlockState blockState = context.state; BlockPos pos = BlockPos.ZERO; @@ -166,8 +166,6 @@ public class DeployerRenderer extends SafeTileEntityRenderer SuperByteBuffer pole = PartialBufferer.get(AllBlockPartials.DEPLOYER_POLE, blockState); SuperByteBuffer hand = PartialBufferer.get(handPose, blockState); - pole = transform(world, pole, blockState, pos, true); - hand = transform(world, hand, blockState, pos, false); double factor; if (context.contraption.stalled || context.position == null || context.data.contains("StationaryTimer")) { @@ -183,14 +181,21 @@ public class DeployerRenderer extends SafeTileEntityRenderer Vector3d offset = Vector3d.of(blockState.get(FACING) .getDirectionVec()).scale(factor); - Matrix4f lighting = msLocal.peek() - .getModel(); - for (MatrixStack m : matrixStacks) - m.translate(offset.x, offset.y, offset.z); - pole.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, builder); - hand.light(lighting, ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, builder); + MatrixStack m = matrices.contraptionStack; + m.push(); + m.translate(offset.x, offset.y, offset.z); + + pole.transform(m); + hand.transform(m); + pole = transform(world, pole, blockState, pos, true); + hand = transform(world, hand, blockState, pos, false); + + pole.light(matrices.entityMatrix, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, builder); + hand.light(matrices.entityMatrix, ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, builder); + + m.pop(); } static PartialModel getHandPose(DeployerTileEntity.Mode mode) { 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 486de2d0e..8235a25a7 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 @@ -7,6 +7,7 @@ import java.util.List; import javax.annotation.Nullable; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; @@ -15,7 +16,6 @@ import com.simibubi.create.content.curiosities.tools.SandPaperItem; import com.simibubi.create.content.curiosities.tools.SandPaperPolishingRecipe.SandPaperInv; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.item.TooltipHelper; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; @@ -327,12 +327,13 @@ public class DeployerTileEntity extends KineticTileEntity { compound.putBoolean("Powered", redstoneLocked); if (player != null) { - compound.put("HeldItem", player.getHeldItemMainhand() - .serializeNBT()); ListNBT invNBT = new ListNBT(); player.inventory.write(invNBT); compound.put("Inventory", invNBT); + compound.put("HeldItem", player.getHeldItemMainhand().serializeNBT()); compound.put("Overflow", NBTHelper.writeItemList(overflowItems)); + } else if (deferredInventoryList != null) { + compound.put("Inventory", deferredInventoryList); } super.write(compound, clientPacket); @@ -407,7 +408,7 @@ public class DeployerTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java index 0440de076..72001c7ee 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/AirCurrent.java @@ -8,8 +8,8 @@ import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.AllTags; import com.simibubi.create.content.contraptions.particle.AirFlowParticleData; -import com.simibubi.create.content.logistics.InWorldProcessing; -import com.simibubi.create.content.logistics.InWorldProcessing.Type; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing.Type; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -89,8 +89,7 @@ public class AirCurrent { protected void tickAffectedEntities(World world, Direction facing) { for (Iterator iterator = caughtEntities.iterator(); iterator.hasNext();) { Entity entity = iterator.next(); - if (!entity.isAlive() || !entity.getBoundingBox() - .intersects(bounds)) { + if (!entity.isAlive() || !entity.getBoundingBox().intersects(bounds) || isPlayerCreativeFlying(entity)) { iterator.remove(); continue; } @@ -389,4 +388,12 @@ public class AirCurrent { isClientPlayerInAirCurrent = false; } + public static boolean isPlayerCreativeFlying(Entity entity) { + if (entity instanceof PlayerEntity) { + PlayerEntity player = (PlayerEntity) entity; + return player.isCreative() && player.abilities.isFlying; + } + return false; + } + } 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 6491d16e3..7424cdf81 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 @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.fan; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -9,7 +10,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -28,7 +28,7 @@ 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; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; Direction direction = te.getBlockState() .get(FACING); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java index 2feec9410..5bae092ce 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/FanInstance.java @@ -2,10 +2,10 @@ package com.simibubi.create.content.contraptions.components.fan; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -18,7 +18,7 @@ public class FanInstance extends KineticTileInstance { final Direction direction; private final Direction opposite; - public FanInstance(InstancedTileRenderer modelManager, EncasedFanTileEntity tile) { + public FanInstance(MaterialManager modelManager, EncasedFanTileEntity tile) { super(modelManager, tile); direction = blockState.get(FACING); @@ -41,7 +41,7 @@ public class FanInstance extends KineticTileInstance { } @Override - protected void update() { + public void update() { updateRotation(shaft); updateRotation(fan, getFanSpeed()); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java index 945e8498c..73066ab14 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/NozzleTileEntity.java @@ -49,7 +49,7 @@ public class NozzleTileEntity extends SmartTileEntity { compound.putFloat("Range", range); compound.putBoolean("Pushing", pushing); } - + @Override protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { super.fromTag(state, compound, clientPacket); @@ -89,14 +89,13 @@ public class NozzleTileEntity extends SmartTileEntity { for (Iterator iterator = pushingEntities.iterator(); iterator.hasNext();) { Entity entity = iterator.next(); Vector3d diff = entity.getPositionVec() - .subtract(center); + .subtract(center); if (!(entity instanceof PlayerEntity) && world.isRemote) continue; double distance = diff.length(); - if (distance > range || entity.isSneaking() - || (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) { + if (distance > range || entity.isSneaking() || AirCurrent.isPlayerCreativeFlying(entity)) { iterator.remove(); continue; } @@ -106,7 +105,7 @@ public class NozzleTileEntity extends SmartTileEntity { float factor = (entity instanceof ItemEntity) ? 1 / 128f : 1 / 32f; Vector3d pushVec = diff.normalize() - .scale((range - distance) * (pushing ? 1 : -1)); + .scale((range - distance) * (pushing ? 1 : -1)); entity.setMotion(entity.getMotion() .add(pushVec.scale(factor))); entity.fallDistance = 0; @@ -150,13 +149,11 @@ public class NozzleTileEntity extends SmartTileEntity { for (Entity entity : world.getEntitiesWithinAABB(Entity.class, bb)) { Vector3d diff = entity.getPositionVec() - .subtract(center); + .subtract(center); double distance = diff.length(); - if (distance > range || entity.isSneaking() - || (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative())) { + if (distance > range || entity.isSneaking() || AirCurrent.isPlayerCreativeFlying(entity)) continue; - } boolean canSee = canSee(entity); if (!canSee) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java index e6eafe17f..9bf446385 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/fan/SplashingRecipe.java @@ -3,22 +3,22 @@ package com.simibubi.create.content.contraptions.components.fan; import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing.SplashingWrapper; import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams; -import com.simibubi.create.content.logistics.InWorldProcessing; -import com.simibubi.create.content.logistics.InWorldProcessing.SplashingInv; import net.minecraft.world.World; @ParametersAreNonnullByDefault -public class SplashingRecipe extends ProcessingRecipe { +public class SplashingRecipe extends ProcessingRecipe { public SplashingRecipe(ProcessingRecipeParams params) { super(AllRecipeTypes.SPLASHING, params); } @Override - public boolean matches(SplashingInv inv, World worldIn) { + public boolean matches(SplashingWrapper inv, World worldIn) { if (inv.isEmpty()) return false; return ingredients.get(0) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java index 219adb6d1..b3cbcb990 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/FlyWheelInstance.java @@ -6,16 +6,16 @@ import java.util.Collections; import java.util.List; import com.google.common.collect.Lists; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; 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.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -45,7 +45,7 @@ public class FlyWheelInstance extends KineticTileInstance im protected float lastAngle = Float.NaN; - public FlyWheelInstance(InstancedTileRenderer modelManager, FlywheelTileEntity tile) { + public FlyWheelInstance(MaterialManager modelManager, FlywheelTileEntity tile) { super(modelManager, tile); facing = blockState.get(HORIZONTAL_FACING); @@ -63,15 +63,15 @@ public class FlyWheelInstance extends KineticTileInstance im connectorAngleMult = flipAngle ? -1 : 1; - RenderMaterial> mat = getTransformMaterial(); + InstanceMaterial mat = getTransformMaterial(); - upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance(); - lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance(); - upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, blockState).createInstance(); - lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, blockState).createInstance(); + upperRotating = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_ROTATING, blockState).createInstance(); + lowerRotating = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_ROTATING, blockState).createInstance(); + upperSliding = mat.getModel(AllBlockPartials.FLYWHEEL_UPPER_SLIDING, blockState).createInstance(); + lowerSliding = mat.getModel(AllBlockPartials.FLYWHEEL_LOWER_SLIDING, blockState).createInstance(); - connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding); - } else { + connectors = Lists.newArrayList(upperRotating, lowerRotating, upperSliding, lowerSliding); + } else { connectors = Collections.emptyList(); } @@ -136,7 +136,7 @@ public class FlyWheelInstance extends KineticTileInstance im } @Override - protected void update() { + public void update() { updateRotation(shaft); } @@ -158,7 +158,7 @@ public class FlyWheelInstance extends KineticTileInstance im connectors.clear(); } - protected InstancedModel shaftModel() { + protected Instancer shaftModel() { Direction opposite = facing.getOpposite(); return getRotatingMaterial().getModel(AllBlockPartials.SHAFT_HALF, blockState, opposite); } 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 bf3b46295..fc67fbd98 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 @@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.flywheel; import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -10,7 +11,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock.ConnectionState; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.block.BlockState; @@ -36,7 +36,7 @@ public class FlywheelRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockState blockState = te.getBlockState(); FlywheelTileEntity wte = (FlywheelTileEntity) te; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineBlock.java index f3d07cf66..a32696209 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineBlock.java @@ -2,8 +2,8 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; import javax.annotation.Nullable; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.content.contraptions.wrench.IWrenchable; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.Block; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java index 3f76914d0..4ce123e96 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineInstance.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -16,7 +16,7 @@ public class EngineInstance extends TileEntityInstance { protected ModelData frame; - public EngineInstance(InstancedTileRenderer modelManager, EngineTileEntity tile) { + public EngineInstance(MaterialManager modelManager, EngineTileEntity tile) { super(modelManager, tile); Block block = blockState diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java index 42be5bedf..ce77b42ef 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/EngineRenderer.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.render.PartialBufferer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; @@ -24,10 +24,10 @@ public class EngineRenderer extends SafeTileEntityRe protected void renderSafe(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; Block block = te.getBlockState() - .getBlock(); + .getBlock(); if (block instanceof EngineBlock) { EngineBlock engineBlock = (EngineBlock) block; PartialModel frame = engineBlock.getFrameModel(); 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 6887efaf4..719a735ca 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 @@ -2,10 +2,10 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; import java.util.List; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelBlock; import com.simibubi.create.content.contraptions.components.flywheel.FlywheelTileEntity; -import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java index e50508ad0..e3083ac1a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/flywheel/engine/FurnaceEngineBlock.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.contraptions.components.flywheel.engine; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; import com.simibubi.create.foundation.block.ITE; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import net.minecraft.block.AbstractFurnaceBlock; 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 index e2f931eba..3cf4316e4 100644 --- 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 @@ -1,20 +1,20 @@ package com.simibubi.create.content.contraptions.components.millstone; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; public class MillStoneCogInstance extends SingleRotatingInstance { - public MillStoneCogInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public MillStoneCogInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { return getRotatingMaterial().getModel(AllBlockPartials.MILLSTONE_COG, tile.getBlockState()); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java index bad0b74f5..dcfb06eb1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/millstone/MillstoneBlock.java @@ -99,13 +99,10 @@ public class MillstoneBlock extends KineticBlock implements ITE getTileEntityClass() { return MillstoneTileEntity.class; } - + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; 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 8d0217b77..7fb801ee7 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 @@ -16,7 +16,7 @@ public class MillstoneRenderer extends KineticTileEntityRenderer { @Override protected SuperByteBuffer getRotatedModel(KineticTileEntity te) { - return CreateClient.bufferCache.renderPartial(AllBlockPartials.MILLSTONE_COG, te.getBlockState()); + return CreateClient.BUFFER_CACHE.renderPartial(AllBlockPartials.MILLSTONE_COG, te.getBlockState()); } } 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 cf0cfe81a..0f84de945 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 @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.components.mixer; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -7,7 +8,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.block.BlockState; @@ -33,7 +33,7 @@ public class MechanicalMixerRenderer extends KineticTileEntityRenderer { protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockState blockState = te.getBlockState(); MechanicalMixerTileEntity mixer = (MechanicalMixerTileEntity) te; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java index 2df6346ab..7aac448c8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/mixer/MixerInstance.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.contraptions.components.mixer; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.content.contraptions.base.ShaftlessCogInstance; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Direction; @@ -16,7 +16,7 @@ public class MixerInstance extends ShaftlessCogInstance implements IDynamicInsta private final OrientedData mixerPole; private final MechanicalMixerTileEntity mixer; - public MixerInstance(InstancedTileRenderer dispatcher, MechanicalMixerTileEntity tile) { + public MixerInstance(MaterialManager dispatcher, MechanicalMixerTileEntity tile) { super(dispatcher, tile); this.mixer = tile; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java index 825d3a9ac..3bc960959 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/BeltPressingCallbacks.java @@ -9,9 +9,9 @@ import java.util.stream.Collectors; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.press.MechanicalPressTileEntity.Mode; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; -import com.simibubi.create.content.logistics.InWorldProcessing; import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; @@ -62,7 +62,7 @@ public class BeltPressingCallbacks { boolean centered = BeltHelper.isItemUpright(stack); copy.stack = stack; copy.locked = true; - copy.angle = centered ? 180 : Create.random.nextInt(360); + copy.angle = centered ? 180 : Create.RANDOM.nextInt(360); return copy; }) .collect(Collectors.toList()); 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 189056eb1..2b31d4afc 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 @@ -2,13 +2,13 @@ package com.simibubi.create.content.contraptions.components.press; import static net.minecraft.state.properties.BlockStateProperties.HORIZONTAL_FACING; +import com.jozufozu.flywheel.backend.Backend; 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.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import net.minecraft.block.BlockState; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -33,7 +33,7 @@ public class MechanicalPressRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockPos pos = te.getPos(); BlockState blockState = te.getBlockState(); 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 e840bc3ae..f87ef8786 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 @@ -10,7 +10,7 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.processing.BasinOperatingTileEntity; import com.simibubi.create.content.contraptions.processing.BasinTileEntity; -import com.simibubi.create.content.logistics.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.ITriggerable; import com.simibubi.create.foundation.config.AllConfigs; @@ -187,7 +187,7 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { AllSoundEvents.MECHANICAL_PRESS_ACTIVATION_ON_BELT.playOnServer(world, pos); else AllSoundEvents.MECHANICAL_PRESS_ACTIVATION.playOnServer(world, pos, .5f, .75f + (Math.abs(getSpeed()) / 1024f)); - + if (!world.isRemote) sendData(); } @@ -258,9 +258,9 @@ public class MechanicalPressTileEntity extends BasinOperatingTileEntity { for (ItemStack result : InWorldProcessing.applyRecipeOn(ItemHandlerHelper.copyStackWithSize(item, 1), recipe.get())) { ItemEntity created = - new ItemEntity(world, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result); + new ItemEntity(world, itemEntity.getX(), itemEntity.getY(), itemEntity.getZ(), result); created.setDefaultPickupDelay(); - created.setMotion(VecHelper.offsetRandomly(Vector3d.ZERO, Create.random, .05f)); + created.setMotion(VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .05f)); world.addEntity(created); } item.shrink(1); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java index 8dc92b64f..866fd4fa3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/press/PressInstance.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.contraptions.components.press; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -16,7 +16,7 @@ public class PressInstance extends ShaftInstance implements IDynamicInstance { private final OrientedData pressHead; private final MechanicalPressTileEntity press; - public PressInstance(InstancedTileRenderer dispatcher, MechanicalPressTileEntity tile) { + public PressInstance(MaterialManager dispatcher, MechanicalPressTileEntity tile) { super(dispatcher, tile); press = tile; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java index a3471f32a..287e1b80f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/saw/SawInstance.java @@ -2,12 +2,12 @@ package com.simibubi.create.content.contraptions.components.saw; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; @@ -15,12 +15,12 @@ import net.minecraft.util.Rotation; public class SawInstance extends SingleRotatingInstance { - public SawInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public SawInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { if (blockState.get(FACING).getAxis().isHorizontal()) { BlockState referenceState = blockState.rotate(tile.getWorld(), tile.getPos(), Rotation.CLOCKWISE_180); Direction facing = referenceState.get(FACING); 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 5ab9a2960..7d4532965 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 @@ -2,22 +2,24 @@ package com.simibubi.create.content.contraptions.components.saw; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; 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.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; 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.VecHelper; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -47,18 +49,16 @@ public class SawRenderer extends SafeTileEntityRenderer { renderItems(te, partialTicks, ms, buffer, light, overlay); FilteringRenderer.renderOnTileEntity(te, partialTicks, ms, buffer, light, overlay); - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; renderShaft(te, ms, buffer, light, overlay); } protected void renderBlade(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light) { BlockState blockState = te.getBlockState(); - SuperByteBuffer superBuffer; PartialModel partial; float speed = te.getSpeed(); - - ms.push(); + boolean rotate = false; if (SawBlock.isHorizontal(blockState)) { if (speed > 0) { @@ -78,16 +78,17 @@ public class SawRenderer extends SafeTileEntityRenderer { } if (!blockState.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE)) - MatrixStacker.of(ms) - .centre() - .rotateY(90) - .unCentre(); + rotate = true; } - superBuffer = PartialBufferer.getFacing(partial, blockState); - superBuffer.light(light) - .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); - ms.pop(); + SuperByteBuffer superBuffer = PartialBufferer.getFacing(partial, blockState); + if (rotate) { + superBuffer.rotateCentered(Direction.UP, AngleHelper.rad(90)); + } + superBuffer + .color(0xFFFFFF) + .light(light) + .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); } protected void renderShaft(SawTileEntity te, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { @@ -143,7 +144,7 @@ public class SawRenderer extends SafeTileEntityRenderer { BlockState state = te.getBlockState(); if (state.get(FACING).getAxis().isHorizontal()) return PartialBufferer.getFacing(AllBlockPartials.SHAFT_HALF, state.rotate(te.getWorld(), te.getPos(), Rotation.CLOCKWISE_180)); - return CreateClient.bufferCache.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE, + return CreateClient.BUFFER_CACHE.renderBlockIn(KineticTileEntityRenderer.KINETIC_TILE, getRenderedBlockState(te)); } @@ -151,11 +152,9 @@ public class SawRenderer extends SafeTileEntityRenderer { return KineticTileEntityRenderer.shaft(KineticTileEntityRenderer.getRotationAxisOf(te)); } - public static void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; + public static void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { BlockState state = context.state; - SuperByteBuffer superBuffer; Direction facing = state.get(SawBlock.FACING); Vector3d facingVec = Vector3d.of(context.state.get(SawBlock.FACING) @@ -171,6 +170,7 @@ public class SawRenderer extends SafeTileEntityRenderer { boolean shouldAnimate = (context.contraption.stalled && horizontal) || (!context.contraption.stalled && !backwards && moving); + SuperByteBuffer superBuffer; if (SawBlock.isHorizontal(state)) { if (shouldAnimate) superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_HORIZONTAL_ACTIVE, state); @@ -183,22 +183,25 @@ public class SawRenderer extends SafeTileEntityRenderer { superBuffer = PartialBufferer.get(AllBlockPartials.SAW_BLADE_VERTICAL_INACTIVE, state); } - for (MatrixStack m : matrixStacks) { + MatrixStack m = matrices.contraptionStack; + m.push(); + MatrixStacker.of(m) + .centre() + .rotateY(AngleHelper.horizontalAngle(facing)) + .rotateX(AngleHelper.verticalAngle(facing)); + if (!SawBlock.isHorizontal(state)) MatrixStacker.of(m) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)); - if (!SawBlock.isHorizontal(state)) - MatrixStacker.of(m) - .rotateZ(state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90); - MatrixStacker.of(m) - .unCentre(); - } + .rotateZ(state.get(SawBlock.AXIS_ALONG_FIRST_COORDINATE) ? 0 : 90); + MatrixStacker.of(m) + .unCentre(); superBuffer - .light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)) - .renderInto(ms, buffer.getBuffer(RenderType.getCutoutMipped())); + .transform(m) + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getCutoutMipped())); + + m.pop(); } } 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 2e4edd2a1..b4f0ab6ef 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 @@ -11,15 +11,18 @@ import java.util.stream.Collectors; import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllRecipeTypes; +import com.simibubi.create.AllSoundEvents; import com.simibubi.create.AllTags; import com.simibubi.create.content.contraptions.components.actors.BlockBreakingKineticTileEntity; import com.simibubi.create.content.contraptions.processing.ProcessingInventory; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.item.ItemHelper; +import com.simibubi.create.foundation.sound.SoundScapes; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.utility.AbstractBlockBreakQueue; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.TreeCutter; import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.recipe.RecipeConditions; @@ -33,10 +36,12 @@ import net.minecraft.block.CactusBlock; import net.minecraft.block.ChorusPlantBlock; import net.minecraft.block.KelpBlock; import net.minecraft.block.KelpTopBlock; +import net.minecraft.block.SoundType; import net.minecraft.block.StemGrownBlock; import net.minecraft.block.SugarCaneBlock; import net.minecraft.entity.item.ItemEntity; import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipeType; @@ -55,6 +60,8 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.registry.Registry; +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.items.CapabilityItemHandler; @@ -72,6 +79,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { private int recipeIndex; private final LazyOptional invProvider; private FilteringBehaviour filtering; + private boolean processingStarted; public SawTileEntity(TileEntityType type) { super(type); @@ -79,6 +87,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { inventory.remainingTime = -1; recipeIndex = 0; invProvider = LazyOptional.of(() -> inventory); + processingStarted = false; } @Override @@ -94,6 +103,11 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { compound.put("Inventory", inventory.serializeNBT()); compound.putInt("RecipeIndex", recipeIndex); super.write(compound, clientPacket); + + if (!clientPacket || !processingStarted) + return; + processingStarted = false; + NBTHelper.putMarker(compound, "ProcessingStarted"); } @Override @@ -101,6 +115,40 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { super.fromTag(state, compound, clientPacket); inventory.deserializeNBT(compound.getCompound("Inventory")); recipeIndex = compound.getInt("RecipeIndex"); + if (compound.contains("ProcessingStarted")) + processingStarted = true; + } + + @Override + @OnlyIn(Dist.CLIENT) + public void tickAudio() { + super.tickAudio(); + if (getSpeed() == 0) + return; + + SoundScapes.play(SoundScapes.AmbienceGroup.SAW, pos, 1); + + ItemStack stackInSlot = inventory.getStackInSlot(0); + if (stackInSlot.isEmpty()) + return; + + boolean isWood = false; + Item item = stackInSlot.getItem(); + if (item instanceof BlockItem) { + Block block = ((BlockItem) item).getBlock(); + isWood = block.getSoundType(block.getDefaultState(), world, pos, null) == SoundType.WOOD; + } + + if (processingStarted) { + processingStarted = false; + if (!isWood) + AllSoundEvents.SAW_ACTIVATE_STONE.playAt(world, pos, 1, 1, true); + else + AllSoundEvents.SAW_ACTIVATE_WOOD.playAt(world, pos, 1, 1, true); + return; + } + +// AllSoundEvents.SAW_PROCESS.playAt(world, pos, 1, 1, true); TODO } @Override @@ -125,9 +173,6 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { if (inventory.remainingTime > 0) spawnParticles(inventory.getStackInSlot(0)); - if (world.isRemote && !isVirtual()) - return; - if (inventory.remainingTime < 20 && !inventory.appliedRecipe) { applyRecipe(); inventory.appliedRecipe = true; @@ -322,7 +367,8 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { List> recipes = getRecipes(); boolean valid = !recipes.isEmpty(); - int time = 100; + processingStarted = true; + int time = 50; if (recipes.isEmpty()) { inventory.remainingTime = inventory.recipeDuration = 10; @@ -375,14 +421,16 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { } super.onBlockBroken(stateToBreak); - TreeCutter.findTree(world, breakingPos).destroyBlocks(world, null, this::dropItemFromCutTree); + TreeCutter.findTree(world, breakingPos) + .destroyBlocks(world, null, this::dropItemFromCutTree); } public void dropItemFromCutTree(BlockPos pos, ItemStack stack) { float distance = (float) Math.sqrt(pos.distanceSq(breakingPos)); Vector3d dropPos = VecHelper.getCenterOf(pos); ItemEntity entity = new ItemEntity(world, dropPos.x, dropPos.y, dropPos.z, stack); - entity.setMotion(Vector3d.of(breakingPos.subtract(this.pos)).scale(distance / 20f)); + entity.setMotion(Vector3d.of(breakingPos.subtract(this.pos)) + .scale(distance / 20f)); world.addEntity(entity); } @@ -393,7 +441,8 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { } public static boolean isSawable(BlockState stateToBreak) { - if (stateToBreak.isIn(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(stateToBreak) || stateToBreak.isIn(BlockTags.LEAVES)) + if (stateToBreak.isIn(BlockTags.LOGS) || AllTags.AllBlockTags.SLIMY_LOGS.matches(stateToBreak) + || stateToBreak.isIn(BlockTags.LEAVES)) return true; Block block = stateToBreak.getBlock(); if (block instanceof BambooBlock) @@ -416,7 +465,7 @@ public class SawTileEntity extends BlockBreakingKineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { 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 5c651529a..7008ac746 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 @@ -15,6 +15,7 @@ import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.AllSoundEvents; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.actors.SeatEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; @@ -57,7 +58,7 @@ import net.minecraftforge.fml.network.PacketDistributor; public abstract class AbstractContraptionEntity extends Entity implements IEntityAdditionalSpawnData { private static final DataParameter STALLED = - EntityDataManager.createKey(AbstractContraptionEntity.class, DataSerializers.BOOLEAN); + EntityDataManager.createKey(AbstractContraptionEntity.class, DataSerializers.BOOLEAN); public final Map collidingEntities; @@ -391,8 +392,8 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit byte[] byteArray = dataOutput.toByteArray(); int estimatedPacketSize = byteArray.length; if (estimatedPacketSize > 2_000_000) { - Create.logger.warn("Could not send Contraption Spawn Data (Packet too big): " - + getContraption().getType().id + " @" + getPositionVec() + " (" + getUniqueID().toString() + ")"); + Create.LOGGER.warn("Could not send Contraption Spawn Data (Packet too big): " + + getContraption().getType().id + " @" + getPositionVec() + " (" + getUniqueID().toString() + ")"); buffer.writeCompoundTag(new CompoundNBT()); return; } @@ -431,7 +432,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit protected void readAdditional(CompoundNBT compound, boolean spawnData) { if (compound.isEmpty()) return; - + initialized = compound.getBoolean("Initialized"); contraption = Contraption.fromNBT(world, compound.getCompound("Contraption"), spawnData); contraption.entity = this; @@ -467,6 +468,7 @@ public abstract class AbstractContraptionEntity extends Entity implements IEntit removePassengers(); moveCollidedEntitiesOnDisassembly(transform); + AllSoundEvents.CONTRAPTION_DISASSEMBLE.playOnServer(world, getBlockPos()); } private void moveCollidedEntitiesOnDisassembly(StructureTransform transform) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java similarity index 63% rename from src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java rename to src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java index 5a47573fe..b8b0da9d1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementTraits.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/BlockMovementChecks.java @@ -1,7 +1,11 @@ package com.simibubi.create.content.contraptions.components.structureMovement; +import java.util.ArrayList; +import java.util.List; + import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTags.AllBlockTags; +import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.actors.AttachedActorBlock; import com.simibubi.create.content.contraptions.components.actors.HarvesterBlock; import com.simibubi.create.content.contraptions.components.actors.PortableStorageInterfaceBlock; @@ -26,9 +30,14 @@ import com.simibubi.create.content.contraptions.fluids.tank.FluidTankBlock; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankConnectivityHandler; import com.simibubi.create.content.logistics.block.redstone.RedstoneLinkBlock; +import com.simibubi.create.foundation.config.AllConfigs; + +import com.simibubi.create.foundation.config.CKinetics; + import net.minecraft.block.AbstractPressurePlateBlock; import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.AbstractSignBlock; +import net.minecraft.block.BedBlock; import net.minecraft.block.BellBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -43,43 +52,153 @@ import net.minecraft.block.LadderBlock; import net.minecraft.block.RedstoneDiodeBlock; import net.minecraft.block.RedstoneWallTorchBlock; import net.minecraft.block.RedstoneWireBlock; +import net.minecraft.block.SpawnerBlock; import net.minecraft.block.StandingSignBlock; import net.minecraft.block.TorchBlock; import net.minecraft.block.WallSignBlock; import net.minecraft.block.WallTorchBlock; import net.minecraft.block.material.PushReaction; import net.minecraft.state.properties.AttachFace; +import net.minecraft.state.properties.BedPart; import net.minecraft.state.properties.BellAttachment; import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.state.properties.DoubleBlockHalf; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockReader; import net.minecraft.world.World; -public class BlockMovementTraits { +public class BlockMovementChecks { - public static boolean movementNecessary(BlockState state, World world, BlockPos pos) { + private static final List MOVEMENT_NECESSARY_CHECKS = new ArrayList<>(); + private static final List MOVEMENT_ALLOWED_CHECKS = new ArrayList<>(); + private static final List BRITTLE_CHECKS = new ArrayList<>(); + private static final List ATTACHED_CHECKS = new ArrayList<>(); + private static final List NOT_SUPPORTIVE_CHECKS = new ArrayList<>(); + public static final ResourceLocation NON_MOVABLE = new ResourceLocation(Create.ID, "non_movable"); + + // Registration + // Add new checks to the front instead of the end + + public static void registerMovementNecessaryCheck(MovementNecessaryCheck check) { + MOVEMENT_NECESSARY_CHECKS.add(0, check); + } + + public static void registerMovementAllowedCheck(MovementAllowedCheck check) { + MOVEMENT_ALLOWED_CHECKS.add(0, check); + } + + public static void registerBrittleCheck(BrittleCheck check) { + BRITTLE_CHECKS.add(0, check); + } + + public static void registerAttachedCheck(AttachedCheck check) { + ATTACHED_CHECKS.add(0, check); + } + + public static void registerNotSupportiveCheck(NotSupportiveCheck check) { + NOT_SUPPORTIVE_CHECKS.add(0, check); + } + + public static void registerAllChecks(AllChecks checks) { + registerMovementNecessaryCheck(checks); + registerMovementAllowedCheck(checks); + registerBrittleCheck(checks); + registerAttachedCheck(checks); + registerNotSupportiveCheck(checks); + } + + // Actual check methods + + public static boolean isMovementNecessary(BlockState state, World world, BlockPos pos) { + for (MovementNecessaryCheck check : MOVEMENT_NECESSARY_CHECKS) { + CheckResult result = check.isMovementNecessary(state, world, pos); + if (result != CheckResult.PASS) { + return result.toBoolean(); + } + } + return isMovementNecessaryFallback(state, world, pos); + } + + public static boolean isMovementAllowed(BlockState state, World world, BlockPos pos) { + for (MovementAllowedCheck check : MOVEMENT_ALLOWED_CHECKS) { + CheckResult result = check.isMovementAllowed(state, world, pos); + if (result != CheckResult.PASS) { + return result.toBoolean(); + } + } + return isMovementAllowedFallback(state, world, pos); + } + + /** + * Brittle blocks will be collected first, as they may break when other blocks + * are removed before them + */ + public static boolean isBrittle(BlockState state) { + for (BrittleCheck check : BRITTLE_CHECKS) { + CheckResult result = check.isBrittle(state); + if (result != CheckResult.PASS) { + return result.toBoolean(); + } + } + return isBrittleFallback(state); + } + + /** + * Attached blocks will move if blocks they are attached to are moved + */ + public static boolean isBlockAttachedTowards(BlockState state, World world, BlockPos pos, + Direction direction) { + for (AttachedCheck check : ATTACHED_CHECKS) { + CheckResult result = check.isBlockAttachedTowards(state, world, pos, direction); + if (result != CheckResult.PASS) { + return result.toBoolean(); + } + } + return isBlockAttachedTowardsFallback(state, world, pos, direction); + } + + /** + * Non-Supportive blocks will not continue a chain of blocks picked up by e.g. a + * piston + */ + public static boolean isNotSupportive(BlockState state, Direction facing) { + for (NotSupportiveCheck check : NOT_SUPPORTIVE_CHECKS) { + CheckResult result = check.isNotSupportive(state, facing); + if (result != CheckResult.PASS) { + return result.toBoolean(); + } + } + return isNotSupportiveFallback(state, facing); + } + + // Fallback checks + + private static boolean isMovementNecessaryFallback(BlockState state, World world, BlockPos pos) { if (isBrittle(state)) return true; if (state.getBlock() instanceof FenceGateBlock) return true; if (state.getMaterial() - .isReplaceable()) + .isReplaceable()) return false; if (state.getCollisionShape(world, pos) - .isEmpty()) + .isEmpty()) return false; return true; } - public static boolean movementAllowed(BlockState state, World world, BlockPos pos) { + private static boolean isMovementAllowedFallback(BlockState state, World world, BlockPos pos) { Block block = state.getBlock(); if (block instanceof AbstractChassisBlock) return true; if (state.getBlockHardness(world, pos) == -1) return false; - if (AllBlockTags.NON_MOVABLE.matches(state)) + if (state.getBlock().getTags().contains(NON_MOVABLE)) + return false; + if (AllConfigs.SERVER.kinetics.spawnerMovement.get() == CKinetics.SpawnerMovementSetting.UNMOVABLE + && block instanceof SpawnerBlock) return false; // Move controllers only when they aren't moving @@ -113,11 +232,7 @@ public class BlockMovementTraits { return state.getPushReaction() != PushReaction.BLOCK; } - /** - * Brittle blocks will be collected first, as they may break when other blocks - * are removed before them - */ - public static boolean isBrittle(BlockState state) { + private static boolean isBrittleFallback(BlockState state) { Block block = state.getBlock(); if (state.contains(BlockStateProperties.HANGING)) return true; @@ -145,11 +260,8 @@ public class BlockMovementTraits { return AllBlockTags.BRITTLE.tag.contains(block); } - /** - * Attached blocks will move if blocks they are attached to are moved - */ - public static boolean isBlockAttachedTowards(IBlockReader world, BlockPos pos, BlockState state, - Direction direction) { + private static boolean isBlockAttachedTowardsFallback(BlockState state, World world, BlockPos pos, + Direction direction) { Block block = state.getBlock(); if (block instanceof LadderBlock) return state.get(LadderBlock.FACING) == direction.getOpposite(); @@ -161,8 +273,17 @@ public class BlockMovementTraits { return direction == Direction.DOWN; if (block instanceof AbstractPressurePlateBlock) return direction == Direction.DOWN; - if (block instanceof DoorBlock) + if (block instanceof DoorBlock) { + if (state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER && direction == Direction.UP) + return true; return direction == Direction.DOWN; + } + if (block instanceof BedBlock) { + Direction facing = state.get(BedBlock.HORIZONTAL_FACING); + if (state.get(BedBlock.PART) == BedPart.HEAD) + facing = facing.getOpposite(); + return direction == facing; + } if (block instanceof RedstoneLinkBlock) return direction.getOpposite() == state.get(RedstoneLinkBlock.FACING); if (block instanceof FlowerPotBlock) @@ -212,21 +333,17 @@ public class BlockMovementTraits { } if (state.getBlock() instanceof SailBlock) return direction.getAxis() != state.get(SailBlock.FACING) - .getAxis(); + .getAxis(); if (state.getBlock() instanceof FluidTankBlock) return FluidTankConnectivityHandler.isConnected(world, pos, pos.offset(direction)); if (AllBlocks.STICKER.has(state) && state.get(StickerBlock.EXTENDED)) { return direction == state.get(StickerBlock.FACING) - && !notSupportive(world.getBlockState(pos.offset(direction)), direction.getOpposite()); + && !isNotSupportive(world.getBlockState(pos.offset(direction)), direction.getOpposite()); } return false; } - /** - * Non-Supportive blocks will not continue a chain of blocks picked up by e.g. a - * piston - */ - public static boolean notSupportive(BlockState state, Direction facing) { + private static boolean isNotSupportiveFallback(BlockState state, Direction facing) { if (AllBlocks.MECHANICAL_DRILL.has(state)) return state.get(BlockStateProperties.FACING) == facing; if (AllBlocks.MECHANICAL_BEARING.has(state)) @@ -248,13 +365,67 @@ public class BlockMovementTraits { .getAxis(); if (AllBlocks.PISTON_EXTENSION_POLE.has(state)) return facing.getAxis() != state.get(BlockStateProperties.FACING) - .getAxis(); + .getAxis(); if (AllBlocks.MECHANICAL_PISTON_HEAD.has(state)) return facing.getAxis() != state.get(BlockStateProperties.FACING) - .getAxis(); + .getAxis(); if (AllBlocks.STICKER.has(state) && !state.get(StickerBlock.EXTENDED)) return facing == state.get(StickerBlock.FACING); return isBrittle(state); } + // Check classes + + public static interface MovementNecessaryCheck { + public CheckResult isMovementNecessary(BlockState state, World world, BlockPos pos); + } + + public static interface MovementAllowedCheck { + public CheckResult isMovementAllowed(BlockState state, World world, BlockPos pos); + } + + public static interface BrittleCheck { + /** + * Brittle blocks will be collected first, as they may break when other blocks + * are removed before them + */ + public CheckResult isBrittle(BlockState state); + } + + public static interface AttachedCheck { + /** + * Attached blocks will move if blocks they are attached to are moved + */ + public CheckResult isBlockAttachedTowards(BlockState state, World world, BlockPos pos, Direction direction); + } + + public static interface NotSupportiveCheck { + /** + * Non-Supportive blocks will not continue a chain of blocks picked up by e.g. a + * piston + */ + public CheckResult isNotSupportive(BlockState state, Direction direction); + } + + public static interface AllChecks extends MovementNecessaryCheck, MovementAllowedCheck, BrittleCheck, AttachedCheck, NotSupportiveCheck { + } + + public static enum CheckResult { + SUCCESS, + FAIL, + PASS; + + public Boolean toBoolean() { + return this == PASS ? null : (this == SUCCESS ? true : false); + } + + public static CheckResult of(boolean b) { + return b ? SUCCESS : FAIL; + } + + public static CheckResult of(Boolean b) { + return b == null ? PASS : (b ? SUCCESS : FAIL); + } + } + } 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 f7c07d10d..761949ae4 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 @@ -25,6 +25,8 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.tuple.MutablePair; import org.apache.commons.lang3.tuple.Pair; +import com.jozufozu.flywheel.backend.IFlywheelWorld; +import com.jozufozu.flywheel.light.GridAlignedBB; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.content.contraptions.base.IRotate; @@ -48,6 +50,7 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pul import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.MagnetBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyBlock.RopeBlock; import com.simibubi.create.content.contraptions.components.structureMovement.pulley.PulleyTileEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.render.EmptyLighter; import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; @@ -56,12 +59,9 @@ import com.simibubi.create.content.logistics.block.inventories.CreativeCrateTile 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.instancing.IFlywheelWorld; -import com.simibubi.create.foundation.render.backend.light.EmptyLighter; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.utility.BlockFace; -import com.simibubi.create.foundation.utility.Coordinate; +import com.simibubi.create.foundation.utility.ICoordinate; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTProcessors; @@ -73,7 +73,6 @@ 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; @@ -87,7 +86,6 @@ import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.NBTUtil; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.ChestType; -import net.minecraft.state.properties.DoubleBlockHalf; import net.minecraft.state.properties.PistonType; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.Direction; @@ -121,7 +119,7 @@ public abstract class Contraption { public Optional> simplifiedEntityColliders; public AbstractContraptionEntity entity; - public CombinedInvWrapper inventory; + public ContraptionInvWrapper inventory; public CombinedTankWrapper fluidInventory; public AxisAlignedBB bounds; public BlockPos anchor; @@ -212,7 +210,7 @@ public abstract class Contraption { if (bounds == null) bounds = new AxisAlignedBB(BlockPos.ZERO); - if (!BlockMovementTraits.isBrittle(world.getBlockState(pos))) + if (!BlockMovementChecks.isBrittle(world.getBlockState(pos))) frontier.add(pos); if (!addToInitialFrontier(world, pos, forcedDirection, frontier)) return false; @@ -241,8 +239,7 @@ public abstract class Contraption { continue; } subContraption.removeBlocksFromWorld(world, BlockPos.ZERO); - OrientedContraptionEntity movedContraption = - OrientedContraptionEntity.create(world, subContraption, Optional.of(face)); + OrientedContraptionEntity movedContraption = OrientedContraptionEntity.create(world, subContraption, face); BlockPos anchor = blockFace.getConnectedPos(); movedContraption.setPosition(anchor.getX() + .5f, anchor.getY(), anchor.getZ() + .5f); world.addEntity(movedContraption); @@ -254,7 +251,7 @@ public abstract class Contraption { .stream() .map(MountedStorage::getItemHandler) .collect(Collectors.toList()); - inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); + inventory = new ContraptionInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class)); List fluidHandlers = fluidStorage.values() .stream() @@ -312,12 +309,12 @@ public abstract class Contraption { if (isAnchoringBlockAt(pos)) return true; BlockState state = world.getBlockState(pos); - if (!BlockMovementTraits.movementNecessary(state, world, pos)) + if (!BlockMovementChecks.isMovementNecessary(state, world, pos)) return true; if (!movementAllowed(state, world, pos)) throw AssemblyException.unmovableBlock(pos, state); if (state.getBlock() instanceof AbstractChassisBlock - && !moveChassis(world, pos, forcedDirection, frontier, visited)) + && !moveChassis(world, pos, forcedDirection, frontier, visited)) return false; if (AllBlocks.ADJUSTABLE_CRATE.has(state)) @@ -336,14 +333,14 @@ public abstract class Contraption { Direction offset = state.get(StickerBlock.FACING); BlockPos attached = pos.offset(offset); if (!visited.contains(attached) - && !BlockMovementTraits.notSupportive(world.getBlockState(attached), offset.getOpposite())) + && !BlockMovementChecks.isNotSupportive(world.getBlockState(attached), offset.getOpposite())) frontier.add(attached); } // Bearings potentially create stabilized sub-contraptions if (AllBlocks.MECHANICAL_BEARING.has(state)) moveBearing(pos, frontier, visited, state); - + // WM Bearings attach their structure when moved if (AllBlocks.WINDMILL_BEARING.has(state)) moveWindmillBearing(pos, frontier, visited, state); @@ -365,13 +362,6 @@ public abstract class Contraption { if (isPistonHead(state)) movePistonHead(world, pos, frontier, visited, state); - // Doors try to stay whole - if (state.getBlock() instanceof DoorBlock) { - BlockPos otherPartPos = pos.up(state.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER ? 1 : -1); - if (!visited.contains(otherPartPos)) - frontier.add(otherPartPos); - } - // Cart assemblers attach themselves BlockPos posDown = pos.down(); BlockState stateBelow = world.getBlockState(posDown); @@ -395,24 +385,24 @@ public abstract class Contraption { boolean wasVisited = visited.contains(offsetPos); boolean faceHasGlue = superglue.containsKey(offset); boolean blockAttachedTowardsFace = - BlockMovementTraits.isBlockAttachedTowards(world, offsetPos, blockState, offset.getOpposite()); - boolean brittle = BlockMovementTraits.isBrittle(blockState); + BlockMovementChecks.isBlockAttachedTowards(blockState, world, offsetPos, offset.getOpposite()); + boolean brittle = BlockMovementChecks.isBrittle(blockState); boolean canStick = !brittle && state.canStickTo(blockState) && blockState.canStickTo(state); if (canStick) { if (state.getPushReaction() == PushReaction.PUSH_ONLY - || blockState.getPushReaction() == PushReaction.PUSH_ONLY) { + || blockState.getPushReaction() == PushReaction.PUSH_ONLY) { canStick = false; } - if (BlockMovementTraits.notSupportive(state, offset)) { + if (BlockMovementChecks.isNotSupportive(state, offset)) { canStick = false; } - if (BlockMovementTraits.notSupportive(blockState, offset.getOpposite())) { + if (BlockMovementChecks.isNotSupportive(blockState, offset.getOpposite())) { canStick = false; } } if (!wasVisited && (canStick || blockAttachedTowardsFace || faceHasGlue - || (offset == forcedDirection && !BlockMovementTraits.notSupportive(state, forcedDirection)))) + || (offset == forcedDirection && !BlockMovementChecks.isNotSupportive(state, forcedDirection)))) frontier.add(offsetPos); if (faceHasGlue) addGlue(superglue.get(offset)); @@ -674,7 +664,7 @@ public abstract class Contraption { } protected boolean movementAllowed(BlockState state, World world, BlockPos pos) { - return BlockMovementTraits.movementAllowed(state, world, pos); + return BlockMovementChecks.isMovementAllowed(state, world, pos); } protected boolean isAnchoringBlockAt(BlockPos pos) { @@ -748,7 +738,7 @@ public abstract class Contraption { for (MountedFluidStorage mountedStorage : fluidStorage.values()) fluidHandlers[index++] = mountedStorage.getFluidHandler(); - inventory = new CombinedInvWrapper(handlers); + inventory = new ContraptionInvWrapper(handlers); fluidInventory = new CombinedTankWrapper(fluidHandlers); if (nbt.contains("BoundsFront")) @@ -944,11 +934,11 @@ public abstract class Contraption { for (Iterator iterator = blocks.values() .iterator(); iterator.hasNext();) { BlockInfo block = iterator.next(); - if (brittles != BlockMovementTraits.isBrittle(block.state)) + if (brittles != BlockMovementChecks.isBrittle(block.state)) continue; BlockPos add = block.pos.add(anchor) - .add(offset); + .add(offset); if (customBlockRemoval(world, add, block.state)) continue; BlockState oldState = world.getBlockState(add); @@ -974,17 +964,14 @@ public abstract class Contraption { // continue; int flags = BlockFlags.IS_MOVING | BlockFlags.DEFAULT; world.notifyBlockUpdate(add, block.state, Blocks.AIR.getDefaultState(), flags); - world.markAndNotifyBlock(add, world.getChunkAt(add), block.state, Blocks.AIR.getDefaultState(), flags, 512); block.state.updateDiagonalNeighbors(world, add, flags & -2); -// world.markAndNotifyBlock(add, null, block.state, Blocks.AIR.getDefaultState(), -// BlockFlags.IS_MOVING | BlockFlags.DEFAULT); this method did strange logspamming with POI-related blocks } } public void addBlocksToWorld(World world, StructureTransform transform) { for (boolean nonBrittles : Iterate.trueAndFalse) { for (BlockInfo block : blocks.values()) { - if (nonBrittles == BlockMovementTraits.isBrittle(block.state)) + if (nonBrittles == BlockMovementChecks.isBrittle(block.state)) continue; BlockPos targetPos = transform.apply(block.pos); @@ -1065,8 +1052,10 @@ public abstract class Contraption { BlockFlags.IS_MOVING | BlockFlags.DEFAULT, 512); } - for (int i = 0; i < inventory.getSlots(); i++) - inventory.setStackInSlot(i, ItemStack.EMPTY); + for (int i = 0; i < inventory.getSlots(); i++) { + if (!inventory.isSlotExternal(i)) + inventory.setStackInSlot(i, ItemStack.EMPTY); + } for (int i = 0; i < fluidInventory.getTanks(); i++) fluidInventory.drain(fluidInventory.getFluidInTank(i), FluidAction.EXECUTE); @@ -1226,16 +1215,16 @@ public abstract class Contraption { switch (axis) { case X: return getMaxDistSqr(blocks, BlockPos::getY, BlockPos::getZ); - case Y: - return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ); - case Z: - return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY); + case Y: + return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getZ); + case Z: + return getMaxDistSqr(blocks, BlockPos::getX, BlockPos::getY); } throw new IllegalStateException("Impossible axis"); } - public static float getMaxDistSqr(Set blocks, Coordinate one, Coordinate other) { + public static float getMaxDistSqr(Set blocks, ICoordinate one, ICoordinate other) { float maxDistSq = -1; for (BlockPos pos : blocks) { float a = one.get(pos); @@ -1273,4 +1262,24 @@ public abstract class Contraption { return pos.equals(te.getPos()); } } + + public static class ContraptionInvWrapper extends CombinedInvWrapper { + protected final boolean isExternal; + + public ContraptionInvWrapper(boolean isExternal, IItemHandlerModifiable... itemHandler) { + super(itemHandler); + this.isExternal = isExternal; + } + + public ContraptionInvWrapper(IItemHandlerModifiable... itemHandler) { + this(false, itemHandler); + } + + public boolean isSlotExternal(int slot) { + if (isExternal) + return true; + IItemHandlerModifiable handler = getHandlerFromIndex(getIndexForSlot(slot)); + return handler instanceof ContraptionInvWrapper && ((ContraptionInvWrapper) handler).isSlotExternal(slot); + } + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java index 271319b91..8d8ed3b62 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionEntityRenderer.java @@ -1,20 +1,19 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; -import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.culling.ClippingHelper; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.MathHelper; public class ContraptionEntityRenderer extends EntityRenderer { - public ContraptionEntityRenderer(EntityRendererManager p_i46179_1_) { - super(p_i46179_1_); + public ContraptionEntityRenderer(EntityRendererManager manager) { + super(manager); } @Override @@ -23,42 +22,26 @@ public class ContraptionEntityRenderer exte } @Override - public boolean shouldRender(C entity, ClippingHelper clippingHelper, double p_225626_3_, double p_225626_5_, - double p_225626_7_) { + public boolean shouldRender(C entity, ClippingHelper clippingHelper, double cameraX, double cameraY, + double cameraZ) { if (entity.getContraption() == null) return false; if (!entity.isAlive()) return false; - return super.shouldRender(entity, clippingHelper, p_225626_3_, p_225626_5_, p_225626_7_); + return super.shouldRender(entity, clippingHelper, cameraX, cameraY, cameraZ); } - + @Override public void render(C entity, float yaw, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffers, int overlay) { super.render(entity, yaw, partialTicks, ms, buffers, overlay); - // Keep a copy of the transforms in order to determine correct lighting - MatrixStack msLocal = translateTo(entity, AnimationTickHolder.getPartialTicks()); - MatrixStack[] matrixStacks = new MatrixStack[] { ms, msLocal }; - - ms.push(); - entity.doLocalTransforms(partialTicks, matrixStacks); + ContraptionMatrices matrices = new ContraptionMatrices(ms, entity); Contraption contraption = entity.getContraption(); if (contraption != null) { - ContraptionRenderDispatcher.render(entity, ms, buffers, msLocal, contraption); + ContraptionRenderDispatcher.render(entity, contraption, matrices, buffers); } - ms.pop(); - - } - - protected MatrixStack translateTo(AbstractContraptionEntity entity, float pt) { - MatrixStack matrixStack = new MatrixStack(); - double x = MathHelper.lerp(pt, entity.lastTickPosX, entity.getX()); - double y = MathHelper.lerp(pt, entity.lastTickPosY, entity.getY()); - double z = MathHelper.lerp(pt, entity.lastTickPosZ, entity.getZ()); - matrixStack.translate(x, y, z); - return matrixStack; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java index 641c3a90c..0e5a776b3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionLighter.java @@ -1,15 +1,15 @@ package com.simibubi.create.content.contraptions.components.structureMovement; +import com.jozufozu.flywheel.light.GridAlignedBB; +import com.jozufozu.flywheel.light.ILightUpdateListener; +import com.jozufozu.flywheel.light.LightUpdater; +import com.jozufozu.flywheel.light.LightVolume; import com.simibubi.create.content.contraptions.components.structureMovement.render.RenderedContraption; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; -import com.simibubi.create.foundation.render.backend.light.LightUpdateListener; -import com.simibubi.create.foundation.render.backend.light.LightUpdater; -import com.simibubi.create.foundation.render.backend.light.LightVolume; import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.LightType; -public abstract class ContraptionLighter implements LightUpdateListener { +public abstract class ContraptionLighter implements ILightUpdateListener { protected final C contraption; public final LightVolume lightVolume; 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 4d70938b2..dbdef7a30 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 @@ -34,6 +34,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { protected Axis rotationAxis; protected float prevAngle; protected float angle; + protected float angleDelta; public ControlledContraptionEntity(EntityType type, World world) { super(type, world); @@ -130,9 +131,10 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { public void setPositionAndRotationDirect(double x, double y, double z, float yw, float pt, int inc, boolean t) {} protected void tickContraption() { + angleDelta = angle - prevAngle; prevAngle = angle; tickActors(); - + if (controllerPos == null) return; if (!world.isBlockPresent(controllerPos)) @@ -171,7 +173,7 @@ public class ControlledContraptionEntity extends AbstractContraptionEntity { return false; if (!VecHelper.onSameAxis(blockInfo.pos, BlockPos.ZERO, facing.getAxis())) return false; - context.motion = Vector3d.of(facing.getDirectionVec()).scale(angle - prevAngle); + context.motion = Vector3d.of(facing.getDirectionVec()).scale(angleDelta / 360.0); context.relativeMotion = context.motion; int timer = context.data.getInt("StationaryTimer"); if (timer > 0) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java index bb0a20b5e..2bf9f5db0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/DirectionalExtenderScrollOptionSlot.java @@ -30,4 +30,4 @@ public class DirectionalExtenderScrollOptionSlot extends CenteredSideValueBoxTra MatrixStacker.of(ms).rotateY(AngleHelper.horizontalAngle(state.get(BlockStateProperties.FACING)) - 90); super.rotate(state, ms); } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java index 02ce47715..fb49312d3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/MountedStorage.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.content.contraptions.processing.ProcessingInventory; import com.simibubi.create.content.logistics.block.inventories.AdjustableCrateBlock; import com.simibubi.create.content.logistics.block.inventories.BottomlessItemHandler; import com.simibubi.create.foundation.utility.NBTHelper; @@ -44,7 +45,8 @@ public class MountedStorage { return true; LazyOptional capability = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); - return capability.orElse(null) instanceof ItemStackHandler; + IItemHandler handler = capability.orElse(null); + return handler instanceof ItemStackHandler && !(handler instanceof ProcessingInventory); } public MountedStorage(TileEntity te) { 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 9b17ea7f5..e2b035323 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 @@ -2,9 +2,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement; import javax.annotation.Nullable; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.entity.item.ItemEntity; @@ -60,12 +61,12 @@ public abstract class MovementBehaviour { } @OnlyIn(Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) {} + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) {} @OnlyIn(Dist.CLIENT) @Nullable - public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { + public ActorInstance createInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { return null; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java index 9ce341586..50345908c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/NonStationaryLighter.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement; +import com.jozufozu.flywheel.light.GridAlignedBB; 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) { 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 49b4d3594..f8e1a3f91 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 @@ -85,17 +85,17 @@ public class OrientedContraptionEntity extends AbstractContraptionEntity { } public static OrientedContraptionEntity create(World world, Contraption contraption, - Optional initialOrientation) { + Direction initialOrientation) { OrientedContraptionEntity entity = new OrientedContraptionEntity(AllEntityTypes.ORIENTED_CONTRAPTION.get(), world); entity.setContraption(contraption); - initialOrientation.ifPresent(entity::setInitialOrientation); + entity.setInitialOrientation(initialOrientation); entity.startAtInitialYaw(); return entity; } public static OrientedContraptionEntity createAtYaw(World world, Contraption contraption, - Optional initialOrientation, float initialYaw) { + Direction initialOrientation, float initialYaw) { OrientedContraptionEntity entity = create(world, contraption, initialOrientation); entity.startAtYaw(initialYaw); entity.manuallyPlaced = true; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java index b5ed7ee45..16bd4e82a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/AnchoredLighter.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import com.jozufozu.flywheel.light.GridAlignedBB; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; public class AnchoredLighter extends ContraptionLighter { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java index f3c46d7d6..52febb972 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/BearingInstance.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.BackHalfShaftInstance; import com.simibubi.create.content.contraptions.base.KineticTileEntity; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -23,7 +23,7 @@ public class BearingInstance e final Vector3f rotationAxis; final Quaternion blockOrientation; - public BearingInstance(InstancedTileRenderer modelManager, B tile) { + public BearingInstance(MaterialManager modelManager, B tile) { super(modelManager, tile); this.bearing = tile; 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 cf6f59b7c..0d23f7523 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 @@ -1,13 +1,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; 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.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.client.renderer.IRenderTypeBuffer; @@ -26,7 +26,7 @@ public class BearingRenderer extends KineticTileEntityRenderer { protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); 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 1816c047c..4d60ec775 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 @@ -119,11 +119,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity protected void applyRotations() { BlockState blockState = getBlockState(); Axis axis = Axis.X; - + if (blockState.contains(BlockStateProperties.FACING)) axis = blockState.get(BlockStateProperties.FACING) .getAxis(); - + if (hourHand != null) { hourHand.setAngle(hourAngle); hourHand.setRotationAxis(axis); @@ -177,21 +177,23 @@ public class ClockworkBearingTileEntity extends KineticTileEntity } protected float getHourTarget(boolean cycle24) { - int dayTime = (int) (world.getDayTime() % 24000); + boolean isNatural = world.getDimension().isNatural(); + int dayTime = (int) ((world.getDayTime() * (isNatural ? 1 : 24)) % 24000); int hours = (dayTime / 1000 + 6) % 24; int offset = getBlockState().get(ClockworkBearingBlock.FACING) - .getAxisDirection() - .getOffset(); + .getAxisDirection() + .getOffset(); float hourTarget = (float) (offset * -360 / (cycle24 ? 24f : 12f) * (hours % (cycle24 ? 24 : 12))); return hourTarget; } protected float getMinuteTarget() { - int dayTime = (int) (world.getDayTime() % 24000); + boolean isNatural = world.getDimension().isNatural(); + int dayTime = (int) ((world.getDayTime() * (isNatural ? 1 : 24)) % 24000); int minutes = (dayTime % 1000) * 60 / 1000; int offset = getBlockState().get(ClockworkBearingBlock.FACING) - .getAxisDirection() - .getOffset(); + .getAxisDirection() + .getOffset(); float minuteTarget = (float) (offset * -360 / 60f * (minutes)); return minuteTarget; } @@ -417,7 +419,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } 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 d7ed6958b..2cc024c2a 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 @@ -6,6 +6,7 @@ import java.util.List; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; +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; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; @@ -80,7 +81,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity super.fromTag(state, compound, clientPacket); return; } - + float angleBefore = angle; running = compound.getBoolean("Running"); angle = compound.getFloat("Angle"); @@ -108,7 +109,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity public void onSpeedChanged(float prevSpeed) { super.onSpeedChanged(prevSpeed); assembleNextTick = true; - + if (movedContraption != null && Math.signum(prevSpeed) != Math.signum(getSpeed()) && prevSpeed != 0) { movedContraption.getContraption() .stop(world); @@ -116,7 +117,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity } public float getAngularSpeed() { - float speed = (isWindmill() ? getGeneratedSpeed() : getSpeed()) * 3 / 10f; + float speed = convertToAngular(isWindmill() ? getGeneratedSpeed() : getSpeed()); if (getSpeed() == 0) speed = 0; if (world.isRemote) { @@ -169,7 +170,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); movedContraption.setRotationAxis(direction.getAxis()); world.addEntity(movedContraption); - + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); running = true; @@ -216,14 +217,13 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity movedContraption.getContraption() .stop(world); disassemble(); + return; } - return; } else { if (speed == 0 && !isWindmill()) return; assemble(); } - return; } if (!running) @@ -323,7 +323,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { 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 73e80c2e3..b4cfaea85 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 @@ -97,7 +97,7 @@ public class SailBlock extends ProperDirectionalBlock { protected void applyDye(BlockState state, World world, BlockPos pos, @Nullable DyeColor color) { BlockState newState = - (color == null ? AllBlocks.SAIL_FRAME : AllBlocks.DYED_SAILS[color.ordinal()]).getDefaultState() + (color == null ? AllBlocks.SAIL_FRAME : AllBlocks.DYED_SAILS.get(color)).getDefaultState() .with(FACING, state.get(FACING)); // Dye the block itself diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java index 49c7007b0..9f7080e50 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/StabilizedBearingInstance.java @@ -1,11 +1,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.bearing; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; import com.simibubi.create.content.contraptions.components.structureMovement.render.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; -import com.simibubi.create.foundation.render.backend.core.OrientedData; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.block.BlockState; import net.minecraft.state.properties.BlockStateProperties; @@ -21,8 +22,8 @@ public class StabilizedBearingInstance extends ActorInstance { final Vector3f rotationAxis; final Quaternion blockOrientation; - public StabilizedBearingInstance(ContraptionKineticRenderer modelManager, MovementContext context) { - super(modelManager, context); + public StabilizedBearingInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + super(materialManager, simulationWorld, context); BlockState blockState = context.state; @@ -31,7 +32,7 @@ public class StabilizedBearingInstance extends ActorInstance { blockOrientation = BearingInstance.getBlockStateOrientation(facing); - topInstance = modelManager.getOrientedMaterial().getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance(); + topInstance = materialManager.getOrientedMaterial().getModel(AllBlockPartials.BEARING_TOP, blockState).createInstance(); topInstance.setPosition(context.localPos) .setRotation(blockOrientation) 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 9d776cb3a..3ca4d5d17 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 @@ -2,7 +2,9 @@ package com.simibubi.create.content.contraptions.components.structureMovement.be import javax.annotation.Nullable; -import com.mojang.blaze3d.matrix.MatrixStack; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; @@ -10,13 +12,12 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov 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.ActorInstance; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionKineticRenderer; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionMatrices; import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -31,9 +32,9 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { @Override @OnlyIn(Dist.CLIENT) - public void renderInContraption(MovementContext context, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - if (FastRenderDispatcher.available()) return; + public void renderInContraption(MovementContext context, PlacementSimulationWorld renderWorld, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + if (Backend.getInstance().canUseInstancing()) return; Direction facing = context.state.get(BlockStateProperties.FACING); PartialModel top = AllBlockPartials.BEARING_TOP; @@ -52,12 +53,14 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { orientation = rotation; + superBuffer.transform(matrices.contraptionStack); superBuffer.rotateCentered(orientation); // render - superBuffer.light(msLocal.peek() - .getModel(), ContraptionRenderDispatcher.getLightOnContraption(context)); - superBuffer.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); + superBuffer + .light(matrices.entityMatrix, + ContraptionRenderDispatcher.getContraptionWorldLight(context, renderWorld)) + .renderInto(matrices.entityStack, buffer.getBuffer(RenderType.getSolid())); } @Override @@ -67,8 +70,8 @@ public class StabilizedBearingMovementBehaviour extends MovementBehaviour { @Nullable @Override - public ActorInstance createInstance(ContraptionKineticRenderer kr, MovementContext context) { - return new StabilizedBearingInstance(kr, context); + public ActorInstance createInstance(MaterialManager materialManager, PlacementSimulationWorld simulationWorld, MovementContext context) { + return new StabilizedBearingInstance(materialManager, simulationWorld, context); } static float getCounterRotationAngle(MovementContext context, Direction facing, float renderPartialTicks) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java index b8784ba92..fee951e82 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/ChassisRangeDisplay.java @@ -35,11 +35,11 @@ public class ChassisRangeDisplay { public Entry(ChassisTileEntity te) { this.te = te; timer = DISPLAY_TIME; - CreateClient.outliner.showCluster(getOutlineKey(), createSelection(te)) - .colored(0xFFFFFF) - .disableNormals() - .lineWidth(1 / 16f) - .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); + CreateClient.OUTLINER.showCluster(getOutlineKey(), createSelection(te)) + .colored(0xFFFFFF) + .disableNormals() + .lineWidth(1 / 16f) + .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED); } protected Object getOutlineKey() { @@ -97,7 +97,7 @@ public class ChassisRangeDisplay { Entry entry = entries.get(pos); if (tickEntry(entry, hasWrench)) iterator.remove(); - CreateClient.outliner.keep(entry.getOutlineKey()); + CreateClient.OUTLINER.keep(entry.getOutlineKey()); } for (Iterator iterator = groupEntries.iterator(); iterator.hasNext();) { @@ -107,7 +107,7 @@ public class ChassisRangeDisplay { if (group == lastHoveredGroup) lastHoveredGroup = null; } - CreateClient.outliner.keep(group.getOutlineKey()); + CreateClient.OUTLINER.keep(group.getOutlineKey()); } if (!hasWrench) @@ -173,9 +173,9 @@ public class ChassisRangeDisplay { GroupEntry hoveredGroup = new GroupEntry(chassis); for (ChassisTileEntity included : hoveredGroup.includedTEs) - CreateClient.outliner.remove(included.getPos()); + CreateClient.OUTLINER.remove(included.getPos()); - groupEntries.forEach(entry -> CreateClient.outliner.remove(entry.getOutlineKey())); + groupEntries.forEach(entry -> CreateClient.OUTLINER.remove(entry.getOutlineKey())); groupEntries.clear(); entries.clear(); groupEntries.add(hoveredGroup); @@ -186,7 +186,7 @@ public class ChassisRangeDisplay { BlockPos pos = chassis.getPos(); GroupEntry entry = getExistingGroupForPos(pos); if (entry != null) - CreateClient.outliner.remove(entry.getOutlineKey()); + CreateClient.OUTLINER.remove(entry.getOutlineKey()); groupEntries.clear(); entries.clear(); 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 0c21d2b83..51e17c7fc 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 @@ -11,7 +11,7 @@ import java.util.Queue; import java.util.Set; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; +import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -165,14 +165,14 @@ public class ChassisTileEntity extends SmartTileEntity { break; // Ignore replaceable Blocks and Air-like - if (!BlockMovementTraits.movementNecessary(currentState, world, current)) + if (!BlockMovementChecks.isMovementNecessary(currentState, world, current)) break; - if (BlockMovementTraits.isBrittle(currentState)) + if (BlockMovementChecks.isBrittle(currentState)) break; positions.add(current); - if (BlockMovementTraits.notSupportive(currentState, facing)) + if (BlockMovementChecks.isNotSupportive(currentState, facing)) break; } } @@ -206,9 +206,9 @@ public class ChassisTileEntity extends SmartTileEntity { continue; if (!searchPos.withinDistance(pos, chassisRange + .5f)) continue; - if (!BlockMovementTraits.movementNecessary(searchedState, world, searchPos)) + if (!BlockMovementChecks.isMovementNecessary(searchedState, world, searchPos)) continue; - if (BlockMovementTraits.isBrittle(searchedState)) + if (BlockMovementChecks.isBrittle(searchedState)) continue; localVisited.add(searchPos); @@ -220,7 +220,7 @@ public class ChassisTileEntity extends SmartTileEntity { continue; if (searchPos.equals(pos) && offset != facing) continue; - if (BlockMovementTraits.notSupportive(searchedState, offset)) + if (BlockMovementChecks.isNotSupportive(searchedState, offset)) continue; localFrontier.add(searchPos.offset(offset)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java index 9e83b008c..f57cebc70 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerInstance.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -23,7 +23,7 @@ public class StickerInstance extends TileEntityInstance imple private final ModelData head; - public StickerInstance(InstancedTileRenderer modelManager, StickerTileEntity tile) { + public StickerInstance(MaterialManager modelManager, StickerTileEntity tile) { super(modelManager, tile); head = getTransformMaterial().getModel(AllBlockPartials.STICKER_HEAD, blockState).createInstance(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java index 1abccec33..a63c27957 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerRenderer.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.contraptions.components.structureMovement.chassis; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.render.PartialBufferer; 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; @@ -26,7 +26,7 @@ public class StickerRenderer extends SafeTileEntityRenderer { protected void renderSafe(StickerTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockState state = te.getBlockState(); SuperByteBuffer head = PartialBufferer.get(AllBlockPartials.STICKER_HEAD, state); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java index 34d4a421f..7282a1183 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/chassis/StickerTileEntity.java @@ -2,12 +2,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ch import java.util.List; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.animation.LerpedFloat; @@ -70,7 +70,7 @@ public class StickerTileEntity extends SmartTileEntity implements IInstanceRende DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> playSound(false)); piston.chase(target, .4f, Chaser.LINEAR); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public boolean isAttachedToBlock() { diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java index fba18244f..e2d3a8630 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageInstance.java @@ -1,13 +1,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; 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.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -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.MatrixStacker; @@ -29,7 +29,7 @@ public class GantryCarriageInstance extends ShaftInstance implements IDynamicIns private float lastAngle = Float.NaN; - public GantryCarriageInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public GantryCarriageInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); gantryCogs = getTransformMaterial() diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java index 72152ff04..5ae13bc6d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageRenderer.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.components.structureMovement.gantry; +import com.jozufozu.flywheel.backend.Backend; 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.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Iterate; @@ -32,14 +32,14 @@ public class GantryCarriageRenderer extends KineticTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockState state = te.getBlockState(); Direction facing = state.get(GantryCarriageBlock.FACING); Boolean alongFirst = state.get(GantryCarriageBlock.AXIS_ALONG_FIRST_COORDINATE); Axis rotationAxis = getRotationAxisOf(te); BlockPos visualPos = facing.getAxisDirection() == AxisDirection.POSITIVE ? te.getPos() - : te.getPos() + : te.getPos() .offset(facing.getOpposite()); float angleForTe = getAngleForTe(te, visualPos, rotationAxis); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java index 055db9ed8..897068624 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/gantry/GantryCarriageTileEntity.java @@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.ga import static net.minecraft.state.properties.BlockStateProperties.FACING; import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; @@ -36,7 +37,7 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp if (shouldAssemble()) queueAssembly(); } - + @Override public void initialize() { super.initialize(); @@ -107,6 +108,7 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp GantryContraptionEntity.create(world, contraption, shaftOrientation); BlockPos anchor = pos; movedContraption.setPosition(anchor.getX(), anchor.getY(), anchor.getZ()); + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); world.addEntity(movedContraption); } @@ -173,7 +175,7 @@ public class GantryCarriageTileEntity extends KineticTileEntity implements IDisp } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java new file mode 100644 index 000000000..cc171a904 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/GlueInstance.java @@ -0,0 +1,136 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.glue; + +import com.jozufozu.flywheel.backend.gl.buffer.VecBuffer; +import com.jozufozu.flywheel.backend.instancing.ITickableInstance; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.entity.EntityInstance; +import com.jozufozu.flywheel.backend.model.BufferedModel; +import com.jozufozu.flywheel.backend.model.IndexedModel; +import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.core.Materials; +import com.jozufozu.flywheel.core.instancing.ConditionalInstance; +import com.jozufozu.flywheel.core.materials.OrientedData; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllStitchedTextures; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.utility.AngleHelper; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.LightType; + +public class GlueInstance extends EntityInstance implements ITickableInstance { + + private static final ResourceLocation TEXTURE = new ResourceLocation(Create.ID, "textures/entity/super_glue/slime.png"); + + private final Quaternion rotation; + protected ConditionalInstance model; + + public GlueInstance(MaterialManager materialManager, SuperGlueEntity entity) { + super(materialManager, entity); + + Instancer instancer = materialManager.getMaterial(Materials.ORIENTED) + .get(entity.getType(), GlueInstance::supplyModel); + + Direction face = entity.getFacingDirection(); + rotation = new Quaternion(AngleHelper.verticalAngle(face), AngleHelper.horizontalAngleNew(face), 0, true); + + model = new ConditionalInstance<>(instancer) + .withCondition(this::shouldShow) + .withSetupFunc(this::positionModel) + .update(); + } + + @Override + public void tick() { + model.update(); + } + + @Override + public void remove() { + model.delete(); + } + + private void positionModel(OrientedData model) { + + model.setPosition(getInstancePosition()) + .setPivot(0, 0, 0) + .setRotation(rotation); + + updateLight(model); + } + + @Override + public void updateLight() { + model.get().ifPresent(this::updateLight); + } + + private void updateLight(OrientedData model) { + BlockPos pos = entity.getHangingPosition(); + model.setBlockLight(world.getLightLevel(LightType.BLOCK, pos)) + .setSkyLight(world.getLightLevel(LightType.SKY, pos)); + } + + private boolean shouldShow() { + PlayerEntity player = Minecraft.getInstance().player; + + return entity.isVisible() + || AllItems.SUPER_GLUE.isIn(player.getHeldItemMainhand()) + || AllItems.SUPER_GLUE.isIn(player.getHeldItemOffhand()); + } + + public static BufferedModel supplyModel() { + Vector3d diff = Vector3d.of(Direction.SOUTH.getDirectionVec()); + Vector3d extension = diff.normalize() + .scale(1 / 32f - 1 / 128f); + + Vector3d plane = VecHelper.axisAlingedPlaneOf(diff); + Direction.Axis axis = Direction.getFacingFromVector(diff.x, diff.y, diff.z) + .getAxis(); + + Vector3d start = Vector3d.ZERO.subtract(extension); + Vector3d end = Vector3d.ZERO.add(extension); + + plane = plane.scale(1 / 2f); + Vector3d a1 = plane.add(start); + Vector3d b1 = plane.add(end); + plane = VecHelper.rotate(plane, -90, axis); + Vector3d a2 = plane.add(start); + Vector3d b2 = plane.add(end); + plane = VecHelper.rotate(plane, -90, axis); + Vector3d a3 = plane.add(start); + Vector3d b3 = plane.add(end); + plane = VecHelper.rotate(plane, -90, axis); + Vector3d a4 = plane.add(start); + Vector3d b4 = plane.add(end); + + VecBuffer buffer = VecBuffer.allocate(Formats.UNLIT_MODEL.getStride() * 8); + + TextureAtlasSprite sprite = AllStitchedTextures.SUPER_GLUE.getSprite(); + + // pos normal uv + // inside quad + buffer.putVec3((float) a1.x, (float) a1.y, (float) a1.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMaxU(), sprite.getMinV()); + buffer.putVec3((float) a2.x, (float) a2.y, (float) a2.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMaxU(), sprite.getMaxV()); + buffer.putVec3((float) a3.x, (float) a3.y, (float) a3.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMinU(), sprite.getMaxV()); + buffer.putVec3((float) a4.x, (float) a4.y, (float) a4.z).putVec3((byte) 0, (byte) 0, (byte) -127).putVec2(sprite.getMinU(), sprite.getMinV()); + // outside quad + buffer.putVec3((float) b4.x, (float) b4.y, (float) b4.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMinU(), sprite.getMinV()); + buffer.putVec3((float) b3.x, (float) b3.y, (float) b3.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMinU(), sprite.getMaxV()); + buffer.putVec3((float) b2.x, (float) b2.y, (float) b2.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMaxU(), sprite.getMaxV()); + buffer.putVec3((float) b1.x, (float) b1.y, (float) b1.z).putVec3((byte) 0, (byte) 0, (byte) 127).putVec2(sprite.getMaxU(), sprite.getMinV()); + + buffer.rewind(); + + + return IndexedModel.fromSequentialQuads(Formats.UNLIT_MODEL, buffer.unwrap(), 8); + } +} 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 5a7957c92..54ec8d2a3 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 @@ -4,12 +4,13 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.Validate; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllEntityTypes; import com.simibubi.create.AllItems; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; -import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; +import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.BearingBlock; import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock; import com.simibubi.create.content.schematics.ISpecialEntityItemRequirement; @@ -64,7 +65,7 @@ import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.network.NetworkHooks; import net.minecraftforge.fml.network.PacketDistributor; -public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement { +public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, IInstanceRendered { private int validationTimer; protected BlockPos hangingPosition; @@ -181,25 +182,27 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat public boolean onValidSurface() { BlockPos pos = hangingPosition; BlockPos pos2 = hangingPosition.offset(getFacingDirection().getOpposite()); + if (pos2.getY() >= 256) + return false; if (!world.isAreaLoaded(pos, 0) || !world.isAreaLoaded(pos2, 0)) return true; if (!isValidFace(world, pos2, getFacingDirection()) - && !isValidFace(world, pos, getFacingDirection().getOpposite())) + && !isValidFace(world, pos, getFacingDirection().getOpposite())) return false; if (isSideSticky(world, pos2, getFacingDirection()) - || isSideSticky(world, pos, getFacingDirection().getOpposite())) + || isSideSticky(world, pos, getFacingDirection().getOpposite())) return false; return world.getEntitiesInAABBexcluding(this, getBoundingBox(), e -> e instanceof SuperGlueEntity) - .isEmpty(); + .isEmpty(); } public static boolean isValidFace(World world, BlockPos pos, Direction direction) { BlockState state = world.getBlockState(pos); - if (BlockMovementTraits.isBlockAttachedTowards(world, pos, state, direction)) + if (BlockMovementChecks.isBlockAttachedTowards(state, world, pos, direction)) return true; - if (!BlockMovementTraits.movementNecessary(state, world, pos)) + if (!BlockMovementChecks.isMovementNecessary(state, world, pos)) return false; - if (BlockMovementTraits.notSupportive(state, direction)) + if (BlockMovementChecks.isNotSupportive(state, direction)) return false; return true; } @@ -480,4 +483,9 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat public boolean doesEntityNotTriggerPressurePlate() { return true; } + + @Override + public World getWorld() { + return world; + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java index cd73d52ff..34bfa5f3b 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/glue/SuperGlueRenderer.java @@ -13,6 +13,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.culling.ClippingHelper; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererManager; import net.minecraft.client.renderer.texture.OverlayTexture; @@ -31,10 +32,8 @@ public class SuperGlueRenderer extends EntityRenderer { private ResourceLocation regular = new ResourceLocation(Create.ID, "textures/entity/super_glue/slime.png"); - private Vector3d[] quad1; - private Vector3d[] quad2; - private float[] u = { 0, 1, 1, 0 }; - private float[] v = { 0, 0, 1, 1 }; + private float[] insideQuad; + private float[] outsideQuad; public SuperGlueRenderer(EntityRendererManager renderManager) { super(renderManager); @@ -47,17 +46,23 @@ public class SuperGlueRenderer extends EntityRenderer { } @Override - public void render(SuperGlueEntity entity, float p_225623_2_, float p_225623_3_, MatrixStack ms, + public boolean shouldRender(SuperGlueEntity entity, ClippingHelper frustum, double x, double y, double z) { + if (super.shouldRender(entity, frustum, x, y, z)) { + PlayerEntity player = Minecraft.getInstance().player; + boolean visible = entity.isVisible(); + boolean holdingGlue = AllItems.SUPER_GLUE.isIn(player.getHeldItemMainhand()) + || AllItems.SUPER_GLUE.isIn(player.getHeldItemOffhand()); + + if (visible || holdingGlue) + return true; + } + return false; + } + + @Override + public void render(SuperGlueEntity entity, float yaw, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light) { - super.render(entity, p_225623_2_, p_225623_3_, ms, buffer, light); - - PlayerEntity player = Minecraft.getInstance().player; - boolean visible = entity.isVisible(); - boolean holdingGlue = AllItems.SUPER_GLUE.isIn(player.getHeldItemMainhand()) - || AllItems.SUPER_GLUE.isIn(player.getHeldItemOffhand()); - - if (!visible && !holdingGlue) - return; + super.render(entity, yaw, partialTicks, ms, buffer, light); IVertexBuilder builder = buffer.getBuffer(RenderType.getEntityCutout(getEntityTexture(entity))); light = getBrightnessForRender(entity); @@ -65,24 +70,13 @@ public class SuperGlueRenderer extends EntityRenderer { ms.push(); MatrixStacker.of(ms) - .rotateY(AngleHelper.horizontalAngle(face)) + .rotateY(AngleHelper.horizontalAngleNew(face)) .rotateX(AngleHelper.verticalAngle(face)); Entry peek = ms.peek(); - Vector3d[][] quads = { quad1, quad2 }; - for (Vector3d[] quad : quads) { - for (int i = 0; i < 4; i++) { - Vector3d vertex = quad[i]; - builder.vertex(peek.getModel(), (float) vertex.x, (float) vertex.y, (float) vertex.z) - .color(255, 255, 255, 255) - .texture(u[i], v[i]) - .overlay(OverlayTexture.DEFAULT_UV) - .light(light) - .normal(peek.getNormal(), face.getXOffset(), face.getYOffset(), face.getZOffset()) - .endVertex(); - } - face = face.getOpposite(); - } + renderQuad(builder, peek, insideQuad, light, -1); + renderQuad(builder, peek, outsideQuad, light, 1); + ms.pop(); } @@ -111,8 +105,18 @@ public class SuperGlueRenderer extends EntityRenderer { Vector3d a4 = plane.add(start); Vector3d b4 = plane.add(end); - quad1 = new Vector3d[] { a2, a3, a4, a1 }; - quad2 = new Vector3d[] { b3, b2, b1, b4 }; + insideQuad = new float[] { + (float) a1.x, (float) a1.y, (float) a1.z, 1, 0, + (float) a2.x, (float) a2.y, (float) a2.z, 1, 1, + (float) a3.x, (float) a3.y, (float) a3.z, 0, 1, + (float) a4.x, (float) a4.y, (float) a4.z, 0, 0, + }; + outsideQuad = new float[] { + (float) b4.x, (float) b4.y, (float) b4.z, 0, 0, + (float) b3.x, (float) b3.y, (float) b3.z, 0, 1, + (float) b2.x, (float) b2.y, (float) b2.z, 1, 1, + (float) b1.x, (float) b1.y, (float) b1.z, 1, 0, + }; } private int getBrightnessForRender(SuperGlueEntity entity) { @@ -126,4 +130,17 @@ public class SuperGlueRenderer extends EntityRenderer { return Math.max(light, light2); } + // Vertex format: pos x, pos y, pos z, u, v + private void renderQuad(IVertexBuilder builder, Entry matrix, float[] data, int light, float normalZ) { + for (int i = 0; i < 4; i++) { + builder.vertex(matrix.getModel(), data[5 * i], data[5 * i + 1], data[5 * i + 2]) + .color(255, 255, 255, 255) + .texture(data[5 * i + 3], data[5 * i + 4]) + .overlay(OverlayTexture.DEFAULT_UV) + .light(light) + .normal(matrix.getNormal(), 0.0f, 0.0f, normalZ) + .endVertex(); + } + } + } 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 09c2653a2..1245feb7e 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 @@ -2,8 +2,6 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo import java.util.ArrayList; import java.util.List; -import java.util.Optional; -import java.util.UUID; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -11,21 +9,12 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; -import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; -import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; -import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; -import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; -import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; import com.simibubi.create.content.contraptions.wrench.IWrenchable; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType; 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; @@ -41,7 +30,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.loot.LootContext; import net.minecraft.loot.LootParameters; -import net.minecraft.nbt.CompoundNBT; import net.minecraft.pathfinding.PathType; import net.minecraft.state.BooleanProperty; import net.minecraft.state.EnumProperty; @@ -54,22 +42,20 @@ 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.Mirror; 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.shapes.ISelectionContext; import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.math.shapes.VoxelShapes; import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3i; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; -import net.minecraftforge.common.util.LazyOptional; public class CartAssemblerBlock extends AbstractRailBlock implements ITE, IWrenchable, ISpecialBlockItemRequirement { @@ -137,42 +123,7 @@ public class CartAssemblerBlock extends AbstractRailBlock if (world.isRemote) return; - withTileEntityDo(world, pos, te -> { - if (!te.isMinecartUpdateValid()) - return; - - CartAssemblerAction action = getActionForCart(state, cart); - if (action.shouldAssemble()) - assemble(world, pos, cart); - if (action.shouldDisassemble()) - disassemble(world, pos, cart); - if (action == CartAssemblerAction.ASSEMBLE_ACCELERATE) { - Direction facing = cart.getAdjustedHorizontalFacing(); - - RailShape railShape = state.get(RAIL_SHAPE); - for (Direction d : Iterate.directionsInAxis(railShape == RailShape.EAST_WEST ? Axis.X : Axis.Z)) - if (world.getBlockState(pos.offset(d)) - .isNormalCube(world, pos.offset(d))) - facing = d.getOpposite(); - - float speed = getRailMaxSpeed(state, world, pos, cart); - cart.setMotion(facing.getXOffset() * speed, facing.getYOffset() * speed, facing.getZOffset() * speed); - } - if (action == CartAssemblerAction.ASSEMBLE_ACCELERATE_DIRECTIONAL) { - Vector3i accelerationVector = ControllerRailBlock.getAccelerationVector( - AllBlocks.CONTROLLER_RAIL.getDefaultState() - .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) - .with(ControllerRailBlock.BACKWARDS, state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS)); - float speed = getRailMaxSpeed(state, world, pos, cart); - cart.setMotion(Vector3d.of(accelerationVector).scale(speed)); - } - if (action == CartAssemblerAction.DISASSEMBLE_BRAKE) { - Vector3d diff = VecHelper.getCenterOf(pos) - .subtract(cart.getPositionVec()); - cart.setMotion(diff.x / 16f, 0, diff.z / 16f); - } - - }); + withTileEntityDo(world, pos, te -> te.assembleNextTick(cart)); } public enum CartAssemblerAction { @@ -244,124 +195,6 @@ public class CartAssemblerBlock extends AbstractRailBlock return ActionResultType.PASS; } - protected void assemble(World world, BlockPos pos, AbstractMinecartEntity cart) { - if (!cart.getPassengers() - .isEmpty()) - return; - - LazyOptional optional = - cart.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); - if (optional.isPresent() && optional.orElse(null) - .isCoupledThroughContraption()) - return; - - Optional assembler = getTileEntityOptional(world, pos); - CartMovementMode mode = assembler.map(te -> CartMovementMode.values()[te.movementMode.value]) - .orElse(CartMovementMode.ROTATE); - - MountedContraption contraption = new MountedContraption(mode); - try { - if (!contraption.assemble(world, pos)) - return; - - assembler.ifPresent(te -> { - te.lastException = null; - te.sendData(); - }); - } catch (AssemblyException e) { - assembler.ifPresent(te -> { - te.lastException = e; - te.sendData(); - }); - return; - } - - boolean couplingFound = contraption.connectedCart != null; - Optional initialOrientation = cart.getMotion() - .length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing()); - - if (couplingFound) { - cart.setPosition(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); - if (!CouplingHandler.tryToCoupleCarts(null, world, cart.getEntityId(), - contraption.connectedCart.getEntityId())) - return; - } - - contraption.removeBlocksFromWorld(world, BlockPos.ZERO); - contraption.startMoving(world); - contraption.expandBoundsAroundAxis(Axis.Y); - - if (couplingFound) { - Vector3d diff = contraption.connectedCart.getPositionVec() - .subtract(cart.getPositionVec()); - initialOrientation = Optional.of(Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI)); - } - - OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation); - if (couplingFound) - entity.setCouplingId(cart.getUniqueID()); - entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); - world.addEntity(entity); - entity.startRiding(cart); - - if (cart instanceof FurnaceMinecartEntity) { - CompoundNBT nbt = cart.serializeNBT(); - nbt.putDouble("PushZ", 0); - nbt.putDouble("PushX", 0); - cart.deserializeNBT(nbt); - } - } - - protected void disassemble(World world, BlockPos pos, AbstractMinecartEntity cart) { - if (cart.getPassengers() - .isEmpty()) - return; - Entity entity = cart.getPassengers() - .get(0); - if (!(entity instanceof OrientedContraptionEntity)) - return; - OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity; - UUID couplingId = contraption.getCouplingId(); - - if (couplingId == null) { - disassembleCart(cart); - return; - } - - Couple coupledCarts = contraption.getCoupledCartsIfPresent(); - if (coupledCarts == null) - return; - - // Make sure connected cart is present and being disassembled - for (boolean current : Iterate.trueAndFalse) { - MinecartController minecartController = coupledCarts.get(current); - if (minecartController.cart() == cart) - continue; - BlockPos otherPos = minecartController.cart() - .getBlockPos(); - BlockState blockState = world.getBlockState(otherPos); - if (!AllBlocks.CART_ASSEMBLER.has(blockState)) - return; - if (!getActionForCart(blockState, minecartController.cart()).shouldDisassemble()) - return; - } - - for (boolean current : Iterate.trueAndFalse) - coupledCarts.get(current) - .removeConnection(current); - disassembleCart(cart); - } - - protected void disassembleCart(AbstractMinecartEntity cart) { - cart.removePassengers(); - if (cart instanceof FurnaceMinecartEntity) { - CompoundNBT nbt = cart.serializeNBT(); - nbt.putDouble("PushZ", cart.getMotion().x); - nbt.putDouble("PushX", cart.getMotion().z); - cart.deserializeNBT(nbt); - } - } - @Override public void neighborChanged(@Nonnull BlockState state, @Nonnull World worldIn, @Nonnull BlockPos pos, @Nonnull Block blockIn, @Nonnull BlockPos fromPos, boolean isMoving) { @@ -432,7 +265,7 @@ public class CartAssemblerBlock extends AbstractRailBlock } @Override - public ItemRequirement getRequiredItems(BlockState state) { + public ItemRequirement getRequiredItems(BlockState state, TileEntity te) { ArrayList reuiredItems = new ArrayList<>(); reuiredItems.add(new ItemStack(getRailItem(state))); reuiredItems.add(new ItemStack(asItem())); @@ -492,29 +325,55 @@ public class CartAssemblerBlock extends AbstractRailBlock public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + @Override public ActionResultType onWrenched(BlockState state, ItemUseContext context) { World world = context.getWorld(); if (world.isRemote) return ActionResultType.SUCCESS; BlockPos pos = context.getPos(); - BlockState newState = state.with(RAIL_SHAPE, - state.get(RAIL_SHAPE) == RailShape.NORTH_SOUTH ? RailShape.EAST_WEST : RailShape.NORTH_SOUTH); - if (state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL - || state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS) { - newState = newState.with(RAIL_TYPE, AllBlocks.CONTROLLER_RAIL.get() - .rotate(AllBlocks.CONTROLLER_RAIL.getDefaultState() - .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) - .with(ControllerRailBlock.BACKWARDS, - state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS), - Rotation.CLOCKWISE_90) - .get(ControllerRailBlock.BACKWARDS) ? CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS - : CartAssembleRailType.CONTROLLER_RAIL); - } - context.getWorld() - .setBlockState(pos, newState, 3); + world.setBlockState(pos, rotate(state, Rotation.CLOCKWISE_90), 3); world.notifyNeighborsOfStateChange(pos.down(), this); return ActionResultType.SUCCESS; } + + @Override + public BlockState rotate(BlockState state, Rotation rotation) { + if (rotation == Rotation.NONE) + return state; + + boolean is_controller_rail_backwards = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS; + boolean is_controller_rail = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL || is_controller_rail_backwards; + BlockState base = AllBlocks.CONTROLLER_RAIL.getDefaultState() + .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) + .with(ControllerRailBlock.BACKWARDS, is_controller_rail_backwards) + .rotate(rotation); + if (is_controller_rail) { + state = state.with(RAIL_TYPE, + base.get(ControllerRailBlock.BACKWARDS) ? CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS : + CartAssembleRailType.CONTROLLER_RAIL + ); + } + return state.with(RAIL_SHAPE, base.get(ControllerRailBlock.SHAPE)); + } + + @Override + public BlockState mirror(BlockState state, Mirror mirror) { + if (mirror == Mirror.NONE) + return state; + + boolean is_controller_rail_backwards = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS; + boolean is_controller_rail = state.get(RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL || is_controller_rail_backwards; + BlockState base = AllBlocks.CONTROLLER_RAIL.getDefaultState() + .with(ControllerRailBlock.SHAPE, state.get(RAIL_SHAPE)) + .with(ControllerRailBlock.BACKWARDS, is_controller_rail_backwards) + .mirror(mirror); + if (is_controller_rail) { + state = state.with(RAIL_TYPE, + base.get(ControllerRailBlock.BACKWARDS) ? CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS : + CartAssembleRailType.CONTROLLER_RAIL + ); + } + return state.with(RAIL_SHAPE, base.get(ControllerRailBlock.SHAPE)); + } } 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 63a942b25..df32d47e8 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,9 +1,16 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mounted; import java.util.List; +import java.util.UUID; +import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException; import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions; +import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; +import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; +import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; +import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.content.contraptions.components.tracks.ControllerRailBlock; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -11,16 +18,36 @@ import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxT import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIconOptions; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.VecHelper; +import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.minecart.AbstractMinecartEntity; +import net.minecraft.entity.item.minecart.FurnaceMinecartEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.Items; import net.minecraft.nbt.CompoundNBT; import net.minecraft.state.properties.RailShape; import net.minecraft.tileentity.TileEntityType; +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.vector.Vector3d; +import net.minecraft.util.math.vector.Vector3i; +import net.minecraft.world.World; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +@EventBusSubscriber public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions { private static final int assemblyCooldown = 8; @@ -28,6 +55,9 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay private int ticksSinceMinecartUpdate; protected AssemblyException lastException; + protected AbstractMinecartEntity cartToAssemble; + protected Direction cartInitialOrientation = Direction.NORTH; + public CartAssemblerTileEntity(TileEntityType type) { super(type); ticksSinceMinecartUpdate = assemblyCooldown; @@ -39,6 +69,165 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay if (ticksSinceMinecartUpdate < assemblyCooldown) { ticksSinceMinecartUpdate++; } + + tryAssemble(cartToAssemble); + cartToAssemble = null; + } + + public void tryAssemble(AbstractMinecartEntity cart) { + if (cart == null) + return; + + if (!isMinecartUpdateValid()) + return; + resetTicksSinceMinecartUpdate(); + + BlockState state = world.getBlockState(pos); + if (!AllBlocks.CART_ASSEMBLER.has(state)) + return; + CartAssemblerBlock block = (CartAssemblerBlock) state.getBlock(); + + CartAssemblerBlock.CartAssemblerAction action = CartAssemblerBlock.getActionForCart(state, cart); + if (action.shouldAssemble()) + assemble(world, pos, cart); + if (action.shouldDisassemble()) + disassemble(world, pos, cart); + if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE) { + Direction facing = cart.getAdjustedHorizontalFacing(); + + RailShape railShape = state.get(CartAssemblerBlock.RAIL_SHAPE); + for (Direction d : Iterate.directionsInAxis(railShape == RailShape.EAST_WEST ? Axis.X : Axis.Z)) + if (world.getBlockState(pos.offset(d)) + .isNormalCube(world, pos.offset(d))) + facing = d.getOpposite(); + + float speed = block.getRailMaxSpeed(state, world, pos, cart); + cart.setMotion(facing.getXOffset() * speed, facing.getYOffset() * speed, facing.getZOffset() * speed); + } + if (action == CartAssemblerBlock.CartAssemblerAction.ASSEMBLE_ACCELERATE_DIRECTIONAL) { + Vector3i accelerationVector = ControllerRailBlock.getAccelerationVector( + AllBlocks.CONTROLLER_RAIL.getDefaultState() + .with(ControllerRailBlock.SHAPE, state.get(CartAssemblerBlock.RAIL_SHAPE)) + .with(ControllerRailBlock.BACKWARDS, state.get(CartAssemblerBlock.RAIL_TYPE) == CartAssembleRailType.CONTROLLER_RAIL_BACKWARDS)); + float speed = block.getRailMaxSpeed(state, world, pos, cart); + cart.setMotion(Vector3d.of(accelerationVector).scale(speed)); + } + if (action == CartAssemblerBlock.CartAssemblerAction.DISASSEMBLE_BRAKE) { + Vector3d diff = VecHelper.getCenterOf(pos) + .subtract(cart.getPositionVec()); + cart.setMotion(diff.x / 16f, 0, diff.z / 16f); + } + } + + protected void assemble(World world, BlockPos pos, AbstractMinecartEntity cart) { + if (!cart.getPassengers() + .isEmpty()) + return; + + LazyOptional optional = + cart.getCapability(CapabilityMinecartController.MINECART_CONTROLLER_CAPABILITY); + if (optional.isPresent() && optional.orElse(null) + .isCoupledThroughContraption()) + return; + + CartMovementMode mode = CartMovementMode.values()[movementMode.value]; + + MountedContraption contraption = new MountedContraption(mode); + try { + if (!contraption.assemble(world, pos)) + return; + + lastException = null; + sendData(); + } catch (AssemblyException e) { + lastException = e; + sendData(); + return; + } + + boolean couplingFound = contraption.connectedCart != null; + Direction initialOrientation = cart.getMotion() + .length() < 1 / 512f ? cartInitialOrientation : cart.getAdjustedHorizontalFacing(); + + if (couplingFound) { + cart.setPosition(pos.getX() + .5f, pos.getY(), pos.getZ() + .5f); + if (!CouplingHandler.tryToCoupleCarts(null, world, cart.getEntityId(), + contraption.connectedCart.getEntityId())) + return; + } + + contraption.removeBlocksFromWorld(world, BlockPos.ZERO); + contraption.startMoving(world); + contraption.expandBoundsAroundAxis(Axis.Y); + + if (couplingFound) { + Vector3d diff = contraption.connectedCart.getPositionVec().subtract(cart.getPositionVec()); + initialOrientation = Direction.fromAngle(MathHelper.atan2(diff.z, diff.x) * 180 / Math.PI); + } + + OrientedContraptionEntity entity = OrientedContraptionEntity.create(world, contraption, initialOrientation); + if (couplingFound) + entity.setCouplingId(cart.getUniqueID()); + entity.setPosition(pos.getX(), pos.getY(), pos.getZ()); + world.addEntity(entity); + entity.startRiding(cart); + + if (cart instanceof FurnaceMinecartEntity) { + CompoundNBT nbt = cart.serializeNBT(); + nbt.putDouble("PushZ", 0); + nbt.putDouble("PushX", 0); + cart.deserializeNBT(nbt); + } + } + + protected void disassemble(World world, BlockPos pos, AbstractMinecartEntity cart) { + if (cart.getPassengers() + .isEmpty()) + return; + Entity entity = cart.getPassengers() + .get(0); + if (!(entity instanceof OrientedContraptionEntity)) + return; + OrientedContraptionEntity contraption = (OrientedContraptionEntity) entity; + UUID couplingId = contraption.getCouplingId(); + + if (couplingId == null) { + disassembleCart(cart); + return; + } + + Couple coupledCarts = contraption.getCoupledCartsIfPresent(); + if (coupledCarts == null) + return; + + // Make sure connected cart is present and being disassembled + for (boolean current : Iterate.trueAndFalse) { + MinecartController minecartController = coupledCarts.get(current); + if (minecartController.cart() == cart) + continue; + BlockPos otherPos = minecartController.cart() + .getBlockPos(); + BlockState blockState = world.getBlockState(otherPos); + if (!AllBlocks.CART_ASSEMBLER.has(blockState)) + return; + if (!CartAssemblerBlock.getActionForCart(blockState, minecartController.cart()).shouldDisassemble()) + return; + } + + for (boolean current : Iterate.trueAndFalse) + coupledCarts.get(current) + .removeConnection(current); + disassembleCart(cart); + } + + protected void disassembleCart(AbstractMinecartEntity cart) { + cart.removePassengers(); + if (cart instanceof FurnaceMinecartEntity) { + CompoundNBT nbt = cart.serializeNBT(); + nbt.putDouble("PushZ", cart.getMotion().x); + nbt.putDouble("PushX", cart.getMotion().z); + cart.deserializeNBT(nbt); + } } @Override @@ -53,12 +242,14 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay public void write(CompoundNBT compound, boolean clientPacket) { AssemblyException.write(compound, lastException); super.write(compound, clientPacket); + NBTHelper.writeEnum(compound, "CartInitialOrientation", cartInitialOrientation); } @Override protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { lastException = AssemblyException.read(compound); super.fromTag(state, compound, clientPacket); + cartInitialOrientation = NBTHelper.readEnum(compound, "CartInitialOrientation", Direction.class); } @Override @@ -71,7 +262,7 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay } private class CartAssemblerValueBoxTransform extends CenteredSideValueBoxTransform { - + public CartAssemblerValueBoxTransform() { super((state, d) -> { if (d.getAxis() @@ -83,15 +274,15 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay return (d.getAxis() == Axis.X) == (railShape == RailShape.NORTH_SOUTH); }); } - + @Override protected Vector3d getSouthLocation() { return VecHelper.voxelSpace(8, 8, 18); } - + } - - public static enum CartMovementMode implements INamedIconOptions { + + public enum CartMovementMode implements INamedIconOptions { ROTATE(AllIcons.I_CART_ROTATE), ROTATE_PAUSED(AllIcons.I_CART_ROTATE_PAUSED), @@ -102,7 +293,7 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay private String translationKey; private AllIcons icon; - private CartMovementMode(AllIcons icon) { + CartMovementMode(AllIcons icon) { this.icon = icon; translationKey = "contraptions.cart_movement_mode." + Lang.asId(name()); } @@ -122,7 +313,35 @@ public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplay ticksSinceMinecartUpdate = 0; } + public void assembleNextTick(AbstractMinecartEntity cart) { + if (cartToAssemble == null) + cartToAssemble = cart; + } + public boolean isMinecartUpdateValid() { return ticksSinceMinecartUpdate >= assemblyCooldown; } + + // TODO: Remove these methods once we give Cart Assemblers directionality + protected void setCartInitialOrientation(Direction direction) { + cartInitialOrientation = direction; + } + @SubscribeEvent + public static void getOrientationOfStationaryCart(PlayerInteractEvent.RightClickBlock event) { + PlayerEntity player = event.getPlayer(); + if (player == null) + return; + + Item item = event.getItemStack().getItem(); + if (item != Items.MINECART && item != Items.CHEST_MINECART && item != Items.FURNACE_MINECART) + return; + Block block = event.getWorld().getBlockState(event.getPos()).getBlock(); + if (!(block instanceof CartAssemblerBlock)) + return; + CartAssemblerTileEntity te = ((CartAssemblerBlock) block).getTileEntity(event.getWorld(), event.getPos()); + if (te == null) + return; + + te.setCartInitialOrientation(player.getHorizontalFacing()); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java index 522163f37..4430d1fab 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/mounted/MinecartContraptionItem.java @@ -12,12 +12,15 @@ import com.simibubi.create.AllItems; 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.OrientedContraptionEntity; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.config.CKinetics; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.NBTHelper; import net.minecraft.block.AbstractRailBlock; import net.minecraft.block.BlockState; import net.minecraft.block.DispenserBlock; +import net.minecraft.block.SpawnerBlock; import net.minecraft.block.material.Material; import net.minecraft.dispenser.DefaultDispenseItemBehavior; import net.minecraft.dispenser.IBlockSource; @@ -170,10 +173,7 @@ public class MinecartContraptionItem extends Item { if (tag.contains("Contraption")) { CompoundNBT contraptionTag = tag.getCompound("Contraption"); - Optional intialOrientation = Optional.empty(); - if (contraptionTag.contains("InitialOrientation")) - intialOrientation = - Optional.of(NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class)); + Direction intialOrientation = NBTHelper.readEnum(contraptionTag, "InitialOrientation", Direction.class); Contraption mountedContraption = Contraption.fromNBT(world, contraptionTag, false); OrientedContraptionEntity contraptionEntity = @@ -218,6 +218,16 @@ public class MinecartContraptionItem extends Item { return; OrientedContraptionEntity contraption = (OrientedContraptionEntity) passengers.get(0); + if (AllConfigs.SERVER.kinetics.spawnerMovement.get() == CKinetics.SpawnerMovementSetting.NO_PICKUP) { + Contraption blocks = contraption.getContraption(); + if (blocks != null && blocks.getBlocks().values().stream() + .anyMatch(i -> i.state.getBlock() instanceof SpawnerBlock)) { + player.sendStatusMessage(Lang.translate("contraption.minecart_contraption_illegal_pickup") + .formatted(TextFormatting.RED), true); + return; + } + } + if (event.getWorld().isRemote) { event.setCancellationResult(ActionResultType.SUCCESS); event.setCanceled(true); @@ -274,8 +284,7 @@ public class MinecartContraptionItem extends Item { tag.remove("Pos"); tag.remove("Motion"); - if (entity.isInitialOrientationPresent()) - NBTHelper.writeEnum(tag, "InitialOrientation", entity.getInitialOrientation()); + NBTHelper.writeEnum(tag, "InitialOrientation", entity.getInitialOrientation()); stack.getOrCreateTag() .put("Contraption", tag); 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 97b75e778..fae052d36 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 @@ -53,7 +53,7 @@ public class MountedContraption extends Contraption { protected ContraptionType getType() { return ContraptionType.MOUNTED; } - + @Override public boolean assemble(World world, BlockPos pos) throws AssemblyException { BlockState state = world.getBlockState(pos); @@ -61,17 +61,17 @@ public class MountedContraption extends Contraption { return false; if (!searchMovedStructure(world, pos, null)) return false; - + Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z; addBlock(pos, Pair.of(new BlockInfo(pos, AllBlocks.MINECART_ANCHOR.getDefaultState() .with(BlockStateProperties.HORIZONTAL_AXIS, axis), null), null)); - + if (blocks.size() == 1) return false; - + return true; } - + @Override protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, Queue frontier) { frontier.clear(); @@ -149,18 +149,18 @@ public class MountedContraption extends Contraption { protected boolean customBlockRemoval(IWorld world, BlockPos pos, BlockState state) { return AllBlocks.MINECART_ANCHOR.has(state); } - + @Override public boolean canBeStabilized(Direction facing, BlockPos localPos) { return true; } - + @Override public void addExtraInventories(Entity cart) { if (!(cart instanceof IInventory)) return; - IItemHandlerModifiable handlerFromInv = new InvWrapper((IInventory) cart); - inventory = new CombinedInvWrapper(handlerFromInv, inventory); + IItemHandlerModifiable handlerFromInv = new ContraptionInvWrapper(true, new InvWrapper((IInventory) cart)); + inventory = new ContraptionInvWrapper(handlerFromInv, inventory); } @Override 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 6cb418ec2..35dfac048 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 @@ -270,7 +270,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity } public float getMovementSpeed() { - float movementSpeed = MathHelper.clamp(getSpeed() / 512f, -.49f, .49f) + clientOffsetDiff / 2f; + float movementSpeed = MathHelper.clamp(convertToLinear(getSpeed()), -.49f, .49f) + clientOffsetDiff / 2f; if (world.isRemote) movementSpeed *= ServerSpeedProvider.get(); return movementSpeed; @@ -288,6 +288,11 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity } } + public void onLengthBroken() { + offset = 0; + sendData(); + } + @Override public boolean isValid() { return !isRemoved(); @@ -311,4 +316,4 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity public BlockPos getBlockPosition() { return pos; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java index bad9651ef..8297c9b20 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/MechanicalPistonTileEntity.java @@ -84,7 +84,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { applyContraptionPosition(); forceMove = true; world.addEntity(movedContraption); - + AllSoundEvents.CONTRAPTION_ASSEMBLE.playOnServer(world, pos); } @@ -118,7 +118,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity { @Override public float getMovementSpeed() { - float movementSpeed = MathHelper.clamp(getSpeed() / 512f, -.49f, .49f); + float movementSpeed = MathHelper.clamp(convertToLinear(getSpeed()), -.49f, .49f); if (world.isRemote) movementSpeed *= ServerSpeedProvider.get(); Direction pistonDirection = getBlockState().get(BlockStateProperties.FACING); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonContraption.java index 7c1ba23b0..b8c33f45b 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 @@ -15,7 +15,7 @@ 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.BlockMovementChecks; 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; @@ -169,13 +169,13 @@ public class PistonContraption extends TranslatingContraption { if (!world.isBlockPresent(currentPos)) throw AssemblyException.unloadedChunk(currentPos); BlockState state = world.getBlockState(currentPos); - if (!BlockMovementTraits.movementNecessary(state, world, currentPos)) + if (!BlockMovementChecks.isMovementNecessary(state, world, currentPos)) return true; - if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock)) + if (BlockMovementChecks.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock)) return true; if (isPistonHead(state) && state.get(FACING) == direction.getOpposite()) return true; - if (!BlockMovementTraits.movementAllowed(state, world, currentPos)) + if (!BlockMovementChecks.isMovementAllowed(state, world, currentPos)) if (retracting) return true; else @@ -183,7 +183,7 @@ public class PistonContraption extends TranslatingContraption { if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY) return true; frontier.add(currentPos); - if (BlockMovementTraits.notSupportive(state, orientation)) + if (BlockMovementChecks.isNotSupportive(state, orientation)) return true; } return true; 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 b88ef5c3a..38191de92 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 @@ -29,6 +29,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.pathfinding.PathType; import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; import net.minecraft.util.Direction.Axis; @@ -71,7 +72,7 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements public boolean isToolEffective(BlockState state, ToolType tool) { return tool == ToolType.AXE || tool == ToolType.PICKAXE; } - + @Override public PushReaction getPushReaction(BlockState state) { return PushReaction.NORMAL; @@ -113,10 +114,17 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements final BlockPos basePos = pistonBase; BlockPos.getAllInBox(pistonBase, pistonHead) - .filter(p -> !p.equals(pos) && !p.equals(basePos)) - .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); + .filter(p -> !p.equals(pos) && !p.equals(basePos)) + .forEach(p -> worldIn.destroyBlock(p, !player.isCreative())); worldIn.setBlockState(basePos, worldIn.getBlockState(basePos) - .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); + .with(MechanicalPistonBlock.STATE, PistonState.RETRACTED)); + + TileEntity te = worldIn.getTileEntity(basePos); + if (te instanceof MechanicalPistonTileEntity) { + MechanicalPistonTileEntity baseTE = (MechanicalPistonTileEntity) te; + baseTE.offset = 0; + baseTE.onLengthBroken(); + } } super.onBlockHarvested(worldIn, pos, state, player); @@ -168,8 +176,8 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements } return state; } - - @Override + + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java index 466d5bae5..84fa87b31 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonLighter.java @@ -1,7 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.piston; +import com.jozufozu.flywheel.light.GridAlignedBB; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; import net.minecraft.util.math.vector.Vector3i; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java index d17c12582..b77adc308 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/AbstractPulleyInstance.java @@ -2,18 +2,18 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pu import java.util.Arrays; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.instancing.ConditionalInstance; +import com.jozufozu.flywheel.core.instancing.GroupInstance; +import com.jozufozu.flywheel.core.instancing.SelectInstance; +import com.jozufozu.flywheel.core.materials.OrientedData; +import com.jozufozu.flywheel.light.GridAlignedBB; +import com.jozufozu.flywheel.light.ILightUpdateListener; +import com.jozufozu.flywheel.light.LightUpdater; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.util.ConditionalInstance; -import com.simibubi.create.foundation.render.backend.instancing.util.InstanceGroup; -import com.simibubi.create.foundation.render.backend.instancing.util.SelectInstance; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; -import com.simibubi.create.foundation.render.backend.light.LightUpdateListener; -import com.simibubi.create.foundation.render.backend.light.LightUpdater; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -22,11 +22,11 @@ import net.minecraft.util.math.vector.Vector3f; import net.minecraft.world.IBlockDisplayReader; import net.minecraft.world.LightType; -public abstract class AbstractPulleyInstance extends ShaftInstance implements IDynamicInstance, LightUpdateListener { +public abstract class AbstractPulleyInstance extends ShaftInstance implements IDynamicInstance, ILightUpdateListener { final OrientedData coil; final SelectInstance magnet; - final InstanceGroup rope; + final GroupInstance rope; final ConditionalInstance halfRope; protected float offset; @@ -37,7 +37,7 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID private byte[] sLight = new byte[1]; private GridAlignedBB volume; - public AbstractPulleyInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public AbstractPulleyInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); rotatingAbout = Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, axis); @@ -51,8 +51,9 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID magnet.addModel(getMagnetModel()) .addModel(getHalfMagnetModel()); - rope = new InstanceGroup<>(getRopeModel()); - halfRope = new ConditionalInstance<>(getHalfRopeModel(), this::shouldRenderHalfRope); + rope = new GroupInstance<>(getRopeModel()); + halfRope = new ConditionalInstance<>(getHalfRopeModel()) + .withCondition(this::shouldRenderHalfRope); } @Override @@ -115,15 +116,15 @@ public abstract class AbstractPulleyInstance extends ShaftInstance implements ID halfRope.delete(); } - protected abstract InstancedModel getRopeModel(); + protected abstract Instancer getRopeModel(); - protected abstract InstancedModel getMagnetModel(); + protected abstract Instancer getMagnetModel(); - protected abstract InstancedModel getHalfMagnetModel(); + protected abstract Instancer getHalfMagnetModel(); - protected abstract InstancedModel getCoilModel(); + protected abstract Instancer getCoilModel(); - protected abstract InstancedModel getHalfRopeModel(); + protected abstract Instancer getHalfRopeModel(); protected abstract float getOffset(); 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 481b065d0..f8994d9e7 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 @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.content.contraptions.base.IRotate; @@ -7,8 +9,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AngleHelper; import net.minecraft.block.BlockState; @@ -44,7 +44,7 @@ public abstract class AbstractPulleyRenderer extends KineticTileEntityRenderer { protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); float offset = getOffset(te, partialTicks); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java index a1adb0e43..b6fb4679c 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/HosePulleyInstance.java @@ -1,37 +1,37 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pulley; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.OrientedData; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.fluids.actors.HosePulleyTileEntity; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; public class HosePulleyInstance extends AbstractPulleyInstance { final HosePulleyTileEntity tile = (HosePulleyTileEntity) super.tile; - public HosePulleyInstance(InstancedTileRenderer dispatcher, HosePulleyTileEntity tile) { + public HosePulleyInstance(MaterialManager dispatcher, HosePulleyTileEntity tile) { super(dispatcher, tile); beginFrame(); } - protected InstancedModel getRopeModel() { + protected Instancer getRopeModel() { return getOrientedMaterial().getModel(AllBlockPartials.HOSE, blockState); } - protected InstancedModel getMagnetModel() { + protected Instancer getMagnetModel() { return getOrientedMaterial().getModel(AllBlockPartials.HOSE_MAGNET, blockState); } - protected InstancedModel getHalfMagnetModel() { + protected Instancer getHalfMagnetModel() { return getOrientedMaterial().getModel(AllBlockPartials.HOSE_HALF_MAGNET, blockState); } - protected InstancedModel getCoilModel() { + protected Instancer getCoilModel() { return getOrientedMaterial().getModel(AllBlockPartials.HOSE_COIL, blockState, rotatingAbout); } - protected InstancedModel getHalfRopeModel() { + protected Instancer getHalfRopeModel() { return getOrientedMaterial().getModel(AllBlockPartials.HOSE_HALF, blockState); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java index 2aa7b6d13..adcaca95f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/pulley/PulleyBlock.java @@ -42,13 +42,13 @@ public class PulleyBlock extends HorizontalAxisKineticBlock implements ITE dispatcher, PulleyTileEntity tile) { + public RopePulleyInstance(MaterialManager dispatcher, PulleyTileEntity tile) { super(dispatcher, tile); beginFrame(); } - protected InstancedModel getRopeModel() { + protected Instancer getRopeModel() { return getOrientedMaterial().getModel(AllBlocks.ROPE.getDefaultState()); } - protected InstancedModel getMagnetModel() { + protected Instancer getMagnetModel() { return getOrientedMaterial().getModel(AllBlocks.PULLEY_MAGNET.getDefaultState()); } - protected InstancedModel getHalfMagnetModel() { + protected Instancer getHalfMagnetModel() { return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF_MAGNET, blockState); } - protected InstancedModel getCoilModel() { + protected Instancer getCoilModel() { return getOrientedMaterial().getModel(AllBlockPartials.ROPE_COIL, blockState, rotatingAbout); } - protected InstancedModel getHalfRopeModel() { + protected Instancer getHalfRopeModel() { return getOrientedMaterial().getModel(AllBlockPartials.ROPE_HALF, blockState); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java index 561d6661b..4c02741d1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ActorInstance.java @@ -1,15 +1,19 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; import net.minecraft.world.LightType; public abstract class ActorInstance { - protected final ContraptionKineticRenderer modelManager; - protected final MovementContext context; + protected final MaterialManager materialManager; + protected final PlacementSimulationWorld simulationWorld; + protected final MovementContext context; - public ActorInstance(ContraptionKineticRenderer modelManager, MovementContext context) { - this.modelManager = modelManager; + public ActorInstance(MaterialManager materialManager, PlacementSimulationWorld world, MovementContext context) { + this.materialManager = materialManager; + this.simulationWorld = world; this.context = context; } @@ -18,6 +22,6 @@ public abstract class ActorInstance { public void beginFrame() { } protected int localBlockLight() { - return modelManager.getContraption().renderWorld.getLightLevel(LightType.BLOCK, context.localPos); + return simulationWorld.getLightLevel(LightType.BLOCK, context.localPos); } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionAttributes.java deleted file mode 100644 index 4e3d65be9..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionAttributes.java +++ /dev/null @@ -1,43 +0,0 @@ -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.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; - -public enum ContraptionAttributes 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; - - ContraptionAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 0; - } - - @Override - public int getBufferIndex() { - return 0; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java new file mode 100644 index 000000000..1cf73852d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionInstanceManager.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.tuple.Pair; + +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileInstanceManager; +import com.simibubi.create.AllMovementBehaviours; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; +import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; + +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.gen.feature.template.Template; + +public class ContraptionInstanceManager extends TileInstanceManager { + + protected ArrayList actors = new ArrayList<>(); + + private final WeakReference contraption; + + ContraptionInstanceManager(RenderedContraption contraption, MaterialManager materialManager) { + super(materialManager); + this.contraption = new WeakReference<>(contraption); + } + + public void tick() { + actors.forEach(ActorInstance::tick); + } + + @Override + public void beginFrame(ActiveRenderInfo info) { + super.beginFrame(info); + + actors.forEach(ActorInstance::beginFrame); + } + + @Override + protected boolean shouldFrameUpdate(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { + return true; + } + + @Nullable + public ActorInstance createActor(Pair actor) { + Template.BlockInfo blockInfo = actor.getLeft(); + MovementContext context = actor.getRight(); + + MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); + + if (movementBehaviour != null && movementBehaviour.hasSpecialInstancedRendering()) { + ActorInstance instance = movementBehaviour.createInstance(materialManager, getContraption().renderWorld, context); + + actors.add(instance); + + return instance; + } + + return null; + } + + public RenderedContraption getContraption() { + return contraption.get(); + } +} + 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 deleted file mode 100644 index 51f02c77b..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionKineticRenderer.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -import javax.annotation.Nullable; - -import org.apache.commons.lang3.tuple.Pair; - -import com.simibubi.create.AllMovementBehaviours; -import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; -import com.simibubi.create.content.contraptions.base.RotatingModel; -import com.simibubi.create.content.contraptions.components.actors.ActorData; -import com.simibubi.create.content.contraptions.components.actors.ActorModel; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementBehaviour; -import com.simibubi.create.content.contraptions.components.structureMovement.MovementContext; -import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel; -import com.simibubi.create.content.logistics.block.FlapModel; -import com.simibubi.create.foundation.render.AllProgramSpecs; -import com.simibubi.create.foundation.render.backend.MaterialTypes; -import com.simibubi.create.foundation.render.backend.core.OrientedModel; -import com.simibubi.create.foundation.render.backend.core.TransformedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; - -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.gen.feature.template.Template; - -public class ContraptionKineticRenderer extends InstancedTileRenderer { - - protected ArrayList actors = new ArrayList<>(); - - private final WeakReference contraption; - - ContraptionKineticRenderer(RenderedContraption contraption) { - this.contraption = new WeakReference<>(contraption); - } - - @Override - public void registerMaterials() { - materials.put(MaterialTypes.TRANSFORMED, new RenderMaterial<>(this, AllProgramSpecs.C_MODEL, TransformedModel::new)); - materials.put(MaterialTypes.ORIENTED, new RenderMaterial<>(this, AllProgramSpecs.C_ORIENTED, OrientedModel::new)); - - materials.put(KineticRenderMaterials.BELTS, new RenderMaterial<>(this, AllProgramSpecs.C_BELT, BeltInstancedModel::new)); - materials.put(KineticRenderMaterials.ROTATING, new RenderMaterial<>(this, AllProgramSpecs.C_ROTATING, RotatingModel::new)); - materials.put(KineticRenderMaterials.FLAPS, new RenderMaterial<>(this, AllProgramSpecs.C_FLAPS, FlapModel::new)); - materials.put(KineticRenderMaterials.ACTORS, new RenderMaterial<>(this, AllProgramSpecs.C_ACTOR, ActorModel::new)); - } - - public void tick() { - actors.forEach(ActorInstance::tick); - } - - @Override - public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) { - super.beginFrame(info, cameraX, cameraY, cameraZ); - - actors.forEach(ActorInstance::beginFrame); - } - - @Override - protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { - return true; - } - - @Nullable - public ActorInstance createActor(Pair actor) { - Template.BlockInfo blockInfo = actor.getLeft(); - MovementContext context = actor.getRight(); - - MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); - - if (movementBehaviour != null && movementBehaviour.hasSpecialInstancedRendering()) { - ActorInstance instance = movementBehaviour.createInstance(this, context); - - actors.add(instance); - - return instance; - } - - return null; - } - - public RenderMaterial> getActorMaterial() { - return getMaterial(KineticRenderMaterials.ACTORS); - } - - public RenderedContraption getContraption() { - return contraption.get(); - } - - @Override - public BlockPos getOriginCoordinate() { - return BlockPos.ZERO; - } -} - diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMaterialManager.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMaterialManager.java new file mode 100644 index 000000000..fc66294b9 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMaterialManager.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.MaterialRenderer; +import com.jozufozu.flywheel.core.WorldContext; +import com.jozufozu.flywheel.core.shader.IProgramCallback; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.util.math.vector.Matrix4f; + +public class ContraptionMaterialManager extends MaterialManager { + public ContraptionMaterialManager(WorldContext context) { + super(context); + } + + @Override + public void render(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ, IProgramCallback callback) { + for (MaterialRenderer material : atlasRenderers) { + material.render(layer, viewProjection, camX, camY, camZ, callback); + } + } +} diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java new file mode 100644 index 000000000..d6e82d17d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionMatrices.java @@ -0,0 +1,65 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.entity.Entity; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix3f; +import net.minecraft.util.math.vector.Matrix4f; + +public class ContraptionMatrices { + public final MatrixStack entityStack; + public final MatrixStack contraptionStack; + public final Matrix4f entityMatrix; + + public ContraptionMatrices(MatrixStack entityStack, AbstractContraptionEntity entity) { + this.entityStack = entityStack; + this.contraptionStack = new MatrixStack(); + float partialTicks = AnimationTickHolder.getPartialTicks(); + entity.doLocalTransforms(partialTicks, new MatrixStack[] { this.contraptionStack }); + entityMatrix = translateTo(entity, partialTicks); + } + + public MatrixStack getFinalStack() { + MatrixStack finalStack = new MatrixStack(); + transform(finalStack, entityStack); + transform(finalStack, contraptionStack); + return finalStack; + } + + public Matrix4f getFinalModel() { + Matrix4f finalModel = entityStack.peek().getModel().copy(); + finalModel.multiply(contraptionStack.peek().getModel()); + return finalModel; + } + + public Matrix3f getFinalNormal() { + Matrix3f finalNormal = entityStack.peek().getNormal().copy(); + finalNormal.multiply(contraptionStack.peek().getNormal()); + return finalNormal; + } + + public Matrix4f getFinalLight() { + Matrix4f lightTransform = entityMatrix.copy(); + lightTransform.multiply(contraptionStack.peek().getModel()); + return lightTransform; + } + + public static Matrix4f translateTo(Entity entity, float partialTicks) { + double x = MathHelper.lerp(partialTicks, entity.lastTickPosX, entity.getX()); + double y = MathHelper.lerp(partialTicks, entity.lastTickPosY, entity.getY()); + double z = MathHelper.lerp(partialTicks, entity.lastTickPosZ, entity.getZ()); + return Matrix4f.translate((float) x, (float) y, (float) z); + } + + public static void transform(MatrixStack ms, MatrixStack transform) { + ms.peek().getModel() + .multiply(transform.peek() + .getModel()); + ms.peek().getNormal() + .multiply(transform.peek() + .getNormal()); + } +} 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 deleted file mode 100644 index 270d8d08d..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionModel.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.simibubi.create.content.contraptions.components.structureMovement.render; - -import java.nio.ByteBuffer; - -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL20; - -import com.simibubi.create.foundation.render.backend.BufferedModel; -import com.simibubi.create.foundation.render.backend.gl.GlBuffer; -import com.simibubi.create.foundation.render.backend.gl.GlPrimitiveType; -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(ContraptionAttributes.class) - .build(); - - protected GlPrimitiveType eboIndexType; - protected GlBuffer ebo; - - public ContraptionModel(BufferBuilder buf) { - super(buf); - } - - @Override - protected void init() { - super.init(); - - createEBO(); - } - - @Override - protected void doRender() { - modelVBO.bind(); - ebo.bind(); - - setupAttributes(); - GL20.glDrawElements(GL20.GL_QUADS, vertexCount, eboIndexType.getGlConstant(), 0); - - int numAttributes = getTotalShaderAttributeCount(); - for (int i = 0; i <= numAttributes; i++) { - GL20.glDisableVertexAttribArray(i); - } - - ebo.unbind(); - modelVBO.unbind(); - } - - protected final void createEBO() { - ebo = new GlBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER); - eboIndexType = GlPrimitiveType.UINT; // TODO: choose this based on the number of vertices - - int indicesSize = vertexCount * eboIndexType.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.putInt(i); - } - }); - - ebo.unbind(); - } - - @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; - } - - @Override - protected void deleteInternal() { - super.deleteInternal(); - ebo.delete(); - } -} 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 index 977593f34..529051f11 100644 --- 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 @@ -1,33 +1,35 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import java.util.List; + import org.lwjgl.opengl.GL20; -import com.simibubi.create.foundation.render.backend.gl.BasicProgram; -import com.simibubi.create.foundation.render.backend.gl.shader.ProgramFogMode; +import com.jozufozu.flywheel.backend.loading.Program; +import com.jozufozu.flywheel.core.shader.WorldProgram; +import com.jozufozu.flywheel.core.shader.extension.IProgramExtension; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.vector.Matrix4f; -public class ContraptionProgram extends BasicProgram { - protected final int uLightBoxSize; - protected final int uLightBoxMin; - protected final int uModel; +public class ContraptionProgram extends WorldProgram { + protected final int uLightBoxSize; + protected final int uLightBoxMin; + protected final int uModel; - protected int uLightVolume; + protected int uLightVolume; - public ContraptionProgram(ResourceLocation name, int handle, ProgramFogMode.Factory fogFactory) { - super(name, handle, fogFactory); - uLightBoxSize = getUniformLocation("uLightBoxSize"); - uLightBoxMin = getUniformLocation("uLightBoxMin"); - uModel = getUniformLocation("uModel"); - } + public ContraptionProgram(Program program, List extensions) { + super(program, extensions); + uLightBoxSize = getUniformLocation("uLightBoxSize"); + uLightBoxMin = getUniformLocation("uLightBoxMin"); + uModel = getUniformLocation("uModel"); + } - @Override - protected void registerSamplers() { - super.registerSamplers(); - uLightVolume = setSamplerBinding("uLightVolume", 4); - } + @Override + protected void registerSamplers() { + super.registerSamplers(); + uLightVolume = setSamplerBinding("uLightVolume", 4); + } public void bind(Matrix4f model, AxisAlignedBB lightVolume) { double sizeX = lightVolume.maxX - lightVolume.minX; diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java index 83c39757f..963b93a91 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionRenderDispatcher.java @@ -1,13 +1,24 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import static org.lwjgl.opengl.GL11.glBindTexture; +import static org.lwjgl.opengl.GL13.GL_QUADS; +import static org.lwjgl.opengl.GL13.GL_TEXTURE0; +import static org.lwjgl.opengl.GL13.GL_TEXTURE4; +import static org.lwjgl.opengl.GL13.GL_TEXTURE_3D; +import static org.lwjgl.opengl.GL13.glActiveTexture; +import static org.lwjgl.opengl.GL13.glDisable; +import static org.lwjgl.opengl.GL13.glEnable; +import static org.lwjgl.opengl.GL20.glUseProgram; + 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.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.event.BeginFrameEvent; +import com.jozufozu.flywheel.event.ReloadRenderersEvent; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.CreateClient; @@ -17,11 +28,10 @@ import com.simibubi.create.content.contraptions.components.structureMovement.Mov 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.CreateContexts; 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; @@ -32,138 +42,180 @@ import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ActiveRenderInfo; import net.minecraft.client.renderer.BlockModelRenderer; -import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BlockModelShapes; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderTypeLookup; import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Matrix4f; import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraft.world.gen.feature.template.Template; import net.minecraftforge.client.ForgeHooksClient; import net.minecraftforge.client.model.data.EmptyModelData; +import net.minecraftforge.common.util.Lazy; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import org.lwjgl.opengl.GL20; + +@Mod.EventBusSubscriber public class ContraptionRenderDispatcher { - public static final Int2ObjectMap renderers = new Int2ObjectOpenHashMap<>(); + private static final Lazy MODEL_RENDERER = Lazy.of(() -> new BlockModelRenderer(Minecraft.getInstance().getBlockColors())); + private static final Lazy BLOCK_MODELS = Lazy.of(() -> Minecraft.getInstance().getModelManager().getBlockModelShapes()); + private static int worldHolderRefreshCounter; + + public static final Int2ObjectMap RENDERERS = new Int2ObjectOpenHashMap<>(); + public static final Int2ObjectMap WORLD_HOLDERS = new Int2ObjectOpenHashMap<>(); public static final Compartment> CONTRAPTION = new Compartment<>(); - protected static PlacementSimulationWorld renderWorld; public static void tick() { if (Minecraft.getInstance().isGamePaused()) return; - for (RenderedContraption contraption : renderers.values()) { + for (RenderedContraption contraption : RENDERERS.values()) { contraption.getLighter().tick(contraption); contraption.kinetics.tick(); } + + worldHolderRefreshCounter++; + if (worldHolderRefreshCounter >= 20) { + removeDeadHolders(); + worldHolderRefreshCounter = 0; + } } - public static void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { - for (RenderedContraption renderer : renderers.values()) { + @SubscribeEvent + public static void beginFrame(BeginFrameEvent event) { + ActiveRenderInfo info = event.getInfo(); + double camX = info.getProjectedView().x; + double camY = info.getProjectedView().y; + double camZ = info.getProjectedView().z; + for (RenderedContraption renderer : RENDERERS.values()) { renderer.beginFrame(info, camX, camY, camZ); } } - public static void renderLayer(RenderType layer, Matrix4f viewProjection, double camX, double camY, double camZ) { - removeDeadContraptions(); + @SubscribeEvent + public static void renderLayer(RenderLayerEvent event) { + removeDeadContraptions(); - if (renderers.isEmpty()) return; + if (RENDERERS.isEmpty()) return; + RenderType layer = event.getType(); - layer.startDrawing(); - GL11.glEnable(GL13.GL_TEXTURE_3D); - GL13.glActiveTexture(GL40.GL_TEXTURE4); // the shaders expect light volumes to be in texture 4 + layer.startDrawing(); + glEnable(GL_TEXTURE_3D); + glActiveTexture(GL_TEXTURE4); // the shaders expect light volumes to be in texture 4 - if (Backend.canUseVBOs()) { - ContraptionProgram structureShader = Backend.getProgram(AllProgramSpecs.C_STRUCTURE); - structureShader.bind(viewProjection, camX, camY, camZ, FastRenderDispatcher.getDebugMode()); - for (RenderedContraption renderer : renderers.values()) { - renderer.doRenderLayer(layer, structureShader); - } - } + if (Backend.getInstance().canUseVBOs()) { + ContraptionProgram structureShader = CreateContexts.STRUCTURE.getProgram(AllProgramSpecs.STRUCTURE); - if (Backend.canUseInstancing()) { - for (RenderedContraption renderer : renderers.values()) { - renderer.kinetics.render(layer, viewProjection, camX, camY, camZ, renderer::setup); - renderer.teardown(); + structureShader.bind(); + structureShader.uploadViewProjection(event.viewProjection); + structureShader.uploadCameraPos(event.camX, event.camY, event.camZ); + + for (RenderedContraption renderer : RENDERERS.values()) { + renderer.doRenderLayer(layer, structureShader); } } + if (Backend.getInstance().canUseInstancing()) { + for (RenderedContraption renderer : RENDERERS.values()) { + renderer.materialManager.render(layer, event.viewProjection, event.camX, event.camY, event.camZ, renderer::setup); + } + } + + glBindTexture(GL_TEXTURE_3D, 0); layer.endDrawing(); - GL11.glDisable(GL13.GL_TEXTURE_3D); - GL13.glActiveTexture(GL40.GL_TEXTURE0); + glDisable(GL_TEXTURE_3D); + glActiveTexture(GL_TEXTURE0); + glUseProgram(0); + } + + @SubscribeEvent + public static void onRendererReload(ReloadRenderersEvent event) { + invalidateAll(); + } + + public static void render(AbstractContraptionEntity entity, Contraption contraption, + ContraptionMatrices matrices, IRenderTypeBuffer buffers) { + World world = entity.world; + if (Backend.getInstance().canUseVBOs() && Backend.isFlywheelWorld(world)) { + RenderedContraption renderer = getRenderer(world, contraption); + PlacementSimulationWorld renderWorld = renderer.renderWorld; + + ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers); + } else { + ContraptionWorldHolder holder = getWorldHolder(world, contraption); + PlacementSimulationWorld renderWorld = holder.renderWorld; + + ContraptionRenderDispatcher.renderDynamic(world, renderWorld, contraption, matrices, buffers); + ContraptionRenderDispatcher.renderStructure(world, renderWorld, contraption, matrices, buffers); + } } private static RenderedContraption getRenderer(World world, Contraption c) { int entityId = c.entity.getEntityId(); - RenderedContraption contraption = renderers.get(entityId); + RenderedContraption contraption = RENDERERS.get(entityId); if (contraption == null) { - contraption = new RenderedContraption(world, c); - renderers.put(entityId, contraption); + PlacementSimulationWorld renderWorld = setupRenderWorld(world, c); + contraption = new RenderedContraption(c, renderWorld); + RENDERERS.put(entityId, contraption); } return contraption; } - public static void render(AbstractContraptionEntity entity, MatrixStack ms, IRenderTypeBuffer buffers, - MatrixStack msLocal, Contraption contraption) { - if (Backend.canUseVBOs() && Backend.isFlywheelWorld(entity.world)) { - 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); + private static ContraptionWorldHolder getWorldHolder(World world, Contraption c) { + int entityId = c.entity.getEntityId(); + ContraptionWorldHolder holder = WORLD_HOLDERS.get(entityId); + + if (holder == null) { + PlacementSimulationWorld renderWorld = setupRenderWorld(world, c); + holder = new ContraptionWorldHolder(c, renderWorld); + WORLD_HOLDERS.put(entityId, holder); } + + return holder; } - public static void renderStructure(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - SuperByteBufferCache bufferCache = CreateClient.bufferCache; - List blockLayers = RenderType.getBlockLayers(); + public static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { + PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); - 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)); - } + renderWorld.setTileEntities(c.presentTileEntities.values()); + + for (Template.BlockInfo info : c.getBlocks() + .values()) + // Skip individual lighting updates to prevent lag with large contraptions + renderWorld.setBlockState(info.pos, info.state, 128); + + renderWorld.updateLightSources(); + renderWorld.lighter.tick(Integer.MAX_VALUE, false, false); + + return renderWorld; } - public static void renderDynamic(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - renderTileEntities(world, c, ms, msLocal, buffer); + public static void renderDynamic(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + renderTileEntities(world, renderWorld, c, matrices, buffer); if (buffer instanceof IRenderTypeBuffer.Impl) ((IRenderTypeBuffer.Impl) buffer).draw(); - renderActors(world, c, ms, msLocal, buffer); + renderActors(world, renderWorld, c, matrices, buffer); } - public static void renderTileEntities(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - PlacementSimulationWorld renderWorld = null; - if (Backend.canUseVBOs() && Backend.isFlywheelWorld(world)) { - RenderedContraption renderer = getRenderer(world, c); - - renderWorld = renderer.renderWorld; - } - TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, ms, msLocal, buffer); - + public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + TileEntityRenderHelper.renderTileEntities(world, renderWorld, c.specialRenderedTileEntities, + matrices.getFinalStack(), matrices.getFinalLight(), buffer); } - protected static void renderActors(World world, Contraption c, MatrixStack ms, MatrixStack msLocal, - IRenderTypeBuffer buffer) { - MatrixStack[] matrixStacks = new MatrixStack[]{ms, msLocal}; + protected static void renderActors(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { for (Pair actor : c.getActors()) { MovementContext context = actor.getRight(); if (context == null) @@ -171,123 +223,108 @@ public class ContraptionRenderDispatcher { if (context.world == null) context.world = world; Template.BlockInfo blockInfo = actor.getLeft(); - for (MatrixStack m : matrixStacks) { - m.push(); - MatrixStacker.of(m) - .translate(blockInfo.pos); - } + + MatrixStack m = matrices.contraptionStack; + m.push(); + MatrixStacker.of(m) + .translate(blockInfo.pos); MovementBehaviour movementBehaviour = AllMovementBehaviours.of(blockInfo.state); if (movementBehaviour != null) - movementBehaviour.renderInContraption(context, ms, msLocal, buffer); + movementBehaviour.renderInContraption(context, renderWorld, matrices, buffer); - for (MatrixStack m : matrixStacks) - m.pop(); + m.pop(); } } - private static SuperByteBuffer buildStructureBuffer(Contraption c, RenderType layer) { - BufferBuilder builder = buildStructure(c, layer); + public static void renderStructure(World world, PlacementSimulationWorld renderWorld, Contraption c, + ContraptionMatrices matrices, IRenderTypeBuffer buffer) { + SuperByteBufferCache bufferCache = CreateClient.BUFFER_CACHE; + 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(renderWorld, c, layer)); + if (contraptionBuffer.isEmpty()) + continue; + contraptionBuffer + .transform(matrices.contraptionStack) + .light(matrices.entityMatrix) + .hybridLight() + .renderInto(matrices.entityStack, buffer.getBuffer(layer)); + } + } + + private static SuperByteBuffer buildStructureBuffer(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + BufferBuilder builder = buildStructure(renderWorld, 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); + public static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + MatrixStack ms = new MatrixStack(); + Random random = new Random(); + BufferBuilder builder = new BufferBuilder(DefaultVertexFormats.BLOCK.getIntegerSize()); + builder.begin(GL_QUADS, DefaultVertexFormats.BLOCK); - 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()); + ForgeHooksClient.setRenderLayer(layer); + BlockModelRenderer.enableCache(); + for (Template.BlockInfo info : c.getBlocks() + .values()) { + BlockState state = info.state; - for (Template.BlockInfo info : c.getBlocks() - .values()) - renderWorld.setBlockState(info.pos, info.state); + if (state.getRenderType() != BlockRenderType.MODEL) + continue; + if (!RenderTypeLookup.canRenderInLayer(state, layer)) + continue; - for (Template.BlockInfo info : c.getBlocks() - .values()) { - BlockState state = info.state; + BlockPos pos = info.pos; - 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; - } - - 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; + ms.push(); + ms.translate(pos.getX(), pos.getY(), pos.getZ()); + MODEL_RENDERER.get().renderModel(renderWorld, BLOCK_MODELS.get().getModel(state), state, pos, ms, builder, true, + random, 42, OverlayTexture.DEFAULT_UV, EmptyModelData.INSTANCE); + ms.pop(); } + BlockModelRenderer.disableCache(); + ForgeHooksClient.setRenderLayer(null); + + builder.finishDrawing(); + return builder; + } + + public static int getLight(World world, float lx, float ly, float lz) { + BlockPos.Mutable pos = new BlockPos.Mutable(); + float block = 0, sky = 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); + block += world.getLightLevel(LightType.BLOCK, pos) / 8f; + sky += world.getLightLevel(LightType.SKY, pos) / 8f; + } + + return LightTexture.pack((int) block, (int) sky); + } + + public static int getContraptionWorldLight(MovementContext context, PlacementSimulationWorld renderWorld) { + return WorldRenderer.getLightmapCoordinates(renderWorld, context.localPos); } public static void invalidateAll() { - for (RenderedContraption renderer : renderers.values()) { + for (RenderedContraption renderer : RENDERERS.values()) { renderer.invalidate(); } - renderers.clear(); + RENDERERS.clear(); + WORLD_HOLDERS.clear(); } public static void removeDeadContraptions() { - renderers.values().removeIf(renderer -> { + RENDERERS.values().removeIf(renderer -> { if (renderer.isDead()) { renderer.invalidate(); return true; @@ -295,4 +332,9 @@ public class ContraptionRenderDispatcher { return false; }); } + + public static void removeDeadHolders() { + WORLD_HOLDERS.values().removeIf(ContraptionWorldHolder::isDead); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionWorldHolder.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionWorldHolder.java new file mode 100644 index 000000000..4ae414016 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/ContraptionWorldHolder.java @@ -0,0 +1,22 @@ +package com.simibubi.create.content.contraptions.components.structureMovement.render; + +import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; +import com.simibubi.create.foundation.utility.worldWrappers.PlacementSimulationWorld; + +public class ContraptionWorldHolder { + public final Contraption contraption; + public final PlacementSimulationWorld renderWorld; + + public ContraptionWorldHolder(Contraption contraption, PlacementSimulationWorld renderWorld) { + this.contraption = contraption; + this.renderWorld = renderWorld; + } + + public int getEntityId() { + return contraption.entity.getEntityId(); + } + + public boolean isDead() { + return !contraption.entity.isAlive(); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/EmptyLighter.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/EmptyLighter.java similarity index 78% rename from src/main/java/com/simibubi/create/foundation/render/backend/light/EmptyLighter.java rename to src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/EmptyLighter.java index a92cf4e27..da4a5384b 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/EmptyLighter.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/EmptyLighter.java @@ -1,5 +1,6 @@ -package com.simibubi.create.foundation.render.backend.light; +package com.simibubi.create.content.contraptions.components.structureMovement.render; +import com.jozufozu.flywheel.light.GridAlignedBB; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionLighter; diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java similarity index 83% rename from src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java rename to src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java index e63257d04..8645e4077 100644 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolumeDebugger.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/LightVolumeDebugger.java @@ -1,9 +1,9 @@ -package com.simibubi.create.foundation.render.backend.light; +package com.simibubi.create.content.contraptions.components.structureMovement.render; import java.util.ArrayList; +import com.jozufozu.flywheel.light.GridAlignedBB; 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.AnimationTickHolder; import com.simibubi.create.foundation.utility.Pair; @@ -11,7 +11,7 @@ import com.simibubi.create.foundation.utility.outliner.AABBOutline; public class LightVolumeDebugger { public static void render(MatrixStack ms, SuperRenderTypeBuffer buffer) { - ContraptionRenderDispatcher.renderers.values() + ContraptionRenderDispatcher.RENDERERS.values() .stream() .flatMap(r -> { GridAlignedBB texture = r.getLighter().lightVolume.getTextureVolume(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java index bf5ffde42..84ce22b80 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/render/RenderedContraption.java @@ -1,221 +1,207 @@ package com.simibubi.create.content.contraptions.components.structureMovement.render; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; import java.util.Collection; import java.util.HashMap; import java.util.List; -import java.util.Random; +import java.util.Map; -import org.lwjgl.opengl.GL11; +import javax.annotation.Nullable; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.model.ArrayModelRenderer; +import com.jozufozu.flywheel.backend.model.BufferedModel; +import com.jozufozu.flywheel.backend.model.IndexedModel; +import com.jozufozu.flywheel.backend.model.ModelRenderer; +import com.jozufozu.flywheel.light.GridAlignedBB; +import com.jozufozu.flywheel.util.BufferBuilderReader; import com.mojang.blaze3d.matrix.MatrixStack; 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.foundation.render.backend.Backend; -import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; -import com.simibubi.create.foundation.render.backend.light.GridAlignedBB; +import com.simibubi.create.foundation.render.CreateContexts; 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.ActiveRenderInfo; -import net.minecraft.client.renderer.BlockModelRenderer; -import net.minecraft.client.renderer.BlockRendererDispatcher; -import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.LightTexture; 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.util.math.vector.Matrix4f; 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 class RenderedContraption extends ContraptionWorldHolder { + public static final VertexFormat FORMAT = VertexFormat.builder() + .addAttributes(CommonAttributes.VEC3, + CommonAttributes.NORMAL, + CommonAttributes.UV, + CommonAttributes.RGBA, + CommonAttributes.LIGHT) + .build(); - public final PlacementSimulationWorld renderWorld; + private final ContraptionLighter lighter; - private final ContraptionLighter lighter; + public final MaterialManager materialManager; + public final ContraptionInstanceManager kinetics; - public final ContraptionKineticRenderer kinetics; + private final Map renderLayers = new HashMap<>(); - public Contraption contraption; + private Matrix4f model; + private AxisAlignedBB lightBox; - private Matrix4f model; - private AxisAlignedBB lightBox; + public RenderedContraption(Contraption contraption, PlacementSimulationWorld renderWorld) { + super(contraption, renderWorld); + this.lighter = contraption.makeLighter(); + this.materialManager = new ContraptionMaterialManager(CreateContexts.CWORLD); + this.kinetics = new ContraptionInstanceManager(this, materialManager); - public RenderedContraption(World world, Contraption contraption) { - this.contraption = contraption; - this.lighter = contraption.makeLighter(); - this.kinetics = new ContraptionKineticRenderer(this); - this.renderWorld = setupRenderWorld(world, contraption); + buildLayers(); + if (Backend.getInstance().canUseInstancing()) { + buildInstancedTiles(); + buildActors(); + } + } - buildLayers(); - if (Backend.canUseInstancing()) { - buildInstancedTiles(); - buildActors(); - } - } + public ContraptionLighter getLighter() { + return lighter; + } - public int getEntityId() { - return contraption.entity.getEntityId(); - } + public void doRenderLayer(RenderType layer, ContraptionProgram shader) { + ModelRenderer structure = renderLayers.get(layer); + if (structure != null) { + setup(shader); + structure.draw(); + } + } - public boolean isDead() { - return !contraption.entity.isAlive(); - } + public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { + kinetics.beginFrame(info); - public ContraptionLighter getLighter() { - return lighter; - } + AbstractContraptionEntity entity = contraption.entity; + float pt = AnimationTickHolder.getPartialTicks(); - public void doRenderLayer(RenderType layer, ContraptionProgram shader) { - ContraptionModel structure = renderLayers.get(layer); - if (structure != null) { - setup(shader); - structure.render(); - teardown(); - } - } + MatrixStack stack = new MatrixStack(); - public void beginFrame(ActiveRenderInfo info, double camX, double camY, double camZ) { - kinetics.beginFrame(info, camX, camY, camZ); + 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); - AbstractContraptionEntity entity = contraption.entity; - float pt = AnimationTickHolder.getPartialTicks(); + entity.doLocalTransforms(pt, new MatrixStack[] { stack }); - MatrixStack stack = new MatrixStack(); + model = stack.peek().getModel(); - 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); + AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()); - entity.doLocalTransforms(pt, new MatrixStack[]{ stack }); + this.lightBox = lightBox.offset(-camX, -camY, -camZ); + } - model = stack.peek().getModel(); + void setup(ContraptionProgram shader) { + if (model == null || lightBox == null) return; + shader.bind(model, lightBox); + lighter.lightVolume.bind(); + } - AxisAlignedBB lightBox = GridAlignedBB.toAABB(lighter.lightVolume.getTextureVolume()); + void invalidate() { + for (ModelRenderer buffer : renderLayers.values()) { + buffer.delete(); + } + renderLayers.clear(); - this.lightBox = lightBox.offset(-camX, -camY, -camZ); - } + lighter.lightVolume.delete(); - void setup(ContraptionProgram shader) { - if (model == null || lightBox == null) return; - shader.bind(model, lightBox); - lighter.lightVolume.bind(); - } + materialManager.delete(); + kinetics.invalidate(); + } - void teardown() { - lighter.lightVolume.unbind(); - } + private void buildLayers() { + for (ModelRenderer buffer : renderLayers.values()) { + buffer.delete(); + } - void invalidate() { - for (ContraptionModel buffer : renderLayers.values()) { - buffer.delete(); - } - renderLayers.clear(); + renderLayers.clear(); - lighter.lightVolume.delete(); + List blockLayers = RenderType.getBlockLayers(); - kinetics.invalidate(); - } + for (RenderType layer : blockLayers) { + BufferedModel layerModel = buildStructureModel(renderWorld, contraption, layer); - private void buildLayers() { - for (ContraptionModel buffer : renderLayers.values()) { - buffer.delete(); - } + if (layerModel != null) { + if (Backend.getInstance().compat.vertexArrayObjectsSupported()) + renderLayers.put(layer, new ArrayModelRenderer(layerModel)); + else + renderLayers.put(layer, new ModelRenderer(layerModel)); + } + } + } - renderLayers.clear(); + 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); + } + } + } + } - List blockLayers = RenderType.getBlockLayers(); + private void buildActors() { + contraption.getActors().forEach(kinetics::createActor); + } - for (RenderType layer : blockLayers) { - renderLayers.put(layer, buildStructureModel(renderWorld, contraption, layer)); - } - } + @Nullable + private static BufferedModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + BufferBuilderReader reader = new BufferBuilderReader(ContraptionRenderDispatcher.buildStructure(renderWorld, c, 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); - } - } - } - } + int vertexCount = reader.getVertexCount(); + if (vertexCount == 0) return null; - private void buildActors() { - contraption.getActors().forEach(kinetics::createActor); - } + VertexFormat format = FORMAT; - private static ContraptionModel buildStructureModel(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { - BufferBuilder builder = buildStructure(renderWorld, c, layer); - return new ContraptionModel(builder); - } + ByteBuffer vertices = ByteBuffer.allocate(format.getStride() * vertexCount); + vertices.order(ByteOrder.nativeOrder()); - private static PlacementSimulationWorld setupRenderWorld(World world, Contraption c) { - PlacementSimulationWorld renderWorld = new PlacementSimulationWorld(world); + for (int i = 0; i < vertexCount; i++) { + vertices.putFloat(reader.getX(i)); + vertices.putFloat(reader.getY(i)); + vertices.putFloat(reader.getZ(i)); - renderWorld.setTileEntities(c.presentTileEntities.values()); + vertices.put(reader.getNX(i)); + vertices.put(reader.getNY(i)); + vertices.put(reader.getNZ(i)); - for (Template.BlockInfo info : c.getBlocks() - .values()) - renderWorld.setBlockState(info.pos, info.state); + vertices.putFloat(reader.getU(i)); + vertices.putFloat(reader.getV(i)); - WorldLightManager lighter = renderWorld.lighter; + vertices.put(reader.getR(i)); + vertices.put(reader.getG(i)); + vertices.put(reader.getB(i)); + vertices.put(reader.getA(i)); - renderWorld.chunkProvider.getLightSources().forEach((pos) -> lighter.func_215573_a(pos, renderWorld.getLightValue(pos))); + int light = reader.getLight(i); - lighter.tick(Integer.MAX_VALUE, true, false); + byte block = (byte) (LightTexture.getBlockLightCoordinates(light) << 4); + byte sky = (byte) (LightTexture.getSkyLightCoordinates(light) << 4); - return renderWorld; - } + vertices.put(block); + vertices.put(sky); + } - private static BufferBuilder buildStructure(PlacementSimulationWorld renderWorld, Contraption c, RenderType layer) { + vertices.rewind(); - 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; - } + return IndexedModel.fromSequentialQuads(format, vertices, vertexCount); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java index c3836991c..e16e87de6 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/CouplingHandler.java @@ -124,7 +124,7 @@ public class CouplingHandler { while (true) { if (safetyCount-- <= 0) { - Create.logger.warn("Infinite loop in coupling iteration"); + Create.LOGGER.warn("Infinite loop in coupling iteration"); return false; } 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 0a6edeb8d..7e987e371 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 @@ -219,24 +219,24 @@ public class CouplingRenderer { MinecartController first = c.getFirst(); AbstractMinecartEntity mainCart = first.cart(); Vector3d mainCenter = mainCart.getPositionVec() - .add(0, yOffset, 0); + .add(0, yOffset, 0); Vector3d connectedCenter = c.getSecond() - .cart() - .getPositionVec() - .add(0, yOffset, 0); + .cart() + .getPositionVec() + .add(0, yOffset, 0); int color = ColorHelper.mixColors(0xabf0e9, 0xee8572, (float) MathHelper - .clamp(Math.abs(first.getCouplingLength(true) - connectedCenter.distanceTo(mainCenter)) * 8, 0, 1)); + .clamp(Math.abs(first.getCouplingLength(true) - connectedCenter.distanceTo(mainCenter)) * 8, 0, 1)); - CreateClient.outliner.showLine(mainCart.getEntityId() + "", mainCenter, connectedCenter) - .colored(color) - .lineWidth(1 / 8f); + CreateClient.OUTLINER.showLine(mainCart.getEntityId() + "", mainCenter, connectedCenter) + .colored(color) + .lineWidth(1 / 8f); Vector3d point = mainCart.getPositionVec() - .add(0, yOffset, 0); - CreateClient.outliner.showLine(mainCart.getEntityId() + "_dot", point, point.add(0, 1 / 128f, 0)) - .colored(0xffffff) - .lineWidth(1 / 4f); + .add(0, yOffset, 0); + CreateClient.OUTLINER.showLine(mainCart.getEntityId() + "_dot", point, point.add(0, 1 / 128f, 0)) + .colored(0xffffff) + .lineWidth(1 / 4f); } } 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 d421c8fb1..66986c18d 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 @@ -4,6 +4,8 @@ import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartController; +import com.simibubi.create.foundation.utility.Iterate; + import net.minecraft.entity.Entity; import net.minecraft.entity.item.minecart.AbstractMinecartEntity; import net.minecraft.entity.player.PlayerEntity; @@ -78,6 +80,11 @@ public class MinecartCouplingItem extends Item { if (event.getWorld().isRemote) return true; + for (boolean forward : Iterate.trueAndFalse) { + if (controller.hasContraptionCoupling(forward)) + couplings--; + } + CouplingHandler.status(player, "removed"); controller.decouple(); if (!player.isCreative()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java index 134b38262..59b33b656 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java +++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/train/capability/MinecartController.java @@ -197,7 +197,7 @@ public class MinecartController implements INBTSerializable { while (true) { if (safetyCount-- <= 0) { - Create.logger.warn("Infinite loop in coupling iteration"); + Create.LOGGER.warn("Infinite loop in coupling iteration"); return; } cartsToFlip.add(current); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java index 364b7cf29..f6b08b2e8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidNetwork.java @@ -12,6 +12,7 @@ import java.util.function.Supplier; import javax.annotation.Nullable; +import com.simibubi.create.content.contraptions.components.actors.PortableFluidInterfaceTileEntity.InterfaceFluidHandler; import com.simibubi.create.content.contraptions.fluids.PipeConnection.Flow; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -157,6 +158,9 @@ public class FluidNetwork { source = sourceSupplier.get(); if (!source.isPresent()) return; + + keepPortableFluidInterfaceEngaged(); + if (targets.isEmpty()) return; for (Pair> pair : targets) { @@ -252,6 +256,15 @@ public class FluidNetwork { // .colored(0xfaaa33); // } + private void keepPortableFluidInterfaceEngaged() { + IFluidHandler handler = source.orElse(null); + if (!(handler instanceof InterfaceFluidHandler)) + return; + if (frontier.isEmpty()) + return; + ((InterfaceFluidHandler) handler).keepAlive(); + } + public void reset() { frontier.clear(); visited.clear(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java index 1d5d087fa..027db42d1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/FluidTransportBehaviour.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.contraptions.fluids; import java.util.Collection; +import java.util.HashMap; import java.util.IdentityHashMap; import java.util.Map; import java.util.function.Predicate; @@ -13,12 +14,14 @@ import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.WorldAttached; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockDisplayReader; +import net.minecraft.world.IWorld; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; @@ -57,8 +60,8 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { super.tick(); World world = getWorld(); BlockPos pos = getPos(); - boolean onClient = world.isRemote; - + boolean onServer = !world.isRemote || tileEntity.isVirtual(); + if (interfaces == null) return; Collection connections = interfaces.values(); @@ -78,7 +81,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { return; } - if (!onClient) { + if (onServer) { boolean sendUpdate = false; for (PipeConnection connection : connections) { sendUpdate |= connection.flipFlowsIfPressureReversed(); @@ -93,7 +96,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { return; } - if (!onClient) { + if (onServer) { FluidStack availableFlow = FluidStack.EMPTY; FluidStack collidingFlow = FluidStack.EMPTY; @@ -128,7 +131,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { sendUpdate |= connection.manageFlows(world, pos, internalFluid, extractionPredicate); } - if (sendUpdate) + if (sendUpdate) tileEntity.notifyUpdate(); } @@ -152,7 +155,7 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { } interfaces.values() - .forEach(connection -> connection.deserializeNBT(nbt, clientPacket)); + .forEach(connection -> connection.deserializeNBT(nbt, tileEntity.getPos(), clientPacket)); } @Override @@ -266,4 +269,23 @@ public abstract class FluidTransportBehaviour extends TileEntityBehaviour { return TYPE; } + // for switching TEs, but retaining flows + + public static final WorldAttached>> interfaceTransfer = + new WorldAttached<>(HashMap::new); + + public static void cacheFlows(IWorld world, BlockPos pos) { + FluidTransportBehaviour pipe = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + if (pipe != null) + interfaceTransfer.get(world) + .put(pos, pipe.interfaces); + } + + public static void loadFlows(IWorld world, BlockPos pos) { + FluidTransportBehaviour newPipe = TileEntityBehaviour.get(world, pos, FluidTransportBehaviour.TYPE); + if (newPipe != null) + newPipe.interfaces = interfaceTransfer.get(world) + .remove(pos); + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java index 7cc6874b3..affb969e3 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/OpenEndedPipe.java @@ -208,8 +208,9 @@ public class OpenEndedPipe extends FlowSource { return compound; } - public static OpenEndedPipe fromNBT(CompoundNBT compound) { - OpenEndedPipe oep = new OpenEndedPipe(BlockFace.fromNBT(compound.getCompound("Location"))); + public static OpenEndedPipe fromNBT(CompoundNBT compound, BlockPos tilePos) { + BlockFace fromNBT = BlockFace.fromNBT(compound.getCompound("Location")); + OpenEndedPipe oep = new OpenEndedPipe(new BlockFace(tilePos, fromNBT.getFace())); oep.fluidHandler.readFromNBT(compound); oep.wasPulling = compound.getBoolean("Pulling"); return oep; 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 5f3fc685b..072abea8c 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 @@ -239,7 +239,7 @@ public class PipeConnection { return source.orElse(null) instanceof OpenEndedPipe; } - public void deserializeNBT(CompoundNBT tag, boolean clientPacket) { + public void deserializeNBT(CompoundNBT tag, BlockPos tilePos, boolean clientPacket) { CompoundNBT connectionData = tag.getCompound(side.getName2()); if (connectionData.contains("Pressure")) { @@ -250,7 +250,7 @@ public class PipeConnection { source = Optional.empty(); if (connectionData.contains("OpenEnd")) - source = Optional.of(OpenEndedPipe.fromNBT(connectionData.getCompound("OpenEnd"))); + source = Optional.of(OpenEndedPipe.fromNBT(connectionData.getCompound("OpenEnd"), tilePos)); if (connectionData.contains("Flow")) { CompoundNBT flowData = connectionData.getCompound("Flow"); @@ -367,8 +367,9 @@ public class PipeConnection { @OnlyIn(Dist.CLIENT) private void spawnParticlesInner(World world, BlockPos pos, FluidStack fluid) { - if (!isRenderEntityWithinDistance(pos)) - return; + if (world == Minecraft.getInstance().world) + if (!isRenderEntityWithinDistance(pos)) + return; if (hasOpenEnd()) spawnPouringLiquid(world, pos, fluid, 1); else if (r.nextFloat() < IDLE_PARTICLE_SPAWN_CHANCE) @@ -377,8 +378,9 @@ public class PipeConnection { @OnlyIn(Dist.CLIENT) private void spawnSplashOnRimInner(World world, BlockPos pos, FluidStack fluid) { - if (!isRenderEntityWithinDistance(pos)) - return; + if (world == Minecraft.getInstance().world) + if (!isRenderEntityWithinDistance(pos)) + return; spawnRimParticles(world, pos, fluid, SPLASH_PARTICLE_AMOUNT); } 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 index 470b5ab4e..119c8b141 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/PumpCogInstance.java @@ -2,24 +2,24 @@ package com.simibubi.create.content.contraptions.fluids; import static net.minecraft.state.properties.BlockStateProperties.FACING; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; public class PumpCogInstance extends SingleRotatingInstance { - public PumpCogInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public PumpCogInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { BlockState referenceState = tile.getBlockState(); Direction facing = referenceState.get(FACING); return getRotatingMaterial().getModel(AllBlockPartials.MECHANICAL_PUMP_COG, referenceState, facing); 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 77dd51c68..3c05b3abf 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 @@ -70,7 +70,8 @@ public class PumpTileEntity extends KineticTileEntity { return; arrowDirection.chase(speed >= 0 ? 1 : -1, .5f, Chaser.EXP); arrowDirection.tickChaser(); - return; + if (!isVirtual()) + return; } sidesToUpdate.forEachWithContext((update, isFront) -> { @@ -96,14 +97,14 @@ public class PumpTileEntity extends KineticTileEntity { return; if (speed != 0) reversed = speed < 0; - if (world.isRemote) + if (world.isRemote && !isVirtual()) return; BlockPos frontPos = pos.offset(getFront()); BlockPos backPos = pos.offset(getFront().getOpposite()); FluidPropagator.propagateChangedPipe(world, frontPos, world.getBlockState(frontPos)); FluidPropagator.propagateChangedPipe(world, backPos, world.getBlockState(backPos)); - + FluidTransportBehaviour behaviour = getBehaviour(FluidTransportBehaviour.TYPE); if (behaviour != null) behaviour.wipePressure(); @@ -380,7 +381,7 @@ public class PumpTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java index 16e61b211..a3c70ed09 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/FluidManipulationBehaviour.java @@ -50,10 +50,10 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { // Search static final int searchedPerTick = 256; + static final int validationTimerMin = 160; List frontier; Set visited; - static final int validationTimer = 160; int revalidateIn; public FluidManipulationBehaviour(SmartTileEntity te) { @@ -68,12 +68,18 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { counterpartActed = true; } + protected int validationTimer() { + int maxBlocks = maxBlocks(); + // Allow enough time for the server's infinite block threshold to be reached + return maxBlocks < 0 ? validationTimerMin : Math.max(validationTimerMin, maxBlocks / searchedPerTick + 1); + } + protected int setValidationTimer() { - return revalidateIn = validationTimer; + return revalidateIn = validationTimer(); } protected int setLongValidationTimer() { - return revalidateIn = validationTimer * 2; + return revalidateIn = validationTimer() * 2; } protected int maxRange() { @@ -177,7 +183,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { frontier.add(new BlockPosEntry(offsetPos, entry.distance + 1)); } } - + return fluid; } @@ -197,7 +203,7 @@ public abstract class FluidManipulationBehaviour extends TileEntityBehaviour { if (world instanceof ServerWorld) AllPackets.sendToNear(world, splooshPos, 10, new FluidSplashPacket(splooshPos, new FluidStack(fluid, 1))); } - + protected boolean canDrainInfinitely(Fluid fluid) { return maxBlocks() != -1; // && !AllFluidTags.NO_INFINITE_DRAINING.matches(fluid); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java index 801f45fd1..271378b4d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/GenericItemFilling.java @@ -5,9 +5,11 @@ import com.simibubi.create.content.contraptions.fluids.potion.PotionFluidHandler import com.simibubi.create.foundation.fluid.FluidHelper; import net.minecraft.fluid.Fluids; +import net.minecraft.item.BucketItem; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; +import net.minecraft.item.MilkBucketItem; import net.minecraft.potion.PotionUtils; import net.minecraft.potion.Potions; import net.minecraft.world.World; @@ -20,6 +22,33 @@ import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper; public class GenericItemFilling { + /** + * Checks if an ItemStack's IFluidHandlerItem is valid. Ideally, this check would + * not be necessary. Unfortunately, some mods that copy the functionality of the + * MilkBucketItem copy the FluidBucketWrapper capability that is patched in by + * Forge without looking into what it actually does. In all cases this is + * incorrect because having a non-bucket item turn into a bucket item does not + * make sense. + * + *

This check is only necessary for filling since a FluidBucketWrapper will be + * empty if it is initialized with a non-bucket item. + * + * @param stack The ItemStack. + * @param fluidHandler The IFluidHandlerItem instance retrieved from the ItemStack. + * @return If the IFluidHandlerItem is valid for the passed ItemStack. + */ + public static boolean isFluidHandlerValid(ItemStack stack, IFluidHandlerItem fluidHandler) { + // Not instanceof in case a correct subclass is made + if (fluidHandler.getClass() == FluidBucketWrapper.class) { + Item item = stack.getItem(); + // Forge does not patch the FluidBucketWrapper onto subclasses of BucketItem + if (item.getClass() != BucketItem.class && !(item instanceof MilkBucketItem)) { + return false; + } + } + return true; + } + public static boolean canItemBeFilled(World world, ItemStack stack) { if (stack.getItem() == Items.GLASS_BOTTLE) return true; @@ -31,6 +60,8 @@ public class GenericItemFilling { IFluidHandlerItem tank = capability.orElse(null); if (tank == null) return false; + if (!isFluidHandlerValid(stack, tank)) + return false; for (int i = 0; i < tank.getTanks(); i++) { if (tank.getFluidInTank(i) .getAmount() < tank.getTankCapacity(i)) 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 3e1a43506..1b93f3fa5 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 @@ -1,11 +1,11 @@ package com.simibubi.create.content.contraptions.fluids.actors; +import com.jozufozu.flywheel.core.PartialModel; 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.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; 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 7871b9e10..bad588a5f 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 @@ -175,7 +175,7 @@ public class HosePulleyTileEntity extends KineticTileEntity { } public float getMovementSpeed() { - float movementSpeed = getSpeed() / 512f; + float movementSpeed = convertToLinear(getSpeed()); if (world.isRemote) movementSpeed *= ServerSpeedProvider.get(); return movementSpeed; @@ -194,7 +194,7 @@ public class HosePulleyTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java index b91ade7c4..5b9e93781 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/actors/ItemDrainBlock.java @@ -36,8 +36,7 @@ public class ItemDrainBlock extends Block implements IWrenchable, ITE { if (!heldItem.isEmpty()) { te.internalTank.allowInsertion(); ActionResultType tryExchange = tryExchange(worldIn, player, handIn, heldItem, te); @@ -45,7 +44,7 @@ public class ItemDrainBlock extends Block implements IWrenchable, ITE dispatcher, KineticTileEntity tile) { + public FluidValveInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); Direction facing = blockState.get(FluidValveBlock.FACING); @@ -37,7 +37,7 @@ public class FluidValveInstance extends ShaftInstance implements IDynamicInstanc boolean twist = pipeAxis.isHorizontal() && shaftAxis == Direction.Axis.Z || pipeAxis.isVertical(); pointerRotationOffset = twist ? 90 : 0; - pointer = renderer.getTransformMaterial().getModel(AllBlockPartials.FLUID_VALVE_POINTER, blockState).createInstance(); + pointer = materialManager.getTransformMaterial().getModel(AllBlockPartials.FLUID_VALVE_POINTER, blockState).createInstance(); transformPointer((FluidValveTileEntity) tile); } 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 3d3a02951..f2f6306cd 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 @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.fluids.pipes; +import com.jozufozu.flywheel.backend.Backend; 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.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -28,7 +28,7 @@ public class FluidValveRenderer extends KineticTileEntityRenderer { protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); BlockState blockState = te.getBlockState(); 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 c57007b7f..8125ea16f 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,9 +78,9 @@ public class FluidValveTileEntity extends KineticTileEntity { public void addBehaviours(List behaviours) { behaviours.add(new ValvePipeBehaviour(this)); } - + @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } 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 5d88c5c9f..d85e25e8f 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 @@ -4,6 +4,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllTileEntities; +import com.simibubi.create.content.contraptions.fluids.FluidTransportBehaviour; import com.simibubi.create.content.schematics.ISpecialBlockItemRequirement; import com.simibubi.create.content.schematics.ItemRequirement; @@ -59,8 +60,10 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable BlockState newState; World world = context.getWorld(); BlockPos pos = context.getPos(); + FluidTransportBehaviour.cacheFlows(world, pos); newState = toRegularPipe(world, pos, state).with(BlockStateProperties.WATERLOGGED, state.get(BlockStateProperties.WATERLOGGED)); world.setBlockState(pos, newState, 3); + FluidTransportBehaviour.loadFlows(world, pos); return ActionResultType.SUCCESS; } @@ -78,15 +81,15 @@ public class GlassFluidPipeBlock extends AxisPipeBlock implements IWaterLoggable return state.get(BlockStateProperties.WATERLOGGED) ? Fluids.WATER.getStillFluidState(false) : Fluids.EMPTY.getDefaultState(); } - + @Override - public ItemRequirement getRequiredItems(BlockState state) { - return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState()); + public ItemRequirement getRequiredItems(BlockState state, TileEntity te) { + return ItemRequirement.of(AllBlocks.FLUID_PIPE.getDefaultState(), te); } - + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; } - + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankConnectivityHandler.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankConnectivityHandler.java index 0c0c8f6ef..39b694816 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankConnectivityHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankConnectivityHandler.java @@ -199,7 +199,7 @@ public class FluidTankConnectivityHandler { if (simulate) return amount; - + boolean opaque = false; for (int yOffset = 0; yOffset < height; yOffset++) { @@ -234,7 +234,7 @@ public class FluidTankConnectivityHandler { } } } - + te.setWindows(!opaque); return amount; @@ -281,7 +281,7 @@ public class FluidTankConnectivityHandler { if (!toDistribute.isEmpty() && tankAt != te) { FluidStack copy = toDistribute.copy(); FluidTank tankInventory = tankAt.tankInventory; - if (tankInventory.isEmpty() && tankInventory instanceof CreativeSmartFluidTank) + if (tankInventory.isEmpty() && tankInventory instanceof CreativeSmartFluidTank) ((CreativeSmartFluidTank) tankInventory).setContainedFluid(toDistribute); else { int split = Math.min(maxCapacity, toDistribute.getAmount()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java index 2818b3a6f..c3d51df67 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/fluids/tank/FluidTankRenderer.java @@ -25,7 +25,7 @@ public class FluidTankRenderer extends SafeTileEntityRenderer tileEntityTypeIn) { super(tileEntityTypeIn); @@ -104,6 +105,10 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI if (fluidLevel != null) fluidLevel.tick(); } + + public BlockPos getLastKnownPos() { + return lastKnownPos; + } public boolean isController() { return controller == null @@ -114,6 +119,8 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI public void initialize() { super.initialize(); sendData(); + if (world.isRemote) + updateRenderBoundingBox(); } private void onPositionChanged() { @@ -154,6 +161,12 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI markDirty(); sendData(); } + + if (isVirtual()) { + if (fluidLevel == null) + fluidLevel = new InterpolatedChasingValue().start(getFillState()); + fluidLevel.target(getFillState()); + } } protected void setLuminosity(int luminosity) { @@ -265,7 +278,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI } public void setController(BlockPos controller) { - if (world.isRemote) + if (world.isRemote && !isVirtual()) return; if (controller.equals(this.controller)) return; @@ -286,18 +299,20 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI return isController() ? pos : controller; } - private AxisAlignedBB cachedBoundingBox; + public void updateRenderBoundingBox() { + if (isController()) + renderBoundingBox = super.getRenderBoundingBox().expand(width - 1, height - 1, width - 1); + else + renderBoundingBox = super.getRenderBoundingBox(); + } @Override @OnlyIn(Dist.CLIENT) public AxisAlignedBB getRenderBoundingBox() { - if (cachedBoundingBox == null) { - if (isController()) - cachedBoundingBox = super.getRenderBoundingBox().expand(width - 1, height - 1, width - 1); - else - cachedBoundingBox = super.getRenderBoundingBox(); + if (renderBoundingBox == null) { + renderBoundingBox = super.getRenderBoundingBox(); } - return cachedBoundingBox; + return renderBoundingBox; } @Override @@ -367,6 +382,7 @@ public class FluidTankTileEntity extends SmartTileEntity implements IHaveGoggleI world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16); if (isController()) tankInventory.setCapacity(getCapacityMultiplier() * getTotalTankSize()); + updateRenderBoundingBox(); } if (isController()) { float fillState = getFillState(); 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 32455af5c..2acd72a7a 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 @@ -22,6 +22,7 @@ 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; +import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.world.ClientWorld; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; @@ -33,24 +34,15 @@ import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextProperties; import net.minecraft.util.text.StringTextComponent; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RenderGameOverlayEvent; -import net.minecraftforge.client.event.RenderGameOverlayEvent.ElementType; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -@EventBusSubscriber(value = Dist.CLIENT) public class GoggleOverlayRenderer { - private static final Map outlines = CreateClient.outliner.getOutlines(); - - @SubscribeEvent - public static void lookingAtBlocksThroughGogglesShowsTooltip(RenderGameOverlayEvent.Post event) { - MatrixStack ms = event.getMatrixStack(); - if (event.getType() != ElementType.HOTBAR) - return; + private static final Map outlines = CreateClient.OUTLINER.getOutlines(); + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver; + if (!(objectMouseOver instanceof BlockRayTraceResult)) return; @@ -58,9 +50,8 @@ public class GoggleOverlayRenderer { if (!entry.isAlive()) continue; Outline outline = entry.getOutline(); - if (outline instanceof ValueBox && !((ValueBox) outline).isPassive) { + if (outline instanceof ValueBox && !((ValueBox) outline).isPassive) return; - } } BlockRayTraceResult result = (BlockRayTraceResult) objectMouseOver; @@ -172,8 +163,8 @@ public class GoggleOverlayRenderer { ms.pop(); } - private static final class TooltipScreen extends Screen { - private TooltipScreen(ITextComponent p_i51108_1_) { + public static final class TooltipScreen extends Screen { + public TooltipScreen(ITextComponent p_i51108_1_) { super(p_i51108_1_); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java index 19ac87552..d4399cde7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/AirFlowParticle.java @@ -4,7 +4,7 @@ import javax.annotation.Nonnull; import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.components.fan.IAirCurrentSource; -import com.simibubi.create.content.logistics.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.VecHelper; @@ -35,7 +35,7 @@ public class AirFlowParticle extends SimpleAnimatedParticle { this.maxAge = 40; canCollide = false; selectSprite(7); - Vector3d offset = VecHelper.offsetRandomly(Vector3d.ZERO, Create.random, .25f); + Vector3d offset = VecHelper.offsetRandomly(Vector3d.ZERO, Create.RANDOM, .25f); this.setPosition(posX + offset.x, posY + offset.y, posZ + offset.z); this.prevPosX = posX; this.prevPosY = posY; diff --git a/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticle.java b/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticle.java index ffe3e0e39..31d219f96 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticle.java +++ b/src/main/java/com/simibubi/create/content/contraptions/particle/AirParticle.java @@ -39,9 +39,9 @@ public class AirParticle extends SimpleAnimatedParticle { targetZ = (float) (z + dz); drag = data.drag; - twirlRadius = Create.random.nextFloat() / 6; - twirlAngleOffset = Create.random.nextFloat() * 360; - twirlAxis = Create.random.nextBoolean() ? Axis.X : Axis.Z; + twirlRadius = Create.RANDOM.nextFloat() / 6; + twirlAngleOffset = Create.RANDOM.nextFloat() * 360; + twirlAxis = Create.RANDOM.nextBoolean() ? Axis.X : Axis.Z; // speed in m/ticks maxAge = Math.min((int) (new Vector3d(dx, dy, dz).length() / data.speed), 60); diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java index cd27761a6..3829c5339 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinBlock.java @@ -92,8 +92,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab BlockRayTraceResult hit) { ItemStack heldItem = player.getHeldItem(handIn); - try { - BasinTileEntity te = getTileEntity(worldIn, pos); + return onTileEntityUse(worldIn, pos, te -> { if (!heldItem.isEmpty()) { if (FluidHelper.tryEmptyItemIntoTE(worldIn, player, handIn, heldItem, te)) return ActionResultType.SUCCESS; @@ -101,7 +100,7 @@ public class BasinBlock extends Block implements ITE, IWrenchab return ActionResultType.SUCCESS; if (EmptyingByBasin.canItemBeEmptied(worldIn, heldItem) - || GenericItemFilling.canItemBeFilled(worldIn, heldItem)) + || GenericItemFilling.canItemBeFilled(worldIn, heldItem)) return ActionResultType.SUCCESS; if (heldItem.getItem() .equals(Items.SPONGE) @@ -126,12 +125,10 @@ public class BasinBlock extends Block implements ITE, IWrenchab } if (success) worldIn.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, .2f, - 1f + Create.random.nextFloat()); + 1f + Create.RANDOM.nextFloat()); te.onEmptied(); - } catch (TileEntityException e) { - } - - return ActionResultType.SUCCESS; + return ActionResultType.SUCCESS; + }); } @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 d948c5af9..a4f77ed6d 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 @@ -89,11 +89,11 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { return false; return BasinRecipe.match(basin.get(), recipe); } - + protected void applyBasinRecipe() { if (currentRecipe == null) return; - + Optional optionalBasin = getBasin(); if (!optionalBasin.isPresent()) return; @@ -101,10 +101,10 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { if (!BasinRecipe.apply(basin, currentRecipe)) return; Optional processedRecipeTrigger = getProcessedRecipeTrigger(); - if (world != null && !world.isRemote && processedRecipeTrigger.isPresent()) + if (world != null && !world.isRemote && processedRecipeTrigger.isPresent()) AllTriggers.triggerForNearbyPlayers(processedRecipeTrigger.get(), world, pos, 4); basin.inputTank.sendDataImmediately(); - + // Continue mixing if (matchBasinRecipe(currentRecipe)) { continueWithPreviousRecipe(); @@ -135,7 +135,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { return Optional.empty(); return Optional.of((BasinTileEntity) basinTE); } - + protected Optional getProcessedRecipeTrigger() { return Optional.empty(); } @@ -145,7 +145,7 @@ public abstract class BasinOperatingTileEntity extends KineticTileEntity { protected abstract Object getRecipeCacheKey(); @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java index fbc1b9a00..c19142761 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/BasinRenderer.java @@ -86,9 +86,9 @@ public class BasinRenderer extends SmartTileEntityRenderer { for (int i = 0; i <= stack.getCount() / 8; i++) { ms.push(); - + Vector3d vec = VecHelper.offsetRandomly(Vector3d.ZERO, r, 1 / 16f); - + ms.translate(vec.x, vec.y, vec.z); renderItem(ms, buffer, light, overlay, stack); ms.pop(); @@ -114,13 +114,13 @@ public class BasinRenderer extends SmartTileEntityRenderer { .getBlockState(basin.getPos() .offset(direction)) .getBlock() instanceof BasinBlock; - + for (IntAttached intAttached : basin.visualizedOutputItems) { float progress = 1 - (intAttached.getFirst() - partialTicks) / BasinTileEntity.OUTPUT_ANIMATION_TIME; - + if (!outToBasin && progress > .35f) continue; - + ms.push(); MatrixStacker.of(ms) .translate(outVec) 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 9601477f0..6df4389e8 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 @@ -17,6 +17,7 @@ import com.simibubi.create.content.contraptions.fluids.particle.FluidParticleDat import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel; +import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; import com.simibubi.create.foundation.fluid.CombinedTankWrapper; import com.simibubi.create.foundation.item.SmartInventory; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; @@ -26,6 +27,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputB import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment; +import com.simibubi.create.foundation.tileEntity.behaviour.inventory.InvManipulationBehaviour; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.IntAttached; @@ -307,9 +309,15 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor Direction direction = blockState.get(BasinBlock.FACING); TileEntity te = world.getTileEntity(pos.down() .offset(direction)); + FilteringBehaviour filter = null; + InvManipulationBehaviour inserter = null; + if (te != null) { + filter = TileEntityBehaviour.get(world, te.getPos(), FilteringBehaviour.TYPE); + inserter = TileEntityBehaviour.get(world, te.getPos(), InvManipulationBehaviour.TYPE); + } IItemHandler targetInv = te == null ? null : te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); + .orElse(inserter == null ? null : inserter.getInventory()); boolean update = false; for (Iterator iterator = spoutputBuffer.iterator(); iterator.hasNext();) { @@ -322,11 +330,14 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor continue; } - if (targetInv == null) + if (targetInv == null) { return; + } if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack, true) .isEmpty()) continue; + if (filter != null && !filter.test(itemStack)) + continue; update = true; ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), false); @@ -414,6 +425,9 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor IItemHandler targetInv = null; IFluidHandler targetTank = null; + TileEntity te = null; + + InvManipulationBehaviour inserter = null; if (direction == Direction.DOWN) { // No output basin, gather locally @@ -425,18 +439,21 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor // Output basin, try moving items to it if (!spoutputBuffer.isEmpty()) return false; - TileEntity te = world.getTileEntity(pos.down() + te = world.getTileEntity(pos.down() .offset(direction)); if (te == null) return false; + + inserter = TileEntityBehaviour.get(world, te.getPos(), InvManipulationBehaviour.TYPE); targetInv = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); + .orElse(inserter == null ? null : inserter.getInventory()); targetTank = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()) - .orElse(null); + .orElse(null); } if (targetInv == null && !outputItems.isEmpty()) return false; + FilteringBehaviour filter = world == null || te == null ? null : TileEntityBehaviour.get(world, te.getPos(), FilteringBehaviour.TYPE); for (ItemStack itemStack : outputItems) { // Catalyst items are never consumed if (itemStack.hasContainerItem() && itemStack.getContainerItem() @@ -445,10 +462,11 @@ public class BasinTileEntity extends SmartTileEntity implements IHaveGoggleInfor if (simulate || direction == Direction.DOWN) { if (!ItemHandlerHelper.insertItemStacked(targetInv, itemStack.copy(), simulate) - .isEmpty()) + .isEmpty() || (filter != null && !filter.test(itemStack))) return false; - } else + } else { spoutputBuffer.add(itemStack.copy()); + } } if (outputFluids.isEmpty()) diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/HeatCondition.java b/src/main/java/com/simibubi/create/content/contraptions/processing/HeatCondition.java index 0f84596cd..d2f3f5f39 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/HeatCondition.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/HeatCondition.java @@ -10,7 +10,7 @@ public enum HeatCondition { NONE(0xffffff), HEATED(0xE88300), SUPERHEATED(0x5C93E8), ; - + private int color; private HeatCondition(int color) { @@ -36,7 +36,7 @@ public enum HeatCondition { public String serialize() { return Lang.asId(name()); } - + public String getTranslationKey() { return "recipe.heat_requirement." + serialize(); } @@ -44,9 +44,9 @@ public enum HeatCondition { public static HeatCondition deserialize(String name) { for (HeatCondition heatCondition : values()) if (heatCondition.serialize() - .equals(name)) + .equals(name)) return heatCondition; - Create.logger.warn("Tried to deserialize invalid heat condition: \"" + name + "\""); + Create.LOGGER.warn("Tried to deserialize invalid heat condition: \"" + name + "\""); return NONE; } diff --git a/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java b/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java similarity index 86% rename from src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java rename to src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java index 670f02cfc..b433755f1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/InWorldProcessing.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/InWorldProcessing.java @@ -1,4 +1,4 @@ -package com.simibubi.create.content.logistics; +package com.simibubi.create.content.contraptions.processing; import static com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.getHeatLevelOf; @@ -12,7 +12,6 @@ import javax.annotation.Nullable; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllRecipeTypes; import com.simibubi.create.content.contraptions.components.fan.SplashingRecipe; -import com.simibubi.create.content.contraptions.processing.ProcessingRecipe; import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.foundation.config.AllConfigs; @@ -37,9 +36,6 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.particles.ParticleTypes; import net.minecraft.particles.RedstoneParticleData; import net.minecraft.tags.BlockTags; -import net.minecraft.tileentity.BlastFurnaceTileEntity; -import net.minecraft.tileentity.FurnaceTileEntity; -import net.minecraft.tileentity.SmokerTileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.world.IBlockReader; @@ -50,13 +46,8 @@ import net.minecraftforge.items.wrapper.RecipeWrapper; public class InWorldProcessing { - public static class SplashingInv extends RecipeWrapper { - public SplashingInv() { - super(new ItemStackHandler(1)); - } - } - - public static SplashingInv splashingInv = new SplashingInv(); + private static final RecipeWrapper WRAPPER = new RecipeWrapper(new ItemStackHandler(1)); + private static final SplashingWrapper SPLASHING_WRAPPER = new SplashingWrapper(); public enum Type { SMOKING, BLASTING, SPLASHING, NONE @@ -104,16 +95,27 @@ public class InWorldProcessing { private static boolean canProcess(ItemStack stack, Type type, World world) { if (type == Type.BLASTING) { - return true; + WRAPPER.setInventorySlotContents(0, stack); + Optional smeltingRecipe = world.getRecipeManager() + .getRecipe(IRecipeType.SMELTING, WRAPPER, world); + + if (smeltingRecipe.isPresent()) + return true; + + WRAPPER.setInventorySlotContents(0, stack); + Optional blastingRecipe = world.getRecipeManager() + .getRecipe(IRecipeType.BLASTING, WRAPPER, world); + + if (blastingRecipe.isPresent()) + return true; + + return !stack.getItem().isFireproof(); } if (type == Type.SMOKING) { - // FIXME this does not need to be a TE - SmokerTileEntity smoker = new SmokerTileEntity(); - smoker.setLocation(world, BlockPos.ZERO); - smoker.setInventorySlotContents(0, stack); + WRAPPER.setInventorySlotContents(0, stack); Optional recipe = world.getRecipeManager() - .getRecipe(IRecipeType.SMOKING, smoker, world); + .getRecipe(IRecipeType.SMOKING, WRAPPER, world); return recipe.isPresent(); } @@ -124,8 +126,8 @@ public class InWorldProcessing { } public static boolean isWashable(ItemStack stack, World world) { - splashingInv.setInventorySlotContents(0, stack); - Optional recipe = AllRecipeTypes.SPLASHING.find(splashingInv, world); + SPLASHING_WRAPPER.setInventorySlotContents(0, stack); + Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); return recipe.isPresent(); } @@ -179,38 +181,29 @@ public class InWorldProcessing { private static List process(ItemStack stack, Type type, World world) { if (type == Type.SPLASHING) { - splashingInv.setInventorySlotContents(0, stack); - Optional recipe = AllRecipeTypes.SPLASHING.find(splashingInv, world); + SPLASHING_WRAPPER.setInventorySlotContents(0, stack); + Optional recipe = AllRecipeTypes.SPLASHING.find(SPLASHING_WRAPPER, world); if (recipe.isPresent()) return applyRecipeOn(stack, recipe.get()); return null; } - // FIXME this does not need to be a TE - SmokerTileEntity smoker = new SmokerTileEntity(); - smoker.setLocation(world, BlockPos.ZERO); - smoker.setInventorySlotContents(0, stack); + WRAPPER.setInventorySlotContents(0, stack); Optional smokingRecipe = world.getRecipeManager() - .getRecipe(IRecipeType.SMOKING, smoker, world); + .getRecipe(IRecipeType.SMOKING, WRAPPER, world); if (type == Type.BLASTING) { - // FIXME this does not need to be a TE - FurnaceTileEntity furnace = new FurnaceTileEntity(); - furnace.setLocation(world, BlockPos.ZERO); - furnace.setInventorySlotContents(0, stack); - Optional smeltingRecipe = world.getRecipeManager() - .getRecipe(IRecipeType.SMELTING, furnace, world); - if (!smokingRecipe.isPresent()) { + WRAPPER.setInventorySlotContents(0, stack); + Optional smeltingRecipe = world.getRecipeManager() + .getRecipe(IRecipeType.SMELTING, WRAPPER, world); + if (smeltingRecipe.isPresent()) return applyRecipeOn(stack, smeltingRecipe.get()); - // FIXME this does not need to be a TE - BlastFurnaceTileEntity blastFurnace = new BlastFurnaceTileEntity(); - blastFurnace.setLocation(world, BlockPos.ZERO); - blastFurnace.setInventorySlotContents(0, stack); + WRAPPER.setInventorySlotContents(0, stack); Optional blastingRecipe = world.getRecipeManager() - .getRecipe(IRecipeType.BLASTING, blastFurnace, world); + .getRecipe(IRecipeType.BLASTING, WRAPPER, world); if (blastingRecipe.isPresent()) return applyRecipeOn(stack, blastingRecipe.get()); @@ -299,6 +292,7 @@ public class InWorldProcessing { return stacks; } + public static void spawnParticlesForProcessing(@Nullable World world, Vector3d vec, Type type) { if (world == null || !world.isRemote) return; @@ -325,4 +319,10 @@ public class InWorldProcessing { } } + public static class SplashingWrapper extends RecipeWrapper { + public SplashingWrapper() { + super(new ItemStackHandler(1)); + } + } + } diff --git a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipe.java b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipe.java index 9fc92040c..78febd8cc 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipe.java +++ b/src/main/java/com/simibubi/create/content/contraptions/processing/ProcessingRecipe.java @@ -85,17 +85,17 @@ public abstract class ProcessingRecipe implements IRecipe< private void validate(String recipeTypeName) { String messageHeader = "Your custom " + recipeTypeName + " recipe (" + id.toString() + ")"; - Logger logger = Create.logger; + Logger logger = Create.LOGGER; int ingredientCount = ingredients.size(); int outputCount = results.size(); if (ingredientCount > getMaxInputCount()) logger.warn(messageHeader + " has more item inputs (" + ingredientCount + ") than supported (" - + getMaxInputCount() + ")."); + + getMaxInputCount() + ")."); if (outputCount > getMaxOutputCount()) logger.warn(messageHeader + " has more item outputs (" + outputCount + ") than supported (" - + getMaxOutputCount() + ")."); + + getMaxOutputCount() + ")."); if (processingDuration > 0 && !canSpecifyDuration()) logger.warn(messageHeader + " specified a duration. Durations have no impact on this type of recipe."); @@ -120,15 +120,15 @@ public abstract class ProcessingRecipe implements IRecipe< public NonNullList getIngredients() { return ingredients; } - + public NonNullList getFluidIngredients() { return fluidIngredients; } - + public NonNullList getRollableResults() { return results; } - + public NonNullList getFluidResults() { return fluidResults; } @@ -156,9 +156,9 @@ public abstract class ProcessingRecipe implements IRecipe< public HeatCondition getRequiredHeat() { return requiredHeat; } - + // IRecipe<> paperwork - + @Override public ItemStack getCraftingResult(T inv) { return getRecipeOutput(); @@ -180,7 +180,7 @@ public abstract class ProcessingRecipe implements IRecipe< public ResourceLocation getId() { return id; } - + @Override public boolean isDynamic() { return true; 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 1d3765ac6..cf99503c0 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 @@ -1,11 +1,11 @@ package com.simibubi.create.content.contraptions.processing.burner; +import com.jozufozu.flywheel.core.PartialModel; 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.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; 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 9592b9d02..19a563c35 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 @@ -169,6 +169,20 @@ public class GantryShaftBlock extends DirectionalKineticBlock { return onWrenched; } + @Override + public void onBlockAdded(BlockState state, World worldIn, BlockPos pos, BlockState oldState, boolean isMoving) { + super.onBlockAdded(state, worldIn, pos, oldState, isMoving); + + if (!worldIn.isRemote() && oldState.getBlock().is(AllBlocks.GANTRY_SHAFT.get())) { + Part oldPart = oldState.get(PART), part = state.get(PART); + if ((oldPart != Part.MIDDLE && part == Part.MIDDLE) || (oldPart == Part.SINGLE && part != Part.SINGLE)) { + TileEntity te = worldIn.getTileEntity(pos); + if (te instanceof GantryShaftTileEntity) + ((GantryShaftTileEntity) te).checkAttachedCarriageBlocks(); + } + } + } + @Override public void neighborChanged(BlockState state, World worldIn, BlockPos pos, Block p_220069_4_, BlockPos p_220069_5_, boolean p_220069_6_) { @@ -260,7 +274,7 @@ public class GantryShaftBlock extends DirectionalKineticBlock { return super.areStatesKineticallyEquivalent(oldState, newState) && oldState.get(POWERED) == newState.get(POWERED); } - + @Override public float getParticleTargetRadius() { return .35f; @@ -270,7 +284,7 @@ public class GantryShaftBlock extends DirectionalKineticBlock { public float getParticleInitialRadius() { return .25f; } - + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java index 681a01269..4cd68bcbf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/GantryShaftTileEntity.java @@ -19,15 +19,12 @@ public class GantryShaftTileEntity extends KineticTileEntity { super(typeIn); } - @Override - public void onSpeedChanged(float previousSpeed) { - super.onSpeedChanged(previousSpeed); - + public void checkAttachedCarriageBlocks() { if (!canAssembleOn()) return; for (Direction d : Iterate.directions) { if (d.getAxis() == getBlockState().get(GantryShaftBlock.FACING) - .getAxis()) + .getAxis()) continue; BlockPos offset = pos.offset(d); BlockState pinionState = world.getBlockState(offset); @@ -39,7 +36,12 @@ public class GantryShaftTileEntity extends KineticTileEntity { if (tileEntity instanceof GantryCarriageTileEntity) ((GantryCarriageTileEntity) tileEntity).queueAssembly(); } + } + @Override + public void onSpeedChanged(float previousSpeed) { + super.onSpeedChanged(previousSpeed); + checkAttachedCarriageBlocks(); } @Override @@ -97,9 +99,9 @@ public class GantryShaftTileEntity extends KineticTileEntity { BlockState blockState = getBlockState(); if (!AllBlocks.GANTRY_SHAFT.has(blockState)) return 0; - return MathHelper.clamp(-getSpeed() / 512f, -.49f, .49f); + return MathHelper.clamp(convertToLinear(-getSpeed()), -.49f, .49f); } - + @Override protected boolean isNoisy() { return false; 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 6d4fec12e..cb6c22d09 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 @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.relays.advanced; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -7,7 +8,6 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import net.minecraft.block.BlockState; @@ -32,7 +32,7 @@ public class SpeedControllerRenderer extends SmartTileEntityRenderer 0 && speedModifier.value < 0 ? 1 : 2; + int getDuration(float currentProgress, float speed) { speed *= speedModifier.value; speed = Math.abs(speed); - double degreesPerTick = (speed * 360) / 60 / 20; - double metersPerTick = speed / 512; + double target = value - currentProgress; + switch (instruction) { case TURN_ANGLE: - return (int) ((1 - initialProgress) * value / degreesPerTick + 1); + double degreesPerTick = KineticTileEntity.convertToAngular(speed); + int ticks = (int) (target / degreesPerTick); + double degreesErr = target - degreesPerTick*ticks; + return ticks + (degreesPerTick > 2*degreesErr ? 0 : 1); case TURN_DISTANCE: - return (int) ((1 - initialProgress) * value / metersPerTick + offset); + double metersPerTick = KineticTileEntity.convertToLinear(speed); + int offset = speed > 0 && speedModifier.value < 0 ? 1 : 2; + return (int) (target / metersPerTick + offset); case DELAY: - return (int) ((1 - initialProgress) * value + 1); + return (int) target; case AWAIT: return -1; @@ -52,6 +57,27 @@ public class Instruction { return 0; } + float getTickProgress(float speed) { + switch(instruction) { + + case TURN_ANGLE: + return KineticTileEntity.convertToAngular(speed); + + case TURN_DISTANCE: + return KineticTileEntity.convertToLinear(speed); + + case DELAY: + return 1; + + case AWAIT: + case END: + default: + break; + + } + return 0; + } + int getSpeedModifier() { switch (instruction) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java index 42b961a98..c65896513 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/advanced/sequencer/SequencedGearshiftTileEntity.java @@ -15,6 +15,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { Vector instructions; int currentInstruction; int currentInstructionDuration; + float currentInstructionProgress; int timer; boolean poweredPreviously; @@ -23,6 +24,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { instructions = Instruction.createDefault(); currentInstruction = -1; currentInstructionDuration = -1; + currentInstructionProgress = 0; timer = 0; poweredPreviously = false; } @@ -39,6 +41,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { return; if (timer < currentInstructionDuration) { timer++; + currentInstructionProgress += getInstruction(currentInstruction).getTickProgress(speed); return; } run(currentInstruction + 1); @@ -59,8 +62,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { run(-1); // Update instruction time with regards to new speed - float initialProgress = timer / (float) currentInstructionDuration; - currentInstructionDuration = instruction.getDuration(initialProgress, getTheoreticalSpeed()); + currentInstructionDuration = instruction.getDuration(currentInstructionProgress, getTheoreticalSpeed()); timer = 0; } @@ -109,6 +111,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { detachKinetics(); currentInstruction = -1; currentInstructionDuration = -1; + currentInstructionProgress = 0; timer = 0; if (!world.isBlockPowered(pos)) world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, 0), 3); @@ -120,6 +123,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { detachKinetics(); currentInstructionDuration = instruction.getDuration(0, getTheoreticalSpeed()); currentInstruction = instructionIndex; + currentInstructionProgress = 0; timer = 0; world.setBlockState(pos, getBlockState().with(SequencedGearshiftBlock.STATE, instructionIndex + 1), 3); } @@ -133,6 +137,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { public void write(CompoundNBT compound, boolean clientPacket) { compound.putInt("InstructionIndex", currentInstruction); compound.putInt("InstructionDuration", currentInstructionDuration); + compound.putFloat("InstructionProgress", currentInstructionProgress); compound.putInt("Timer", timer); compound.putBoolean("PrevPowered", poweredPreviously); compound.put("Instructions", Instruction.serializeAll(instructions)); @@ -143,6 +148,7 @@ public class SequencedGearshiftTileEntity extends SplitShaftTileEntity { protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { currentInstruction = compound.getInt("InstructionIndex"); currentInstructionDuration = compound.getInt("InstructionDuration"); + currentInstructionProgress = compound.getFloat("InstructionProgress"); poweredPreviously = compound.getBoolean("PrevPowered"); timer = compound.getInt("Timer"); instructions = Instruction.deserializeAll(compound.getList("Instructions", NBT.TAG_COMPOUND)); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltAttributes.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltAttributes.java deleted file mode 100644 index 4753f1eb2..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltAttributes.java +++ /dev/null @@ -1,42 +0,0 @@ -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.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; - -public enum BeltAttributes implements IVertexAttrib { - INSTANCE_ROTATION("aInstanceRot", CommonAttributes.QUATERNION), - SOURCE_TEX("aSourceTexture", CommonAttributes.UV), - SCROLL_TEX("aScrollTexture", CommonAttributes.VEC4), - SCROLL_MULT("aScrollMult", CommonAttributes.NORMALIZED_BYTE), - ; - - private final String name; - private final VertexAttribSpec spec; - - BeltAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 1; - } - - @Override - public int getBufferIndex() { - return 1; - } -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java index f942d4983..c8a2f3ce2 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java @@ -4,6 +4,8 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import com.simibubi.create.content.contraptions.relays.belt.transport.BeltTunnelInteractionHandler; + import org.apache.commons.lang3.mutable.MutableBoolean; import com.simibubi.create.AllBlocks; @@ -102,11 +104,8 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE { ItemEntity itemEntity = (ItemEntity) entityIn; IItemHandler handler = te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) @@ -274,7 +275,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE { if (context.getEntity() == null) return shape; - BeltTileEntity belt = getTileEntity(worldIn, pos); - BeltTileEntity controller = belt.getControllerTE(); - + BeltTileEntity controller = te.getControllerTE(); if (controller == null) return shape; - if (controller.passengers == null || !controller.passengers.containsKey(context.getEntity())) { + if (controller.passengers == null || !controller.passengers.containsKey(context.getEntity())) return BeltShapes.getCollisionShape(state); - } + return shape; - } catch (TileEntityException e) { - } - return shape; + }).orElse(shape); } @Override @@ -478,6 +475,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE required = new ArrayList<>(); if (state.get(PART) != BeltPart.MIDDLE) required.add(AllBlocks.SHAFT.asStack()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java index ec0b082c5..2727ddbe1 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltData.java @@ -1,10 +1,9 @@ package com.simibubi.create.content.contraptions.relays.belt; -import java.nio.ByteBuffer; - +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.backend.instancing.Instancer; import com.simibubi.create.content.contraptions.base.KineticData; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.math.vector.Quaternion; @@ -22,9 +21,9 @@ public class BeltData extends KineticData { private float maxV; private byte scrollMult; - protected BeltData(InstancedModel owner) { - super(owner); - } + public BeltData(Instancer owner) { + super(owner); + } public BeltData setRotation(Quaternion q) { this.qX = q.getX(); @@ -47,24 +46,22 @@ public class BeltData extends KineticData { this.maxV = target.getMaxV(); markDirty(); - return this; - } + return this; + } - public BeltData setScrollMult(float scrollMult) { - this.scrollMult = (byte) (scrollMult * 127); - markDirty(); - return this; - } + public BeltData setScrollMult(float scrollMult) { + this.scrollMult = (byte) (scrollMult * 127); + markDirty(); + return this; + } - @Override - public void write(ByteBuffer buf) { - super.write(buf); + @Override + public void write(MappedBuffer buf) { + super.write(buf); - putVec4(buf, qX, qY, qZ, qW); - - putVec2(buf, sourceU, sourceV); - putVec4(buf, minU, minV, maxU, maxV); - - put(buf, scrollMult); - } + buf.putVec4(qX, qY, qZ, qW); + buf.putVec2(sourceU, sourceV); + buf.putVec4(minU, minV, maxU, maxV); + buf.put(scrollMult); + } } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java index 5546490ea..510e9f125 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstance.java @@ -3,17 +3,17 @@ package com.simibubi.create.content.contraptions.relays.belt; import java.util.ArrayList; import java.util.function.Supplier; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; -import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; 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.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; +import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -35,8 +35,8 @@ public class BeltInstance extends KineticTileInstance { protected ArrayList keys; protected RotatingData pulleyKey; - public BeltInstance(InstancedTileRenderer modelManager, BeltTileEntity tile) { - super(modelManager, tile); + public BeltInstance(MaterialManager materialManager, BeltTileEntity tile) { + super(materialManager, tile); if (!AllBlocks.BELT.has(blockState)) return; @@ -61,7 +61,7 @@ public class BeltInstance extends KineticTileInstance { PartialModel beltPartial = BeltRenderer.getBeltPartial(diagonal, start, end, bottom); SpriteShiftEntry spriteShift = BeltRenderer.getSpriteShiftEntry(color, diagonal, bottom); - InstancedModel beltModel = modelManager.getMaterial(KineticRenderMaterials.BELTS).getModel(beltPartial, blockState); + Instancer beltModel = materialManager.getMaterial(AllMaterialSpecs.BELTS).getModel(beltPartial, blockState); keys.add(setup(beltModel.createInstance(), bottom, spriteShift)); @@ -69,7 +69,7 @@ public class BeltInstance extends KineticTileInstance { } if (tile.hasPulley()) { - InstancedModel pulleyModel = getPulleyModel(); + Instancer pulleyModel = getPulleyModel(); pulleyKey = setup(pulleyModel.createInstance()); } @@ -121,7 +121,7 @@ public class BeltInstance extends KineticTileInstance { return speed; } - private InstancedModel getPulleyModel() { + private Instancer getPulleyModel() { Direction dir = getOrientation(); Direction.Axis axis = dir.getAxis(); 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 deleted file mode 100644 index 7b75ce395..000000000 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltInstancedModel.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.simibubi.create.content.contraptions.relays.belt; - -import com.simibubi.create.content.contraptions.base.KineticAttributes; -import com.simibubi.create.foundation.render.backend.core.BasicAttributes; -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 static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(BasicAttributes.class) - .addAttributes(KineticAttributes.class) - .addAttributes(BeltAttributes.class) - .build(); - - public BeltInstancedModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected BeltData newInstance() { - return new BeltData(this); - } - - @Override - protected VertexFormat getInstanceFormat() { - return FORMAT; - } - -} diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java index 4beec3bb0..780de7876 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 @@ -3,6 +3,8 @@ package com.simibubi.create.content.contraptions.relays.belt; import java.util.Random; import java.util.function.Supplier; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -15,8 +17,6 @@ import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.render.PartialBufferer; 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.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -57,7 +57,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { protected void renderSafe(BeltTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (!FastRenderDispatcher.available(te.getWorld())) { + if (!Backend.getInstance().canUseInstancing(te.getWorld())) { BlockState blockState = te.getBlockState(); if (!AllBlocks.BELT.has(blockState)) return; @@ -143,7 +143,7 @@ public class BeltRenderer extends SafeTileEntityRenderer { return stack; }; - SuperByteBuffer superBuffer = CreateClient.bufferCache.renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, matrixStackSupplier); + SuperByteBuffer superBuffer = CreateClient.BUFFER_CACHE.renderDirectionalPartial(AllBlockPartials.BELT_PULLEY, blockState, dir, matrixStackSupplier); KineticTileEntityRenderer.standardKineticRotationTransform(superBuffer, te, light).renderInto(ms, vb); } } 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 6280c7bb7..5beca0399 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 @@ -12,6 +12,10 @@ import java.util.Map; import java.util.Optional; import java.util.function.Function; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; +import com.jozufozu.flywheel.light.GridAlignedBB; +import com.jozufozu.flywheel.light.ILightUpdateListener; +import com.jozufozu.flywheel.light.LightUpdater; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.KineticTileEntity; @@ -22,10 +26,6 @@ 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.render.backend.light.GridAlignedBB; -import com.simibubi.create.foundation.render.backend.light.LightUpdateListener; -import com.simibubi.create.foundation.render.backend.light.LightUpdater; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; @@ -60,7 +60,7 @@ import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; -public class BeltTileEntity extends KineticTileEntity implements LightUpdateListener { +public class BeltTileEntity extends KineticTileEntity implements ILightUpdateListener { public Map passengers; public Optional color; @@ -267,7 +267,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList belt.color = Optional.ofNullable(colorIn); belt.markDirty(); belt.sendData(); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(belt)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(belt)); } } @@ -518,7 +518,7 @@ public class BeltTileEntity extends KineticTileEntity implements LightUpdateList } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { if (world == null) return isController(); BlockState state = getBlockState(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java index 29d5ad0b3..1df40f3b8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java @@ -47,7 +47,7 @@ public class BeltConnectorItem extends BlockItem { @Override public void fillItemGroup(ItemGroup p_150895_1_, NonNullList p_150895_2_) { - if (p_150895_1_ == Create.baseCreativeTab) + if (p_150895_1_ == Create.BASE_CREATIVE_TAB) return; super.fillItemGroup(p_150895_1_, p_150895_2_); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java index 9786a30c4..e96ebabdf 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java @@ -95,9 +95,8 @@ public class BeltMovementHandler { // Lock entities in place boolean isPlayer = entityIn instanceof PlayerEntity; - if (entityIn instanceof LivingEntity && !isPlayer) { + if (entityIn instanceof LivingEntity && !isPlayer) ((LivingEntity) entityIn).addPotionEffect(new EffectInstance(Effects.SLOWNESS, 10, 1, false, false)); - } final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING); final BeltSlope slope = blockState.get(BeltBlock.SLOPE); @@ -138,12 +137,14 @@ public class BeltMovementHandler { movement = movement.add(0, -Math.abs(axis.getCoordinate(movement.x, movement.y, movement.z)), 0); Vector3d centering = Vector3d.of(centeringDirection).scale(diffCenter * Math.min(Math.abs(movementSpeed), .1f) * 4); - float step = entityIn.stepHeight; - if (!isPlayer) { + if (!(entityIn instanceof LivingEntity) + || ((LivingEntity) entityIn).moveForward == 0 && ((LivingEntity) entityIn).moveStrafing == 0) movement = movement.add(centering); + + float step = entityIn.stepHeight; + if (!isPlayer) entityIn.stepHeight = 1; - } // Entity Collisions if (Math.abs(movementSpeed) < .5f) { @@ -175,6 +176,8 @@ public class BeltMovementHandler { } else { entityIn.move(SELF, movement); } + + entityIn.onGround = true; if (!isPlayer) entityIn.stepHeight = step; @@ -189,6 +192,7 @@ public class BeltMovementHandler { entityIn.setMotion(movement); entityIn.velocityChanged = true; } + } public static boolean shouldIgnoreBlocking(Entity me, Entity other) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java index 91b31e8f5..6ff160496 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java @@ -43,8 +43,8 @@ public class BeltTunnelInteractionHandler { World world = beltInventory.belt.getWorld(); boolean onServer = !world.isRemote || beltInventory.belt.isVirtual(); boolean removed = false; - BeltTunnelTileEntity nextTunnel = getTunnelOnSegement(beltInventory, upcomingSegment); - + BeltTunnelTileEntity nextTunnel = getTunnelOnSegment(beltInventory, upcomingSegment); + if (nextTunnel instanceof BrassTunnelTileEntity) { BrassTunnelTileEntity brassTunnel = (BrassTunnelTileEntity) nextTunnel; if (brassTunnel.hasDistributionBehaviour()) { @@ -80,13 +80,13 @@ public class BeltTunnelInteractionHandler { continue; if (!behaviour.canInsertFromSide(d)) continue; - + ItemStack toinsert = ItemHandlerHelper.copyStackWithSize(current.stack, 1); if (!behaviour.handleInsertion(toinsert, d, false).isEmpty()) return true; - if (onServer) + if (onServer) flapTunnel(beltInventory, upcomingSegment, d, false); - + current.stack.shrink(1); beltInventory.belt.sendData(); if (current.stack.getCount() <= 1) @@ -124,25 +124,25 @@ public class BeltTunnelInteractionHandler { } public static void flapTunnel(BeltInventory beltInventory, int offset, Direction side, boolean inward) { - BeltTunnelTileEntity te = getTunnelOnSegement(beltInventory, offset); + BeltTunnelTileEntity te = getTunnelOnSegment(beltInventory, offset); if (te == null) return; te.flap(side, inward); } - protected static BeltTunnelTileEntity getTunnelOnSegement(BeltInventory beltInventory, int offset) { + protected static BeltTunnelTileEntity getTunnelOnSegment(BeltInventory beltInventory, int offset) { BeltTileEntity belt = beltInventory.belt; if (belt.getBlockState() .get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL) return null; - BlockPos pos = BeltHelper.getPositionForOffset(belt, offset) - .up(); - if (!(belt.getWorld() - .getBlockState(pos) - .getBlock() instanceof BeltTunnelBlock)) + return getTunnelOnPosition(belt.getWorld(), BeltHelper.getPositionForOffset(belt, offset)); + } + + public static BeltTunnelTileEntity getTunnelOnPosition(World world, BlockPos pos) { + pos = pos.up(); + if (!(world.getBlockState(pos).getBlock() instanceof BeltTunnelBlock)) return null; - TileEntity te = belt.getWorld() - .getTileEntity(pos); + TileEntity te = world.getTileEntity(pos); if (te == null || !(te instanceof BeltTunnelTileEntity)) return null; return ((BeltTunnelTileEntity) te); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java index 5202ea1df..85cea6d9a 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/TransportedItemStack.java @@ -2,8 +2,8 @@ package com.simibubi.create.content.contraptions.relays.belt.transport; import java.util.Random; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; -import com.simibubi.create.content.logistics.InWorldProcessing; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java index 28b3c46a6..390a3ed1d 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedKineticBlockModel.java @@ -4,8 +4,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; -import com.simibubi.create.foundation.utility.VirtualEmptyModelData; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; @@ -21,7 +21,7 @@ import net.minecraftforge.client.model.data.ModelProperty; public class BracketedKineticBlockModel extends BakedModelWrapper { - private static ModelProperty BRACKET_PROPERTY = new ModelProperty<>(); + private static final ModelProperty BRACKET_PROPERTY = new ModelProperty<>(); public BracketedKineticBlockModel(IBakedModel template) { super(template); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java index f2dbec548..c926acd2f 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/elementary/BracketedTileEntityBehaviour.java @@ -4,6 +4,7 @@ import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; +import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.ITriggerable; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; @@ -38,7 +39,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { this.pred = pred; bracket = Optional.empty(); } - + public BracketedTileEntityBehaviour withTrigger(Function trigger) { this.trigger = trigger; return this; @@ -54,7 +55,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { reRender = true; tileEntity.notifyUpdate(); } - + public void triggerAdvancements(World world, PlayerEntity player, BlockState state) { if (trigger == null) return; @@ -73,7 +74,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { tileEntity.notifyUpdate(); } - public boolean isBacketPresent() { + public boolean isBracketPresent() { return getBracket() != Blocks.AIR.getDefaultState(); } @@ -81,6 +82,16 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour { return bracket.orElse(Blocks.AIR.getDefaultState()); } + @Override + public ItemRequirement getRequiredItems() { + return ItemRequirement.of(getBracket(), null); + } + + @Override + public boolean isSafeNBT() { + return true; + } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { bracket.ifPresent(p -> nbt.put("Bracket", NBTUtil.writeBlockState(p))); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java index d74f8f72e..09e6749a7 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/EncasedShaftBlock.java @@ -22,11 +22,11 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe public static EncasedShaftBlock andesite(Properties properties) { return new EncasedShaftBlock(properties, AllBlocks.ANDESITE_CASING); } - + public static EncasedShaftBlock brass(Properties properties) { return new EncasedShaftBlock(properties, AllBlocks.BRASS_CASING); } - + protected EncasedShaftBlock(Properties properties, BlockEntry casing) { super(properties); this.casing = casing; @@ -36,7 +36,7 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe public TileEntity createTileEntity(BlockState state, IBlockReader world) { return AllTileEntities.ENCASED_SHAFT.create(); } - + public BlockEntry getCasing() { return casing; } @@ -49,10 +49,10 @@ public class EncasedShaftBlock extends AbstractEncasedShaftBlock implements ISpe KineticTileEntity.switchToBlockState(context.getWorld(), context.getPos(), AllBlocks.SHAFT.getDefaultState().with(AXIS, state.get(AXIS))); return ActionResultType.SUCCESS; } - + @Override - public ItemRequirement getRequiredItems(BlockState state) { - return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState()); + public ItemRequirement getRequiredItems(BlockState state, TileEntity te) { + return ItemRequirement.of(AllBlocks.SHAFT.getDefaultState(), te); } } 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 index b2929b67f..0761c6e43 100644 --- 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 @@ -1,14 +1,14 @@ package com.simibubi.create.content.contraptions.relays.encased; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import net.minecraft.block.BlockState; public class ShaftInstance extends SingleRotatingInstance { - public ShaftInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public ShaftInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); } diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java index f317fd24d..9dfd819d0 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/encased/SplitShaftInstance.java @@ -2,14 +2,14 @@ package com.simibubi.create.content.contraptions.relays.encased; import java.util.ArrayList; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.Block; @@ -19,18 +19,18 @@ public class SplitShaftInstance extends KineticTileInstance keys; - public SplitShaftInstance(InstancedTileRenderer modelManager, SplitShaftTileEntity tile) { + public SplitShaftInstance(MaterialManager modelManager, SplitShaftTileEntity tile) { super(modelManager, tile); keys = new ArrayList<>(2); float speed = tile.getSpeed(); - RenderMaterial> rotatingMaterial = getRotatingMaterial(); + InstanceMaterial rotatingMaterial = getRotatingMaterial(); for (Direction dir : Iterate.directionsInAxis(getRotationAxis())) { - InstancedModel half = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, dir); + Instancer half = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, dir); float splitSpeed = speed * tile.getRotationSpeedModifier(dir); 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 cac191681..03d7026da 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 @@ -1,5 +1,6 @@ package com.simibubi.create.content.contraptions.relays.encased; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.IRotate; @@ -7,7 +8,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; 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; @@ -28,7 +28,7 @@ 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; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; Block block = te.getBlockState().getBlock(); final Axis boxAxis = ((IRotate) block).getRotationAxis(te.getBlockState()); diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java index dd0a740dd..de3a27ed8 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gauge/GaugeInstance.java @@ -2,14 +2,14 @@ package com.simibubi.create.content.contraptions.relays.gauge; import java.util.ArrayList; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Iterate; @@ -24,7 +24,7 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns protected MatrixStack ms; - protected GaugeInstance(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + protected GaugeInstance(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); faces = new ArrayList<>(2); @@ -32,8 +32,8 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns GaugeTileEntity gaugeTile = (GaugeTileEntity) tile; GaugeBlock gaugeBlock = (GaugeBlock) blockState.getBlock(); - InstancedModel dialModel = getTransformMaterial().getModel(AllBlockPartials.GAUGE_DIAL, blockState); - InstancedModel headModel = getHeadModel(); + Instancer dialModel = getTransformMaterial().getModel(AllBlockPartials.GAUGE_DIAL, blockState); + Instancer headModel = getHeadModel(); ms = new MatrixStack(); MatrixStacker msr = MatrixStacker.of(ms); @@ -53,7 +53,7 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns } } - private DialFace makeFace(Direction face, InstancedModel dialModel, InstancedModel headModel) { + private DialFace makeFace(Direction face, Instancer dialModel, Instancer headModel) { return new DialFace(face, dialModel.createInstance(), headModel.createInstance()); } @@ -88,7 +88,7 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns faces.forEach(DialFace::delete); } - protected abstract InstancedModel getHeadModel(); + protected abstract Instancer getHeadModel(); private class DialFace extends Couple { @@ -144,23 +144,23 @@ public abstract class GaugeInstance extends ShaftInstance implements IDynamicIns } public static class Speed extends GaugeInstance { - public Speed(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public Speed(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); } @Override - protected InstancedModel getHeadModel() { + protected Instancer getHeadModel() { return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_SPEED, blockState); } } public static class Stress extends GaugeInstance { - public Stress(InstancedTileRenderer dispatcher, KineticTileEntity tile) { + public Stress(MaterialManager dispatcher, KineticTileEntity tile) { super(dispatcher, tile); } @Override - protected InstancedModel getHeadModel() { + protected Instancer getHeadModel() { return getTransformMaterial().getModel(AllBlockPartials.GAUGE_HEAD_STRESS, blockState); } } 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 56c9fb89b..442cb9bdf 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 @@ -1,5 +1,7 @@ package com.simibubi.create.content.contraptions.relays.gauge; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -8,8 +10,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.contraptions.relays.gauge.GaugeBlock.Type; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.block.BlockState; @@ -40,7 +40,7 @@ public class GaugeRenderer extends KineticTileEntityRenderer { @Override protected void renderSafe(KineticTileEntity te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; super.renderSafe(te, partialTicks, ms, buffer, light, overlay); BlockState gaugeState = te.getBlockState(); 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 13dac75fa..1a1c4a8b2 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 @@ -53,7 +53,7 @@ public class GaugeTileEntity extends KineticTileEntity implements IHaveGoggleInf } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { 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 index a991802fa..fc795f92e 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java +++ b/src/main/java/com/simibubi/create/content/contraptions/relays/gearbox/GearboxInstance.java @@ -3,13 +3,13 @@ package com.simibubi.create.content.contraptions.relays.gearbox; import java.util.EnumMap; import java.util.Map; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.utility.Iterate; import net.minecraft.state.properties.BlockStateProperties; @@ -22,7 +22,7 @@ public class GearboxInstance extends KineticTileInstance { protected final EnumMap keys; protected Direction sourceFacing; - public GearboxInstance(InstancedTileRenderer modelManager, GearboxTileEntity tile) { + public GearboxInstance(MaterialManager modelManager, GearboxTileEntity tile) { super(modelManager, tile); keys = new EnumMap<>(Direction.class); @@ -33,14 +33,14 @@ public class GearboxInstance extends KineticTileInstance { int skyLight = world.getLightLevel(LightType.SKY, pos); updateSourceFacing(); - RenderMaterial> rotatingMaterial = getRotatingMaterial(); + InstanceMaterial rotatingMaterial = getRotatingMaterial(); for (Direction direction : Iterate.directions) { final Direction.Axis axis = direction.getAxis(); if (boxAxis == axis) continue; - InstancedModel shaft = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, direction); + Instancer shaft = rotatingMaterial.getModel(AllBlockPartials.SHAFT_HALF, blockState, direction); RotatingData key = shaft.createInstance(); 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 72c2e09e8..0c9313b2f 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 @@ -1,12 +1,12 @@ package com.simibubi.create.content.contraptions.relays.gearbox; +import com.jozufozu.flywheel.backend.Backend; 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.PartialBufferer; 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; @@ -27,7 +27,7 @@ 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; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; final Axis boxAxis = te.getBlockState().get(BlockStateProperties.AXIS); final BlockPos pos = te.getPos(); diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java index 52d9489c4..68b5365a5 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/IWrenchable.java @@ -71,11 +71,11 @@ public interface IWrenchable { } default void playRemoveSound(World world, BlockPos pos) { - AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1, Create.random.nextFloat() * .5f + .5f); + AllSoundEvents.WRENCH_REMOVE.playOnServer(world, pos, 1, Create.RANDOM.nextFloat() * .5f + .5f); } default void playRotateSound(World world, BlockPos pos) { - AllSoundEvents.WRENCH_ROTATE.playOnServer(world, pos, 1, Create.random.nextFloat() + .5f); + AllSoundEvents.WRENCH_ROTATE.playOnServer(world, pos, 1, Create.RANDOM.nextFloat() + .5f); } default BlockState getRotatedBlockState(BlockState originalState, Direction targetedFace) { diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java index bde917413..7b9e15cda 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchItemRenderer.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.contraptions.wrench; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.PartialItemModelRenderer; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueHandler; import com.simibubi.create.foundation.utility.AnimationTickHolder; diff --git a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java index 081449d68..7d58c0514 100644 --- a/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java +++ b/src/main/java/com/simibubi/create/content/contraptions/wrench/WrenchModel.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.contraptions.wrench; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java index f127b8b26..f5512c873 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankArmorLayer.java @@ -59,18 +59,18 @@ public class CopperBacktankArmorLayer model = (BipedModel) entityModel; BlockState renderedState = AllBlocks.COPPER_BACKTANK.getDefaultState() - .with(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); + .with(CopperBacktankBlock.HORIZONTAL_FACING, Direction.SOUTH); RenderType renderType = RenderType.getCutout(); - SuperByteBuffer backtank = CreateClient.bufferCache.renderBlock(renderedState); + SuperByteBuffer backtank = CreateClient.BUFFER_CACHE.renderBlock(renderedState); SuperByteBuffer cogs = - CreateClient.bufferCache.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, renderedState); + CreateClient.BUFFER_CACHE.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, renderedState); model.bipedBody.rotate(ms); ms.translate(-1 / 2f, 10 / 16f, 1f); ms.scale(1, -1, -1); backtank.light(light) - .renderInto(ms, buffer.getBuffer(renderType)); + .renderInto(ms, buffer.getBuffer(renderType)); cogs.matrixStacker() .centre() diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java index 067dca850..dda0ab339 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankInstance.java @@ -1,20 +1,20 @@ package com.simibubi.create.content.curiosities.armor; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; 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.InstancedTileRenderer; public class CopperBacktankInstance extends SingleRotatingInstance { - public CopperBacktankInstance(InstancedTileRenderer modelManager, KineticTileEntity tile) { + public CopperBacktankInstance(MaterialManager modelManager, KineticTileEntity tile) { super(modelManager, tile); } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { return getRotatingMaterial().getModel(AllBlockPartials.COPPER_BACKTANK_SHAFT, blockState); } diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java index 8cf2b2c89..1fe8b76a6 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankRenderer.java @@ -27,7 +27,7 @@ public class CopperBacktankRenderer extends KineticTileEntityRenderer { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); SuperByteBuffer cogs = - CreateClient.bufferCache.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, te.getBlockState()); + CreateClient.BUFFER_CACHE.renderPartial(AllBlockPartials.COPPER_BACKTANK_COGS, te.getBlockState()); cogs.matrixStacker() .centre() .rotateY(180 + AngleHelper.horizontalAngle(te.getBlockState() diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java index 5ac126910..30b63d8c2 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/CopperBacktankTileEntity.java @@ -42,7 +42,7 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName int max = getMaxAir(); if (world.isRemote) { Vector3d centerOf = VecHelper.getCenterOf(pos); - Vector3d v = VecHelper.offsetRandomly(centerOf, Create.random, .65f); + Vector3d v = VecHelper.offsetRandomly(centerOf, Create.RANDOM, .65f); Vector3d m = centerOf.subtract(v); if (airLevel != max) world.addParticle(new AirParticleData(1, .05f), v.x, v.y, v.z, m.x, m.y, m.z); @@ -121,9 +121,9 @@ public class CopperBacktankTileEntity extends KineticTileEntity implements IName : new TranslationTextComponent(AllItems.COPPER_BACKTANK.get() .getTranslationKey()); } - + @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java b/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java index 4eed417c6..6562b9416 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java +++ b/src/main/java/com/simibubi/create/content/curiosities/armor/DivingHelmetItem.java @@ -3,11 +3,13 @@ package com.simibubi.create.content.curiosities.armor; import com.simibubi.create.AllItems; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.potion.EffectInstance; import net.minecraft.potion.Effects; +import net.minecraft.tags.FluidTags; import net.minecraft.world.World; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -34,7 +36,9 @@ public class DivingHelmetItem extends CopperArmorItem { if (!AllItems.DIVING_HELMET.get() .isWornBy(entity)) return; - if (!entity.isInWater()) + if (!entity.areEyesInFluid(FluidTags.WATER)) + return; + if (entity instanceof PlayerEntity && ((PlayerEntity) entity).isCreative()) return; ItemStack backtank = ItemStack.EMPTY; diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorBlock.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorBlock.java new file mode 100644 index 000000000..86fcea0f8 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorBlock.java @@ -0,0 +1,64 @@ +package com.simibubi.create.content.curiosities.projector; + +import javax.annotation.Nullable; + +import com.simibubi.create.AllItems; +import com.simibubi.create.AllTileEntities; +import com.simibubi.create.foundation.block.ITE; +import com.simibubi.create.foundation.gui.ScreenOpener; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; + +public class ChromaticProjectorBlock extends Block implements ITE { + public ChromaticProjectorBlock(Properties p_i48440_1_) { + super(p_i48440_1_); + } + + @Override + public ActionResultType onUse(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn, + BlockRayTraceResult hit) { + ItemStack held = player.getHeldItemMainhand(); + if (AllItems.WRENCH.isIn(held)) + return ActionResultType.PASS; + + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, + () -> () -> withTileEntityDo(worldIn, pos, te -> this.displayScreen(te, player))); + return ActionResultType.SUCCESS; + } + + @OnlyIn(value = Dist.CLIENT) + protected void displayScreen(ChromaticProjectorTileEntity te, PlayerEntity player) { + if (player instanceof ClientPlayerEntity) + ScreenOpener.open(new ChromaticProjectorScreen(te)); + } + + @Override + public boolean hasTileEntity(BlockState state) { + return true; + } + + @Nullable + @Override + public TileEntity createTileEntity(BlockState state, IBlockReader world) { + return null;//AllTileEntities.CHROMATIC_PROJECTOR.create(); + } + + @Override + public Class getTileEntityClass() { + return ChromaticProjectorTileEntity.class; + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorInstance.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorInstance.java new file mode 100644 index 000000000..2cd7c8f6f --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorInstance.java @@ -0,0 +1,31 @@ +package com.simibubi.create.content.curiosities.projector; + +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.simibubi.create.foundation.render.effects.EffectsHandler; + +public class ChromaticProjectorInstance extends TileEntityInstance implements IDynamicInstance { + + public ChromaticProjectorInstance(MaterialManager renderer, ChromaticProjectorTileEntity tile) { + super(renderer, tile); + } + + @Override + public void beginFrame() { + EffectsHandler instance = EffectsHandler.getInstance(); + + if (instance != null) + instance.addSphere(tile.getFilter()); + } + + @Override + public boolean decreaseFramerateWithDistance() { + return false; + } + + @Override + public void remove() { + + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java new file mode 100644 index 000000000..88761bc35 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorScreen.java @@ -0,0 +1,315 @@ +package com.simibubi.create.content.curiosities.projector; + +import java.util.Collections; +import java.util.Vector; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.widgets.IconButton; +import com.simibubi.create.foundation.gui.widgets.ScrollInput; +import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.StringTextComponent; + +public class ChromaticProjectorScreen extends AbstractSimiScreen { + + private final ItemStack renderedItem = ItemStack.EMPTY;//AllBlocks.CHROMATIC_PROJECTOR.asStack(); + private final AllGuiTextures background = AllGuiTextures.PROJECTOR; + private final int guiBottom = guiTop + background.height; + private final int guiRight = guiLeft + background.width; + private IconButton confirmButton; + + private final ITextComponent title = Lang.translate("gui.chromatic_projector.title"); + private final Vector stages; + + private Vector> inputs; + + ChromaticProjectorTileEntity tile; + + private ScrollInput radius; + private ScrollInput density; + private ScrollInput feather; + private ScrollInput fade; + + private IconButton blend; + + private ScrollInput strength; + private IconButton fieldEffect; + + private IconButton rChannel; + private IconButton gChannel; + private IconButton bChannel; + + public ChromaticProjectorScreen(ChromaticProjectorTileEntity te) { + this.tile = te; + this.stages = te.stages; + } + + private static Integer step(ScrollValueBehaviour.StepContext ctx, int base) { + if (ctx.control) return 1; + return base * (ctx.shift ? 5 : 1) - ctx.currentValue % base; + } + + @Override + protected void init() { + setWindowSize(background.width + 50, background.height); + super.init(); + widgets.clear(); + + inputs = new Vector<>(FilterStep.MAX_STEPS); + for (int row = 0; row < inputs.capacity(); row++) + inputs.add(new Vector<>(2)); + + for (int row = 0; row < stages.size(); row++) + initInputsOfRow(row); + + int guiBottom = guiTop + background.height; + int guiRight = guiLeft + background.width; + confirmButton = + new IconButton(guiRight - 33, guiBottom - 26, AllIcons.I_CONFIRM); + widgets.add(confirmButton); + + initEffectSettings(); + initMetaSettings(); + } + + private void initMetaSettings() { + int guiBottom = guiTop + background.height; + int y = guiBottom - 23; + + blend = new IconButton(guiLeft + 16, y, AllIcons.I_FX_BLEND); + blend.setToolTip(Lang.translate("gui.chromatic_projector.blend")); + + int channelX = guiLeft + 39; + rChannel = new IconButton(channelX, y, AllIcons.I_FX_BLEND); + rChannel.setToolTip(new StringTextComponent("R")); + channelX += 18; + gChannel = new IconButton(channelX, y, AllIcons.I_FX_BLEND); + gChannel.setToolTip(new StringTextComponent("G")); + channelX += 18; + bChannel = new IconButton(channelX, y, AllIcons.I_FX_BLEND); + bChannel.setToolTip(new StringTextComponent("B")); + + fieldEffect = new IconButton(guiLeft + 135, y, tile.field ? AllIcons.I_FX_FIELD_ON : AllIcons.I_FX_FIELD_OFF); + fieldEffect.setToolTip(Lang.translate("gui.chromatic_projector.field")); + + strength = new ScrollInput(guiLeft + 159, y, 25, 18) + .titled(Lang.translate("gui.chromatic_projector.strength")) + .withStepFunction(ctx -> step(ctx, 5)) + .calling(tile::setStrength) + .withRange(-100, 101) + .setState((int) (tile.strength * 100)); + + Collections.addAll(widgets, blend, rChannel, gChannel, bChannel, fieldEffect, strength); + } + + private void initEffectSettings() { + int x = guiLeft + 188; + int y = guiTop + 40; + + radius = new ScrollInput(x, y, 28, 18) + .titled(Lang.translate("gui.chromatic_projector.radius")) + .withStepFunction(ctx -> step(ctx, 2)) + .calling(tile::setRadius) + .withRange(0, 201) + .setState((int) (tile.radius * 2)); + y += 22; + feather = new ScrollInput(x, y, 28, 18) + .titled(Lang.translate("gui.chromatic_projector.feather")) + .withStepFunction(ctx -> step(ctx, 5)) + .calling(tile::setFeather) + .withRange(0, 201) + .setState((int) (tile.feather * 10)); + y += 22; + density = new ScrollInput(x, y, 28, 18) + .titled(Lang.translate("gui.chromatic_projector.density")) + .withStepFunction(ctx -> step(ctx, 10)) + .calling(tile::setDensity) + .withRange(0, 401) + .setState((int) (tile.density * 100)); + y += 22; + fade = new ScrollInput(x, y, 28, 18) + .titled(Lang.translate("gui.chromatic_projector.fade")) + .withStepFunction(ctx -> step(ctx, 1)) + .calling(tile::setFade) + .withRange(0, 51) + .setState((int) (tile.fade * 10)); + + Collections.addAll(widgets, radius, density, feather, fade); + } + + public void initInputsOfRow(int row) { + int x = guiLeft + 30; + int y = guiTop + 18; + int rowHeight = 22; + + Vector rowInputs = inputs.get(row); + rowInputs.forEach(widgets::remove); + rowInputs.clear(); + FilterStep filter = stages.get(row); + + ScrollInput type = + new SelectionScrollInput(x, y + rowHeight * row, 86, 18) + .forOptions(ColorEffect.getOptions()) + .calling(state -> stageUpdated(row, state)) + .setState(filter.filter.id) + .titled(Lang.translate("gui.chromatic_projector.filter")); + ScrollInput value = + new ScrollInput(x + 86 + 2, y + rowHeight * row, 28, 18) + .calling(state -> filter.value = state); + + rowInputs.add(type); + rowInputs.add(value); + + widgets.addAll(rowInputs); + updateParamsOfRow(row); + } + + public void updateParamsOfRow(int row) { + FilterStep instruction = stages.get(row); + Vector rowInputs = inputs.get(row); + ColorEffect def = instruction.filter; + boolean hasValue = def.hasParameter; + + ScrollInput value = rowInputs.get(1); + value.active = value.visible = hasValue; + if (hasValue) + value.withRange(def.minValue, def.maxValue + 1) + //.titled(Lang.translate(def.parameterKey)) + .setState(instruction.value) + .onChanged(); + + value.withStepFunction(def.step()); + } + + @Override + protected void renderWindow(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + int hFontColor = 0xD3CBBE; + background.draw(matrixStack, this, guiLeft, guiTop); + + for (int row = 0; row < stages.capacity(); row++) { + AllGuiTextures toDraw = AllGuiTextures.PROJECTOR_EMPTY; + int yOffset = toDraw.height * row; + if (row >= stages.size()) { + toDraw.draw(matrixStack, guiLeft, guiTop + 14 + yOffset); + continue; + } + + FilterStep step = stages.get(row); + ColorEffect def = step.filter; + def.background.draw(matrixStack, guiLeft, guiTop + 14 + yOffset); + + if (def != ColorEffect.END) + label(matrixStack, 36, yOffset - 3, Lang.translate(def.translationKey)); + if (def.hasParameter) { + String text = step.filter.formatValue(step.value); + int stringWidth = textRenderer.getStringWidth(text); + label(matrixStack, 118 + (12 - stringWidth / 2), yOffset - 3, new StringTextComponent(text)); + } + } + + renderScroll(matrixStack, radius, 2f); + renderScroll(matrixStack, density, 100f); + renderScroll(matrixStack, feather, 10f); + renderScroll(matrixStack, fade, 10f); + + renderScroll(matrixStack, strength, 100f); + + textRenderer.drawWithShadow(matrixStack, title, guiLeft - 3 + (background.width - textRenderer.getWidth(title)) / 2, guiTop + 3, + 0xffffff); + + GuiGameElement.of(renderedItem) + .scale(5) + .at(guiLeft + background.width + 10, guiTop + 140, -150) + .render(matrixStack); + } + + private void renderScroll(MatrixStack matrixStack, ScrollInput input, float divisor) { + + String text = String.valueOf(input.getState() / divisor); + + int stringWidth = textRenderer.getStringWidth(text); + textRenderer.drawWithShadow(matrixStack, text, input.x + 2, input.y + 5, 0xFFFFEE); + } + + private void label(MatrixStack matrixStack, int x, int y, ITextComponent text) { + textRenderer.drawWithShadow(matrixStack, text, guiLeft + x, guiTop + 26 + y, 0xFFFFEE); + } + + public void sendPacket() { + AllPackets.channel.sendToServer(new ConfigureProjectorPacket(tile)); + } + + @Override + public void removed() { + sendPacket(); + } + + private void stageUpdated(int index, int state) { + ColorEffect newValue = ColorEffect.all.get(state); + stages.get(index).filter = newValue; + stages.get(index).value = newValue.defaultValue; + updateParamsOfRow(index); + if (newValue == ColorEffect.END) { + for (int i = stages.size() - 1; i > index; i--) { + stages.remove(i); + Vector rowInputs = inputs.get(i); + rowInputs.forEach(widgets::remove); + rowInputs.clear(); + } + } else { + if (index + 1 < stages.capacity() && index + 1 == stages.size()) { + stages.add(new FilterStep(ColorEffect.END)); + initInputsOfRow(index + 1); + } + } + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + if (confirmButton.isHovered()) { + Minecraft.getInstance().player.closeScreen(); + return true; + } + + if (blend.isHovered()) { + tile.blend = !tile.blend; + return true; + } + + if (fieldEffect.isHovered()) { + tile.field = !tile.field; + + fieldEffect.setIcon(tile.field ? AllIcons.I_FX_FIELD_ON : AllIcons.I_FX_FIELD_OFF); + return fieldEffect.mouseClicked(x, y, button); + } + + if (rChannel.isHovered()) { + tile.rMask = !tile.rMask; + return true; + } + + if (gChannel.isHovered()) { + tile.gMask = !tile.gMask; + return true; + } + + if (bChannel.isHovered()) { + tile.bMask = !tile.bMask; + return true; + } + + return super.mouseClicked(x, y, button); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java new file mode 100644 index 000000000..ad80feb79 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ChromaticProjectorTileEntity.java @@ -0,0 +1,140 @@ +package com.simibubi.create.content.curiosities.projector; + +import java.util.Vector; + +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.simibubi.create.foundation.render.effects.FilterSphere; +import com.simibubi.create.foundation.tileEntity.SyncedTileEntity; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.tileentity.TileEntityType; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.util.Constants; + +public class ChromaticProjectorTileEntity extends SyncedTileEntity implements IInstanceRendered { + + Vector stages = FilterStep.createDefault(); + + float radius = 3f; + + float feather = 1; + float density = 1; + float fade = 1; + boolean blend = true; + + public boolean surface = true; + public boolean field = true; + public float strength = 1; + + public boolean rMask = true; + public boolean gMask = true; + public boolean bMask = true; + + public ChromaticProjectorTileEntity(TileEntityType te) { + super(te); + } + + public FilterSphere getFilter() { + + BlockPos pos = getPos(); + FilterSphere sphere = new FilterSphere(); + + sphere.x = (float) (pos.getX() + 0.5); + sphere.y = (float) (pos.getY() + 0.5); + sphere.z = (float) (pos.getZ() + 0.5); + sphere.radius = radius; + + sphere.feather = feather; + sphere.density = density; + sphere.fade = fade; + sphere.blend = blend; + + sphere.surface = surface; + sphere.field = field; + sphere.strength = strength; + + sphere.rMask = rMask; + sphere.gMask = gMask; + sphere.bMask = bMask; + + sphere.filter = FilterStep.fold(stages); + return sphere; + } + + public ChromaticProjectorTileEntity setRadius(int radius) { + this.radius = radius / 2f; + return this; + } + + public ChromaticProjectorTileEntity setDensity(int density) { + this.density = density / 100f; + return this; + } + + public ChromaticProjectorTileEntity setFeather(int feather) { + this.feather = feather / 10f; + return this; + } + + public ChromaticProjectorTileEntity setFade(int fade) { + this.fade = fade / 10f; + return this; + } + + public ChromaticProjectorTileEntity setBlend(boolean blend) { + this.blend = blend; + return this; + } + + public ChromaticProjectorTileEntity setStrength(int strength) { + this.strength = strength / 100f; + return this; + } + + @Override + public CompoundNBT write(CompoundNBT tag) { + super.write(tag); + + tag.put("filters", FilterStep.writeAll(stages)); + + tag.putFloat("radius", radius); + + tag.putFloat("feather", feather); + tag.putFloat("density", density); + tag.putFloat("fade", fade); + tag.putBoolean("blend", blend); + + tag.putBoolean("surface", surface); + tag.putBoolean("field", field); + tag.putFloat("strength", strength); + + tag.putBoolean("rMask", rMask); + tag.putBoolean("gMask", gMask); + tag.putBoolean("bMask", bMask); + + return tag; + } + + @Override + public void fromTag(BlockState state, CompoundNBT tag) { + super.fromTag(state, tag); + + stages = FilterStep.readAll(tag.getList("filters", Constants.NBT.TAG_COMPOUND)); + + radius = tag.getFloat("radius"); + + feather = tag.getFloat("feather"); + density = tag.getFloat("density"); + fade = tag.getFloat("fade"); + blend = tag.getBoolean("blend"); + + surface = tag.getBoolean("surface"); + field = tag.getBoolean("field"); + strength = tag.getFloat("strength"); + + rMask = tag.getBoolean("rMask"); + gMask = tag.getBoolean("gMask"); + bMask = tag.getBoolean("bMask"); + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java new file mode 100644 index 000000000..d9dd6ca09 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ColorEffect.java @@ -0,0 +1,113 @@ +package com.simibubi.create.content.curiosities.projector; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.function.Function; +import java.util.function.Supplier; + +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.render.effects.ColorMatrices; +import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.text.ITextComponent; + +public class ColorEffect { + static final ArrayList all = new ArrayList<>(); + static final HashMap lookup = new HashMap<>(); + private static int nextId = 0; + + public static final ColorEffect SEPIA = create("sepia", ColorMatrices::sepia); + public static final ColorEffect GRAYSCALE = create("grayscale", ColorMatrices::grayscale); + public static final ColorEffect DARKEN = create("darken", ColorMatrices::darken).setDefaultValue(20); + public static final ColorEffect CONTRAST = create("contrast", ColorMatrices::contrast).setRange(0, 200).setDefaultValue(100); + public static final ColorEffect SATURATE = create("saturate", ColorMatrices::saturate).setRange(0, 200); + public static final ColorEffect HUE_SHIFT = create("hue_shift", ColorMatrices::hueShift).setRange(0, 360).setDivisor(1f).setDefaultValue(120); + public static final ColorEffect INVERT = create("invert", ColorMatrices::invert); + public static final ColorEffect END = create("end", ColorMatrices::identity).setBackground(AllGuiTextures.PROJECTOR_END); + + boolean hasParameter; + AllGuiTextures background; + + int defaultValue = 100; + int minValue = 0; + int maxValue = 100; + float divisor = 100f; + + final int id; + final FilterFactory filter; + final String name; + final String translationKey; + + public ColorEffect(String name, FilterFactory filter) { + this.filter = filter; + this.name = name; + this.translationKey = "gui.chromatic_projector.filter." + Lang.asId(name); + this.id = nextId++; + + lookup.put(name, this); + all.add(this); + } + + public ColorEffect setHasParameter(boolean hasParameter) { + this.hasParameter = hasParameter; + return setBackground(hasParameter ? AllGuiTextures.PROJECTOR_FILTER_STRENGTH : AllGuiTextures.PROJECTOR_FILTER); + } + + public ColorEffect setBackground(AllGuiTextures background) { + this.background = background; + return this; + } + + public ColorEffect setDefaultValue(int defaultValue) { + this.defaultValue = defaultValue; + return this; + } + + public ColorEffect setRange(int minValue, int maxValue) { + this.minValue = minValue; + this.maxValue = maxValue; + return this; + } + + public ColorEffect setDivisor(float divisor) { + this.divisor = divisor; + return this; + } + + public Function step() { + return c -> { + if (c.control) return 1; + if (c.shift) return 20; + return 5; + }; + } + + String formatValue(int value) { + if (this == HUE_SHIFT) + return value + Lang.translate("generic.unit.degrees").getString(); + return "" + value; + } + + static List getOptions() { + List options = new ArrayList<>(); + for (ColorEffect entry : all) + options.add(Lang.translate(entry.translationKey)); + return options; + } + + @FunctionalInterface + public interface FilterFactory { + Matrix4f create(float param); + } + + public static ColorEffect create(String name, Supplier filter) { + return new ColorEffect(name, $ -> filter.get()).setHasParameter(false); + } + + public static ColorEffect create(String name, FilterFactory filter) { + return new ColorEffect(name, filter).setHasParameter(true); + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/ConfigureProjectorPacket.java b/src/main/java/com/simibubi/create/content/curiosities/projector/ConfigureProjectorPacket.java new file mode 100644 index 000000000..89eb463b3 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/ConfigureProjectorPacket.java @@ -0,0 +1,126 @@ +package com.simibubi.create.content.curiosities.projector; + +import java.util.Vector; +import java.util.stream.Collectors; + +import com.simibubi.create.foundation.networking.TileEntityConfigurationPacket; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; + +public class ConfigureProjectorPacket extends TileEntityConfigurationPacket { + + Vector stages; + float radius; + + float feather; + float density; + float fade; + boolean blend; + + public boolean surface; + public boolean field; + public float strength; + + public boolean rMask; + public boolean gMask; + public boolean bMask; + + public ConfigureProjectorPacket(PacketBuffer buffer) { + super(buffer); + } + + public ConfigureProjectorPacket(ChromaticProjectorTileEntity tile) { + super(tile.getPos()); + + stages = tile.stages.stream() + .map(FilterStep::write) + .collect(Collectors.toCollection(Vector::new)); + radius = tile.radius; + + feather = tile.feather; + density = tile.density; + fade = tile.fade; + blend = tile.blend; + + surface = tile.surface; + field = tile.field; + strength = tile.strength; + + rMask = tile.rMask; + gMask = tile.gMask; + bMask = tile.bMask; + } + + @Override + protected void writeSettings(PacketBuffer buffer) { + buffer.writeFloat(radius); + + buffer.writeFloat(feather); + buffer.writeFloat(density); + buffer.writeFloat(fade); + buffer.writeBoolean(blend); + + buffer.writeBoolean(surface); + buffer.writeBoolean(field); + buffer.writeFloat(strength); + + buffer.writeBoolean(rMask); + buffer.writeBoolean(gMask); + buffer.writeBoolean(bMask); + + buffer.writeInt(stages.size()); + for (CompoundNBT stage : stages) { + buffer.writeCompoundTag(stage); + } + } + + @Override + protected void readSettings(PacketBuffer buffer) { + radius = buffer.readFloat(); + + feather = buffer.readFloat(); + density = buffer.readFloat(); + fade = buffer.readFloat(); + blend = buffer.readBoolean(); + + surface = buffer.readBoolean(); + field = buffer.readBoolean(); + strength = buffer.readFloat(); + + rMask = buffer.readBoolean(); + gMask = buffer.readBoolean(); + bMask = buffer.readBoolean(); + + int count = buffer.readInt(); + stages = new Vector<>(FilterStep.MAX_STEPS); + + for (int i = 0; i < count; i++) { + stages.add(buffer.readCompoundTag()); + } + } + + @Override + protected void applySettings(ChromaticProjectorTileEntity tile) { + tile.stages = stages.stream() + .map(FilterStep::new) + .collect(Collectors.toCollection(Vector::new)); + + tile.radius = radius; + + tile.feather = feather; + tile.density = density; + tile.fade = fade; + tile.blend = blend; + + tile.surface = surface; + tile.field = field; + tile.strength = strength; + + tile.rMask = rMask; + tile.gMask = gMask; + tile.bMask = bMask; + + tile.sendData(); + } +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java b/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java new file mode 100644 index 000000000..5e745b8af --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/projector/FilterStep.java @@ -0,0 +1,85 @@ +package com.simibubi.create.content.curiosities.projector; + +import java.util.Iterator; +import java.util.Vector; + +import com.simibubi.create.foundation.render.effects.ColorMatrices; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.util.math.vector.Matrix4f; + +public class FilterStep { + + public static final int MAX_STEPS = 6; + ColorEffect filter; + int value; + + public FilterStep(ColorEffect filter) { + this.filter = filter; + } + + public FilterStep(ColorEffect filter, int value) { + this.filter = filter; + this.value = value; + } + + public FilterStep(CompoundNBT nbt) { + this.filter = ColorEffect.lookup.get(nbt.getString("id")); + this.value = nbt.getInt("value"); + } + + public Matrix4f createFilter() { + return filter.filter.create(value / filter.divisor); + } + + public CompoundNBT write() { + CompoundNBT nbt = new CompoundNBT(); + + nbt.putString("id", filter.name); + nbt.putInt("value", value); + + return nbt; + } + + public static Vector readAll(ListNBT list) { + Vector steps = new Vector<>(MAX_STEPS); + + for (int i = 0; i < list.size(); i++) { + steps.add(new FilterStep(list.getCompound(i))); + } + + return steps; + } + + public static ListNBT writeAll(Vector filters) { + ListNBT out = new ListNBT(); + + for (FilterStep filter : filters) { + out.add(filter.write()); + } + + return out; + } + + public static Matrix4f fold(Vector filters) { + Iterator stepIterator = filters.stream().filter(it -> it != null && it.filter != ColorEffect.END).iterator(); + + if (stepIterator.hasNext()) { + Matrix4f accum = stepIterator.next().createFilter(); + + stepIterator.forEachRemaining(filterStep -> accum.multiply(filterStep.createFilter())); + + return accum; + } + + return ColorMatrices.identity(); + } + + public static Vector createDefault() { + Vector instructions = new Vector<>(MAX_STEPS); + instructions.add(new FilterStep(ColorEffect.SEPIA, 100)); + instructions.add(new FilterStep(ColorEffect.END)); + return instructions; + } +} 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 fb23177aa..9ef60eaa1 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 @@ -7,6 +7,8 @@ import java.util.Map; import javax.annotation.Nonnull; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock; import com.simibubi.create.content.curiosities.symmetry.mirror.CrossPlaneMirror; import com.simibubi.create.content.curiosities.symmetry.mirror.EmptyMirror; import com.simibubi.create.content.curiosities.symmetry.mirror.PlaneMirror; @@ -225,12 +227,21 @@ public class SymmetryWandItem extends Item { BlockState toReplace = world.getBlockState(position); if (!toReplace.getMaterial() - .isReplaceable()) + .isReplaceable()) continue; if (toReplace.getBlockHardness(world, position) == -1) continue; - if (BlockHelper.findAndRemoveInInventory(blockState, player, 1) == 0) - continue; + + if (AllBlocks.CART_ASSEMBLER.has(blockState)) { + BlockState railBlock = CartAssemblerBlock.getRailBlock(blockState); + if (BlockHelper.findAndRemoveInInventory(railBlock, player, 1) == 0) + continue; + if (BlockHelper.findAndRemoveInInventory(blockState, player, 1) == 0) + blockState = railBlock; + } else { + if (BlockHelper.findAndRemoveInInventory(blockState, player, 1) == 0) + continue; + } BlockSnapshot blocksnapshot = BlockSnapshot.create(world.getRegistryKey(), world, position); FluidState ifluidstate = world.getFluidState(position); diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java index 51cd757ba..0c0461daf 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandItemRenderer.java @@ -1,8 +1,8 @@ package com.simibubi.create.content.curiosities.symmetry.client; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.PartialItemModelRenderer; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.renderer.IRenderTypeBuffer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java index ce5796427..f361c3c9f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/client/SymmetryWandModel.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.curiosities.symmetry.client; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java index 805673bec..562393881 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/CrossPlaneMirror.java @@ -5,9 +5,9 @@ import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.MatrixStacker; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java index 9e953ae5b..0fbdba41f 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/EmptyMirror.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableList; -import com.simibubi.create.foundation.render.backend.core.PartialModel; +import com.jozufozu.flywheel.core.PartialModel; import net.minecraft.block.BlockState; import net.minecraft.util.IStringSerializable; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java index 53f8a55c3..af20b66ef 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/PlaneMirror.java @@ -5,9 +5,9 @@ import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.MatrixStacker; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java index 02e950e9e..d704c0723 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/SymmetryMirror.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java index 838d4b366..abf923a58 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java +++ b/src/main/java/com/simibubi/create/content/curiosities/symmetry/mirror/TriplePlaneMirror.java @@ -5,8 +5,8 @@ import java.util.List; import java.util.Map; import com.google.common.collect.ImmutableList; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintAssignCompleteRecipePacket.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintAssignCompleteRecipePacket.java new file mode 100644 index 000000000..2e9a2349a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintAssignCompleteRecipePacket.java @@ -0,0 +1,49 @@ +package com.simibubi.create.content.curiosities.tools; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class BlueprintAssignCompleteRecipePacket extends SimplePacketBase { + + private ResourceLocation recipeID; + + public BlueprintAssignCompleteRecipePacket(ResourceLocation recipeID) { + this.recipeID = recipeID; + } + + public BlueprintAssignCompleteRecipePacket(PacketBuffer buffer) { + recipeID = buffer.readResourceLocation(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeResourceLocation(recipeID); + } + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + if (player.openContainer instanceof BlueprintContainer) { + BlueprintContainer c = (BlueprintContainer) player.openContainer; + player.getServerWorld() + .getRecipeManager() + .getRecipe(recipeID) + .ifPresent(r -> BlueprintItem.assignCompleteRecipe(c.ghostInventory, r)); + } + }); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java new file mode 100644 index 000000000..5d1e5b1bc --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintContainer.java @@ -0,0 +1,173 @@ +package com.simibubi.create.content.curiosities.tools; + +import java.util.Optional; + +import com.simibubi.create.AllContainerTypes; +import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; +import com.simibubi.create.foundation.gui.GhostItemContainer; +import com.simibubi.create.foundation.gui.IClearableContainer; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ICraftingRecipe; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.SSetSlotPacket; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class BlueprintContainer extends GhostItemContainer implements IClearableContainer { + + public BlueprintContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id, inv, extraData); + } + + public BlueprintContainer(ContainerType type, int id, PlayerInventory inv, BlueprintSection section) { + super(type, id, inv, section); + } + + public static BlueprintContainer create(int id, PlayerInventory inv, BlueprintSection section) { + return new BlueprintContainer(AllContainerTypes.CRAFTING_BLUEPRINT.get(), id, inv, section); + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + protected void addSlots() { + addPlayerSlots(9, 131); + + int x = 29; + int y = 21; + int index = 0; + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 3; ++col) + this.addSlot(new BlueprintCraftSlot(ghostInventory, index++, x + col * 18, y + row * 18)); + + addSlot(new BlueprintCraftSlot(ghostInventory, index++, 123, 40)); + addSlot(new SlotItemHandler(ghostInventory, index++, 135, 57)); + } + + public void onCraftMatrixChanged() { + if (contentHolder.getBlueprintWorld().isRemote) + return; + + ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) player; + CraftingInventory craftingInventory = new BlueprintCraftingInventory(this, ghostInventory); + Optional optional = player.getServer() + .getRecipeManager() + .getRecipe(IRecipeType.CRAFTING, craftingInventory, player.getEntityWorld()); + + if (!optional.isPresent()) { + if (ghostInventory.getStackInSlot(9) + .isEmpty()) + return; + if (!contentHolder.inferredIcon) + return; + + ghostInventory.setStackInSlot(9, ItemStack.EMPTY); + serverplayerentity.connection.sendPacket(new SSetSlotPacket(windowId, 36 + 9, ItemStack.EMPTY)); + contentHolder.inferredIcon = false; + return; + } + + ICraftingRecipe icraftingrecipe = optional.get(); + ItemStack itemstack = icraftingrecipe.getCraftingResult(craftingInventory); + ghostInventory.setStackInSlot(9, itemstack); + contentHolder.inferredIcon = true; + ItemStack toSend = itemstack.copy(); + toSend.getOrCreateTag() + .putBoolean("InferredFromRecipe", true); + serverplayerentity.connection.sendPacket(new SSetSlotPacket(windowId, 36 + 9, toSend)); + } + + @Override + public void putStackInSlot(int p_75141_1_, ItemStack p_75141_2_) { + if (p_75141_1_ == 36 + 9) { + if (p_75141_2_.hasTag()) { + contentHolder.inferredIcon = p_75141_2_.getTag() + .getBoolean("InferredFromRecipe"); + p_75141_2_.getTag() + .remove("InferredFromRecipe"); + } else + contentHolder.inferredIcon = false; + } + super.putStackInSlot(p_75141_1_, p_75141_2_); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return contentHolder.getItems(); + } + + @Override + protected void readData(BlueprintSection contentHolder) { + } + + @Override + protected void saveData(BlueprintSection contentHolder) { + contentHolder.save(ghostInventory); + } + + @Override + @OnlyIn(Dist.CLIENT) + protected BlueprintSection createOnClient(PacketBuffer extraData) { + int entityID = extraData.readVarInt(); + int section = extraData.readVarInt(); + Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityID); + if (!(entityByID instanceof BlueprintEntity)) + return null; + BlueprintEntity blueprintEntity = (BlueprintEntity) entityByID; + BlueprintSection blueprintSection = blueprintEntity.getSection(section); + return blueprintSection; + } + + static class BlueprintCraftingInventory extends CraftingInventory { + + public BlueprintCraftingInventory(Container container, ItemStackHandler items) { + super(container, 3, 3); + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + ItemStack stack = items.getStackInSlot(y * 3 + x); + setInventorySlotContents(y * 3 + x, stack == null ? ItemStack.EMPTY : stack.copy()); + } + } + } + + } + + class BlueprintCraftSlot extends SlotItemHandler { + + private int index; + + public BlueprintCraftSlot(IItemHandler itemHandler, int index, int xPosition, int yPosition) { + super(itemHandler, index, xPosition, yPosition); + this.index = index; + } + + @Override + public void onSlotChanged() { + super.onSlotChanged(); + if (index == 9 && getHasStack() && !contentHolder.getBlueprintWorld().isRemote) { + contentHolder.inferredIcon = false; + ServerPlayerEntity serverplayerentity = (ServerPlayerEntity) player; + serverplayerentity.connection.sendPacket(new SSetSlotPacket(windowId, 36 + 9, getStack())); + } + if (index < 9) + onCraftMatrixChanged(); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java new file mode 100644 index 000000000..344bd3405 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintEntity.java @@ -0,0 +1,549 @@ +package com.simibubi.create.content.curiosities.tools; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; + +import javax.annotation.Nullable; + +import org.apache.commons.lang3.Validate; + +import com.simibubi.create.AllEntityTypes; +import com.simibubi.create.AllItems; +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.item.filter.FilterItem; +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.ISyncPersistentData; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.VecHelper; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.RedstoneDiodeBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntitySize; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.Pose; +import net.minecraft.entity.item.HangingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ICraftingRecipe; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.IPacket; +import net.minecraft.network.PacketBuffer; +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.NonNullList; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.SoundEvents; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.GameRules; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.common.ForgeMod; +import net.minecraftforge.common.util.FakePlayer; +import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; +import net.minecraftforge.fml.hooks.BasicEventHooks; +import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.wrapper.InvWrapper; + +public class BlueprintEntity extends HangingEntity + implements IEntityAdditionalSpawnData, ISpecialEntityItemRequirement, ISyncPersistentData { + + protected int size; + protected Direction verticalOrientation; + + @SuppressWarnings("unchecked") + public BlueprintEntity(EntityType p_i50221_1_, World p_i50221_2_) { + super((EntityType) p_i50221_1_, p_i50221_2_); + size = 1; + } + + public BlueprintEntity(World world, BlockPos pos, Direction facing, Direction verticalOrientation) { + super(AllEntityTypes.CRAFTING_BLUEPRINT.get(), world, pos); + + for (int size = 3; size > 0; size--) { + this.size = size; + this.updateFacingWithBoundingBox(facing, verticalOrientation); + if (this.onValidSurface()) + break; + } + } + + public static EntityType.Builder build(EntityType.Builder builder) { + @SuppressWarnings("unchecked") + EntityType.Builder entityBuilder = (EntityType.Builder) builder; + return entityBuilder; + } + + @Override + public IPacket createSpawnPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + public void writeAdditional(CompoundNBT p_213281_1_) { + p_213281_1_.putByte("Facing", (byte) this.facingDirection.getIndex()); + p_213281_1_.putByte("Orientation", (byte) this.verticalOrientation.getIndex()); + p_213281_1_.putInt("Size", size); + super.writeAdditional(p_213281_1_); + } + + @Override + public void readAdditional(CompoundNBT p_70037_1_) { + this.facingDirection = Direction.byIndex(p_70037_1_.getByte("Facing")); + this.verticalOrientation = Direction.byIndex(p_70037_1_.getByte("Orientation")); + this.size = p_70037_1_.getInt("Size"); + super.readAdditional(p_70037_1_); + this.updateFacingWithBoundingBox(this.facingDirection, this.verticalOrientation); + } + + protected void updateFacingWithBoundingBox(Direction facing, Direction verticalOrientation) { + Validate.notNull(facing); + this.facingDirection = facing; + this.verticalOrientation = verticalOrientation; + if (facing.getAxis() + .isHorizontal()) { + this.rotationPitch = 0.0F; + this.rotationYaw = (float) (this.facingDirection.getHorizontalIndex() * 90); + } else { + this.rotationPitch = (float) (-90 * facing.getAxisDirection() + .getOffset()); + this.rotationYaw = verticalOrientation.getAxis() + .isHorizontal() ? 180 + verticalOrientation.getHorizontalAngle() : 0; + } + + this.prevRotationPitch = this.rotationPitch; + this.prevRotationYaw = this.rotationYaw; + this.updateBoundingBox(); + } + + @Override + protected float getEyeHeight(Pose p_213316_1_, EntitySize p_213316_2_) { + return 0; + } + + @Override + protected void updateBoundingBox() { + if (this.facingDirection == null) + return; + if (this.verticalOrientation == null) + return; + + Vector3d pos = Vector3d.of(hangingPosition) + .add(.5, .5, .5) + .subtract(Vector3d.of(facingDirection.getDirectionVec()) + .scale(0.46875)); + double d1 = pos.x; + double d2 = pos.y; + double d3 = pos.z; + this.setPos(d1, d2, d3); + + Axis axis = facingDirection.getAxis(); + if (size == 2) + pos = pos.add(Vector3d.of(axis.isHorizontal() ? facingDirection.rotateYCCW() + .getDirectionVec() + : verticalOrientation.rotateY() + .getDirectionVec()) + .scale(0.5)) + .add(Vector3d + .of(axis.isHorizontal() ? Direction.UP.getDirectionVec() + : facingDirection == Direction.UP ? verticalOrientation.getDirectionVec() + : verticalOrientation.getOpposite() + .getDirectionVec()) + .scale(0.5)); + + d1 = pos.x; + d2 = pos.y; + d3 = pos.z; + + double d4 = (double) this.getWidthPixels(); + double d5 = (double) this.getHeightPixels(); + double d6 = (double) this.getWidthPixels(); + Direction.Axis direction$axis = this.facingDirection.getAxis(); + switch (direction$axis) { + case X: + d4 = 1.0D; + break; + case Y: + d5 = 1.0D; + break; + case Z: + d6 = 1.0D; + } + + d4 = d4 / 32.0D; + d5 = d5 / 32.0D; + d6 = d6 / 32.0D; + this.setBoundingBox(new AxisAlignedBB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6)); + } + + public boolean onValidSurface() { + if (!world.isSpaceEmpty(this)) + return false; + + int i = Math.max(1, this.getWidthPixels() / 16); + int j = Math.max(1, this.getHeightPixels() / 16); + BlockPos blockpos = this.hangingPosition.offset(this.facingDirection.getOpposite()); + Direction upDirection = facingDirection.getAxis() + .isHorizontal() ? Direction.UP + : facingDirection == Direction.UP ? verticalOrientation : verticalOrientation.getOpposite(); + Direction direction = facingDirection.getAxis() + .isVertical() ? verticalOrientation.rotateY() : facingDirection.rotateYCCW(); + BlockPos.Mutable blockpos$mutable = new BlockPos.Mutable(); + + for (int k = 0; k < i; ++k) { + for (int l = 0; l < j; ++l) { + int i1 = (i - 1) / -2; + int j1 = (j - 1) / -2; + blockpos$mutable.setPos(blockpos) + .move(direction, k + i1) + .move(upDirection, l + j1); + BlockState blockstate = this.world.getBlockState(blockpos$mutable); + if (Block.hasEnoughSolidSide(this.world, blockpos$mutable, this.facingDirection)) + continue; + if (!blockstate.getMaterial() + .isSolid() && !RedstoneDiodeBlock.isDiode(blockstate)) { + return false; + } + } + } + + return this.world.getEntitiesInAABBexcluding(this, this.getBoundingBox(), IS_HANGING_ENTITY) + .isEmpty(); + } + + @Override + public int getWidthPixels() { + return 16 * size; + } + + @Override + public int getHeightPixels() { + return 16 * size; + } + + @Override + public boolean hitByEntity(Entity source) { + if (!(source instanceof PlayerEntity) || world.isRemote) + return super.hitByEntity(source); + + PlayerEntity player = (PlayerEntity) source; + double attrib = player.getAttribute(ForgeMod.REACH_DISTANCE.get()) + .getValue() + (player.isCreative() ? 0 : -0.5F); + + Vector3d eyePos = source.getEyePosition(1); + Vector3d look = source.getLook(1); + Vector3d target = eyePos.add(look.scale(attrib)); + + Optional rayTrace = getBoundingBox().rayTrace(eyePos, target); + if (!rayTrace.isPresent()) + return super.hitByEntity(source); + + Vector3d hitVec = rayTrace.get(); + BlueprintSection sectionAt = getSectionAt(hitVec.subtract(getPositionVec())); + ItemStackHandler items = sectionAt.getItems(); + + if (items.getStackInSlot(9) + .isEmpty()) + return super.hitByEntity(source); + for (int i = 0; i < items.getSlots(); i++) + items.setStackInSlot(i, ItemStack.EMPTY); + sectionAt.save(items); + return true; + } + + @Override + public void onBroken(@Nullable Entity p_110128_1_) { + if (!world.getGameRules() + .getBoolean(GameRules.DO_ENTITY_DROPS)) + return; + + playSound(SoundEvents.ENTITY_PAINTING_BREAK, 1.0F, 1.0F); + if (p_110128_1_ instanceof PlayerEntity) { + PlayerEntity playerentity = (PlayerEntity) p_110128_1_; + if (playerentity.abilities.isCreativeMode) { + return; + } + } + + entityDropItem(AllItems.CRAFTING_BLUEPRINT.asStack()); + } + + @Override + public ItemStack getPickedResult(RayTraceResult target) { + return AllItems.CRAFTING_BLUEPRINT.asStack(); + } + + @Override + public ItemRequirement getRequiredItems() { + return new ItemRequirement(ItemUseType.CONSUME, AllItems.CRAFTING_BLUEPRINT.get()); + } + + @Override + public void playPlaceSound() { + this.playSound(SoundEvents.ENTITY_PAINTING_PLACE, 1.0F, 1.0F); + } + + @Override + public void setLocationAndAngles(double p_70012_1_, double p_70012_3_, double p_70012_5_, float p_70012_7_, + float p_70012_8_) { + this.setPosition(p_70012_1_, p_70012_3_, p_70012_5_); + } + + @Override + @OnlyIn(Dist.CLIENT) + public void setPositionAndRotationDirect(double p_180426_1_, double p_180426_3_, double p_180426_5_, + float p_180426_7_, float p_180426_8_, int p_180426_9_, boolean p_180426_10_) { + BlockPos blockpos = + this.hangingPosition.add(p_180426_1_ - this.getX(), p_180426_3_ - this.getY(), p_180426_5_ - this.getZ()); + this.setPosition((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); + } + + @Override + public void writeSpawnData(PacketBuffer buffer) { + CompoundNBT compound = new CompoundNBT(); + writeAdditional(compound); + buffer.writeCompoundTag(compound); + buffer.writeCompoundTag(getPersistentData()); + } + + @Override + public void readSpawnData(PacketBuffer additionalData) { + readAdditional(additionalData.readCompoundTag()); + getPersistentData().merge(additionalData.readCompoundTag()); + } + + @Override + public ActionResultType applyPlayerInteraction(PlayerEntity player, Vector3d vec, Hand hand) { + if (player instanceof FakePlayer) + return ActionResultType.PASS; + + boolean holdingWrench = AllItems.WRENCH.isIn(player.getHeldItem(hand)); + BlueprintSection section = getSectionAt(vec); + ItemStackHandler items = section.getItems(); + + if (!holdingWrench && !world.isRemote && !items.getStackInSlot(9) + .isEmpty()) { + + IItemHandlerModifiable playerInv = new InvWrapper(player.inventory); + boolean firstPass = true; + int amountCrafted = 0; + ForgeHooks.setCraftingPlayer(player); + Optional recipe = Optional.empty(); + + do { + Map stacksTaken = new HashMap<>(); + Map craftingGrid = new HashMap<>(); + boolean success = true; + + Search: for (int i = 0; i < 9; i++) { + ItemStack requestedItem = items.getStackInSlot(i); + if (requestedItem.isEmpty()) { + craftingGrid.put(i, ItemStack.EMPTY); + continue; + } + + for (int slot = 0; slot < playerInv.getSlots(); slot++) { + if (!FilterItem.test(world, playerInv.getStackInSlot(slot), requestedItem)) + continue; + ItemStack currentItem = playerInv.extractItem(slot, 1, false); + if (stacksTaken.containsKey(slot)) + stacksTaken.get(slot) + .grow(1); + else + stacksTaken.put(slot, currentItem.copy()); + craftingGrid.put(i, currentItem); + continue Search; + } + + success = false; + break; + } + + if (success) { + CraftingInventory craftingInventory = new BlueprintCraftingInventory(craftingGrid); + + if (!recipe.isPresent()) + recipe = world.getRecipeManager() + .getRecipe(IRecipeType.CRAFTING, craftingInventory, world); + ItemStack result = recipe.filter(r -> r.matches(craftingInventory, world)) + .map(r -> r.getCraftingResult(craftingInventory)) + .orElse(ItemStack.EMPTY); + + if (result.isEmpty()) { + success = false; + } else if (result.getCount() + amountCrafted > 64) { + success = false; + } else { + amountCrafted += result.getCount(); + result.onCrafting(player.world, player, 1); + BasicEventHooks.firePlayerCraftingEvent(player, result, craftingInventory); + NonNullList nonnulllist = world.getRecipeManager() + .getRecipeNonNull(IRecipeType.CRAFTING, craftingInventory, world); + + if (firstPass) + world.playSound(null, player.getBlockPos(), SoundEvents.ENTITY_ITEM_PICKUP, + SoundCategory.PLAYERS, .2f, 1f + Create.RANDOM.nextFloat()); + player.inventory.placeItemBackInInventory(world, result); + for (ItemStack itemStack : nonnulllist) + player.inventory.placeItemBackInInventory(world, itemStack); + firstPass = false; + } + } + + if (!success) { + for (Entry entry : stacksTaken.entrySet()) + playerInv.insertItem(entry.getKey(), entry.getValue(), false); + break; + } + + } while (player.isSneaking()); + ForgeHooks.setCraftingPlayer(null); + return ActionResultType.SUCCESS; + } + + int i = section.index; + if (!world.isRemote && player instanceof ServerPlayerEntity) { + NetworkHooks.openGui((ServerPlayerEntity) player, section, buf -> { + buf.writeVarInt(getEntityId()); + buf.writeVarInt(i); + }); + } + + return ActionResultType.SUCCESS; + } + + public BlueprintSection getSectionAt(Vector3d vec) { + int index = 0; + if (size > 1) { + vec = VecHelper.rotate(vec, rotationYaw, Axis.Y); + vec = VecHelper.rotate(vec, -rotationPitch, Axis.X); + vec = vec.add(0.5, 0.5, 0); + if (size == 3) + vec = vec.add(1, 1, 0); + int x = MathHelper.clamp(MathHelper.floor(vec.x), 0, size - 1); + int y = MathHelper.clamp(MathHelper.floor(vec.y), 0, size - 1); + index = x + y * size; + } + + BlueprintSection section = getSection(index); + return section; + } + + static class BlueprintCraftingInventory extends CraftingInventory { + + private static Container dummyContainer = new Container(null, -1) { + public boolean canInteractWith(PlayerEntity playerIn) { + return false; + } + }; + + public BlueprintCraftingInventory(Map items) { + super(dummyContainer, 3, 3); + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 3; x++) { + ItemStack stack = items.get(y * 3 + x); + setInventorySlotContents(y * 3 + x, stack == null ? ItemStack.EMPTY : stack.copy()); + } + } + } + + } + + public CompoundNBT getOrCreateRecipeCompound() { + CompoundNBT persistentData = getPersistentData(); + if (!persistentData.contains("Recipes")) + persistentData.put("Recipes", new CompoundNBT()); + return persistentData.getCompound("Recipes"); + } + + private Map sectionCache = new HashMap<>(); + + public BlueprintSection getSection(int index) { + return sectionCache.computeIfAbsent(index, i -> new BlueprintSection(i)); + } + + class BlueprintSection implements INamedContainerProvider { + int index; + Couple cachedDisplayItems; + public boolean inferredIcon = false; + + public BlueprintSection(int index) { + this.index = index; + } + + public Couple getDisplayItems() { + if (cachedDisplayItems != null) + return cachedDisplayItems; + ItemStackHandler items = getItems(); + return cachedDisplayItems = Couple.create(items.getStackInSlot(9), items.getStackInSlot(10)); + } + + public ItemStackHandler getItems() { + ItemStackHandler newInv = new ItemStackHandler(11); + CompoundNBT list = getOrCreateRecipeCompound(); + CompoundNBT invNBT = list.getCompound(index + ""); + inferredIcon = list.getBoolean("InferredIcon"); + if (!invNBT.isEmpty()) + newInv.deserializeNBT(invNBT); + return newInv; + } + + public void save(ItemStackHandler inventory) { + CompoundNBT list = getOrCreateRecipeCompound(); + list.put(index + "", inventory.serializeNBT()); + list.putBoolean("InferredIcon", inferredIcon); + cachedDisplayItems = null; + if (!world.isRemote) + syncPersistentDataWithTracking(BlueprintEntity.this); + } + + public boolean isEntityAlive() { + return isAlive(); + } + + public World getBlueprintWorld() { + return world; + } + + @Override + public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { + return BlueprintContainer.create(id, inv, this); + } + + @Override + public ITextComponent getDisplayName() { + return new TranslationTextComponent(AllItems.CRAFTING_BLUEPRINT.get() + .getTranslationKey()); + } + + } + + @Override + public void onPersistentDataUpdated() { + sectionCache.clear(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintItem.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintItem.java new file mode 100644 index 000000000..355df3b30 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintItem.java @@ -0,0 +1,154 @@ +package com.simibubi.create.content.curiosities.tools; + +import java.util.Collection; + +import com.simibubi.create.AllItems; +import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; +import com.simibubi.create.content.logistics.item.filter.FilterItem; +import com.simibubi.create.content.logistics.item.filter.ItemAttribute; + +import net.minecraft.entity.EntityType; +import net.minecraft.entity.item.HangingEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUseContext; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.item.crafting.Ingredient.IItemList; +import net.minecraft.item.crafting.Ingredient.SingleItemList; +import net.minecraft.item.crafting.Ingredient.TagList; +import net.minecraft.item.crafting.ShapedRecipe; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; +import net.minecraft.util.JSONUtils; +import net.minecraft.util.NonNullList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.common.crafting.StackList; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class BlueprintItem extends Item { + + public BlueprintItem(Properties p_i48487_1_) { + super(p_i48487_1_); + } + + @Override + public ActionResultType onItemUse(ItemUseContext ctx) { + Direction face = ctx.getFace(); + PlayerEntity player = ctx.getPlayer(); + ItemStack stack = ctx.getItem(); + BlockPos pos = ctx.getPos() + .offset(face); + + if (player != null && !player.canPlayerEdit(pos, face, stack)) + return ActionResultType.FAIL; + + World world = ctx.getWorld(); + HangingEntity hangingentity = new BlueprintEntity(world, pos, face, face.getAxis() + .isHorizontal() ? Direction.DOWN : ctx.getPlacementHorizontalFacing()); + CompoundNBT compoundnbt = stack.getTag(); + + if (compoundnbt != null) + EntityType.applyItemNBT(world, player, hangingentity, compoundnbt); + if (!hangingentity.onValidSurface()) + return ActionResultType.CONSUME; + if (!world.isRemote) { + hangingentity.playPlaceSound(); + world.addEntity(hangingentity); + } + + stack.shrink(1); + return ActionResultType.success(world.isRemote); + } + + protected boolean canPlace(PlayerEntity p_200127_1_, Direction p_200127_2_, ItemStack p_200127_3_, + BlockPos p_200127_4_) { + return p_200127_1_.canPlayerEdit(p_200127_4_, p_200127_2_, p_200127_3_); + } + + public static void assignCompleteRecipe(ItemStackHandler inv, IRecipe recipe) { + NonNullList ingredients = recipe.getIngredients(); + + for (int i = 0; i < 9; i++) + inv.setStackInSlot(i, ItemStack.EMPTY); + inv.setStackInSlot(9, recipe.getRecipeOutput()); + + if (recipe instanceof ShapedRecipe) { + ShapedRecipe shapedRecipe = (ShapedRecipe) recipe; + for (int row = 0; row < shapedRecipe.getHeight(); row++) + for (int col = 0; col < shapedRecipe.getWidth(); col++) + inv.setStackInSlot(row * 3 + col, + convertIngredientToFilter(ingredients.get(row * shapedRecipe.getWidth() + col))); + } else { + for (int i = 0; i < ingredients.size(); i++) + inv.setStackInSlot(i, convertIngredientToFilter(ingredients.get(i))); + } + } + + private static ItemStack convertIngredientToFilter(Ingredient ingredient) { + Ingredient.IItemList[] acceptedItems = + ObfuscationReflectionHelper.getPrivateValue(Ingredient.class, ingredient, "field_199807_b"); + if (acceptedItems == null || acceptedItems.length > 18) + return ItemStack.EMPTY; + if (acceptedItems.length == 0) + return ItemStack.EMPTY; + if (acceptedItems.length == 1) + return convertIItemListToFilter(acceptedItems[0]); + + ItemStack result = AllItems.FILTER.asStack(); + ItemStackHandler filterItems = FilterItem.getFilterItems(result); + for (int i = 0; i < acceptedItems.length; i++) + filterItems.setStackInSlot(i, convertIItemListToFilter(acceptedItems[i])); + result.getOrCreateTag() + .put("Items", filterItems.serializeNBT()); + return result; + } + + private static ItemStack convertIItemListToFilter(IItemList itemList) { + Collection stacks = itemList.getStacks(); + if (itemList instanceof SingleItemList) { + for (ItemStack itemStack : stacks) + return itemStack; + } + + if (itemList instanceof TagList) { + ResourceLocation resourcelocation = new ResourceLocation(JSONUtils.getString(itemList.serialize(), "tag")); + ItemStack filterItem = AllItems.ATTRIBUTE_FILTER.asStack(); + filterItem.getOrCreateTag() + .putInt("WhitelistMode", WhitelistMode.WHITELIST_DISJ.ordinal()); + ListNBT attributes = new ListNBT(); + ItemAttribute at = new ItemAttribute.InTag(resourcelocation); + CompoundNBT compoundNBT = new CompoundNBT(); + at.serializeNBT(compoundNBT); + compoundNBT.putBoolean("Inverted", false); + attributes.add(compoundNBT); + filterItem.getOrCreateTag() + .put("MatchedAttributes", attributes); + return filterItem; + } + + if (itemList instanceof StackList) { + ItemStack result = AllItems.FILTER.asStack(); + ItemStackHandler filterItems = FilterItem.getFilterItems(result); + int i = 0; + for (ItemStack itemStack : stacks) { + if (i >= 18) + break; + filterItems.setStackInSlot(i++, itemStack); + } + CompoundNBT tag = result.getOrCreateTag(); + tag.put("Items", filterItems.serializeNBT()); + tag.putBoolean("RespectNBT", true); + return result; + } + + return ItemStack.EMPTY; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java new file mode 100644 index 000000000..156ff11ae --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintOverlayRenderer.java @@ -0,0 +1,296 @@ +package com.simibubi.create.content.curiosities.tools; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintCraftingInventory; +import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; +import com.simibubi.create.content.logistics.item.filter.AttributeFilterContainer.WhitelistMode; +import com.simibubi.create.content.logistics.item.filter.FilterItem; +import com.simibubi.create.content.logistics.item.filter.ItemAttribute; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.Pair; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.inventory.CraftingInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.crafting.ICraftingRecipe; +import net.minecraft.item.crafting.IRecipeType; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.tags.ITag; +import net.minecraft.tags.TagCollectionManager; +import net.minecraft.util.math.EntityRayTraceResult; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.RayTraceResult.Type; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.common.util.Constants.NBT; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public class BlueprintOverlayRenderer { + + static boolean active; + static boolean empty; + static boolean lastSneakState; + static BlueprintSection lastTargetedSection; + + static Map cachedRenderedFilters = new IdentityHashMap<>(); + static List> ingredients = new ArrayList<>(); + static ItemStack result = ItemStack.EMPTY; + static boolean resultCraftable = false; + + public static void tick() { + Minecraft mc = Minecraft.getInstance(); + RayTraceResult mouseOver = mc.objectMouseOver; + BlueprintSection last = lastTargetedSection; + boolean sneak = mc.player.isSneaking(); + lastTargetedSection = null; + active = false; + if (mouseOver == null) + return; + if (mouseOver.getType() != Type.ENTITY) + return; + + EntityRayTraceResult entityRay = (EntityRayTraceResult) mouseOver; + if (!(entityRay.getEntity() instanceof BlueprintEntity)) + return; + + BlueprintEntity blueprintEntity = (BlueprintEntity) entityRay.getEntity(); + BlueprintSection sectionAt = blueprintEntity.getSectionAt(entityRay.getHitVec() + .subtract(blueprintEntity.getPositionVec())); + + lastTargetedSection = last; + active = true; + + if (sectionAt != lastTargetedSection || AnimationTickHolder.getTicks() % 10 == 0 || lastSneakState != sneak) + rebuild(sectionAt, sneak); + + lastTargetedSection = sectionAt; + lastSneakState = sneak; + } + + public static void rebuild(BlueprintSection sectionAt, boolean sneak) { + cachedRenderedFilters.clear(); + ItemStackHandler items = sectionAt.getItems(); + boolean empty = true; + for (int i = 0; i < 9; i++) { + if (!items.getStackInSlot(i) + .isEmpty()) { + empty = false; + break; + } + } + + BlueprintOverlayRenderer.empty = empty; + BlueprintOverlayRenderer.result = ItemStack.EMPTY; + + if (empty) + return; + + boolean firstPass = true; + boolean success = true; + Minecraft mc = Minecraft.getInstance(); + ItemStackHandler playerInv = new ItemStackHandler(mc.player.inventory.getSizeInventory()); + for (int i = 0; i < playerInv.getSlots(); i++) + playerInv.setStackInSlot(i, mc.player.inventory.getStackInSlot(i) + .copy()); + + int amountCrafted = 0; + Optional recipe = Optional.empty(); + Map craftingGrid = new HashMap<>(); + ingredients.clear(); + ItemStackHandler missingItems = new ItemStackHandler(64); + ItemStackHandler availableItems = new ItemStackHandler(64); + List newlyAdded = new ArrayList<>(); + List newlyMissing = new ArrayList<>(); + boolean invalid = false; + + do { + craftingGrid.clear(); + newlyAdded.clear(); + newlyMissing.clear(); + + Search: for (int i = 0; i < 9; i++) { + ItemStack requestedItem = items.getStackInSlot(i); + if (requestedItem.isEmpty()) { + craftingGrid.put(i, ItemStack.EMPTY); + continue; + } + + for (int slot = 0; slot < playerInv.getSlots(); slot++) { + if (!FilterItem.test(mc.world, playerInv.getStackInSlot(slot), requestedItem)) + continue; + ItemStack currentItem = playerInv.extractItem(slot, 1, false); + craftingGrid.put(i, currentItem); + newlyAdded.add(currentItem); + continue Search; + } + + success = false; + newlyMissing.add(requestedItem); + } + + if (success) { + CraftingInventory craftingInventory = new BlueprintCraftingInventory(craftingGrid); + if (!recipe.isPresent()) + recipe = mc.world.getRecipeManager() + .getRecipe(IRecipeType.CRAFTING, craftingInventory, mc.world); + ItemStack resultFromRecipe = recipe.filter(r -> r.matches(craftingInventory, mc.world)) + .map(r -> r.getCraftingResult(craftingInventory)) + .orElse(ItemStack.EMPTY); + + if (resultFromRecipe.isEmpty()) { + if (!recipe.isPresent()) + invalid = true; + success = false; + } else if (resultFromRecipe.getCount() + amountCrafted > 64) { + success = false; + } else { + amountCrafted += resultFromRecipe.getCount(); + if (result.isEmpty()) + result = resultFromRecipe.copy(); + else + result.grow(resultFromRecipe.getCount()); + resultCraftable = true; + firstPass = false; + } + } + + if (success || firstPass) { + newlyAdded.forEach(s -> ItemHandlerHelper.insertItemStacked(availableItems, s, false)); + newlyMissing.forEach(s -> ItemHandlerHelper.insertItemStacked(missingItems, s, false)); + } + + if (!success) { + if (firstPass) { + result = invalid ? ItemStack.EMPTY : items.getStackInSlot(9); + resultCraftable = false; + } + break; + } + + if (!sneak) + break; + + } while (success); + + for (int i = 0; i < 9; i++) { + ItemStack available = availableItems.getStackInSlot(i); + if (available.isEmpty()) + continue; + ingredients.add(Pair.of(available, true)); + } + for (int i = 0; i < 9; i++) { + ItemStack missing = missingItems.getStackInSlot(i); + if (missing.isEmpty()) + continue; + ingredients.add(Pair.of(missing, false)); + } + } + + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { + if (!active || empty) + return; + + Minecraft mc = Minecraft.getInstance(); + int w = 30 + 21 * ingredients.size() + 21; + + int x = (mc.getWindow() + .getScaledWidth() - w) / 2; + int y = (int) (mc.getWindow() + .getScaledHeight() / 3f * 2); + + for (Pair pair : ingredients) { + RenderSystem.enableBlend(); + (pair.getSecond() ? AllGuiTextures.HOTSLOT_ACTIVE : AllGuiTextures.HOTSLOT).draw(ms, x, y); + ItemStack itemStack = pair.getFirst(); + String count = pair.getSecond() || itemStack.getCount() == 1 ? null + : TextFormatting.GOLD.toString() + itemStack.getCount(); + drawItemStack(ms, mc, x, y, itemStack, count); + x += 21; + } + + x += 5; + RenderSystem.enableBlend(); + AllGuiTextures.HOTSLOT_ARROW.draw(ms, x, y + 4); + x += 25; + + if (result.isEmpty()) { + AllGuiTextures.HOTSLOT.draw(ms, x, y); + GuiGameElement.of(Items.BARRIER) + .at(x + 3, y + 3) + .render(ms); + } else { + (resultCraftable ? AllGuiTextures.HOTSLOT_SUPER_ACTIVE : AllGuiTextures.HOTSLOT).draw(ms, + resultCraftable ? x - 1 : x, resultCraftable ? y - 1 : y); + drawItemStack(ms, mc, x, y, result, null); + } + } + + public static void drawItemStack(MatrixStack ms, Minecraft mc, int x, int y, ItemStack itemStack, String count) { + if (itemStack.getItem() instanceof FilterItem) { + int step = AnimationTickHolder.getTicks(mc.world) / 10; + ItemStack[] itemsMatchingFilter = getItemsMatchingFilter(itemStack); + if (itemsMatchingFilter.length > 0) + itemStack = itemsMatchingFilter[step % itemsMatchingFilter.length]; + } + + GuiGameElement.of(itemStack) + .at(x + 3, y + 3) + .render(ms); + mc.getItemRenderer() + .renderItemOverlayIntoGUI(mc.fontRenderer, itemStack, x + 3, y + 3, count); + } + + private static ItemStack[] getItemsMatchingFilter(ItemStack filter) { + return cachedRenderedFilters.computeIfAbsent(filter, itemStack -> { + CompoundNBT tag = itemStack.getOrCreateTag(); + + if (AllItems.FILTER.isIn(itemStack) && !tag.getBoolean("Blacklist")) { + ItemStackHandler filterItems = FilterItem.getFilterItems(itemStack); + List list = new ArrayList<>(); + for (int slot = 0; slot < filterItems.getSlots(); slot++) { + ItemStack stackInSlot = filterItems.getStackInSlot(slot); + if (!stackInSlot.isEmpty()) + list.add(stackInSlot); + } + return list.toArray(new ItemStack[list.size()]); + } + + if (AllItems.ATTRIBUTE_FILTER.isIn(itemStack)) { + WhitelistMode whitelistMode = WhitelistMode.values()[tag.getInt("WhitelistMode")]; + ListNBT attributes = tag.getList("MatchedAttributes", NBT.TAG_COMPOUND); + if (whitelistMode == WhitelistMode.WHITELIST_DISJ && attributes.size() == 1) { + ItemAttribute fromNBT = ItemAttribute.fromNBT((CompoundNBT) attributes.get(0)); + if (fromNBT instanceof ItemAttribute.InTag) { + ItemAttribute.InTag inTag = (ItemAttribute.InTag) fromNBT; + ITag itag = TagCollectionManager.getTagManager() + .getItems() + .get(inTag.tagName); + if (itag != null) + return Ingredient.fromTag(itag) + .getMatchingStacks(); + } + } + } + + return new ItemStack[0]; + }); + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java new file mode 100644 index 000000000..f741eedce --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintRenderer.java @@ -0,0 +1,140 @@ +package com.simibubi.create.content.curiosities.tools; + +import com.jozufozu.flywheel.core.PartialModel; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.curiosities.tools.BlueprintEntity.BlueprintSection; +import com.simibubi.create.foundation.render.PartialBufferer; +import com.simibubi.create.foundation.render.SuperByteBuffer; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.MatrixStacker; + +import net.minecraft.block.Blocks; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererManager; +import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.inventory.container.PlayerContainer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix3f; + +public class BlueprintRenderer extends EntityRenderer { + + public BlueprintRenderer(EntityRendererManager p_i46179_1_) { + super(p_i46179_1_); + } + + @Override + public void render(BlueprintEntity entity, float yaw, float pt, MatrixStack ms, IRenderTypeBuffer buffer, + int overlay) { + PartialModel partialModel = entity.size == 3 ? AllBlockPartials.CRAFTING_BLUEPRINT_3x3 + : entity.size == 2 ? AllBlockPartials.CRAFTING_BLUEPRINT_2x2 : AllBlockPartials.CRAFTING_BLUEPRINT_1x1; + SuperByteBuffer sbb = PartialBufferer.get(partialModel, Blocks.AIR.getDefaultState()); + int light = WorldRenderer.getLightmapCoordinates(entity.world, entity.getBlockPos()); + sbb.matrixStacker() + .rotateY(-yaw) + .rotateX(90.0F + entity.rotationPitch) + .translate(-.5, -1 / 32f, -.5); + if (entity.size == 2) + sbb.translate(.5, 0, -.5); + + RenderType entitySolid = RenderType.getEntitySolid(PlayerContainer.BLOCK_ATLAS_TEXTURE); + sbb.asEntityModel() + .light(light) + .renderInto(ms, buffer.getBuffer(entitySolid)); + super.render(entity, yaw, pt, ms, buffer, light); + + ms.push(); + + float fakeNormalXRotation = -15; + int bl = light >> 4 & 0xf; + int sl = light >> 20 & 0xf; + boolean vertical = entity.rotationPitch != 0; + if (entity.rotationPitch == -90) + fakeNormalXRotation = -45; + else if (entity.rotationPitch == 90 || yaw % 180 != 0) { + bl /= 1.35; + sl /= 1.35; + } + int itemLight = MathHelper.floor(sl + .5) << 20 | (MathHelper.floor(bl + .5) & 0xf) << 4; + + MatrixStacker.of(ms) + .rotateY(vertical ? 0 : -yaw) + .rotateX(fakeNormalXRotation); + Matrix3f copy = ms.peek() + .getNormal() + .copy(); + + ms.pop(); + ms.push(); + + MatrixStacker.of(ms) + .rotateY(-yaw) + .rotateX(entity.rotationPitch) + .translate(0, 0, 1 / 32f + .001); + + if (entity.size == 3) + ms.translate(-1, -1, 0); + + MatrixStack squashedMS = new MatrixStack(); + squashedMS.peek() + .getModel() + .multiply(ms.peek() + .getModel()); + + for (int x = 0; x < entity.size; x++) { + squashedMS.push(); + for (int y = 0; y < entity.size; y++) { + BlueprintSection section = entity.getSection(x * entity.size + y); + Couple displayItems = section.getDisplayItems(); + squashedMS.push(); + squashedMS.scale(.5f, .5f, 1 / 1024f); + displayItems.forEachWithContext((stack, primary) -> { + if (stack.isEmpty()) + return; + + squashedMS.push(); + if (!primary) { + squashedMS.translate(0.325f, -0.325f, 1); + squashedMS.scale(.625f, .625f, 1); + } + + Matrix3f n = squashedMS.peek() + .getNormal(); + n.a00 = copy.a00; + n.a01 = copy.a01; + n.a02 = copy.a02; + n.a10 = copy.a10; + n.a11 = copy.a11; + n.a12 = copy.a12; + n.a20 = copy.a20; + n.a21 = copy.a21; + n.a22 = copy.a22; + + Minecraft.getInstance() + .getItemRenderer() + .renderItem(stack, TransformType.GUI, itemLight, OverlayTexture.DEFAULT_UV, squashedMS, buffer); + squashedMS.pop(); + }); + squashedMS.pop(); + squashedMS.translate(1, 0, 0); + } + squashedMS.pop(); + squashedMS.translate(0, 1, 0); + } + + ms.pop(); + } + + @Override + public ResourceLocation getEntityTexture(BlueprintEntity p_110775_1_) { + return null; + } + +} diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java new file mode 100644 index 000000000..a587a6b86 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/BlueprintScreen.java @@ -0,0 +1,193 @@ +package com.simibubi.create.content.curiosities.tools; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllBlockPartials; +import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; +import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket.Option; +import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.widgets.IconButton; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; + +public class BlueprintScreen extends AbstractSimiContainerScreen { + + protected AllGuiTextures background; + private List extraAreas = Collections.emptyList(); + + private IconButton resetButton; + private IconButton confirmButton; + + public BlueprintScreen(BlueprintContainer container, PlayerInventory inv, ITextComponent title) { + super(container, inv, title); + this.background = AllGuiTextures.BLUEPRINT; + } + + @Override + protected void init() { + setWindowSize(background.width, background.height + 4 + PLAYER_INVENTORY.height); + super.init(); + widgets.clear(); + + int x = guiLeft; + int y = guiTop; + + resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + + widgets.add(resetButton); + widgets.add(confirmButton); + + extraAreas = ImmutableList.of( + new Rectangle2d(x + background.width, guiTop + background.height - 36, 56, 44) + ); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int invLeft = guiLeft - windowXOffset + (xSize - PLAYER_INVENTORY.width) / 2; + int invTop = guiTop + background.height + 4; + + PLAYER_INVENTORY.draw(ms, this, invLeft, invTop); + textRenderer.draw(ms, playerInventory.getDisplayName(), invLeft + 8, invTop + 6, 0x404040); + + int x = guiLeft; + int y = guiTop; + + background.draw(ms, this, x, y); + textRenderer.draw(ms, title, x + 15, y + 4, 0xFFFFFF); + + GuiGameElement.of(AllBlockPartials.CRAFTING_BLUEPRINT_1x1) + .at(x + background.width + 20, guiTop + background.height - 32, 0) + .rotate(45, -45, 22.5f) + .scale(40) + .render(ms); + } + + @Override + protected void drawMouseoverTooltip(MatrixStack ms, int x, int y) { + if (!this.client.player.inventory.getItemStack() + .isEmpty() || this.hoveredSlot == null || this.hoveredSlot.getHasStack() + || hoveredSlot.inventory == container.playerInventory) { + super.drawMouseoverTooltip(ms, x, y); + return; + } + renderWrappedToolTip(ms, addToTooltip(new LinkedList<>(), hoveredSlot.getSlotIndex(), true), x, y, + textRenderer); + } + + @Override + public List getTooltipFromItem(ItemStack stack) { + List list = super.getTooltipFromItem(stack); + if (hoveredSlot.inventory == container.playerInventory) + return list; + return hoveredSlot != null ? addToTooltip(list, hoveredSlot.getSlotIndex(), false) : list; + } + + private List addToTooltip(List list, int slot, boolean isEmptySlot) { + if (slot < 0 || slot > 10) + return list; + + if (slot < 9) { + list.add(Lang.createTranslationTextComponent("crafting_blueprint.crafting_slot") + .formatted(TextFormatting.GOLD)); + if (isEmptySlot) + list.add(Lang.createTranslationTextComponent("crafting_blueprint.filter_items_viable") + .formatted(TextFormatting.GRAY)); + + } else if (slot == 9) { + list.add(Lang.createTranslationTextComponent("crafting_blueprint.display_slot") + .formatted(TextFormatting.GOLD)); + if (!isEmptySlot) + list.add(Lang + .createTranslationTextComponent("crafting_blueprint." + + (container.contentHolder.inferredIcon ? "inferred" : "manually_assigned")) + .formatted(TextFormatting.GRAY)); + + } else if (slot == 10) { + list.add(Lang.createTranslationTextComponent("crafting_blueprint.secondary_display_slot") + .formatted(TextFormatting.GOLD)); + if (isEmptySlot) + list.add(Lang.createTranslationTextComponent("crafting_blueprint.optional") + .formatted(TextFormatting.GRAY)); + } + + return list; + } + + @Override + public void tick() { +// handleTooltips(); + super.tick(); + + if (!container.contentHolder.isEntityAlive()) + client.player.closeScreen(); + } + +// protected void handleTooltips() { +// List tooltipButtons = getTooltipButtons(); +// +// for (IconButton button : tooltipButtons) { +// if (!button.getToolTip() +// .isEmpty()) { +// button.setToolTip(button.getToolTip() +// .get(0)); +// button.getToolTip() +// .add(TooltipHelper.holdShift(Palette.Yellow, hasShiftDown())); +// } +// } +// +// if (hasShiftDown()) { +// List tooltipDescriptions = getTooltipDescriptions(); +// for (int i = 0; i < tooltipButtons.size(); i++) +// fillToolTip(tooltipButtons.get(i), tooltipDescriptions.get(i)); +// } +// } + + @Override + public boolean mouseClicked(double x, double y, int button) { + boolean mouseClicked = super.mouseClicked(x, y, button); + + if (button == 0) { + if (confirmButton.isHovered()) { + client.player.closeScreen(); + return true; + } + if (resetButton.isHovered()) { + container.clearContents(); + contentsCleared(); + container.sendClearPacket(); + return true; + } + } + + return mouseClicked; + } + + protected void contentsCleared() {} + + protected void sendOptionUpdate(Option option) { + AllPackets.channel.sendToServer(new FilterScreenPacket(option)); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} 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 ecba3ded1..3b6a2acc6 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 @@ -37,6 +37,7 @@ import net.minecraftforge.event.entity.living.LivingAttackEvent; import net.minecraftforge.event.entity.living.LivingEvent.LivingUpdateEvent; import net.minecraftforge.event.entity.living.LivingKnockBackEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; @@ -62,17 +63,18 @@ public class ExtendoGripItem extends Item { public ExtendoGripItem(Properties properties) { super(properties.maxStackSize(1) - .rarity(Rarity.UNCOMMON)); + .rarity(Rarity.UNCOMMON)); } + public static final String EXTENDO_MARKER = "createExtendo"; + public static final String DUAL_EXTENDO_MARKER = "createDualExtendo"; + @SubscribeEvent public static void holdingExtendoGripIncreasesRange(LivingUpdateEvent event) { if (!(event.getEntity() instanceof PlayerEntity)) return; PlayerEntity player = (PlayerEntity) event.getEntityLiving(); - String marker = "createExtendo"; - String dualMarker = "createDualExtendo"; CompoundNBT persistentData = player.getPersistentData(); boolean inOff = AllItems.EXTENDO_GRIP.isIn(player.getHeldItemOffhand()); @@ -80,38 +82,49 @@ public class ExtendoGripItem extends Item { boolean holdingDualExtendo = inOff && inMain; boolean holdingExtendo = inOff ^ inMain; holdingExtendo &= !holdingDualExtendo; - boolean wasHoldingExtendo = persistentData.contains(marker); - boolean wasHoldingDualExtendo = persistentData.contains(dualMarker); + boolean wasHoldingExtendo = persistentData.contains(EXTENDO_MARKER); + boolean wasHoldingDualExtendo = persistentData.contains(DUAL_EXTENDO_MARKER); if (holdingExtendo != wasHoldingExtendo) { if (!holdingExtendo) { player.getAttributes().removeModifiers(rangeModifier.getValue()); - persistentData.remove(marker); + persistentData.remove(EXTENDO_MARKER); } else { if (player instanceof ServerPlayerEntity) AllTriggers.EXTENDO.trigger((ServerPlayerEntity) player); player.getAttributes() - .addTemporaryModifiers(rangeModifier.getValue()); - persistentData.putBoolean(marker, true); + .addTemporaryModifiers(rangeModifier.getValue()); + persistentData.putBoolean(EXTENDO_MARKER, true); } } if (holdingDualExtendo != wasHoldingDualExtendo) { if (!holdingDualExtendo) { player.getAttributes() - .removeModifiers(doubleRangeModifier.getValue()); - persistentData.remove(dualMarker); + .removeModifiers(doubleRangeModifier.getValue()); + persistentData.remove(DUAL_EXTENDO_MARKER); } else { if (player instanceof ServerPlayerEntity) AllTriggers.GIGA_EXTENDO.trigger((ServerPlayerEntity) player); player.getAttributes() - .addTemporaryModifiers(doubleRangeModifier.getValue()); - persistentData.putBoolean(dualMarker, true); + .addTemporaryModifiers(doubleRangeModifier.getValue()); + persistentData.putBoolean(DUAL_EXTENDO_MARKER, true); } } } + @SubscribeEvent + public static void addReachToJoiningPlayersHoldingExtendo(PlayerEvent.PlayerLoggedInEvent event) { + PlayerEntity player = event.getPlayer(); + CompoundNBT persistentData = player.getPersistentData(); + + if (persistentData.contains(DUAL_EXTENDO_MARKER)) + player.getAttributes().addTemporaryModifiers(doubleRangeModifier.getValue()); + else if (persistentData.contains(EXTENDO_MARKER)) + player.getAttributes().addTemporaryModifiers(rangeModifier.getValue()); + } + @SubscribeEvent @OnlyIn(Dist.CLIENT) public static void dontMissEntitiesWhenYouHaveHighReachDistance(ClickInputEvent event) { 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 2869afcea..c604eeb3a 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 @@ -2,8 +2,8 @@ package com.simibubi.create.content.curiosities.tools; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.PartialItemModelRenderer; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java index aa8718952..cd37439f5 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripModel.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.curiosities.tools; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java index 9177a0df2..17fadd6c2 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/tools/ExtendoGripRenderHandler.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.curiosities.tools; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllItems; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; 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 a5ce27abe..fca6a5c45 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 @@ -1,7 +1,7 @@ package com.simibubi.create.content.curiosities.tools; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java index 9904b6d39..db8beb57b 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/ZapperItemRenderer.java @@ -1,9 +1,9 @@ package com.simibubi.create.content.curiosities.zapper; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModelRenderer; -import com.simibubi.create.foundation.item.PartialItemModelRenderer; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import net.minecraft.block.BlockState; import net.minecraft.block.FourWayBlock; 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 f69316011..38d37a547 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 @@ -90,10 +90,10 @@ public class ZapperRenderHandler { return; cachedBeams.forEach(beam -> { - CreateClient.outliner.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity) - .disableNormals() - .colored(0xffffff) - .lineWidth(beam.itensity * 1 / 8f); + CreateClient.OUTLINER.endChasingLine(beam, beam.start, beam.end, 1 - beam.itensity) + .disableNormals() + .colored(0xffffff) + .lineWidth(beam.itensity * 1 / 8f); }); cachedBeams.forEach(b -> b.itensity *= .6f); diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java index 9c2369935..3b5886bab 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperItemRenderer.java @@ -5,7 +5,7 @@ import static net.minecraft.util.math.MathHelper.clamp; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.content.curiosities.zapper.ZapperItemRenderer; -import com.simibubi.create.foundation.item.PartialItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java index d28e0a2af..c27b76932 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperModel.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.curiosities.zapper.terrainzapper; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; diff --git a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java index 9edd53a8d..872bc9de7 100644 --- a/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java +++ b/src/main/java/com/simibubi/create/content/curiosities/zapper/terrainzapper/WorldshaperRenderHandler.java @@ -31,11 +31,11 @@ public class WorldshaperRenderHandler { if (renderedPositions == null) return; - CreateClient.outliner.showCluster("terrainZapper", renderedPositions.get()) - .colored(0xbfbfbf) - .disableNormals() - .lineWidth(1 / 32f) - .withFaceTexture(AllSpecialTextures.CHECKERED); + CreateClient.OUTLINER.showCluster("terrainZapper", renderedPositions.get()) + .colored(0xbfbfbf) + .disableNormals() + .lineWidth(1 / 32f) + .withFaceTexture(AllSpecialTextures.CHECKERED); } protected static void gatherSelectedBlocks() { diff --git a/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java new file mode 100644 index 000000000..34286e6f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/IRedstoneLinkable.java @@ -0,0 +1,23 @@ +package com.simibubi.create.content.logistics; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; + +import net.minecraft.util.math.BlockPos; + +public interface IRedstoneLinkable { + + public int getTransmittedStrength(); + + public void setReceivedStrength(int power); + + public boolean isListening(); + + public boolean isAlive(); + + public Pair getNetworkKey(); + + public BlockPos getLocation(); + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java b/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java index 910ef68d1..38ab8b08c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/RedstoneLinkNetworkHandler.java @@ -18,11 +18,11 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.world.IWorld; -import net.minecraft.world.World; public class RedstoneLinkNetworkHandler { - static final Map, Set>> connections = new IdentityHashMap<>(); + static final Map, Set>> connections = + new IdentityHashMap<>(); public static class Frequency { public static final Frequency EMPTY = new Frequency(ItemStack.EMPTY); @@ -60,60 +60,55 @@ public class RedstoneLinkNetworkHandler { if (this == obj) return true; return obj instanceof Frequency ? ((Frequency) obj).item == item && ((Frequency) obj).color == color - : false; + : false; } } public void onLoadWorld(IWorld world) { connections.put(world, new HashMap<>()); - Create.logger.debug("Prepared Redstone Network Space for " + WorldHelper.getDimensionID(world)); + Create.LOGGER.debug("Prepared Redstone Network Space for " + WorldHelper.getDimensionID(world)); } public void onUnloadWorld(IWorld world) { connections.remove(world); - Create.logger.debug("Removed Redstone Network Space for " + WorldHelper.getDimensionID(world)); + Create.LOGGER.debug("Removed Redstone Network Space for " + WorldHelper.getDimensionID(world)); } - public Set getNetworkOf(LinkBehaviour actor) { - Map, Set> networksInWorld = networksIn(actor.getWorld()); + public Set getNetworkOf(IWorld world, IRedstoneLinkable actor) { + Map, Set> networksInWorld = networksIn(world); Pair key = actor.getNetworkKey(); if (!networksInWorld.containsKey(key)) networksInWorld.put(key, new LinkedHashSet<>()); return networksInWorld.get(key); } - public void addToNetwork(LinkBehaviour actor) { - getNetworkOf(actor).add(actor); - updateNetworkOf(actor); + public void addToNetwork(IWorld world, IRedstoneLinkable actor) { + getNetworkOf(world, actor).add(actor); + updateNetworkOf(world, actor); } - public void removeFromNetwork(LinkBehaviour actor) { - Set network = getNetworkOf(actor); + public void removeFromNetwork(IWorld world, IRedstoneLinkable actor) { + Set network = getNetworkOf(world, actor); network.remove(actor); if (network.isEmpty()) { - networksIn(actor.getWorld()).remove(actor.getNetworkKey()); + networksIn(world).remove(actor.getNetworkKey()); return; } - updateNetworkOf(actor); + updateNetworkOf(world, actor); } - public void updateNetworkOf(LinkBehaviour actor) { - Set network = getNetworkOf(actor); + public void updateNetworkOf(IWorld world, IRedstoneLinkable actor) { + Set network = getNetworkOf(world, actor); int power = 0; - for (Iterator iterator = network.iterator(); iterator.hasNext();) { - LinkBehaviour other = iterator.next(); - if (other.tileEntity.isRemoved()) { + for (Iterator iterator = network.iterator(); iterator.hasNext();) { + IRedstoneLinkable other = iterator.next(); + if (!other.isAlive()) { iterator.remove(); continue; } - World world = actor.getWorld(); - if (!world.isBlockPresent(other.tileEntity.getPos())) { - iterator.remove(); - continue; - } - if (world.getTileEntity(other.tileEntity.getPos()) != other.tileEntity) { + if (!world.isAreaLoaded(other.getLocation(), 0)) { iterator.remove(); continue; } @@ -124,28 +119,31 @@ public class RedstoneLinkNetworkHandler { power = Math.max(other.getTransmittedStrength(), power); } - // fix one-to-one loading order problem - if (actor.isListening()) { - actor.newPosition = true; - actor.updateReceiver(power); + if (actor instanceof LinkBehaviour) { + LinkBehaviour linkBehaviour = (LinkBehaviour) actor; + // fix one-to-one loading order problem + if (linkBehaviour.isListening()) { + linkBehaviour.newPosition = true; + linkBehaviour.setReceivedStrength(power); + } } - for (LinkBehaviour other : network) { + for (IRedstoneLinkable other : network) { if (other != actor && other.isListening() && withinRange(actor, other)) - other.updateReceiver(power); + other.setReceivedStrength(power); } } - public static boolean withinRange(LinkBehaviour from, LinkBehaviour to) { + public static boolean withinRange(IRedstoneLinkable from, IRedstoneLinkable to) { if (from == to) return true; - return from.getPos().withinDistance(to.getPos(), AllConfigs.SERVER.logistics.linkRange.get()); + return from.getLocation() + .withinDistance(to.getLocation(), AllConfigs.SERVER.logistics.linkRange.get()); } - public Map, Set> networksIn(IWorld world) { + public Map, Set> networksIn(IWorld world) { if (!connections.containsKey(world)) { - Create.logger.warn( - "Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world)); + Create.LOGGER.warn("Tried to Access unprepared network space of " + WorldHelper.getDimensionID(world)); return new HashMap<>(); } return connections.get(world); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapAttributes.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapAttributes.java deleted file mode 100644 index 71a8db0af..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/FlapAttributes.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.simibubi.create.content.logistics.block; - -import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; -import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; - -public enum FlapAttributes implements IVertexAttrib { - INSTANCE_POSITION("aInstancePos",CommonAttributes.VEC3), - LIGHT("aLight", CommonAttributes.LIGHT), - SEGMENT_OFFSET("aSegmentOffset", CommonAttributes.VEC3), - PIVOT("aPivot", CommonAttributes.VEC3), - HORIZONTAL_ANGLE("aHorizontalAngle", CommonAttributes.FLOAT), - INTENSITY("aIntensity", CommonAttributes.FLOAT), - FLAP_SCALE("aFlapScale", CommonAttributes.FLOAT), - FLAPNESS("aFlapness", CommonAttributes.FLOAT), - ; - - private final String name; - private final VertexAttribSpec spec; - - FlapAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 1; - } - - @Override - public int getBufferIndex() { - return 1; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java index 2a91a9e94..73ca73d70 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/FlapData.java @@ -1,13 +1,13 @@ package com.simibubi.create.content.logistics.block; -import java.nio.ByteBuffer; - -import com.simibubi.create.foundation.render.backend.core.IFlatLight; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.core.materials.IFlatLight; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3f; +import net.minecraft.util.math.vector.Vector3i; public class FlapData extends InstanceData implements IFlatLight { @@ -31,7 +31,7 @@ public class FlapData extends InstanceData implements IFlatLight { private float flapness; - public FlapData(InstancedModel owner) { + public FlapData(Instancer owner) { super(owner); } @@ -44,7 +44,7 @@ public class FlapData extends InstanceData implements IFlatLight { } public FlapData setPosition(int x, int y, int z) { - BlockPos origin = owner.renderer.getOriginCoordinate(); + Vector3i origin = owner.originCoordinate.get(); return setPosition((float) (x - origin.getX()), (float) (y - origin.getY()), @@ -114,17 +114,17 @@ public class FlapData extends InstanceData implements IFlatLight { } @Override - public void write(ByteBuffer buf) { - putVec3(buf, x, y, z); - putVec2(buf, blockLight, skyLight); + public void write(MappedBuffer buf) { + buf.putVec3(x, y, z); + buf.putVec2(blockLight, skyLight); - putVec3(buf, segmentOffsetX, segmentOffsetY, segmentOffsetZ); - putVec3(buf, pivotX, pivotY, pivotZ); + buf.putVec3(segmentOffsetX, segmentOffsetY, segmentOffsetZ); + buf.putVec3(pivotX, pivotY, pivotZ); - put(buf, horizontalAngle); - put(buf, intensity); - put(buf, flapScale); + buf.putFloat(horizontalAngle); + buf.putFloat(intensity); + buf.putFloat(flapScale); - put(buf, flapness); + buf.putFloat(flapness); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/FlapModel.java b/src/main/java/com/simibubi/create/content/logistics/block/FlapModel.java deleted file mode 100644 index 7a6a00f14..000000000 --- a/src/main/java/com/simibubi/create/content/logistics/block/FlapModel.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.content.logistics.block; - -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexFormat; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; - -import net.minecraft.client.renderer.BufferBuilder; - -public class FlapModel extends InstancedModel { - public static VertexFormat FORMAT = VertexFormat.builder() - .addAttributes(FlapAttributes.class) - .build(); - - public FlapModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected FlapData newInstance() { - return new FlapData(this); - } - - @Override - protected VertexFormat getInstanceFormat() { - return FORMAT; - } -} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java index 81793455e..e40dfdff0 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelInstance.java @@ -5,15 +5,15 @@ import java.util.Collection; import java.util.EnumMap; import java.util.Map; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; import com.simibubi.create.content.logistics.block.FlapData; import com.simibubi.create.foundation.gui.widgets.InterpolatedValue; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; +import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Direction; @@ -23,13 +23,13 @@ public class BeltTunnelInstance extends TileEntityInstance private final Map> tunnelFlaps; - public BeltTunnelInstance(InstancedTileRenderer modelManager, BeltTunnelTileEntity tile) { + public BeltTunnelInstance(MaterialManager modelManager, BeltTunnelTileEntity tile) { super(modelManager, tile); tunnelFlaps = new EnumMap<>(Direction.class); - InstancedModel model = modelManager.getMaterial(KineticRenderMaterials.FLAPS) - .getModel(AllBlockPartials.BELT_TUNNEL_FLAP, blockState); + Instancer model = modelManager.getMaterial(AllMaterialSpecs.FLAPS) + .getModel(AllBlockPartials.BELT_TUNNEL_FLAP, blockState); int blockLight = world.getLightLevel(LightType.BLOCK, pos); int skyLight = world.getLightLevel(LightType.SKY, pos); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java index 49252ec37..920d64259 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelRenderer.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.logistics.block.belts.tunnel; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.render.PartialBufferer; 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.AngleHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -31,7 +31,7 @@ public class BeltTunnelRenderer extends SmartTileEntityRenderer flaps; public Set sides; - + protected LazyOptional cap = LazyOptional.empty(); protected List> flapsToSend; @@ -67,12 +67,12 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe for (Direction direction : flaps.keySet()) flapsNBT.add(IntNBT.of(direction.getIndex())); compound.put("Flaps", flapsNBT); - + ListNBT sidesNBT = new ListNBT(); for (Direction direction : sides) sidesNBT.add(IntNBT.of(direction.getIndex())); compound.put("Sides", sidesNBT); - + super.write(compound, clientPacket); } @@ -83,7 +83,7 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe for (INBT inbt : flapsNBT) if (inbt instanceof IntNBT) newFlaps.add(Direction.byIndex(((IntNBT) inbt).getInt())); - + sides.clear(); ListNBT sidesNBT = compound.getList("Sides", NBT.TAG_INT); for (INBT inbt : sidesNBT) @@ -97,13 +97,13 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe flaps.put(d, new InterpolatedChasingValue().start(.25f) .target(0) .withSpeed(.05f)); - + // Backwards compat if (!compound.contains("Sides") && compound.contains("Flaps")) sides.addAll(flaps.keySet()); super.fromTag(state, compound, clientPacket); if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } public void updateTunnelConnections() { @@ -122,9 +122,9 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe if (!positive && shape == Shape.T_RIGHT) continue; } - + sides.add(direction); - + // Flap might be occluded BlockState nextState = world.getBlockState(pos.offset(direction)); if (nextState.getBlock() instanceof BeltTunnelBlock) @@ -176,10 +176,10 @@ public class BeltTunnelTileEntity extends SmartTileEntity implements IInstanceRe } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } - + @Override public void addBehaviours(List behaviours) {} diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java index 60970e62d..34e2a3976 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/chute/AbstractChuteBlock.java @@ -200,24 +200,18 @@ public abstract class AbstractChuteBlock extends Block implements IWrenchable, I public ActionResultType onUse(BlockState p_225533_1_, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult p_225533_6_) { if (!player.getHeldItem(hand) - .isEmpty()) + .isEmpty()) return ActionResultType.PASS; if (world.isRemote) return ActionResultType.SUCCESS; - try { - ChuteTileEntity te = getTileEntity(world, pos); - if (te == null) - return ActionResultType.PASS; + + return onTileEntityUse(world, pos, te -> { if (te.item.isEmpty()) return ActionResultType.PASS; player.inventory.placeItemBackInInventory(world, te.item); te.setItem(ItemStack.EMPTY); return ActionResultType.SUCCESS; - - } catch (TileEntityException e) { - e.printStackTrace(); - } - return ActionResultType.PASS; + }); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java index 701ca4566..63e776d3c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/chute/ChuteTileEntity.java @@ -313,12 +313,12 @@ public class ChuteTileEntity extends SmartTileEntity implements IHaveGoggleInfor return; AirParticleData airParticleData = new AirParticleData(drag, motion); Vector3d origin = Vector3d.of(pos); - float xOff = Create.random.nextFloat() * .5f + .25f; - float zOff = Create.random.nextFloat() * .5f + .25f; + float xOff = Create.RANDOM.nextFloat() * .5f + .25f; + float zOff = Create.RANDOM.nextFloat() * .5f + .25f; Vector3d v = origin.add(xOff, verticalStart, zOff); Vector3d d = origin.add(xOff, verticalEnd, zOff) - .subtract(v); - if (Create.random.nextFloat() < 2 * motion) + .subtract(v); + if (Create.RANDOM.nextFloat() < 2 * motion) world.addOptionalParticle(airParticleData, v.x, v.y, v.z, d.x, d.y, d.z); } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java index 02748a50d..ecac9759c 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/DepotBehaviour.java @@ -11,6 +11,7 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.relays.belt.BeltHelper; import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack; import com.simibubi.create.content.logistics.block.funnel.AbstractFunnelBlock; +import com.simibubi.create.foundation.item.ItemHelper; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; @@ -86,7 +87,7 @@ public class DepotBehaviour extends TileEntityBehaviour { if (heldItem == null) { heldItem = ts; } else { - if (!ItemHandlerHelper.canItemStacksStack(heldItem.stack, ts.stack)) { + if (!ItemHelper.canItemStackAmountsStack(heldItem.stack, ts.stack)) { Vector3d vec = VecHelper.getCenterOf(tileEntity.getPos()); InventoryHelper.spawnItemStack(tileEntity.getWorld(), vec.x, vec.y + .5f, vec.z, ts.stack); } else { @@ -250,7 +251,7 @@ public class DepotBehaviour extends TileEntityBehaviour { ItemStack inserted = heldItem.stack; if (remainingSpace <= 0) return inserted; - if (this.heldItem != null && !ItemHandlerHelper.canItemStacksStack(this.heldItem.stack, inserted)) + if (this.heldItem != null && !ItemHelper.canItemStackAmountsStack(this.heldItem.stack, inserted)) return inserted; ItemStack returned = ItemStack.EMPTY; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java index ad44cb651..8fc2a0883 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorInstance.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.logistics.block.depot; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.relays.encased.ShaftInstance; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -19,7 +19,7 @@ public class EjectorInstance extends ShaftInstance implements IDynamicInstance { private float lastProgress = Float.NaN; - public EjectorInstance(InstancedTileRenderer dispatcher, EjectorTileEntity tile) { + public EjectorInstance(MaterialManager dispatcher, EjectorTileEntity tile) { super(dispatcher, tile); this.tile = tile; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java index ddb028c7a..1ddf7bfa7 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorRenderer.java @@ -1,5 +1,6 @@ package com.simibubi.create.content.logistics.block.depot; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -7,7 +8,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.IntAttached; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -45,7 +45,7 @@ public class EjectorRenderer extends KineticTileEntityRenderer { float lidProgress = ((EjectorTileEntity) te).getLidProgress(partialTicks); float angle = lidProgress * 70; - if (!FastRenderDispatcher.available(te.getWorld())) { + if (!Backend.getInstance().canUseInstancing(te.getWorld())) { SuperByteBuffer model = PartialBufferer.get(AllBlockPartials.EJECTOR_TOP, te.getBlockState()); applyLidAngle(te, angle, model.matrixStacker()); model.light(light) @@ -55,7 +55,7 @@ public class EjectorRenderer extends KineticTileEntityRenderer { MatrixStacker msr = MatrixStacker.of(ms); float maxTime = - (float) (ejector.earlyTarget != null ? ejector.earlyTargetTime : ejector.launcher.getTotalFlyingTicks()); + (float) (ejector.earlyTarget != null ? ejector.earlyTargetTime : ejector.launcher.getTotalFlyingTicks()); for (IntAttached intAttached : ejector.launchedItems) { float time = intAttached.getFirst() + partialTicks; if (time > maxTime) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java index db730fdc6..6fc1c45fc 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTargetHandler.java @@ -210,14 +210,14 @@ public class EjectorTargetHandler { ClientWorld world = mc.world; AxisAlignedBB bb = new AxisAlignedBB(0, 0, 0, 1, 0, 1).offset(currentSelection.add(-validX, -yDiff, -validZ)); - CreateClient.outliner.chaseAABB("valid", bb) - .colored(intColor) - .lineWidth(1 / 16f); + CreateClient.OUTLINER.chaseAABB("valid", bb) + .colored(intColor) + .lineWidth(1 / 16f); for (int i = 0; i < segments; i++) { double ticks = ((AnimationTickHolder.getRenderTime() / 3) % tickOffset) + i * tickOffset; Vector3d vec = launcher.getGlobalPos(ticks, d, pos) - .add(xDiff - validX, 0, zDiff - validZ); + .add(xDiff - validX, 0, zDiff - validZ); world.addParticle(data, vec.x, vec.y, vec.z, 0, 0, 0); } } @@ -260,9 +260,9 @@ public class EjectorTargetHandler { BlockState state = world.getBlockState(pos); VoxelShape shape = state.getShape(world, pos); AxisAlignedBB boundingBox = shape.isEmpty() ? new AxisAlignedBB(BlockPos.ZERO) : shape.getBoundingBox(); - CreateClient.outliner.showAABB("target", boundingBox.offset(pos)) - .colored(0xffcb74) - .lineWidth(1 / 16f); + CreateClient.OUTLINER.showAABB("target", boundingBox.offset(pos)) + .colored(0xffcb74) + .lineWidth(1 / 16f); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java index 5188e1ab0..e99dfe741 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/EjectorTileEntity.java @@ -482,13 +482,20 @@ public class EjectorTileEntity extends KineticTileEntity { } } + @Override + public void writeSafe(CompoundNBT compound, boolean clientPacket) { + super.writeSafe(compound, clientPacket); + compound.putInt("HorizontalDistance", launcher.getHorizontalDistance()); + compound.putInt("VerticalDistance", launcher.getVerticalDistance()); + } + @Override protected void fromTag(BlockState blockState, CompoundNBT compound, boolean clientPacket) { super.fromTag(blockState, compound, clientPacket); int horizontalDistance = compound.getInt("HorizontalDistance"); int verticalDistance = compound.getInt("VerticalDistance"); - if (launcher == null || launcher.getHorizontalDistance() != horizontalDistance + if (launcher.getHorizontalDistance() != horizontalDistance || launcher.getVerticalDistance() != verticalDistance) { launcher.set(horizontalDistance, verticalDistance); launcher.clamp(AllConfigs.SERVER.kinetics.maxEjectorDistance.get()); @@ -542,7 +549,7 @@ public class EjectorTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java b/src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java index 7470f7703..55ba80aad 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/depot/SharedDepotBlockMethods.java @@ -53,7 +53,7 @@ public class SharedDepotBlockMethods { player.inventory.placeItemBackInInventory(world, mainItemStack); behaviour.removeHeldItem(); world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, .2f, - 1f + Create.random.nextFloat()); + 1f + Create.RANDOM.nextFloat()); } ItemStackHandler outputs = behaviour.processingOutputBuffer; for (int i = 0; i < outputs.getSlots(); i++) diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java index 4bef959ea..4d278d0b5 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterInstance.java @@ -1,11 +1,11 @@ package com.simibubi.create.content.logistics.block.diodes; +import com.jozufozu.flywheel.backend.instancing.ITickableInstance; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.ITickableInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -15,7 +15,7 @@ public class AdjustableRepeaterInstance extends TileEntityInstance modelManager, AdjustableRepeaterTileEntity tile) { + public AdjustableRepeaterInstance(MaterialManager modelManager, AdjustableRepeaterTileEntity tile) { super(modelManager, tile); indicator = modelManager.getTransformMaterial().getModel(AllBlockPartials.FLEXPEATER_INDICATOR, blockState).createInstance(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java index 363daea76..c678c6085 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/diodes/AdjustableRepeaterTileEntity.java @@ -5,7 +5,7 @@ import static net.minecraft.block.RedstoneDiodeBlock.POWERED; import java.util.List; -import com.simibubi.create.foundation.render.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueBehaviour; @@ -36,10 +36,10 @@ public class AdjustableRepeaterTileEntity extends SmartTileEntity implements IIn maxState.withFormatter(this::format); maxState.withUnit(this::getUnit); maxState.withCallback(this::onMaxDelayChanged); - + behaviours.add(maxState); } - + private void onMaxDelayChanged(int newMax) { state = MathHelper.clamp(state, 0, newMax); sendData(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java index 839053db0..56de5730e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/BeltFunnelBlock.java @@ -22,6 +22,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; import net.minecraft.state.EnumProperty; import net.minecraft.state.StateContainer.Builder; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ActionResultType; import net.minecraft.util.Direction; import net.minecraft.util.IStringSerializable; @@ -192,8 +193,8 @@ public class BeltFunnelBlock extends AbstractHorizontalFunnelBlock implements IS } @Override - public ItemRequirement getRequiredItems(BlockState state) { - return ItemRequirement.of(parent.getDefaultState()); + public ItemRequirement getRequiredItems(BlockState state, TileEntity te) { + return ItemRequirement.of(parent.getDefaultState(), te); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java index 16090ddbd..26a975859 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelInstance.java @@ -2,15 +2,15 @@ package com.simibubi.create.content.logistics.block.funnel; import java.util.ArrayList; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.core.PartialModel; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.content.contraptions.base.KineticRenderMaterials; import com.simibubi.create.content.logistics.block.FlapData; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; +import com.simibubi.create.foundation.render.AllMaterialSpecs; import com.simibubi.create.foundation.utility.AnimationTickHolder; import net.minecraft.util.Direction; @@ -20,17 +20,17 @@ public class FunnelInstance extends TileEntityInstance impleme private final ArrayList flaps; - public FunnelInstance(InstancedTileRenderer modelManager, FunnelTileEntity tile) { + public FunnelInstance(MaterialManager modelManager, FunnelTileEntity tile) { super(modelManager, tile); flaps = new ArrayList<>(4); if (!tile.hasFlap()) return; - PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP - : AllBlockPartials.BELT_FUNNEL_FLAP); - InstancedModel model = modelManager.getMaterial(KineticRenderMaterials.FLAPS) - .getModel(flapPartial, blockState); + PartialModel flapPartial = (blockState.getBlock() instanceof FunnelBlock ? AllBlockPartials.FUNNEL_FLAP + : AllBlockPartials.BELT_FUNNEL_FLAP); + Instancer model = modelManager.getMaterial(AllMaterialSpecs.FLAPS) + .getModel(flapPartial, blockState); int blockLight = world.getLightLevel(LightType.BLOCK, pos); int skyLight = world.getLightLevel(LightType.SKY, pos); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java index 87d762e51..7416c18ba 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelRenderer.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.logistics.block.funnel; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.renderer.SmartTileEntityRenderer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -30,7 +30,7 @@ public class FunnelRenderer extends SmartTileEntityRenderer { int light, int overlay) { super.renderSafe(te, partialTicks, ms, buffer, light, overlay); - if (!te.hasFlap() || FastRenderDispatcher.available(te.getWorld())) + if (!te.hasFlap() || Backend.getInstance().canUseInstancing(te.getWorld())) return; BlockState blockState = te.getBlockState(); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java index 02464be74..116d74468 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/funnel/FunnelTileEntity.java @@ -3,6 +3,8 @@ package com.simibubi.create.content.logistics.block.funnel; import java.lang.ref.WeakReference; import java.util.List; +import com.jozufozu.flywheel.backend.instancing.IInstanceRendered; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllSoundEvents; import com.simibubi.create.content.contraptions.goggles.IHaveHoveringInformation; @@ -14,8 +16,6 @@ import com.simibubi.create.content.logistics.packet.FunnelFlapPacket; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.gui.widgets.InterpolatedChasingValue; import com.simibubi.create.foundation.networking.AllPackets; -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.tileEntity.behaviour.belt.DirectBeltInputBehaviour; @@ -327,7 +327,7 @@ public class FunnelTileEntity extends SmartTileEntity implements IHaveHoveringIn extractionCooldown = compound.getInt("TransferCooldown"); if (clientPacket) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> FastRenderDispatcher.enqueueUpdate(this)); + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> InstancedRenderDispatcher.enqueueUpdate(this)); } @Override @@ -341,7 +341,7 @@ public class FunnelTileEntity extends SmartTileEntity implements IHaveHoveringIn } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateContainer.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateContainer.java index 5b7db777c..eeb7cc22b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateContainer.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateContainer.java @@ -7,6 +7,7 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; @@ -19,8 +20,8 @@ public class AdjustableCrateContainer extends Container { public PlayerInventory playerInventory; public boolean doubleCrate; - public AdjustableCrateContainer(int id, PlayerInventory inv, PacketBuffer extraData) { - super(AllContainerTypes.FLEXCRATE.type, id); + public AdjustableCrateContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id); ClientWorld world = Minecraft.getInstance().world; TileEntity tileEntity = world.getTileEntity(extraData.readBlockPos()); this.playerInventory = inv; @@ -31,16 +32,20 @@ public class AdjustableCrateContainer extends Container { } } - public AdjustableCrateContainer(int id, PlayerInventory inv, AdjustableCrateTileEntity te) { - super(AllContainerTypes.FLEXCRATE.type, id); + public AdjustableCrateContainer(ContainerType type, int id, PlayerInventory inv, AdjustableCrateTileEntity te) { + super(type, id); this.te = te; this.playerInventory = inv; init(); } + public static AdjustableCrateContainer create(int id, PlayerInventory inv, AdjustableCrateTileEntity te) { + return new AdjustableCrateContainer(AllContainerTypes.FLEXCRATE.get(), id, inv, te); + } + private void init() { doubleCrate = te.isDoubleCrate(); - int x = doubleCrate ? 51 : 123; + int x = doubleCrate ? 23 : 53; int maxCol = doubleCrate ? 8 : 4; for (int row = 0; row < 4; ++row) { for (int col = 0; col < maxCol; ++col) { @@ -49,8 +54,8 @@ public class AdjustableCrateContainer extends Container { } // player Slots - int xOffset = 58; - int yOffset = 155; + int xOffset = doubleCrate ? 20 : 8; + int yOffset = 149; for (int row = 0; row < 3; ++row) { for (int col = 0; col < 9; ++col) { this.addSlot(new Slot(playerInventory, col + row * 9 + 9, xOffset + col * 18, yOffset + row * 18)); diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateScreen.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateScreen.java index d8e532662..6004c3c5e 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateScreen.java @@ -4,9 +4,10 @@ import static com.simibubi.create.foundation.gui.AllGuiTextures.ADJUSTABLE_CRATE import static com.simibubi.create.foundation.gui.AllGuiTextures.ADJUSTABLE_DOUBLE_CRATE; import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket; @@ -26,32 +27,45 @@ import net.minecraft.util.text.StringTextComponent; public class AdjustableCrateScreen extends AbstractSimiContainerScreen { + protected AllGuiTextures background; + private List extraAreas = Collections.emptyList(); + private AdjustableCrateTileEntity te; private Label allowedItemsLabel; private ScrollInput allowedItems; private int lastModification; - private List extraAreas; + private int itemLabelOffset; + private int textureXShift; + private int itemYShift; private final ItemStack renderedItem = AllBlocks.ADJUSTABLE_CRATE.asStack(); - private final ITextComponent title = Lang.translate("gui.adjustable_crate.title"); private final ITextComponent storageSpace = Lang.translate("gui.adjustable_crate.storageSpace"); public AdjustableCrateScreen(AdjustableCrateContainer container, PlayerInventory inv, ITextComponent title) { super(container, inv, title); te = container.te; lastModification = -1; + background = container.doubleCrate ? ADJUSTABLE_DOUBLE_CRATE : ADJUSTABLE_CRATE; } @Override protected void init() { - setWindowSize(PLAYER_INVENTORY.width + 100, ADJUSTABLE_CRATE.height + PLAYER_INVENTORY.height + 20); + setWindowSize(Math.max(background.width, PLAYER_INVENTORY.width), background.height + 4 + PLAYER_INVENTORY.height); + setWindowOffset(container.doubleCrate ? -2 : 0, 0); super.init(); widgets.clear(); - allowedItemsLabel = new Label(guiLeft + 100 + 69, guiTop + 108, StringTextComponent.EMPTY).colored(0xfefefe) + itemLabelOffset = container.doubleCrate ? 137 : 65; + textureXShift = container.doubleCrate ? 0 : (xSize - (background.width - 8)) / 2; + itemYShift = container.doubleCrate ? 0 : -16; + + int crateLeft = guiLeft + textureXShift; + int crateTop = guiTop; + + allowedItemsLabel = new Label(crateLeft + itemLabelOffset + 4, crateTop + 108, StringTextComponent.EMPTY).colored(0xFFFFFF) .withShadow(); - allowedItems = new ScrollInput(guiLeft + 100 + 65, guiTop + 104, 41, 14).titled(storageSpace.copy()) + allowedItems = new ScrollInput(crateLeft + itemLabelOffset, crateTop + 104, 41, 16).titled(storageSpace.copy()) .withRange(1, (container.doubleCrate ? 2049 : 1025)) .writingTo(allowedItemsLabel) .withShiftStep(64) @@ -61,31 +75,27 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreen(); - extraAreas.add(new Rectangle2d(guiLeft + ADJUSTABLE_CRATE.width + 110, guiTop + 46, 71, 70)); + extraAreas = ImmutableList.of( + new Rectangle2d(crateLeft + background.width, crateTop + background.height - 56 + itemYShift, 80, 80) + ); } @Override - protected void renderWindow(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { - int crateLeft = guiLeft + 100; + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int invLeft = guiLeft - windowXOffset + (xSize - AllGuiTextures.PLAYER_INVENTORY.width) / 2; + int invTop = guiTop + background.height + 4; + + PLAYER_INVENTORY.draw(ms, this, invLeft, invTop); + textRenderer.draw(ms, playerInventory.getDisplayName(), invLeft + 8, invTop + 6, 0x404040); + + int crateLeft = guiLeft + textureXShift; int crateTop = guiTop; - int invLeft = guiLeft + 50; - int invTop = crateTop + ADJUSTABLE_CRATE.height + 10; - int fontColor = 0x4B3A22; - if (container.doubleCrate) { - crateLeft -= 72; - ADJUSTABLE_DOUBLE_CRATE.draw(matrixStack, this, crateLeft, crateTop); - } else - ADJUSTABLE_CRATE.draw(matrixStack,this, crateLeft, crateTop); + background.draw(ms, this, crateLeft, crateTop); + drawCenteredText(ms, textRenderer, title, crateLeft + (background.width - 8) / 2, crateTop + 3, 0xFFFFFF); - textRenderer.drawWithShadow(matrixStack, title, crateLeft - 3 + (ADJUSTABLE_CRATE.width - textRenderer.getWidth(title)) / 2, - crateTop + 3, 0xfefefe); - String itemCount = "" + te.itemCount; - textRenderer.draw(matrixStack, itemCount, guiLeft + 100 + 53 - textRenderer.getStringWidth(itemCount), crateTop + 107, fontColor); - - PLAYER_INVENTORY.draw(matrixStack, this, invLeft, invTop); - textRenderer.draw(matrixStack, playerInventory.getDisplayName(), invLeft + 7, invTop + 6, 0x666666); + String itemCount = String.valueOf(te.itemCount); + textRenderer.draw(ms, itemCount, crateLeft + itemLabelOffset - 13 - textRenderer.getStringWidth(itemCount), crateTop + 108, 0x4B3A22); for (int slot = 0; slot < (container.doubleCrate ? 32 : 16); slot++) { if (allowedItems.getState() > slot * 64) @@ -93,13 +103,13 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreenat(guiLeft + ADJUSTABLE_CRATE.width + 110, guiTop + 70, -150) + .at(crateLeft + background.width, crateTop + background.height - 56 + itemYShift, -200) .scale(5) - .render(matrixStack); + .render(ms); } @Override @@ -130,4 +140,5 @@ public class AdjustableCrateScreen extends AbstractSimiContainerScreen getExtraAreas() { return extraAreas; } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateTileEntity.java index ec986de25..e2a0a4860 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/inventories/AdjustableCrateTileEntity.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.logistics.block.inventories; import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -72,7 +73,7 @@ public class AdjustableCrateTileEntity extends CrateTileEntity implements INamed @Override public Container createMenu(int id, PlayerInventory inventory, PlayerEntity player) { - return new AdjustableCrateContainer(id, inventory, this); + return AdjustableCrateContainer.create(id, inventory, this); } public AdjustableCrateTileEntity getOtherCrate() { @@ -159,8 +160,7 @@ public class AdjustableCrateTileEntity extends CrateTileEntity implements INamed @Override public ITextComponent getDisplayName() { - return new StringTextComponent(getType().getRegistryName() - .toString()); + return Lang.translate("gui.adjustable_crate.title"); } public void sendToContainer(PacketBuffer buffer) { diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java index 941b35260..3f0f4b12b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInstance.java @@ -3,16 +3,16 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; import java.util.ArrayList; import com.google.common.collect.Lists; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.Instancer; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.content.contraptions.base.RotatingData; import com.simibubi.create.content.contraptions.base.SingleRotatingInstance; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -37,17 +37,17 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta private final ArmTileEntity arm; private final Boolean ceiling; - private boolean firstTick = true; + private boolean firstRender = true; private float baseAngle = Float.NaN; private float lowerArmAngle = Float.NaN; private float upperArmAngle = Float.NaN; private float headAngle = Float.NaN; - public ArmInstance(InstancedTileRenderer modelManager, ArmTileEntity tile) { + public ArmInstance(MaterialManager modelManager, ArmTileEntity tile) { super(modelManager, tile); - RenderMaterial> mat = getTransformMaterial(); + InstanceMaterial mat = getTransformMaterial(); base = mat.getModel(AllBlockPartials.ARM_BASE, blockState).createInstance(); lowerBody = mat.getModel(AllBlockPartials.ARM_LOWER_BODY, blockState).createInstance(); @@ -55,7 +55,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta head = mat.getModel(AllBlockPartials.ARM_HEAD, blockState).createInstance(); claw = mat.getModel(AllBlockPartials.ARM_CLAW_BASE, blockState).createInstance(); - InstancedModel clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, blockState); + Instancer clawHalfModel = mat.getModel(AllBlockPartials.ARM_CLAW_GRIP, blockState); ModelData clawGrip1 = clawHalfModel.createInstance(); ModelData clawGrip2 = clawHalfModel.createInstance(); @@ -69,8 +69,9 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta @Override public void beginFrame() { - if (arm.phase == ArmTileEntity.Phase.DANCING) { + if (arm.phase == ArmTileEntity.Phase.DANCING && tile.getSpeed() != 0) { animateArm(true); + firstRender = true; return; } @@ -91,20 +92,19 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta this.upperArmAngle = upperArmAngleNow; this.headAngle = headAngleNow; - if (!settled || firstTick) + if (!settled || firstRender) animateArm(false); - if (settled) - firstTick = false; + if (firstRender) + firstRender = false; } private void animateArm(boolean rave) { - - int color; float baseAngle; float lowerArmAngle; float upperArmAngle; float headAngle; + int color; if (rave) { float renderTick = AnimationTickHolder.getRenderTime(this.arm.getWorld()) + (tile.hashCode() % 64); @@ -112,14 +112,12 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); headAngle = -lowerArmAngle; - color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); } else { baseAngle = this.baseAngle; lowerArmAngle = this.lowerArmAngle - 135; upperArmAngle = this.upperArmAngle - 90; headAngle = this.headAngle; - color = 0xFFFFFF; } @@ -173,7 +171,7 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta } @Override - protected InstancedModel getModel() { + protected Instancer getModel() { return getRotatingMaterial().getModel(AllBlockPartials.ARM_COG, tile.getBlockState()); } @@ -182,4 +180,5 @@ public class ArmInstance extends SingleRotatingInstance implements IDynamicInsta super.remove(); models.forEach(InstanceData::delete); } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java index 84baeee39..2a0398b38 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPoint.java @@ -7,6 +7,7 @@ import javax.annotation.Nullable; import org.apache.commons.lang3.mutable.MutableBoolean; import com.google.common.collect.ImmutableMap; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.AllBlocks; @@ -27,7 +28,6 @@ import com.simibubi.create.content.logistics.block.funnel.FunnelBlock; import com.simibubi.create.content.logistics.block.funnel.FunnelTileEntity; import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.item.SmartInventory; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.belt.TransportedItemStackHandlerBehaviour.TransportedResult; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java index 1dfe270bf..ff7cbdcc1 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/mechanicalArm/ArmInteractionPointHandler.java @@ -195,10 +195,10 @@ public class ArmInteractionPointHandler { continue; int color = point.mode == Mode.DEPOSIT ? 0xffcb74 : 0x4f8a8b; - CreateClient.outliner.showAABB(point, shape.getBoundingBox() - .offset(pos)) - .colored(color) - .lineWidth(1 / 16f); + CreateClient.OUTLINER.showAABB(point, shape.getBoundingBox() + .offset(pos)) + .colored(color) + .lineWidth(1 / 16f); } } 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 2a9a72ac3..3955b833c 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 @@ -1,5 +1,6 @@ package com.simibubi.create.content.logistics.block.mechanicalArm; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -8,7 +9,6 @@ import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmTileEntity.Phase; import com.simibubi.create.foundation.render.PartialBufferer; 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.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -40,12 +40,11 @@ public class ArmRenderer extends KineticTileEntityRenderer { protected void renderSafe(KineticTileEntity te, float pt, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { super.renderSafe(te, pt, ms, buffer, light, overlay); + ArmTileEntity arm = (ArmTileEntity) te; - - boolean usingFlywheel = FastRenderDispatcher.available(te.getWorld()); - ItemStack item = arm.heldItem; boolean hasItem = !item.isEmpty(); + boolean usingFlywheel = Backend.getInstance().canUseInstancing(te.getWorld()); if (usingFlywheel && !hasItem) return; @@ -61,21 +60,27 @@ public class ArmRenderer extends KineticTileEntityRenderer { MatrixStack msLocal = new MatrixStack(); MatrixStacker msr = MatrixStacker.of(msLocal); - int color = 0xFFFFFF; - float baseAngle = arm.baseAngle.get(pt); - float lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; - float upperArmAngle = arm.upperArmAngle.get(pt) - 90; - float headAngle = arm.headAngle.get(pt); + float baseAngle; + float lowerArmAngle; + float upperArmAngle; + float headAngle; + int color; - boolean rave = arm.phase == Phase.DANCING; - float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 64); + boolean rave = arm.phase == Phase.DANCING && te.getSpeed() != 0; if (rave) { + float renderTick = AnimationTickHolder.getRenderTime(te.getWorld()) + (te.hashCode() % 64); baseAngle = (renderTick * 10) % 360; lowerArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 4) + 1) / 2, -45, 15); upperArmAngle = MathHelper.lerp((MathHelper.sin(renderTick / 8) + 1) / 4, -45, 95); headAngle = -lowerArmAngle; color = ColorHelper.rainbowColor(AnimationTickHolder.getTicks() * 100); + } else { + baseAngle = arm.baseAngle.get(pt); + lowerArmAngle = arm.lowerArmAngle.get(pt) - 135; + upperArmAngle = arm.upperArmAngle.get(pt) - 90; + headAngle = arm.headAngle.get(pt); + color = 0xFFFFFF; } msr.centre(); 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 ae0a584e3..9db6a126a 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 @@ -122,14 +122,14 @@ public class ArmTileEntity extends KineticTileEntity { } if (world.isRemote) return; - + if (phase == Phase.MOVE_TO_INPUT) collectItem(); else if (phase == Phase.MOVE_TO_OUTPUT) depositItem(); else if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) searchForItem(); - + if (targetReached) lazyTick(); } @@ -142,7 +142,7 @@ public class ArmTileEntity extends KineticTileEntity { return; if (chasedPointProgress < .5f) return; - if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) + if (phase == Phase.SEARCH_INPUTS || phase == Phase.DANCING) checkForMusic(); if (phase == Phase.SEARCH_OUTPUTS) searchForDestination(); @@ -175,7 +175,7 @@ public class ArmTileEntity extends KineticTileEntity { } private boolean tickMovementProgress() { - boolean targetReachedPreviously = chasedPointProgress >= 1; + boolean targetReachedPreviously = chasedPointProgress >= 1; chasedPointProgress += Math.min(256, Math.abs(getSpeed())) / 1024f; if (chasedPointProgress > 1) chasedPointProgress = 1; @@ -349,10 +349,10 @@ public class ArmTileEntity extends KineticTileEntity { chasedPointIndex = -1; sendData(); markDirty(); - + if (!prevHeld.isItemEqual(heldItem)) world.playSound(null, pos, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.BLOCKS, .125f, - .5f + Create.random.nextFloat() * .25f); + .5f + Create.RANDOM.nextFloat() * .25f); return; } @@ -416,23 +416,26 @@ public class ArmTileEntity extends KineticTileEntity { markDirty(); } + public void writeInteractionPoints(CompoundNBT compound) { + if (updateInteractionPoints) { + compound.put("InteractionPoints", interactionPointTag); + } else { + ListNBT pointsNBT = new ListNBT(); + inputs.stream() + .map(aip -> aip.serialize(pos)) + .forEach(pointsNBT::add); + outputs.stream() + .map(aip -> aip.serialize(pos)) + .forEach(pointsNBT::add); + compound.put("InteractionPoints", pointsNBT); + } + } + @Override public void write(CompoundNBT compound, boolean clientPacket) { super.write(compound, clientPacket); - if (updateInteractionPoints) { - compound.put("InteractionPoints", interactionPointTag); - - } else { - ListNBT pointsNBT = new ListNBT(); - inputs.stream() - .map(aip -> aip.serialize(pos)) - .forEach(pointsNBT::add); - outputs.stream() - .map(aip -> aip.serialize(pos)) - .forEach(pointsNBT::add); - compound.put("InteractionPoints", pointsNBT); - } + writeInteractionPoints(compound); NBTHelper.writeEnum(compound, "Phase", phase); compound.putBoolean("Powered", redstoneLocked); @@ -441,6 +444,13 @@ public class ArmTileEntity extends KineticTileEntity { compound.putFloat("MovementProgress", chasedPointProgress); } + @Override + public void writeSafe(CompoundNBT compound, boolean clientPacket) { + super.writeSafe(compound, clientPacket); + + writeInteractionPoints(compound); + } + @Override protected void fromTag(BlockState state, CompoundNBT compound, boolean clientPacket) { int previousIndex = chasedPointIndex; @@ -494,7 +504,7 @@ public class ArmTileEntity extends KineticTileEntity { } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java index 3d018cb61..bda0d93db 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverBlock.java @@ -47,30 +47,25 @@ public class AnalogLeverBlock extends HorizontalFaceBlock implements ITE { boolean sneak = player.isSneaking(); - AnalogLeverTileEntity te = getTileEntity(worldIn, pos); te.changeState(sneak); float f = .25f + ((te.state + 5) / 15f) * .5f; worldIn.playSound(null, pos, SoundEvents.BLOCK_LEVER_CLICK, SoundCategory.BLOCKS, 0.2F, f); - } catch (TileEntityException e) {} - - return ActionResultType.SUCCESS; + return ActionResultType.SUCCESS; + }); } @Override public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) { - try { - return getTileEntity(blockAccess, pos).state; - } catch (TileEntityException e) { - return 0; - } + return getTileEntityOptional(blockAccess, pos).map(al -> al.state) + .orElse(0); } @Override @@ -86,27 +81,26 @@ public class AnalogLeverBlock extends HorizontalFaceBlock implements ITE { + if (te.state != 0 && rand.nextFloat() < 0.25F) addParticles(stateIn, worldIn, pos, 0.5F); - } catch (TileEntityException e) {} + }); } @Override public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) { - try { - AnalogLeverTileEntity tileEntity = getTileEntity(worldIn, pos); - if (!isMoving && state.getBlock() != newState.getBlock()) { - if (tileEntity.state != 0) - updateNeighbors(state, worldIn, pos); - worldIn.removeTileEntity(pos); - } - } catch (TileEntityException e) {} + if (isMoving || state.getBlock() == newState.getBlock()) + return; + withTileEntityDo(worldIn, pos, te -> { + if (te.state != 0) + updateNeighbors(state, worldIn, pos); + worldIn.removeTileEntity(pos); + }); } private static void addParticles(BlockState state, IWorld worldIn, BlockPos pos, float alpha) { - Direction direction = state.get(HORIZONTAL_FACING).getOpposite(); + Direction direction = state.get(HORIZONTAL_FACING) + .getOpposite(); Direction direction1 = getFacing(state).getOpposite(); double d0 = (double) pos.getX() + 0.5D + 0.1D * (double) direction.getXOffset() + 0.2D * (double) direction1.getXOffset(); @@ -137,7 +131,7 @@ public class AnalogLeverBlock extends HorizontalFaceBlock implements ITE getTileEntityClass() { return AnalogLeverTileEntity.class; } - + @Override public boolean allowsMovement(BlockState state, IBlockReader reader, BlockPos pos, PathType type) { return false; diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java index 416766dcf..db89e4cb4 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/AnalogLeverInstance.java @@ -1,13 +1,12 @@ package com.simibubi.create.content.logistics.block.redstone; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.ColorHelper; @@ -24,10 +23,10 @@ public class AnalogLeverInstance extends TileEntityInstance modelManager, AnalogLeverTileEntity tile) { + public AnalogLeverInstance(MaterialManager modelManager, AnalogLeverTileEntity tile) { super(modelManager, tile); - RenderMaterial> mat = getTransformMaterial(); + InstanceMaterial mat = getTransformMaterial(); handle = mat.getModel(AllBlockPartials.ANALOG_LEVER_HANDLE, blockState).createInstance(); indicator = mat.getModel(AllBlockPartials.ANALOG_LEVER_INDICATOR, blockState).createInstance(); 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 329760ede..cfbbe0bfd 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 @@ -1,11 +1,11 @@ package com.simibubi.create.content.logistics.block.redstone; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; import com.simibubi.create.foundation.render.PartialBufferer; 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.ColorHelper; @@ -28,7 +28,7 @@ public class AnalogLeverRenderer extends SafeTileEntityRenderer te.displayCustomNameOf(heldItem, rowPosition)); - BlockPos nextPos = currentPos.offset(right); - if (world.getBlockState(nextPos) != state) - break; - currentPos = nextPos; - index++; - } + BlockPos currentPos = pos; + while (true) { + BlockPos nextPos = currentPos.offset(left); + if (world.getBlockState(nextPos) != state) + break; + currentPos = nextPos; } - } catch (TileEntityException e) { + int index = 0; + + while (true) { + final int rowPosition = index; + withTileEntityDo(world, currentPos, te -> te.displayCustomNameOf(heldItem, rowPosition)); + BlockPos nextPos = currentPos.offset(right); + if (world.getBlockState(nextPos) != state) + break; + currentPos = nextPos; + index++; + } } return ActionResultType.PASS; 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 6c58c7651..0469c1161 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 @@ -114,12 +114,8 @@ public class RedstoneLinkBlock extends ProperDirectionalBlock implements ITE { Boolean wasReceiver = state.get(RECEIVER); boolean blockPowered = worldIn.isBlockPowered(pos); worldIn.setBlockState(pos, state.cycle(RECEIVER) - .with(POWERED, blockPowered), 3); + .with(POWERED, blockPowered), 3); te.transmit(wasReceiver ? 0 : getPower(worldIn, pos)); return ActionResultType.SUCCESS; - } catch (TileEntityException e) { - } - return ActionResultType.PASS; + }); } @Override 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 6055c1aac..7dc6293fa 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 @@ -1,5 +1,7 @@ package com.simibubi.create.content.logistics.block.redstone; +import java.util.Random; + import com.simibubi.create.AllItems; import com.simibubi.create.AllShapes; import com.simibubi.create.AllTileEntities; @@ -27,6 +29,7 @@ import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.IBlockReader; import net.minecraft.world.IWorldReader; import net.minecraft.world.World; +import net.minecraft.world.server.ServerWorld; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; @@ -82,11 +85,14 @@ public class StockpileSwitchBlock extends HorizontalBlock implements ITE 15) + .orElse(0); + } + + @Override + public void scheduledTick(BlockState blockState, ServerWorld world, BlockPos pos, Random random) { + getTileEntityOptional(world, pos).ifPresent(StockpileSwitchTileEntity::updatePowerAfterDelay); } @Override diff --git a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java index 87f406177..51800ee50 100644 --- a/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java +++ b/src/main/java/com/simibubi/create/content/logistics/block/redstone/StockpileSwitchTileEntity.java @@ -14,6 +14,7 @@ import net.minecraft.nbt.CompoundNBT; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.TickPriority; import net.minecraftforge.items.IItemHandler; public class StockpileSwitchTileEntity extends SmartTileEntity { @@ -23,6 +24,7 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { public float currentLevel; private boolean state; private boolean inverted; + private boolean poweredAfterDelay; private FilteringBehaviour filtering; private InvManipulationBehaviour observedInventory; @@ -34,6 +36,7 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { currentLevel = -1; state = false; inverted = false; + poweredAfterDelay = false; setLazyTickRate(10); } @@ -44,6 +47,7 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { currentLevel = compound.getFloat("Current"); state = compound.getBoolean("Powered"); inverted = compound.getBoolean("Inverted"); + poweredAfterDelay = compound.getBoolean("PoweredAfterDelay"); super.fromTag(blockState, compound, clientPacket); } @@ -54,6 +58,7 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { compound.putFloat("Current", currentLevel); compound.putBoolean("Powered", state); compound.putBoolean("Inverted", inverted); + compound.putBoolean("PoweredAfterDelay", poweredAfterDelay); super.write(compound, clientPacket); } @@ -110,8 +115,10 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { if (currentLevel > 0) displayLevel = (int) (currentLevel * 6); world.setBlockState(pos, getBlockState().with(StockpileSwitchBlock.INDICATOR, displayLevel), update ? 3 : 2); - if (update) - world.updateNeighbors(pos, getBlockState().getBlock()); + + if (update && !world.getPendingBlockTicks().isTickPending(pos, getBlockState().getBlock())) + world.getPendingBlockTicks().scheduleTick(pos, getBlockState().getBlock(), 2, TickPriority.NORMAL); + if (changed || update) sendData(); } @@ -137,19 +144,28 @@ public class StockpileSwitchTileEntity extends SmartTileEntity { public float getLevelForDisplay() { return currentLevel == -1 ? 0 : currentLevel; } - + public boolean getState() { return state; } - - public boolean isPowered() { + + public boolean shouldBePowered() { return inverted != state; } - + + public void updatePowerAfterDelay() { + poweredAfterDelay = shouldBePowered(); + world.updateNeighbors(pos, getBlockState().getBlock()); + } + + public boolean isPowered() { + return poweredAfterDelay; + } + public boolean isInverted() { return inverted; } - + public void setInverted(boolean inverted) { if (inverted == this.inverted) return; diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java new file mode 100644 index 000000000..2671e1d14 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerBindPacket.java @@ -0,0 +1,58 @@ +package com.simibubi.create.content.logistics.item; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.ItemStackHandler; + +public class LinkedControllerBindPacket extends LinkedControllerPacketBase { + + private int button; + private BlockPos linkLocation; + + public LinkedControllerBindPacket(int button, BlockPos linkLocation) { + this.button = button; + this.linkLocation = linkLocation; + } + + public LinkedControllerBindPacket(PacketBuffer buffer) { + this.button = buffer.readVarInt(); + this.linkLocation = buffer.readBlockPos(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeVarInt(button); + buffer.writeBlockPos(linkLocation); + } + + @Override + protected void handle(ServerPlayerEntity player, ItemStack heldItem) { + if (player.isSpectator()) + return; + + ItemStackHandler frequencyItems = LinkedControllerItem.getFrequencyItems(heldItem); + LinkBehaviour linkBehaviour = TileEntityBehaviour.get(player.world, linkLocation, LinkBehaviour.TYPE); + if (linkBehaviour == null) + return; + + Pair pair = linkBehaviour.getNetworkKey(); + frequencyItems.setStackInSlot(button * 2, pair.getKey() + .getStack() + .copy()); + frequencyItems.setStackInSlot(button * 2 + 1, pair.getValue() + .getStack() + .copy()); + + heldItem.getTag() + .put("Items", frequencyItems.serializeNBT()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java new file mode 100644 index 000000000..279470766 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerClientHandler.java @@ -0,0 +1,240 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Vector; + +import org.lwjgl.glfw.GLFW; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.CreateClient; +import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer.TooltipScreen; +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; +import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkBehaviour; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.GameSettings; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.client.util.InputMappings; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.shapes.VoxelShape; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; + +public class LinkedControllerClientHandler { + + enum Mode { + IDLE, ACTIVE, BIND + } + + public static Mode MODE = Mode.IDLE; + public static int PACKET_RATE = 5; + public static Collection currentlyPressed = new HashSet<>(); + private static BlockPos selectedLocation = BlockPos.ZERO; + private static Vector controls; + + private static int packetCooldown; + + public static Vector getControls() { + if (controls == null) { + GameSettings gameSettings = Minecraft.getInstance().gameSettings; + controls = new Vector<>(6); + controls.add(gameSettings.keyBindForward); + controls.add(gameSettings.keyBindBack); + controls.add(gameSettings.keyBindLeft); + controls.add(gameSettings.keyBindRight); + controls.add(gameSettings.keyBindJump); + controls.add(gameSettings.keySneak); + } + return controls; + } + + public static void toggleBindMode(BlockPos location) { + if (MODE == Mode.IDLE) { + MODE = Mode.BIND; + selectedLocation = location; + } else { + MODE = Mode.IDLE; + onReset(); + } + } + + public static void toggle() { + if (MODE == Mode.IDLE) + MODE = Mode.ACTIVE; + else { + MODE = Mode.IDLE; + onReset(); + } + } + + protected static void onReset() { + getControls().forEach(kb -> kb.setPressed(isActuallyPressed(kb))); + packetCooldown = 0; + selectedLocation = BlockPos.ZERO; + + if (!currentlyPressed.isEmpty()) + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(currentlyPressed, false)); + currentlyPressed.clear(); + } + + protected static boolean isActuallyPressed(KeyBinding kb) { + return InputMappings.isKeyDown(Minecraft.getInstance() + .getWindow() + .getHandle(), + kb.getKey() + .getKeyCode()); + } + + public static void tick() { + LinkedControllerItemRenderer.tick(); + if (MODE == Mode.IDLE) + return; + if (packetCooldown > 0) + packetCooldown--; + + Minecraft mc = Minecraft.getInstance(); + ClientPlayerEntity player = mc.player; + ItemStack heldItem = player.getHeldItemMainhand(); + + if (player.isSpectator()) { + MODE = Mode.IDLE; + onReset(); + return; + } + + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) { + heldItem = player.getHeldItemOffhand(); + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) { + MODE = Mode.IDLE; + onReset(); + return; + } + } + + if (mc.currentScreen != null) { + MODE = Mode.IDLE; + onReset(); + return; + } + + if (InputMappings.isKeyDown(mc.getWindow().getHandle(), GLFW.GLFW_KEY_ESCAPE)) { + MODE = Mode.IDLE; + onReset(); + return; + } + + Vector controls = getControls(); + Collection pressedKeys = new HashSet<>(); + for (int i = 0; i < controls.size(); i++) { + if (isActuallyPressed(controls.get(i))) + pressedKeys.add(i); + } + + Collection newKeys = new HashSet<>(pressedKeys); + Collection releasedKeys = currentlyPressed; + newKeys.removeAll(releasedKeys); + releasedKeys.removeAll(pressedKeys); + + if (MODE == Mode.ACTIVE) { + // Released Keys + if (!releasedKeys.isEmpty()) { + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(releasedKeys, false)); + AllSoundEvents.CONTROLLER_CLICK.playAt(player.world, player.getBlockPos(), 1f, .5f, true); + } + + // Newly Pressed Keys + if (!newKeys.isEmpty()) { + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(newKeys, true)); + packetCooldown = PACKET_RATE; + AllSoundEvents.CONTROLLER_CLICK.playAt(player.world, player.getBlockPos(), 1f, .75f, true); + } + + // Keepalive Pressed Keys + if (packetCooldown == 0) { + if (!pressedKeys.isEmpty()) { + AllPackets.channel.sendToServer(new LinkedControllerInputPacket(pressedKeys, true)); + packetCooldown = PACKET_RATE; + } + } + } + + if (MODE == Mode.BIND) { + VoxelShape shape = mc.world.getBlockState(selectedLocation) + .getShape(mc.world, selectedLocation); + if (!shape.isEmpty()) + CreateClient.OUTLINER.showAABB("controller", shape.getBoundingBox() + .offset(selectedLocation)) + .colored(0xB73C2D) + .lineWidth(1 / 16f); + + for (Integer integer : newKeys) { + LinkBehaviour linkBehaviour = TileEntityBehaviour.get(mc.world, selectedLocation, LinkBehaviour.TYPE); + if (linkBehaviour != null) { + AllPackets.channel.sendToServer(new LinkedControllerBindPacket(integer, selectedLocation)); + Lang.sendStatus(mc.player, "linked_controller.key_bound", controls.get(integer) + .getBoundKeyLocalizedText() + .getString()); + } + MODE = Mode.IDLE; + break; + } + } + + currentlyPressed = pressedKeys; + controls.forEach(kb -> kb.setPressed(false)); + } + + public static void renderOverlay(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, + float partialTicks) { + if (MODE != Mode.BIND) + return; + Minecraft mc = Minecraft.getInstance(); + + ms.push(); + Screen tooltipScreen = new TooltipScreen(null); + tooltipScreen.init(mc, mc.getWindow() + .getScaledWidth(), + mc.getWindow() + .getScaledHeight()); + + Object[] keys = new Object[6]; + Vector controls = getControls(); + for (int i = 0; i < controls.size(); i++) { + KeyBinding keyBinding = controls.get(i); + keys[i] = keyBinding.getBoundKeyLocalizedText() + .getString(); + } + + List list = new ArrayList<>(); + list.add(Lang.createTranslationTextComponent("linked_controller.bind_mode") + .formatted(TextFormatting.GOLD)); + list.addAll( + TooltipHelper.cutTextComponent(Lang.createTranslationTextComponent("linked_controller.press_keybind", keys), + TextFormatting.GRAY, TextFormatting.GRAY)); + + int width = 0; + int height = list.size() * mc.fontRenderer.FONT_HEIGHT; + for (ITextComponent iTextComponent : list) + width = Math.max(width, mc.fontRenderer.getWidth(iTextComponent)); + int x = (tooltipScreen.width / 3) - width / 2; + int y = tooltipScreen.height - height; + + tooltipScreen.renderTooltip(ms, list, x, y); + + ms.pop(); + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java new file mode 100644 index 000000000..5d0a54190 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerContainer.java @@ -0,0 +1,158 @@ +package com.simibubi.create.content.logistics.item; + +import com.simibubi.create.AllContainerTypes; +import com.simibubi.create.foundation.gui.IClearableContainer; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.ClickType; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class LinkedControllerContainer extends Container implements IClearableContainer { + + public PlayerEntity player; + protected PlayerInventory playerInventory; + public ItemStack mainItem; + public ItemStackHandler filterInventory; + + public LinkedControllerContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + this(type, id, inv, extraData.readItemStack()); + } + + public LinkedControllerContainer(ContainerType type, int id, PlayerInventory inv, ItemStack filterItem) { + super(type, id); + player = inv.player; + playerInventory = inv; + this.mainItem = filterItem; + init(); + } + + public static LinkedControllerContainer create(int id, PlayerInventory inv, ItemStack filterItem) { + return new LinkedControllerContainer(AllContainerTypes.LINKED_CONTROLLER.get(), id, inv, filterItem); + } + + protected void init() { + this.filterInventory = createFilterInventory(); +// readData(mainItem); + addPlayerSlots(); + addLinkSlots(); + detectAndSendChanges(); + } + + protected void addPlayerSlots() { + int x = 9; + int y = 131; + + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + protected void addLinkSlots() { + int x = 12; + int y = 34; + int slot = 0; + + for (int column = 0; column < 6; column++) { + for (int row = 0; row < 2; ++row) + addSlot(new SlotItemHandler(filterInventory, slot++, x, y + row * 18)); + x += 24; + if (column == 3) + x += 11; + } + } + + @Override + public void clearContents() { + for (int i = 0; i < filterInventory.getSlots(); i++) + filterInventory.setStackInSlot(i, ItemStack.EMPTY); + } + + @Override + public boolean canMergeSlot(ItemStack stack, Slot slotIn) { + return canDragIntoSlot(slotIn); + } + + @Override + public boolean canDragIntoSlot(Slot slotIn) { + return slotIn.inventory == playerInventory; + } + + @Override + public boolean canInteractWith(PlayerEntity playerIn) { + return true; + } + + @Override + public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) { + if (slotId == playerInventory.currentItem && clickTypeIn != ClickType.THROW) + return ItemStack.EMPTY; + + ItemStack held = playerInventory.getItemStack(); + if (slotId < 36) + return super.slotClick(slotId, dragType, clickTypeIn, player); + if (clickTypeIn == ClickType.THROW) + return ItemStack.EMPTY; + + int slot = slotId - 36; + if (clickTypeIn == ClickType.CLONE) { + if (player.isCreative() && held.isEmpty()) { + ItemStack stackInSlot = filterInventory.getStackInSlot(slot) + .copy(); + stackInSlot.setCount(64); + playerInventory.setItemStack(stackInSlot); + return ItemStack.EMPTY; + } + return ItemStack.EMPTY; + } + + if (held.isEmpty()) { + filterInventory.setStackInSlot(slot, ItemStack.EMPTY); + return ItemStack.EMPTY; + } + + ItemStack insert = held.copy(); + insert.setCount(1); + filterInventory.setStackInSlot(slot, insert); + return held; + } + + protected ItemStackHandler createFilterInventory() { + return LinkedControllerItem.getFrequencyItems(mainItem); + } + + @Override + public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + if (index < 36) { + ItemStack stackToInsert = playerInventory.getStackInSlot(index); + for (int i = 0; i < filterInventory.getSlots(); i++) { + ItemStack stack = filterInventory.getStackInSlot(i); + if (stack.isEmpty()) { + ItemStack copy = stackToInsert.copy(); + copy.setCount(1); + filterInventory.insertItem(i, copy, false); + break; + } + } + } else + filterInventory.extractItem(index - 36, 1, false); + return ItemStack.EMPTY; + } + + @Override + public void onContainerClosed(PlayerEntity playerIn) { + super.onContainerClosed(playerIn); + mainItem.getOrCreateTag() + .put("Items", filterInventory.serializeNBT()); +// saveData(filterItem); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java new file mode 100644 index 000000000..4a6834424 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerInputPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.UUID; +import java.util.stream.Collectors; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class LinkedControllerInputPacket extends LinkedControllerPacketBase { + + private Collection activatedButtons; + private boolean press; + + public LinkedControllerInputPacket(Collection activatedButtons, boolean press) { + this.activatedButtons = activatedButtons; + this.press = press; + } + + public LinkedControllerInputPacket(PacketBuffer buffer) { + activatedButtons = new ArrayList<>(); + press = buffer.readBoolean(); + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) + activatedButtons.add(buffer.readVarInt()); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeBoolean(press); + buffer.writeVarInt(activatedButtons.size()); + activatedButtons.forEach(buffer::writeVarInt); + } + + @Override + protected void handle(ServerPlayerEntity player, ItemStack heldItem) { + World world = player.getEntityWorld(); + UUID uniqueID = player.getUniqueID(); + BlockPos pos = player.getBlockPos(); + + if (player.isSpectator() && press) + return; + + LinkedControllerServerHandler.receivePressed(world, pos, uniqueID, activatedButtons.stream() + .map(i -> LinkedControllerItem.toFrequency(heldItem, i)) + .collect(Collectors.toList()), press); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java new file mode 100644 index 000000000..04af661ae --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItem.java @@ -0,0 +1,115 @@ +package com.simibubi.create.content.logistics.item; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.utility.Couple; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.INamedContainerProvider; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUseContext; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.World; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.network.NetworkHooks; +import net.minecraftforge.items.ItemStackHandler; + +public class LinkedControllerItem extends Item implements INamedContainerProvider { + + public LinkedControllerItem(Properties properties) { + super(properties); + } + + @Override + public ActionResultType onItemUse(ItemUseContext ctx) { + PlayerEntity player = ctx.getPlayer(); + if (player == null) + return ActionResultType.PASS; + World world = ctx.getWorld(); + + if (!player.isSneaking() && player.isAllowEdit() + && AllBlocks.REDSTONE_LINK.has(world.getBlockState(ctx.getPos()))) { + if (world.isRemote) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> this.toggleBindMode(ctx.getPos())); + player.getCooldownTracker() + .setCooldown(this, 2); + return ActionResultType.SUCCESS; + } + + return onItemRightClick(world, player, ctx.getHand()).getType(); + } + + @Override + public ActionResult onItemRightClick(World world, PlayerEntity player, Hand hand) { + ItemStack heldItem = player.getHeldItem(hand); + + if (player.isSneaking() && hand == Hand.MAIN_HAND) { + if (!world.isRemote && player instanceof ServerPlayerEntity && player.isAllowEdit()) + NetworkHooks.openGui((ServerPlayerEntity) player, this, buf -> { + buf.writeItemStack(heldItem); + }); + return ActionResult.success(heldItem); + } + + if (!player.isSneaking()) { + if (world.isRemote) + DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::toggleActive); + player.getCooldownTracker() + .setCooldown(this, 2); + } + + return ActionResult.pass(heldItem); + } + + @OnlyIn(Dist.CLIENT) + private void toggleBindMode(BlockPos pos) { + LinkedControllerClientHandler.toggleBindMode(pos); + } + + @OnlyIn(Dist.CLIENT) + private void toggleActive() { + LinkedControllerClientHandler.toggle(); + } + + public static ItemStackHandler getFrequencyItems(ItemStack stack) { + ItemStackHandler newInv = new ItemStackHandler(12); + if (AllItems.LINKED_CONTROLLER.get() != stack.getItem()) + throw new IllegalArgumentException("Cannot get frequency items from non-controller: " + stack); + CompoundNBT invNBT = stack.getOrCreateChildTag("Items"); + if (!invNBT.isEmpty()) + newInv.deserializeNBT(invNBT); + return newInv; + } + + public static Couple toFrequency(ItemStack controller, int slot) { + ItemStackHandler frequencyItems = getFrequencyItems(controller); + return Couple.create(Frequency.of(frequencyItems.getStackInSlot(slot * 2)), + Frequency.of(frequencyItems.getStackInSlot(slot * 2 + 1))); + } + + @Override + public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { + ItemStack heldItem = player.getHeldItemMainhand(); + return LinkedControllerContainer.create(id, inv, heldItem); + } + + @Override + public ITextComponent getDisplayName() { + return new TranslationTextComponent(getTranslationKey()); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java new file mode 100644 index 000000000..a7e524e5a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerItemRenderer.java @@ -0,0 +1,134 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.Vector; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler.Mode; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModelRenderer; +import com.simibubi.create.foundation.item.render.PartialItemModelRenderer; +import com.simibubi.create.foundation.utility.AnimationTickHolder; +import com.simibubi.create.foundation.utility.MatrixStacker; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import com.simibubi.create.foundation.utility.animation.LerpedFloat.Chaser; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.model.ItemCameraTransforms; +import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; +import net.minecraft.item.ItemStack; +import net.minecraft.util.HandSide; +import net.minecraft.util.math.MathHelper; + +public class LinkedControllerItemRenderer extends CustomRenderedItemModelRenderer { + + static LerpedFloat equipProgress; + static Vector buttons; + + static { + equipProgress = LerpedFloat.linear() + .startWithValue(0); + buttons = new Vector<>(6); + for (int i = 0; i < 6; i++) + buttons.add(LerpedFloat.linear() + .startWithValue(0)); + } + + static void tick() { + boolean active = LinkedControllerClientHandler.MODE != Mode.IDLE; + equipProgress.chase(active ? 1 : 0, .2f, Chaser.EXP); + equipProgress.tickChaser(); + + if (!active) + return; + + for (int i = 0; i < buttons.size(); i++) { + LerpedFloat lerpedFloat = buttons.get(i); + lerpedFloat.chase(LinkedControllerClientHandler.currentlyPressed.contains(i) ? 1 : 0, .4f, Chaser.EXP); + lerpedFloat.tickChaser(); + } + } + + @Override + protected void render(ItemStack stack, LinkedControllerModel model, PartialItemModelRenderer renderer, + ItemCameraTransforms.TransformType transformType, MatrixStack ms, IRenderTypeBuffer buffer, int light, + int overlay) { + float pt = AnimationTickHolder.getPartialTicks(); + MatrixStacker msr = MatrixStacker.of(ms); + + ms.push(); + + Minecraft mc = Minecraft.getInstance(); + boolean rightHanded = mc.gameSettings.mainHand == HandSide.RIGHT; + TransformType mainHand = + rightHanded ? TransformType.FIRST_PERSON_RIGHT_HAND : TransformType.FIRST_PERSON_LEFT_HAND; + TransformType offHand = + rightHanded ? TransformType.FIRST_PERSON_LEFT_HAND : TransformType.FIRST_PERSON_RIGHT_HAND; + + boolean active = false; + boolean noControllerInMain = !AllItems.LINKED_CONTROLLER.isIn(mc.player.getHeldItemMainhand()); + + if (transformType == mainHand || (transformType == offHand && noControllerInMain)) { + float equip = equipProgress.getValue(pt); + int handModifier = transformType == TransformType.FIRST_PERSON_LEFT_HAND ? -1 : 1; + msr.translate(0, equip / 4, equip / 4 * handModifier); + msr.rotateY(equip * -30 * handModifier); + msr.rotateZ(equip * -30); + active = true; + } + + if (transformType == TransformType.GUI) { + if (stack == mc.player.getHeldItemMainhand()) + active = true; + if (stack == mc.player.getHeldItemOffhand() && noControllerInMain) + active = true; + } + + active &= LinkedControllerClientHandler.MODE != Mode.IDLE; + renderer.render(active ? model.getPartial("powered") : model.getOriginalModel(), light); + + if (!active) { + ms.pop(); + return; + } + + IBakedModel button = model.getPartial("button"); + float s = 1 / 16f; + float b = s * -.75f; + int index = 0; + + if (LinkedControllerClientHandler.MODE == Mode.BIND) { + int i = (int) MathHelper.lerp((MathHelper.sin(AnimationTickHolder.getRenderTime() / 4f) + 1) / 2, 5, 15); + light = i << 20; + } + + ms.push(); + msr.translate(2 * s, 0, 8 * s); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(4 * s, 0, 0); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(-2 * s, 0, 2 * s); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(0, 0, -4 * s); + button(renderer, ms, light, pt, button, b, index++); + ms.pop(); + + msr.translate(3 * s, 0, 3 * s); + button(renderer, ms, light, pt, button, b, index++); + msr.translate(2 * s, 0, 0); + button(renderer, ms, light, pt, button, b, index++); + + ms.pop(); + } + + protected void button(PartialItemModelRenderer renderer, MatrixStack ms, int light, float pt, IBakedModel button, + float b, int index) { + ms.push(); + ms.translate(0, b * buttons.get(index) + .getValue(pt), 0); + renderer.renderSolid(button, light); + ms.pop(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java new file mode 100644 index 000000000..a900bddf4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerModel.java @@ -0,0 +1,20 @@ +package com.simibubi.create.content.logistics.item; + +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; + +import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.client.renderer.tileentity.ItemStackTileEntityRenderer; + +public class LinkedControllerModel extends CustomRenderedItemModel { + + public LinkedControllerModel(IBakedModel template) { + super(template, "linked_controller"); + addPartials("powered", "button"); + } + + @Override + public ItemStackTileEntityRenderer createRenderer() { + return new LinkedControllerItemRenderer(); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java new file mode 100644 index 000000000..bbc5918c4 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerPacketBase.java @@ -0,0 +1,37 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.function.Supplier; + +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public abstract class LinkedControllerPacketBase extends SimplePacketBase { + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + + ItemStack heldItem = player.getHeldItemMainhand(); + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) { + heldItem = player.getHeldItemOffhand(); + if (!AllItems.LINKED_CONTROLLER.isIn(heldItem)) + return; + } + handle(player, heldItem); + }); + context.get() + .setPacketHandled(true); + } + + protected abstract void handle(ServerPlayerEntity player, ItemStack heldItem); + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java new file mode 100644 index 000000000..caef8889d --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerScreen.java @@ -0,0 +1,141 @@ +package com.simibubi.create.content.logistics.item; + +import static com.simibubi.create.foundation.gui.AllGuiTextures.PLAYER_INVENTORY; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.gui.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.widgets.IconButton; +import com.simibubi.create.foundation.utility.Lang; + +import net.minecraft.client.renderer.Rectangle2d; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextFormatting; + +public class LinkedControllerScreen extends AbstractSimiContainerScreen { + + protected AllGuiTextures background; + private List extraAreas = Collections.emptyList(); + + private IconButton resetButton; + private IconButton confirmButton; + + public LinkedControllerScreen(LinkedControllerContainer container, PlayerInventory inv, ITextComponent title) { + super(container, inv, title); + this.background = AllGuiTextures.LINKED_CONTROLLER; + } + + @Override + protected void init() { + setWindowSize(background.width, background.height + 4 + PLAYER_INVENTORY.height); + super.init(); + widgets.clear(); + + int x = guiLeft; + int y = guiTop; + + resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + + widgets.add(resetButton); + widgets.add(confirmButton); + + extraAreas = ImmutableList.of( + new Rectangle2d(x + background.width + 4, y + background.height - 44, 64, 56) + ); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int invLeft = guiLeft - windowXOffset + (xSize - PLAYER_INVENTORY.width) / 2; + int invTop = guiTop + background.height + 4; + + PLAYER_INVENTORY.draw(ms, this, invLeft, invTop); + textRenderer.draw(ms, playerInventory.getDisplayName(), invLeft + 8, invTop + 6, 0x404040); + + int x = guiLeft; + int y = guiTop; + + background.draw(ms, this, x, y); + textRenderer.draw(ms, title, x + 15, y + 4, 0x442000); + + GuiGameElement.of(container.mainItem) + .at(x + background.width - 4, y + background.height - 56, -200) + .scale(5) + .render(ms); + } + + @Override + public void tick() { + super.tick(); + if (!container.player.getHeldItemMainhand() + .equals(container.mainItem, false)) + client.player.closeScreen(); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + boolean mouseClicked = super.mouseClicked(x, y, button); + + if (button == 0) { + if (confirmButton.isHovered()) { + client.player.closeScreen(); + return true; + } + if (resetButton.isHovered()) { + container.clearContents(); + container.sendClearPacket(); + return true; + } + } + + return mouseClicked; + } + + @Override + protected void drawMouseoverTooltip(MatrixStack ms, int x, int y) { + if (!this.client.player.inventory.getItemStack() + .isEmpty() || this.hoveredSlot == null || this.hoveredSlot.getHasStack() + || hoveredSlot.inventory == container.playerInventory) { + super.drawMouseoverTooltip(ms, x, y); + return; + } + renderWrappedToolTip(ms, addToTooltip(new LinkedList<>(), hoveredSlot.getSlotIndex()), x, y, textRenderer); + } + + @Override + public List getTooltipFromItem(ItemStack stack) { + List list = super.getTooltipFromItem(stack); + if (hoveredSlot.inventory == container.playerInventory) + return list; + return hoveredSlot != null ? addToTooltip(list, hoveredSlot.getSlotIndex()) : list; + } + + private List addToTooltip(List list, int slot) { + if (slot < 0 || slot >= 12) + return list; + list.add(Lang + .createTranslationTextComponent("linked_controller.frequency_slot_" + ((slot % 2) + 1), + LinkedControllerClientHandler.getControls() + .get(slot / 2) + .getBoundKeyLocalizedText() + .getString()) + .formatted(TextFormatting.GOLD)); + return list; + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java new file mode 100644 index 000000000..8e35e0cb6 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/item/LinkedControllerServerHandler.java @@ -0,0 +1,123 @@ +package com.simibubi.create.content.logistics.item; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.apache.commons.lang3.tuple.Pair; + +import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.IRedstoneLinkable; +import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.IntAttached; +import com.simibubi.create.foundation.utility.WorldAttached; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; + +public class LinkedControllerServerHandler { + + public static WorldAttached>> receivedInputs = + new WorldAttached<>(HashMap::new); + static final int TIMEOUT = 30; + + public static void tick(IWorld world) { + Map> map = receivedInputs.get(world); + for (Iterator>> iterator = map.entrySet() + .iterator(); iterator.hasNext();) { + + Entry> entry = iterator.next(); + Collection list = entry.getValue(); + + for (Iterator entryIterator = list.iterator(); entryIterator.hasNext();) { + ManualFrequencyEntry manualFrequencyEntry = entryIterator.next(); + manualFrequencyEntry.decrement(); + if (!manualFrequencyEntry.isAlive()) { + Create.REDSTONE_LINK_NETWORK_HANDLER.removeFromNetwork(world, manualFrequencyEntry); + entryIterator.remove(); + } + } + + if (list.isEmpty()) + iterator.remove(); + } + } + + public static void receivePressed(IWorld world, BlockPos pos, UUID uniqueID, List> collect, + boolean pressed) { + Map> map = receivedInputs.get(world); + Collection list = map.computeIfAbsent(uniqueID, $ -> new ArrayList<>()); + + WithNext: for (Couple activated : collect) { + for (Iterator iterator = list.iterator(); iterator.hasNext();) { + ManualFrequencyEntry entry = iterator.next(); + if (entry.getSecond() + .equals(activated)) { + if (!pressed) + entry.setFirst(0); + else + entry.updatePosition(pos); + continue WithNext; + } + } + + if (!pressed) + continue; + + ManualFrequencyEntry entry = new ManualFrequencyEntry(pos, activated); + Create.REDSTONE_LINK_NETWORK_HANDLER.addToNetwork(world, entry); + list.add(entry); + } + } + + static class ManualFrequencyEntry extends IntAttached> implements IRedstoneLinkable { + + private BlockPos pos; + + public ManualFrequencyEntry(BlockPos pos, Couple second) { + super(TIMEOUT, second); + this.pos = pos; + } + + public void updatePosition(BlockPos pos) { + this.pos = pos; + setFirst(TIMEOUT); + } + + @Override + public int getTransmittedStrength() { + return isAlive() ? 15 : 0; + } + + @Override + public boolean isAlive() { + return getFirst() > 0; + } + + @Override + public BlockPos getLocation() { + return pos; + } + + @Override + public void setReceivedStrength(int power) {} + + @Override + public boolean isListening() { + return false; + } + + @Override + public Pair getNetworkKey() { + return Pair.of(getSecond().getFirst(), getSecond().getSecond()); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java index 1bd54d34d..ebf23f2fb 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterContainer.java @@ -1,142 +1,60 @@ package com.simibubi.create.content.logistics.item.filter; +import com.simibubi.create.foundation.gui.GhostItemContainer; + import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.ClickType; -import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.ContainerType; -import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; -import net.minecraftforge.items.ItemHandlerHelper; -import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; -public abstract class AbstractFilterContainer extends Container { - - public PlayerEntity player; - protected PlayerInventory playerInventory; - public ItemStack filterItem; - public ItemStackHandler filterInventory; +public abstract class AbstractFilterContainer extends GhostItemContainer { protected AbstractFilterContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { - this(type, id, inv, extraData.readItemStack()); + super(type, id, inv, extraData); } - protected AbstractFilterContainer(ContainerType type, int id, PlayerInventory inv, ItemStack filterItem) { - super(type, id); - player = inv.player; - playerInventory = inv; - this.filterItem = filterItem; - init(); - } - - protected void init() { - this.filterInventory = createFilterInventory(); - readData(filterItem); - addPlayerSlots(); - addFilterSlots(); - detectAndSendChanges(); - } - - protected void clearContents() { - for (int i = 0; i < filterInventory.getSlots(); i++) - filterInventory.setStackInSlot(i, ItemStack.EMPTY); - } - - protected abstract int getInventoryOffset(); - - protected abstract void addFilterSlots(); - - protected abstract ItemStackHandler createFilterInventory(); - - protected abstract void readData(ItemStack filterItem); - - protected abstract void saveData(ItemStack filterItem); - - protected void addPlayerSlots() { - int x = 8; - int y = 28 + getInventoryOffset(); - - for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) - this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); - for (int row = 0; row < 3; ++row) - for (int col = 0; col < 9; ++col) - this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); - } - - @Override - public boolean canMergeSlot(ItemStack stack, Slot slotIn) { - return canDragIntoSlot(slotIn); - } - - @Override - public boolean canDragIntoSlot(Slot slotIn) { - return slotIn.inventory == playerInventory; - } - - @Override - public boolean canInteractWith(PlayerEntity playerIn) { - return true; + protected AbstractFilterContainer(ContainerType type, int id, PlayerInventory inv, ItemStack contentHolder) { + super(type, id, inv, contentHolder); } @Override public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) { if (slotId == playerInventory.currentItem && clickTypeIn != ClickType.THROW) return ItemStack.EMPTY; - - ItemStack held = playerInventory.getItemStack(); - if (slotId < 36) - return super.slotClick(slotId, dragType, clickTypeIn, player); - if (clickTypeIn == ClickType.THROW) - return ItemStack.EMPTY; - - int slot = slotId - 36; - if (clickTypeIn == ClickType.CLONE) { - if (player.isCreative() && held.isEmpty()) { - ItemStack stackInSlot = filterInventory.getStackInSlot(slot).copy(); - stackInSlot.setCount(64); - playerInventory.setItemStack(stackInSlot); - return ItemStack.EMPTY; - } - return ItemStack.EMPTY; - } - - if (held.isEmpty()) { - filterInventory.setStackInSlot(slot, ItemStack.EMPTY); - return ItemStack.EMPTY; - } - - ItemStack insert = held.copy(); - insert.setCount(1); - filterInventory.setStackInSlot(slot, insert); - return held; + return super.slotClick(slotId, dragType, clickTypeIn, player); } @Override - public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { - if (index < 36) { - ItemStack stackToInsert = playerInventory.getStackInSlot(index); - for (int i = 0; i < filterInventory.getSlots(); i++) { - ItemStack stack = filterInventory.getStackInSlot(i); - if (ItemHandlerHelper.canItemStacksStack(stack, stackToInsert)) - break; - if (stack.isEmpty()) { - ItemStack copy = stackToInsert.copy(); - copy.setCount(1); - filterInventory.insertItem(i, copy, false); - break; - } - } - } else - filterInventory.extractItem(index - 36, 1, false); - return ItemStack.EMPTY; + protected boolean allowRepeats() { + return false; } @Override - public void onContainerClosed(PlayerEntity playerIn) { - super.onContainerClosed(playerIn); - filterItem.getOrCreateTag().put("Items", filterInventory.serializeNBT()); - saveData(filterItem); + @OnlyIn(Dist.CLIENT) + protected ItemStack createOnClient(PacketBuffer extraData) { + return extraData.readItemStack(); + } + + protected abstract int getPlayerInventoryXOffset(); + + protected abstract int getPlayerInventoryYOffset(); + + protected abstract void addFilterSlots(); + + @Override + protected void addSlots() { + addPlayerSlots(getPlayerInventoryXOffset(), getPlayerInventoryYOffset()); + addFilterSlots(); + } + + @Override + protected void saveData(ItemStack contentHolder) { + contentHolder.getOrCreateTag() + .put("Items", ghostInventory.serializeNBT()); } } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java index bade51cb0..039b215ef 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AbstractFilterScreen.java @@ -22,7 +22,6 @@ import com.simibubi.create.foundation.networking.AllPackets; import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.renderer.Rectangle2d; -import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.ITextComponent; @@ -30,7 +29,7 @@ import net.minecraft.util.text.ITextComponent; public abstract class AbstractFilterScreen extends AbstractSimiContainerScreen { protected AllGuiTextures background; - private List extraAreas = Collections.EMPTY_LIST; + private List extraAreas = Collections.emptyList(); private IconButton resetButton; private IconButton confirmButton; @@ -42,37 +41,42 @@ public abstract class AbstractFilterScreen ex @Override protected void init() { - setWindowSize(PLAYER_INVENTORY.width, background.height + PLAYER_INVENTORY.height + 20); + setWindowSize(Math.max(background.width, PLAYER_INVENTORY.width), background.height + 4 + PLAYER_INVENTORY.height); super.init(); widgets.clear(); - int x = guiLeft - 50; - int offset = guiTop < 30 ? 30 - guiTop : 0; - extraAreas = ImmutableList.of(new Rectangle2d(x, guiTop + offset, background.width + 70, background.height - offset)); - resetButton = new IconButton(x + background.width - 62, guiTop + background.height - 24, AllIcons.I_TRASH); - confirmButton = new IconButton(x + background.width - 33, guiTop + background.height - 24, AllIcons.I_CONFIRM); + int x = guiLeft; + int y = guiTop; + + resetButton = new IconButton(x + background.width - 62, y + background.height - 24, AllIcons.I_TRASH); + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); widgets.add(resetButton); widgets.add(confirmButton); + + extraAreas = ImmutableList.of( + new Rectangle2d(x + background.width, y + background.height - 40, 80, 48) + ); } @Override protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { - int x = guiLeft - 50; + int invLeft = guiLeft - windowXOffset + (xSize - PLAYER_INVENTORY.width) / 2; + int invTop = guiTop + background.height + 4; + + PLAYER_INVENTORY.draw(ms, this, invLeft, invTop); + textRenderer.draw(ms, playerInventory.getDisplayName(), invLeft + 8, invTop + 6, 0x404040); + + int x = guiLeft; int y = guiTop; + background.draw(ms, this, x, y); + drawCenteredText(ms, textRenderer, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); - int invX = guiLeft; - int invY = y + background.height + 10; - PLAYER_INVENTORY.draw(ms, this, invX, invY); - textRenderer.draw(ms, playerInventory.getDisplayName(), invX + 7, invY + 6, 0x666666); - textRenderer.draw(ms, I18n.format(container.filterItem.getTranslationKey()), x + 15, y + 3, 0xdedede); - - GuiGameElement.of(container.filterItem) - .at(x + background.width, guiTop + background.height - 60, -200) + GuiGameElement.of(container.contentHolder) + .at(x + background.width, y + background.height - 56, -200) .scale(5) .render(ms); - } @Override @@ -82,7 +86,7 @@ public abstract class AbstractFilterScreen ex handleIndicators(); if (!container.player.getHeldItemMainhand() - .equals(container.filterItem, false)) + .equals(container.contentHolder, false)) client.player.closeScreen(); } @@ -146,7 +150,7 @@ public abstract class AbstractFilterScreen ex if (resetButton.isHovered()) { container.clearContents(); contentsCleared(); - sendOptionUpdate(Option.CLEAR); + container.sendClearPacket(); return true; } } @@ -164,4 +168,5 @@ public abstract class AbstractFilterScreen ex public List getExtraAreas() { return extraAreas; } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java index 8d4b209e8..c6ddeec64 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterContainer.java @@ -9,6 +9,7 @@ import com.simibubi.create.foundation.utility.Pair; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.ClickType; +import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; @@ -30,12 +31,16 @@ public class AttributeFilterContainer extends AbstractFilterContainer { WhitelistMode whitelistMode; List> selectedAttributes; - public AttributeFilterContainer(int id, PlayerInventory inv, PacketBuffer extraData) { - super(AllContainerTypes.ATTRIBUTE_FILTER.type, id, inv, extraData); + public AttributeFilterContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id, inv, extraData); } - public AttributeFilterContainer(int id, PlayerInventory inv, ItemStack stack) { - super(AllContainerTypes.ATTRIBUTE_FILTER.type, id, inv, stack); + public AttributeFilterContainer(ContainerType type, int id, PlayerInventory inv, ItemStack stack) { + super(type, id, inv, stack); + } + + public static AttributeFilterContainer create(int id, PlayerInventory inv, ItemStack stack) { + return new AttributeFilterContainer(AllContainerTypes.ATTRIBUTE_FILTER.get(), id, inv, stack); } public void appendSelectedAttribute(ItemAttribute itemAttribute, boolean inverted) { @@ -43,27 +48,28 @@ public class AttributeFilterContainer extends AbstractFilterContainer { } @Override - protected void clearContents() { - selectedAttributes.clear(); - } - - @Override - protected void init() { - super.init(); + protected void init(PlayerInventory inv, ItemStack contentHolder) { + super.init(inv, contentHolder); ItemStack stack = new ItemStack(Items.NAME_TAG); stack.setDisplayName( - new StringTextComponent("Selected Tags").formatted(TextFormatting.RESET, TextFormatting.BLUE)); - filterInventory.setStackInSlot(1, stack); + new StringTextComponent("Selected Tags").formatted(TextFormatting.RESET, TextFormatting.BLUE)); + ghostInventory.setStackInSlot(1, stack); } @Override - protected ItemStackHandler createFilterInventory() { - return new ItemStackHandler(2); + protected int getPlayerInventoryXOffset() { + return 51; } + @Override + protected int getPlayerInventoryYOffset() { + return 105; + } + + @Override protected void addFilterSlots() { - this.addSlot(new SlotItemHandler(filterInventory, 0, -34, 22)); - this.addSlot(new SlotItemHandler(filterInventory, 1, -28, 57) { + this.addSlot(new SlotItemHandler(ghostInventory, 0, 16, 22)); + this.addSlot(new SlotItemHandler(ghostInventory, 1, 22, 57) { @Override public boolean canTakeStack(PlayerEntity playerIn) { return false; @@ -71,6 +77,16 @@ public class AttributeFilterContainer extends AbstractFilterContainer { }); } + @Override + protected ItemStackHandler createGhostInventory() { + return new ItemStackHandler(2); + } + + @Override + public void clearContents() { + selectedAttributes.clear(); + } + @Override public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) { if (slotId == 37) @@ -97,23 +113,18 @@ public class AttributeFilterContainer extends AbstractFilterContainer { if (index == 37) return ItemStack.EMPTY; if (index == 36) { - filterInventory.setStackInSlot(37, ItemStack.EMPTY); + ghostInventory.setStackInSlot(37, ItemStack.EMPTY); return ItemStack.EMPTY; } if (index < 36) { ItemStack stackToInsert = playerInventory.getStackInSlot(index); ItemStack copy = stackToInsert.copy(); copy.setCount(1); - filterInventory.setStackInSlot(0, copy); + ghostInventory.setStackInSlot(0, copy); } return ItemStack.EMPTY; } - @Override - protected int getInventoryOffset() { - return 83; - } - @Override protected void readData(ItemStack filterItem) { selectedAttributes = new ArrayList<>(); @@ -129,14 +140,16 @@ public class AttributeFilterContainer extends AbstractFilterContainer { @Override protected void saveData(ItemStack filterItem) { + super.saveData(filterItem); filterItem.getOrCreateTag() - .putInt("WhitelistMode", whitelistMode.ordinal()); + .putInt("WhitelistMode", whitelistMode.ordinal()); ListNBT attributes = new ListNBT(); selectedAttributes.forEach(at -> { if (at == null) return; CompoundNBT compoundNBT = new CompoundNBT(); - at.getFirst().serializeNBT(compoundNBT); + at.getFirst() + .serializeNBT(compoundNBT); compoundNBT.putBoolean("Inverted", at.getSecond()); attributes.add(compoundNBT); }); diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java index b71172708..ba7ccfa45 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/AttributeFilterScreen.java @@ -61,8 +61,10 @@ public class AttributeFilterScreen extends AbstractFilterScreen type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id, inv, extraData); } - public FilterContainer(int id, PlayerInventory inv, ItemStack stack) { - super(AllContainerTypes.FILTER.type, id, inv, stack); + public FilterContainer(ContainerType type, int id, PlayerInventory inv, ItemStack stack) { + super(type, id, inv, stack); + } + + public static FilterContainer create(int id, PlayerInventory inv, ItemStack stack) { + return new FilterContainer(AllContainerTypes.FILTER.get(), id, inv, stack); + } + + @Override + protected int getPlayerInventoryXOffset() { + return 38; + } + + @Override + protected int getPlayerInventoryYOffset() { + return 119; } @Override protected void addFilterSlots() { - int x = -27; + int x = 23; int y = 20; - for (int row = 0; row < 2; ++row) for (int col = 0; col < 9; ++col) - this.addSlot(new SlotItemHandler(filterInventory, col + row * 9, x + col * 18, y + row * 18)); + this.addSlot(new SlotItemHandler(ghostInventory, col + row * 9, x + col * 18, y + row * 18)); } @Override - protected ItemStackHandler createFilterInventory() { - return FilterItem.getFilterItems(filterItem); - } - - @Override - protected int getInventoryOffset() { - return 97; + protected ItemStackHandler createGhostInventory() { + return FilterItem.getFilterItems(contentHolder); } @Override @@ -51,6 +60,7 @@ public class FilterContainer extends AbstractFilterContainer { @Override protected void saveData(ItemStack filterItem) { + super.saveData(filterItem); CompoundNBT tag = filterItem.getOrCreateTag(); tag.putBoolean("RespectNBT", respectNBT); tag.putBoolean("Blacklist", blacklist); diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterItem.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterItem.java index 16d7dcdf2..7687a2d7b 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterItem.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterItem.java @@ -31,6 +31,7 @@ import net.minecraft.util.Hand; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.world.World; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @@ -157,15 +158,15 @@ public class FilterItem extends Item implements INamedContainerProvider { public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { ItemStack heldItem = player.getHeldItemMainhand(); if (type == FilterType.REGULAR) - return new FilterContainer(id, inv, heldItem); + return FilterContainer.create(id, inv, heldItem); if (type == FilterType.ATTRIBUTE) - return new AttributeFilterContainer(id, inv, heldItem); + return AttributeFilterContainer.create(id, inv, heldItem); return null; } @Override public ITextComponent getDisplayName() { - return new StringTextComponent(getTranslationKey()); + return new TranslationTextComponent(getTranslationKey()); } public static ItemStackHandler getFilterItems(ItemStack stack) { diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java index 694adfe80..d4fcd2618 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreen.java @@ -40,7 +40,9 @@ public class FilterScreen extends AbstractFilterScreen { @Override protected void init() { + setWindowOffset(-11, 5); super.init(); + int x = guiLeft; int y = guiTop; @@ -59,6 +61,7 @@ public class FilterScreen extends AbstractFilterScreen { respectNBTIndicator = new Indicator(x + 60, y + 67, StringTextComponent.EMPTY); ignoreNBTIndicator = new Indicator(x + 78, y + 67, StringTextComponent.EMPTY); widgets.addAll(Arrays.asList(respectNBT, ignoreNBT, respectNBTIndicator, ignoreNBTIndicator)); + handleIndicators(); } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java index 071baffa2..1b1f61398 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/FilterScreenPacket.java @@ -13,7 +13,7 @@ import net.minecraftforge.fml.network.NetworkEvent.Context; public class FilterScreenPacket extends SimplePacketBase { public enum Option { - CLEAR, WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, UPDATE_FILTER_ITEM, ADD_TAG, ADD_INVERTED_TAG; + WHITELIST, WHITELIST2, BLACKLIST, RESPECT_DATA, IGNORE_DATA, UPDATE_FILTER_ITEM, ADD_TAG, ADD_INVERTED_TAG; } private final Option option; @@ -46,14 +46,6 @@ public class FilterScreenPacket extends SimplePacketBase { if (player == null) return; - if (player.openContainer instanceof AbstractFilterContainer) { - AbstractFilterContainer c = (AbstractFilterContainer) player.openContainer; - if (option == Option.CLEAR) { - c.clearContents(); - return; - } - } - if (player.openContainer instanceof FilterContainer) { FilterContainer c = (FilterContainer) player.openContainer; if (option == Option.WHITELIST) @@ -65,7 +57,7 @@ public class FilterScreenPacket extends SimplePacketBase { if (option == Option.IGNORE_DATA) c.respectNBT = false; if (option == Option.UPDATE_FILTER_ITEM) - c.filterInventory.setStackInSlot( + c.ghostInventory.setStackInSlot( data.getInt("Slot"), net.minecraft.item.ItemStack.read(data.getCompound("Item"))); } diff --git a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java b/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java index 884156c60..4f79b0eee 100644 --- a/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java +++ b/src/main/java/com/simibubi/create/content/logistics/item/filter/ItemAttribute.java @@ -12,7 +12,7 @@ import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import com.simibubi.create.AllRecipeTypes; -import com.simibubi.create.content.logistics.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import com.simibubi.create.content.logistics.item.filter.attribute.BookAuthorAttribute; import com.simibubi.create.content.logistics.item.filter.attribute.BookCopyAttribute; import com.simibubi.create.content.logistics.item.filter.attribute.ColorAttribute; @@ -222,7 +222,7 @@ public interface ItemAttribute { public static class InTag implements ItemAttribute { - ResourceLocation tagName; + public ResourceLocation tagName; public InTag(ResourceLocation tagName) { this.tagName = tagName; diff --git a/src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java b/src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java index dfb730b13..f51eb78a1 100644 --- a/src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java +++ b/src/main/java/com/simibubi/create/content/palettes/AllPaletteBlocks.java @@ -36,7 +36,7 @@ import net.minecraftforge.common.Tags; public class AllPaletteBlocks { private static final CreateRegistrate REGISTRATE = Create.registrate() - .itemGroup(() -> Create.palettesCreativeTab) + .itemGroup(() -> Create.PALETTES_CREATIVE_TAB) .startSection(AllSections.PALETTES); // Windows and Glass @@ -96,13 +96,13 @@ public class AllPaletteBlocks { // Vanilla stone variant patterns public static final PalettesVariantEntry GRANITE_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.GRANITE, PaletteBlockPatterns.vanillaRange, () -> Blocks.GRANITE); + new PalettesVariantEntry(PaletteStoneVariants.GRANITE, PaletteBlockPattern.VANILLA_RANGE, () -> Blocks.GRANITE); public static final PalettesVariantEntry DIORITE_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.DIORITE, PaletteBlockPatterns.vanillaRange, () -> Blocks.DIORITE); + new PalettesVariantEntry(PaletteStoneVariants.DIORITE, PaletteBlockPattern.VANILLA_RANGE, () -> Blocks.DIORITE); public static final PalettesVariantEntry ANDESITE_VARIANTS = new PalettesVariantEntry(PaletteStoneVariants.ANDESITE, - PaletteBlockPatterns.vanillaRange, () -> Blocks.ANDESITE); + PaletteBlockPattern.VANILLA_RANGE, () -> Blocks.ANDESITE); // Create stone variants @@ -115,37 +115,42 @@ public class AllPaletteBlocks { public static final BlockEntry LIMESTONE = REGISTRATE.baseBlock("limestone", Block::new, () -> Blocks.SANDSTONE, true) .tag(BlockTags.BASE_STONE_OVERWORLD) + .loot(cobblestoneLoot(PaletteStoneVariants.LIMESTONE)) .register(); public static final PalettesVariantEntry LIMESTONE_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.LIMESTONE, PaletteBlockPatterns.standardRange, LIMESTONE); + new PalettesVariantEntry(PaletteStoneVariants.LIMESTONE, PaletteBlockPattern.STANDARD_RANGE, LIMESTONE); public static final BlockEntry WEATHERED_LIMESTONE = REGISTRATE.baseBlock("weathered_limestone", Block::new, () -> Blocks.SANDSTONE, true) .tag(BlockTags.BASE_STONE_OVERWORLD) + .loot(cobblestoneLoot(PaletteStoneVariants.WEATHERED_LIMESTONE)) .register(); public static final PalettesVariantEntry WEATHERED_LIMESTONE_VARIANTS = new PalettesVariantEntry( - PaletteStoneVariants.WEATHERED_LIMESTONE, PaletteBlockPatterns.standardRange, WEATHERED_LIMESTONE); + PaletteStoneVariants.WEATHERED_LIMESTONE, PaletteBlockPattern.STANDARD_RANGE, WEATHERED_LIMESTONE); public static final BlockEntry DOLOMITE = REGISTRATE.baseBlock("dolomite", Block::new, () -> Blocks.QUARTZ_BLOCK, true) .tag(BlockTags.BASE_STONE_OVERWORLD) + .loot(cobblestoneLoot(PaletteStoneVariants.DOLOMITE)) .register(); public static final PalettesVariantEntry DOLOMITE_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.DOLOMITE, PaletteBlockPatterns.standardRange, DOLOMITE); + new PalettesVariantEntry(PaletteStoneVariants.DOLOMITE, PaletteBlockPattern.STANDARD_RANGE, DOLOMITE); public static final BlockEntry GABBRO = REGISTRATE.baseBlock("gabbro", Block::new, () -> Blocks.ANDESITE, true) .tag(BlockTags.BASE_STONE_OVERWORLD) + .loot(cobblestoneLoot(PaletteStoneVariants.GABBRO)) .register(); public static final PalettesVariantEntry GABBRO_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.GABBRO, PaletteBlockPatterns.standardRange, GABBRO); + new PalettesVariantEntry(PaletteStoneVariants.GABBRO, PaletteBlockPattern.STANDARD_RANGE, GABBRO); public static final BlockEntry SCORIA = REGISTRATE.baseBlock("scoria", Block::new, () -> Blocks.ANDESITE, true) + .loot(cobblestoneLoot(PaletteStoneVariants.SCORIA)) .register(); public static final BlockEntry NATURAL_SCORIA = REGISTRATE.block("natural_scoria", Block::new) @@ -158,18 +163,25 @@ public class AllPaletteBlocks { .register(); public static final PalettesVariantEntry SCORIA_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.SCORIA, PaletteBlockPatterns.standardRange, SCORIA); + new PalettesVariantEntry(PaletteStoneVariants.SCORIA, PaletteBlockPattern.STANDARD_RANGE, SCORIA); public static final BlockEntry DARK_SCORIA = REGISTRATE.baseBlock("dark_scoria", Block::new, () -> Blocks.ANDESITE, false) + .loot(cobblestoneLoot(PaletteStoneVariants.DARK_SCORIA)) .register(); public static final PalettesVariantEntry DARK_SCORIA_VARIANTS = - new PalettesVariantEntry(PaletteStoneVariants.DARK_SCORIA, PaletteBlockPatterns.standardRange, DARK_SCORIA); + new PalettesVariantEntry(PaletteStoneVariants.DARK_SCORIA, PaletteBlockPattern.STANDARD_RANGE, DARK_SCORIA); - public static void register() {} + private static NonNullBiConsumer cobblestoneLoot(PaletteStoneVariants variant) { + return (loot, block) -> loot.registerLootTable(block, RegistrateBlockLootTables.droppingWithSilkTouch(block, + variant.getVariants().registeredBlocks.get(0).get())); + } private static NonNullBiConsumer, RegistrateBlockstateProvider> palettesCubeAll() { return (c, p) -> BlockStateGen.cubeAll(c, p, "palettes/"); } + + public static void register() {} + } 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 ba6ff24a4..9c79046af 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java +++ b/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPartial.java @@ -34,8 +34,8 @@ public abstract class PaletteBlockPartial { public static final PaletteBlockPartial UNIQUE_SLAB = new Slab(true); public static final PaletteBlockPartial WALL = new Wall(); - public static final PaletteBlockPartial[] AllPartials = { STAIR, SLAB, WALL }; - public static final PaletteBlockPartial[] ForPolished = { STAIR, UNIQUE_SLAB, WALL }; + public static final PaletteBlockPartial[] ALL_PARTIALS = { STAIR, SLAB, WALL }; + public static final PaletteBlockPartial[] FOR_POLISHED = { STAIR, UNIQUE_SLAB, WALL }; private String name; @@ -43,7 +43,7 @@ public abstract class PaletteBlockPartial { this.name = name; } - public @NonnullType BlockBuilder create(String variantName, PaletteBlockPatterns pattern, + public @NonnullType BlockBuilder create(String variantName, PaletteBlockPattern pattern, Supplier block) { String patternName = pattern.createName(variantName); String blockName = patternName + "_" + this.name; @@ -57,19 +57,19 @@ public abstract class PaletteBlockPartial { .build(); } - protected ResourceLocation getMainTexture(String variantName, PaletteBlockPatterns pattern) { + protected ResourceLocation getMainTexture(String variantName, PaletteBlockPattern pattern) { return pattern.toLocation(variantName, pattern.getTextureForPartials()); } protected BlockBuilder transformBlock(BlockBuilder builder, - String variantName, PaletteBlockPatterns pattern) { + String variantName, PaletteBlockPattern pattern) { getBlockTags().forEach(builder::tag); return builder; } protected ItemBuilder> transformItem( ItemBuilder> builder, String variantName, - PaletteBlockPatterns pattern) { + PaletteBlockPattern pattern) { getItemTags().forEach(builder::tag); return builder; } @@ -84,7 +84,7 @@ public abstract class PaletteBlockPartial { RegistrateRecipeProvider p); protected abstract void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - String variantName, PaletteBlockPatterns pattern, Supplier block); + String variantName, PaletteBlockPattern pattern, Supplier block); private static class Stairs extends PaletteBlockPartial { @@ -100,7 +100,7 @@ public abstract class PaletteBlockPartial { @Override protected void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - String variantName, PaletteBlockPatterns pattern, Supplier block) { + String variantName, PaletteBlockPattern pattern, Supplier block) { prov.stairsBlock(ctx.get(), getMainTexture(variantName, pattern)); } @@ -140,7 +140,7 @@ public abstract class PaletteBlockPartial { @Override protected void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - String variantName, PaletteBlockPatterns pattern, Supplier block) { + String variantName, PaletteBlockPattern pattern, Supplier block) { String name = ctx.getName(); ResourceLocation mainTexture = getMainTexture(variantName, pattern); ResourceLocation sideTexture = @@ -185,7 +185,7 @@ public abstract class PaletteBlockPartial { @Override protected BlockBuilder transformBlock( BlockBuilder builder, - String variantName, PaletteBlockPatterns pattern) { + String variantName, PaletteBlockPattern pattern) { builder.loot((lt, block) -> lt.registerLootTable(block, RegistrateBlockLootTables.droppingSlab(block))); return super.transformBlock(builder, variantName, pattern); } @@ -206,14 +206,14 @@ public abstract class PaletteBlockPartial { @Override protected ItemBuilder> transformItem( ItemBuilder> builder, String variantName, - PaletteBlockPatterns pattern) { + PaletteBlockPattern pattern) { builder.model((c, p) -> p.wallInventory(c.getName(), getMainTexture(variantName, pattern))); return super.transformItem(builder, variantName, pattern); } @Override protected void generateBlockState(DataGenContext ctx, RegistrateBlockstateProvider prov, - String variantName, PaletteBlockPatterns pattern, Supplier block) { + String variantName, PaletteBlockPattern pattern, Supplier block) { prov.wallBlock(ctx.get(), pattern.createName(variantName), getMainTexture(variantName, pattern)); } diff --git a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPatterns.java b/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPattern.java similarity index 70% rename from src/main/java/com/simibubi/create/content/palettes/PaletteBlockPatterns.java rename to src/main/java/com/simibubi/create/content/palettes/PaletteBlockPattern.java index 4fa8d9b7d..16cdd6dfe 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPatterns.java +++ b/src/main/java/com/simibubi/create/content/palettes/PaletteBlockPattern.java @@ -1,10 +1,10 @@ package com.simibubi.create.content.palettes; -import static com.simibubi.create.content.palettes.PaletteBlockPartial.AllPartials; -import static com.simibubi.create.content.palettes.PaletteBlockPartial.ForPolished; -import static com.simibubi.create.content.palettes.PatternNameType.Prefix; -import static com.simibubi.create.content.palettes.PatternNameType.Suffix; -import static com.simibubi.create.content.palettes.PatternNameType.Wrap; +import static com.simibubi.create.content.palettes.PaletteBlockPartial.ALL_PARTIALS; +import static com.simibubi.create.content.palettes.PaletteBlockPartial.FOR_POLISHED; +import static com.simibubi.create.content.palettes.PaletteBlockPattern.PatternNameType.PREFIX; +import static com.simibubi.create.content.palettes.PaletteBlockPattern.PatternNameType.SUFFIX; +import static com.simibubi.create.content.palettes.PaletteBlockPattern.PatternNameType.WRAP; import java.util.Optional; import java.util.function.Function; @@ -28,73 +28,83 @@ import net.minecraft.block.AbstractBlock.Properties; import net.minecraft.block.Block; import net.minecraft.block.RotatedPillarBlock; import net.minecraft.client.renderer.RenderType; +import net.minecraft.data.CookingRecipeBuilder; import net.minecraft.data.ShapedRecipeBuilder; import net.minecraft.util.ResourceLocation; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.client.model.generators.ModelFile; -public class PaletteBlockPatterns { +public class PaletteBlockPattern { - public static final PaletteBlockPatterns + public static final PaletteBlockPattern - COBBLESTONE = create("cobblestone", Suffix, AllPartials), + COBBLESTONE = create("cobblestone", SUFFIX, ALL_PARTIALS) + .addRecipes(v -> (c, p) -> { + DataIngredient ingredient = DataIngredient.items(c.get()); + Block result = v.getBaseBlock().get(); + CookingRecipeBuilder.smeltingRecipe(ingredient, result, 0.1f, 200) + .addCriterion("has_" + p.safeName(ingredient), ingredient.getCritereon(p)) + .build(p, p.safeId(result)); + }), - POLISHED = create("polished", Prefix, ForPolished) - .addRecipes(v -> (c, - p) -> { + POLISHED = create("polished", PREFIX, FOR_POLISHED) + .addRecipes(v -> (c, p) -> { DataIngredient ingredient = DataIngredient.items(v.getBaseBlock().get()); - ShapedRecipeBuilder.shapedRecipe(c.get(), 4).key('X', ingredient) - .patternLine("XX").patternLine("XX") - .addCriterion("has_" + p.safeName(ingredient), ingredient.getCritereon(p)).build(p, p.safeId(c.get())); - } - ), + ShapedRecipeBuilder.shapedRecipe(c.get(), 4) + .key('#', ingredient) + .patternLine("##") + .patternLine("##") + .addCriterion("has_" + p.safeName(ingredient), ingredient.getCritereon(p)) + .build(p, p.safeId(c.get())); + }), - BRICKS = create("bricks", Suffix, AllPartials), FANCY_BRICKS = create("fancy_bricks", Wrap, AllPartials), + BRICKS = create("bricks", SUFFIX, ALL_PARTIALS), FANCY_BRICKS = create("fancy_bricks", WRAP, ALL_PARTIALS), - PAVED = create("paved", Prefix, AllPartials).blockStateFactory(p -> p::paved) + PAVED = create("paved", PREFIX, ALL_PARTIALS).blockStateFactory(p -> p::paved) .block(PavedBlock::new) .textures("paved", "paved_borderless", "paved_top"), - LAYERED = create("layered", Prefix).blockStateFactory(p -> p::cubeColumn) + LAYERED = create("layered", PREFIX).blockStateFactory(p -> p::cubeColumn) .textures("layered", "polished") .connectedTextures(v -> new HorizontalCTBehaviour(ct(v, CTs.LAYERED), ct(v, CTs.POLISHED))), - CHISELED = create("chiseled", Prefix).blockStateFactory(p -> p::cubeColumn) + CHISELED = create("chiseled", PREFIX).blockStateFactory(p -> p::cubeColumn) .textures("chiseled", "chiseled_top"), - PILLAR = create("pillar", Suffix).blockStateFactory(p -> p::pillar) + PILLAR = create("pillar", SUFFIX).blockStateFactory(p -> p::pillar) .block(RotatedPillarBlock::new) .textures("pillar", "pillar_end") - .addRecipes(v -> (c, p) -> ShapedRecipeBuilder.shapedRecipe(c.get(), 2) - .key('#', v.getBaseBlock() - .get()) - .patternLine("#") - .patternLine("#") - .addCriterion("has_ingredient", p.hasItem(v.getBaseBlock() - .get())) - .build(p::accept)), + .addRecipes(v -> (c, p) -> { + DataIngredient ingredient = DataIngredient.items(v.getBaseBlock().get()); + ShapedRecipeBuilder.shapedRecipe(c.get(), 2) + .key('#', ingredient) + .patternLine("#") + .patternLine("#") + .addCriterion("has_" + p.safeName(ingredient), ingredient.getCritereon(p)) + .build(p, p.safeId(c.get())); + }), - MOSSY = create("mossy", Prefix).blockStateFactory(p -> p::cubeAllButMossy) + MOSSY = create("mossy", PREFIX).blockStateFactory(p -> p::cubeAllButMossy) .textures("bricks", "mossy") .useTranslucentLayer() .withFoliage(), - OVERGROWN = create("overgrown", Prefix).blockStateFactory(p -> p::cubeAllButMossy) + OVERGROWN = create("overgrown", PREFIX).blockStateFactory(p -> p::cubeAllButMossy) .textures("bricks", "overgrown") .useTranslucentLayer() .withFoliage() ; - public static final PaletteBlockPatterns[] vanillaRange = + public static final PaletteBlockPattern[] VANILLA_RANGE = { COBBLESTONE, BRICKS, FANCY_BRICKS, PILLAR, PAVED, LAYERED, MOSSY, OVERGROWN }; - public static final PaletteBlockPatterns[] standardRange = + public static final PaletteBlockPattern[] STANDARD_RANGE = { COBBLESTONE, POLISHED, BRICKS, FANCY_BRICKS, PILLAR, PAVED, LAYERED, CHISELED, MOSSY, OVERGROWN }; - static final String textureLocation = "block/palettes/%s/%s"; - static final String overlayLocation = "block/palettes/%s"; + static final String TEXTURE_LOCATION = "block/palettes/%s/%s"; + static final String OVERLAY_LOCATION = "block/palettes/%s"; private PatternNameType nameType; private String[] textures; @@ -111,9 +121,9 @@ public class PaletteBlockPatterns { @OnlyIn(Dist.CLIENT) private RenderType renderType; - private static PaletteBlockPatterns create(String name, PatternNameType nameType, + private static PaletteBlockPattern create(String name, PatternNameType nameType, PaletteBlockPartial... partials) { - PaletteBlockPatterns pattern = new PaletteBlockPatterns(); + PaletteBlockPattern pattern = new PaletteBlockPattern(); pattern.id = name; pattern.ctBehaviour = Optional.empty(); pattern.nameType = nameType; @@ -163,37 +173,37 @@ public class PaletteBlockPatterns { // Builder - private PaletteBlockPatterns blockStateFactory(IPatternBlockStateGenerator factory) { + private PaletteBlockPattern blockStateFactory(IPatternBlockStateGenerator factory) { blockStateGenerator = factory; return this; } - private PaletteBlockPatterns textures(String... textures) { + private PaletteBlockPattern textures(String... textures) { this.textures = textures; return this; } - private PaletteBlockPatterns block(NonNullFunction blockFactory) { + private PaletteBlockPattern block(NonNullFunction blockFactory) { this.blockFactory = blockFactory; return this; } - private PaletteBlockPatterns useTranslucentLayer() { + private PaletteBlockPattern useTranslucentLayer() { isTranslucent = true; return this; } - private PaletteBlockPatterns withFoliage() { + private PaletteBlockPattern withFoliage() { hasFoliage = true; return this; } - private PaletteBlockPatterns connectedTextures(Function factory) { + private PaletteBlockPattern connectedTextures(Function factory) { this.ctBehaviour = Optional.of(factory); return this; } - private PaletteBlockPatterns addRecipes( + private PaletteBlockPattern addRecipes( NonNullFunction, RegistrateRecipeProvider>> func) { this.additionalRecipes = func; return this; @@ -251,7 +261,7 @@ public class PaletteBlockPatterns { // Utility protected String createName(String variant) { - if (nameType == Wrap) { + if (nameType == WRAP) { String[] split = id.split("_"); if (split.length == 2) { String formatString = "%s_%s_%s"; @@ -259,15 +269,15 @@ public class PaletteBlockPatterns { } } String formatString = "%s_%s"; - return nameType == Suffix ? String.format(formatString, variant, id) : String.format(formatString, id, variant); + return nameType == SUFFIX ? String.format(formatString, variant, id) : String.format(formatString, id, variant); } protected ResourceLocation toLocation(String variant, String texture) { - return Create.asResource(String.format(textureLocation, variant, texture)); + return Create.asResource(String.format(TEXTURE_LOCATION, variant, texture)); } protected ResourceLocation toOverlayLocation(String texture) { - return Create.asResource(String.format(overlayLocation, texture)); + return Create.asResource(String.format(OVERLAY_LOCATION, texture)); } protected static CTSpriteShiftEntry ct(PaletteStoneVariants variant, CTs texture) { @@ -276,7 +286,7 @@ public class PaletteBlockPatterns { @FunctionalInterface static interface IPatternBlockStateGenerator - extends Function> { + extends Function> { } @FunctionalInterface @@ -284,6 +294,10 @@ public class PaletteBlockPatterns { extends NonNullBiConsumer, RegistrateBlockstateProvider> { } + enum PatternNameType { + PREFIX, SUFFIX, WRAP + } + // Textures with connectability, used by Spriteshifter public static enum CTs { diff --git a/src/main/java/com/simibubi/create/content/palettes/PaletteStoneVariants.java b/src/main/java/com/simibubi/create/content/palettes/PaletteStoneVariants.java index ac43b64e9..f15d019f3 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PaletteStoneVariants.java +++ b/src/main/java/com/simibubi/create/content/palettes/PaletteStoneVariants.java @@ -7,26 +7,32 @@ import net.minecraft.block.Blocks; public enum PaletteStoneVariants { - GRANITE(() -> () -> Blocks.GRANITE), - DIORITE(() -> () -> Blocks.DIORITE), - ANDESITE(() -> () -> Blocks.ANDESITE), - LIMESTONE(() -> AllPaletteBlocks.LIMESTONE), - WEATHERED_LIMESTONE(() -> AllPaletteBlocks.WEATHERED_LIMESTONE), - DOLOMITE(() -> AllPaletteBlocks.DOLOMITE), - GABBRO(() -> AllPaletteBlocks.GABBRO), - SCORIA(() -> AllPaletteBlocks.SCORIA), - DARK_SCORIA(() -> AllPaletteBlocks.DARK_SCORIA) + GRANITE(() -> () -> Blocks.GRANITE, () -> AllPaletteBlocks.GRANITE_VARIANTS), + DIORITE(() -> () -> Blocks.DIORITE, () -> AllPaletteBlocks.DIORITE_VARIANTS), + ANDESITE(() -> () -> Blocks.ANDESITE, () -> AllPaletteBlocks.ANDESITE_VARIANTS), + LIMESTONE(() -> AllPaletteBlocks.LIMESTONE, () -> AllPaletteBlocks.LIMESTONE_VARIANTS), + WEATHERED_LIMESTONE(() -> AllPaletteBlocks.WEATHERED_LIMESTONE, () -> AllPaletteBlocks.WEATHERED_LIMESTONE_VARIANTS), + DOLOMITE(() -> AllPaletteBlocks.DOLOMITE, () -> AllPaletteBlocks.DOLOMITE_VARIANTS), + GABBRO(() -> AllPaletteBlocks.GABBRO, () -> AllPaletteBlocks.GABBRO_VARIANTS), + SCORIA(() -> AllPaletteBlocks.SCORIA, () -> AllPaletteBlocks.SCORIA_VARIANTS), + DARK_SCORIA(() -> AllPaletteBlocks.DARK_SCORIA, () -> AllPaletteBlocks.DARK_SCORIA_VARIANTS) ; private Supplier> baseBlock; + private Supplier variants; - private PaletteStoneVariants(Supplier> baseBlock) { + private PaletteStoneVariants(Supplier> baseBlock, Supplier variants) { this.baseBlock = baseBlock; + this.variants = variants; } public Supplier getBaseBlock() { return baseBlock.get(); } + public PalettesVariantEntry getVariants() { + return variants.get(); + } + } diff --git a/src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java b/src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java index 794016d13..9543a7b37 100644 --- a/src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java +++ b/src/main/java/com/simibubi/create/content/palettes/PalettesVariantEntry.java @@ -3,10 +3,10 @@ package com.simibubi.create.content.palettes; import static com.simibubi.create.foundation.data.CreateRegistrate.connectedTextures; import com.google.common.collect.ImmutableList; -import com.simibubi.create.AllColorHandlers; import com.simibubi.create.AllTags; import com.simibubi.create.Create; import com.simibubi.create.foundation.data.CreateRegistrate; +import com.simibubi.create.foundation.utility.ColorHandlers; import com.simibubi.create.foundation.utility.Lang; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.util.DataIngredient; @@ -21,14 +21,13 @@ public class PalettesVariantEntry { public ImmutableList> registeredBlocks; public ImmutableList> registeredPartials; - public PalettesVariantEntry(PaletteStoneVariants variant, PaletteBlockPatterns[] patterns, + public PalettesVariantEntry(PaletteStoneVariants variant, PaletteBlockPattern[] patterns, NonNullSupplier initialProperties) { - String name = Lang.asId(variant.name()); ImmutableList.Builder> registeredBlocks = ImmutableList.builder(); ImmutableList.Builder> registeredPartials = ImmutableList.builder(); - for (PaletteBlockPatterns pattern : patterns) { + for (PaletteBlockPattern pattern : patterns) { CreateRegistrate registrate = Create.registrate(); BlockBuilder builder = registrate.block(pattern.createName(name), pattern.getBlockFactory()) @@ -39,10 +38,10 @@ public class PalettesVariantEntry { if (pattern.isTranslucent()) builder.addLayer(() -> RenderType::getTranslucent); - if (pattern == PaletteBlockPatterns.COBBLESTONE) + if (pattern == PaletteBlockPattern.COBBLESTONE) builder.item().tag(AllTags.AllItemTags.COBBLESTONE.tag); if (pattern.hasFoliage()) - builder.onRegister(CreateRegistrate.blockColors(() -> AllColorHandlers::getGrassyBlock)); + builder.color(() -> ColorHandlers::getGrassyBlock); pattern.createCTBehaviour(variant) .ifPresent(b -> builder.onRegister(connectedTextures(b))); @@ -54,7 +53,7 @@ public class PalettesVariantEntry { if (pattern.hasFoliage()) builder.item() - .onRegister(CreateRegistrate.itemColors(() -> AllColorHandlers::getGrassyItem)) + .color(() -> ColorHandlers::getGrassyItem) .build(); else builder.simpleItem(); @@ -65,11 +64,10 @@ public class PalettesVariantEntry { for (PaletteBlockPartial partialBlock : pattern.getPartials()) registeredPartials.add(partialBlock.create(name, pattern, block) .register()); - } + this.registeredBlocks = registeredBlocks.build(); this.registeredPartials = registeredPartials.build(); - } } diff --git a/src/main/java/com/simibubi/create/content/palettes/PatternNameType.java b/src/main/java/com/simibubi/create/content/palettes/PatternNameType.java deleted file mode 100644 index 67c9cf1d5..000000000 --- a/src/main/java/com/simibubi/create/content/palettes/PatternNameType.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.simibubi.create.content.palettes; - -enum PatternNameType { - Prefix, Suffix, Wrap -} \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/palettes/ScoriaVertexColor.java b/src/main/java/com/simibubi/create/content/palettes/ScoriaVertexColor.java index ef93a2872..0629ec035 100644 --- a/src/main/java/com/simibubi/create/content/palettes/ScoriaVertexColor.java +++ b/src/main/java/com/simibubi/create/content/palettes/ScoriaVertexColor.java @@ -1,6 +1,6 @@ package com.simibubi.create.content.palettes; -import com.simibubi.create.foundation.block.IBlockVertexColor; +import com.simibubi.create.foundation.block.render.IBlockVertexColor; import com.simibubi.create.foundation.utility.ColorHelper; public class ScoriaVertexColor implements IBlockVertexColor { diff --git a/src/main/java/com/simibubi/create/content/schematics/ClientSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ClientSchematicLoader.java index 9ddd18729..0416a9acd 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ClientSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ClientSchematicLoader.java @@ -59,7 +59,7 @@ public class ClientSchematicLoader { Path path = Paths.get("schematics", schematic); if (!Files.exists(path)) { - Create.logger.fatal("Missing Schematic file: " + path.toString()); + Create.LOGGER.fatal("Missing Schematic file: " + path.toString()); return; } diff --git a/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java index c23feb02a..d8c65892a 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java +++ b/src/main/java/com/simibubi/create/content/schematics/ISpecialBlockItemRequirement.java @@ -1,11 +1,12 @@ package com.simibubi.create.content.schematics; import net.minecraft.block.BlockState; +import net.minecraft.tileentity.TileEntity; public interface ISpecialBlockItemRequirement { - default ItemRequirement getRequiredItems(BlockState state) { + default ItemRequirement getRequiredItems(BlockState state, TileEntity te) { return ItemRequirement.INVALID; } - + } diff --git a/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java b/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java index 67c013348..e4fa3f827 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java +++ b/src/main/java/com/simibubi/create/content/schematics/ItemRequirement.java @@ -3,6 +3,10 @@ package com.simibubi.create.content.schematics; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import net.minecraft.block.Block; import net.minecraft.block.BlockState; @@ -24,6 +28,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.SlabType; +import net.minecraft.tileentity.TileEntity; public class ItemRequirement { @@ -31,8 +36,17 @@ public class ItemRequirement { CONSUME, DAMAGE } - ItemUseType usage; - List requiredItems; + public static class StackRequirement { + public final ItemStack item; + public final ItemUseType usage; + + public StackRequirement(ItemUseType usage, ItemStack item) { + this.item = item; + this.usage = usage; + } + } + + List requiredItems; public static ItemRequirement INVALID = new ItemRequirement(); public static ItemRequirement NONE = new ItemRequirement(); @@ -40,21 +54,43 @@ public class ItemRequirement { private ItemRequirement() { } - public ItemRequirement(ItemUseType usage, Item item) { - this(usage, Arrays.asList(new ItemStack(item))); - } - - public ItemRequirement(ItemUseType usage, List requiredItems) { - this.usage = usage; + public ItemRequirement(List requiredItems) { this.requiredItems = requiredItems; } - public static ItemRequirement of(BlockState state) { + public ItemRequirement(ItemUseType usage, ItemStack items) { + this(Arrays.asList(new StackRequirement(usage, items))); + } + + public ItemRequirement(ItemUseType usage, Item item) { + this(usage, new ItemStack(item)); + } + + public ItemRequirement(ItemUseType usage, List requiredItems) { + this(requiredItems.stream().map(req -> new StackRequirement(usage, req)).collect(Collectors.toList())); + } + + + public static ItemRequirement of(BlockState state, TileEntity te) { Block block = state.getBlock(); + + ItemRequirement baseRequirement; + if (block instanceof ISpecialBlockItemRequirement) { + baseRequirement = ((ISpecialBlockItemRequirement) block).getRequiredItems(state, te); + } else { + baseRequirement = ofBlockState(state, block); + } + + // Behaviours can add additional required items + if (te instanceof SmartTileEntity) + baseRequirement = baseRequirement.with(((SmartTileEntity) te).getRequiredItems()); + + return baseRequirement; + } + + private static ItemRequirement ofBlockState(BlockState state, Block block) { if (block == Blocks.AIR) return NONE; - if (block instanceof ISpecialBlockItemRequirement) - return ((ISpecialBlockItemRequirement) block).getRequiredItems(state); Item item = BlockItem.BLOCK_TO_ITEM.getOrDefault(state.getBlock(), Items.AIR); @@ -125,16 +161,25 @@ public class ItemRequirement { return INVALID == this; } - public List getRequiredItems() { + public List getRequiredItems() { return requiredItems; } - public ItemUseType getUsage() { - return usage; - } - public static boolean validate(ItemStack required, ItemStack present) { return required.isEmpty() || required.getItem() == present.getItem(); } + public ItemRequirement with(ItemRequirement other) { + if (this.isInvalid() || other.isInvalid()) + return INVALID; + if (this.isEmpty()) + return other; + if (other.isEmpty()) + return this; + + return new ItemRequirement( + Stream.concat(requiredItems.stream(), other.requiredItems.stream()).collect(Collectors.toList()) + ); + } + } diff --git a/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java b/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java index e4a37dcc3..1619173b4 100644 --- a/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java +++ b/src/main/java/com/simibubi/create/content/schematics/MaterialChecklist.java @@ -43,11 +43,11 @@ public class MaterialChecklist { if (requirement.isInvalid()) return; - for (ItemStack stack : requirement.requiredItems) { - if (requirement.getUsage() == ItemUseType.DAMAGE) - putOrIncrement(damageRequired, stack); - if (requirement.getUsage() == ItemUseType.CONSUME) - putOrIncrement(required, stack); + for (ItemRequirement.StackRequirement stack : requirement.requiredItems) { + if (stack.usage == ItemUseType.DAMAGE) + putOrIncrement(damageRequired, stack.item); + if (stack.usage == ItemUseType.CONSUME) + putOrIncrement(required, stack.item); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java b/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java new file mode 100644 index 000000000..4006b976a --- /dev/null +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicPrinter.java @@ -0,0 +1,298 @@ +package com.simibubi.create.content.schematics; + +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks; +import com.simibubi.create.content.schematics.item.SchematicItem; +import com.simibubi.create.foundation.utility.BlockHelper; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.nbt.NBTUtil; +import net.minecraft.state.properties.BedPart; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.state.properties.DoubleBlockHalf; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MutableBoundingBox; +import net.minecraft.util.math.vector.Vector3i; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.template.PlacementSettings; +import net.minecraft.world.gen.feature.template.Template; + +public class SchematicPrinter { + + public enum PrintStage { + BLOCKS, DEFERRED_BLOCKS, ENTITIES + } + + private boolean schematicLoaded; + private SchematicWorld blockReader; + private BlockPos schematicAnchor; + + private BlockPos currentPos; + private int printingEntityIndex; + private PrintStage printStage; + private List deferredBlocks; + + public SchematicPrinter() { + printingEntityIndex = -1; + printStage = PrintStage.BLOCKS; + deferredBlocks = new LinkedList<>(); + } + + public void fromTag(CompoundNBT compound, boolean clientPacket) { + if (compound.contains("CurrentPos")) + currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos")); + + printingEntityIndex = compound.getInt("EntityProgress"); + printStage = PrintStage.valueOf(compound.getString("PrintStage")); + compound.getList("DeferredBlocks", 10).stream() + .map(p -> NBTUtil.readBlockPos((CompoundNBT) p)) + .collect(Collectors.toCollection(() -> deferredBlocks)); + } + + public void write(CompoundNBT compound) { + if (currentPos != null) + compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos)); + + compound.putInt("EntityProgress", printingEntityIndex); + compound.putString("PrintStage", printStage.name()); + ListNBT tagDeferredBlocks = new ListNBT(); + for (BlockPos p : deferredBlocks) + tagDeferredBlocks.add(NBTUtil.writeBlockPos(p)); + compound.put("DeferredBlocks", tagDeferredBlocks); + } + + public void loadSchematic(ItemStack blueprint, World originalWorld, boolean processNBT) { + if (!blueprint.hasTag() || !blueprint.getTag().getBoolean("Deployed")) + return; + + Template activeTemplate = SchematicItem.loadSchematic(blueprint); + PlacementSettings settings = SchematicItem.getSettings(blueprint, processNBT); + + schematicAnchor = NBTUtil.readBlockPos(blueprint.getTag().getCompound("Anchor")); + blockReader = new SchematicWorld(schematicAnchor, originalWorld); + activeTemplate.place(blockReader, schematicAnchor, settings, blockReader.getRandom()); + + printingEntityIndex = -1; + printStage = PrintStage.BLOCKS; + deferredBlocks.clear(); + MutableBoundingBox bounds = blockReader.getBounds(); + currentPos = new BlockPos(bounds.minX - 1, bounds.minY, bounds.minZ); + schematicLoaded = true; + } + + public void resetSchematic() { + schematicLoaded = false; + schematicAnchor = null; + currentPos = null; + blockReader = null; + printingEntityIndex = -1; + printStage = PrintStage.BLOCKS; + deferredBlocks.clear(); + } + + public boolean isLoaded() { + return schematicLoaded; + } + + public BlockPos getCurrentTarget() { + if (!isLoaded()) + return null; + return schematicAnchor.add(currentPos); + } + + public PrintStage getPrintStage() { + return printStage; + } + + public BlockPos getAnchor() { + return schematicAnchor; + } + + public boolean isWorldEmpty() { + return blockReader.getBounds().getLength().equals(new Vector3i(0,0,0)); + } + + @FunctionalInterface + public interface BlockTargetHandler { + void handle(BlockPos target, BlockState blockState, TileEntity tileEntity); + } + @FunctionalInterface + public interface EntityTargetHandler { + void handle(BlockPos target, Entity entity); + } + + public void handleCurrentTarget(BlockTargetHandler blockHandler, EntityTargetHandler entityHandler) { + BlockPos target = getCurrentTarget(); + + if (printStage == PrintStage.ENTITIES) { + Entity entity = blockReader.getEntities() + .collect(Collectors.toList()) + .get(printingEntityIndex); + entityHandler.handle(target, entity); + } else { + BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); + TileEntity tileEntity = blockReader.getTileEntity(target); + blockHandler.handle(target, blockState, tileEntity); + } + } + + @FunctionalInterface + public interface PlacementPredicate { + boolean shouldPlace(BlockPos target, BlockState blockState, TileEntity tileEntity, + BlockState toReplace, BlockState toReplaceOther, boolean isNormalCube); + } + + public boolean shouldPlaceCurrent(World world) { return shouldPlaceCurrent(world, (a,b,c,d,e,f) -> true); } + + public boolean shouldPlaceCurrent(World world, PlacementPredicate predicate) { + if (world == null) + return false; + + if (printStage == PrintStage.ENTITIES) + return true; + + return shouldPlaceBlock(world, predicate, getCurrentTarget()); + } + + public boolean shouldPlaceBlock(World world, PlacementPredicate predicate, BlockPos pos) { + BlockState state = BlockHelper.setZeroAge(blockReader.getBlockState(pos)); + TileEntity tileEntity = blockReader.getTileEntity(pos); + + BlockState toReplace = world.getBlockState(pos); + BlockState toReplaceOther = null; + if (state.contains(BlockStateProperties.BED_PART) && state.contains(BlockStateProperties.HORIZONTAL_FACING) + && state.get(BlockStateProperties.BED_PART) == BedPart.FOOT) + toReplaceOther = world.getBlockState(pos.offset(state.get(BlockStateProperties.HORIZONTAL_FACING))); + if (state.contains(BlockStateProperties.DOUBLE_BLOCK_HALF) + && state.get(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER) + toReplaceOther = world.getBlockState(pos.up()); + + if (!world.isBlockPresent(pos)) + return false; + if (!world.getWorldBorder().contains(pos)) + return false; + if (toReplace == state) + return false; + if (toReplace.getBlockHardness(world, pos) == -1 + || (toReplaceOther != null && toReplaceOther.getBlockHardness(world, pos) == -1)) + return false; + + boolean isNormalCube = state.isNormalCube(blockReader, currentPos); + return predicate.shouldPlace(pos, state, tileEntity, toReplace, toReplaceOther, isNormalCube); + } + + public ItemRequirement getCurrentRequirement() { + if (printStage == PrintStage.ENTITIES) + return ItemRequirement.of(blockReader.getEntities() + .collect(Collectors.toList()) + .get(printingEntityIndex)); + + BlockPos target = getCurrentTarget(); + BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); + TileEntity tileEntity = blockReader.getTileEntity(target); + return ItemRequirement.of(blockState, tileEntity); + } + + public int markAllBlockRequirements(MaterialChecklist checklist, World world, PlacementPredicate predicate) { + int blocksToPlace = 0; + for (BlockPos pos : blockReader.getAllPositions()) { + BlockPos relPos = pos.add(schematicAnchor); + BlockState required = blockReader.getBlockState(relPos); + TileEntity requiredTE = blockReader.getTileEntity(relPos); + + if (!world.isAreaLoaded(pos.add(schematicAnchor), 0)) { + checklist.warnBlockNotLoaded(); + continue; + } + if (!shouldPlaceBlock(world, predicate, relPos)) + continue; + ItemRequirement requirement = ItemRequirement.of(required, requiredTE); + if (requirement.isEmpty()) + continue; + if (requirement.isInvalid()) + continue; + checklist.require(requirement); + blocksToPlace++; + } + return blocksToPlace; + } + + public void markAllEntityRequirements(MaterialChecklist checklist) { + blockReader.getEntities() + .forEach(entity -> { + ItemRequirement requirement = ItemRequirement.of(entity); + if (requirement.isEmpty()) + return; + if (requirement.isInvalid()) + return; + checklist.require(requirement); + }); + } + + public boolean advanceCurrentPos() { + List entities = blockReader.getEntities().collect(Collectors.toList()); + + do { + if (printStage == PrintStage.BLOCKS) { + while (tryAdvanceCurrentPos()) { + deferredBlocks.add(currentPos); + } + } + + if (printStage == PrintStage.DEFERRED_BLOCKS) { + if (deferredBlocks.isEmpty()) { + printStage = PrintStage.ENTITIES; + } else { + currentPos = deferredBlocks.remove(0); + } + } + + if (printStage == PrintStage.ENTITIES) { + if (printingEntityIndex + 1 < entities.size()) { + printingEntityIndex++; + currentPos = entities.get(printingEntityIndex).getBlockPos().subtract(schematicAnchor); + } else { + // Reached end of printing + return false; + } + } + } while (!blockReader.getBounds().isVecInside(currentPos)); + + // More things available to print + return true; + } + + public boolean tryAdvanceCurrentPos() { + currentPos = currentPos.offset(Direction.EAST); + MutableBoundingBox bounds = blockReader.getBounds(); + BlockPos posInBounds = currentPos.add(-bounds.minX, -bounds.minY, -bounds.minZ); + + if (posInBounds.getX() > bounds.getXSize()) + currentPos = new BlockPos(bounds.minX, currentPos.getY(), currentPos.getZ() + 1).west(); + if (posInBounds.getZ() > bounds.getZSize()) + currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, bounds.minZ).west(); + + // End of blocks reached + if (currentPos.getY() > bounds.getYSize()) { + printStage = PrintStage.DEFERRED_BLOCKS; + return false; + } + + return shouldDeferBlock(blockReader.getBlockState(getCurrentTarget())); + } + + public static boolean shouldDeferBlock(BlockState state) { + return state.getBlock().is(AllBlocks.GANTRY_CARRIAGE.get()) || BlockMovementChecks.isBrittle(state); + } + +} diff --git a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java index e60bb7a40..58df85ed1 100644 --- a/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java +++ b/src/main/java/com/simibubi/create/content/schematics/SchematicWorld.java @@ -104,7 +104,7 @@ public class SchematicWorld extends WrappedWorld implements IServerWorld { } return tileEntity; } catch (Exception e) { - Create.logger.debug("Could not create TE of block " + blockState + ": " + e); + Create.LOGGER.debug("Could not create TE of block " + blockState + ": " + e); } } return null; @@ -202,6 +202,9 @@ public class SchematicWorld extends WrappedWorld implements IServerWorld { return true; } + @Override + public void notifyBlockUpdate(BlockPos pos, BlockState oldState, BlockState newState, int flags) { } + @Override public ITickList getPendingBlockTicks() { return EmptyTickList.get(); @@ -233,4 +236,5 @@ public class SchematicWorld extends WrappedWorld implements IServerWorld { } throw new IllegalStateException("Cannot use IServerWorld#getWorld in a client environment"); } + } diff --git a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java index f6750f506..151fdaf08 100644 --- a/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java +++ b/src/main/java/com/simibubi/create/content/schematics/ServerSchematicLoader.java @@ -72,7 +72,7 @@ public class ServerSchematicLoader { SchematicUploadEntry entry = activeUploads.get(upload); if (entry.idleTime++ > getConfig().schematicIdleTimeout.get()) { - Create.logger.warn("Schematic Upload timed out: " + upload); + Create.LOGGER.warn("Schematic Upload timed out: " + upload); deadEntries.add(upload); } @@ -94,7 +94,7 @@ public class ServerSchematicLoader { // Unsupported Format if (!schematic.endsWith(".nbt")) { - Create.logger.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId); + Create.LOGGER.warn("Attempted Schematic Upload with non-supported Format: " + playerSchematicId); return; } @@ -102,7 +102,7 @@ public class ServerSchematicLoader { Path uploadPath = playerSchematicsPath.resolve(schematic).normalize(); if (!uploadPath.startsWith(playerSchematicsPath)) { - Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); + Create.LOGGER.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); return; } @@ -148,7 +148,7 @@ public class ServerSchematicLoader { table.startUpload(schematic); } catch (IOException e) { - Create.logger.error("Exception Thrown when starting Upload: " + playerSchematicId); + Create.LOGGER.error("Exception Thrown when starting Upload: " + playerSchematicId); e.printStackTrace(); } } @@ -178,13 +178,13 @@ public class ServerSchematicLoader { // Size Validations if (data.length > getConfig().maxSchematicPacketSize.get()) { - Create.logger.warn("Oversized Upload Packet received: " + playerSchematicId); + Create.LOGGER.warn("Oversized Upload Packet received: " + playerSchematicId); cancelUpload(playerSchematicId); return; } if (entry.bytesUploaded > entry.totalBytes) { - Create.logger.warn("Received more data than Expected: " + playerSchematicId); + Create.LOGGER.warn("Received more data than Expected: " + playerSchematicId); cancelUpload(playerSchematicId); return; } @@ -200,7 +200,7 @@ public class ServerSchematicLoader { table.sendUpdate = true; } catch (IOException e) { - Create.logger.error("Exception Thrown when uploading Schematic: " + playerSchematicId); + Create.LOGGER.error("Exception Thrown when uploading Schematic: " + playerSchematicId); e.printStackTrace(); cancelUpload(playerSchematicId); } @@ -215,10 +215,10 @@ public class ServerSchematicLoader { try { entry.stream.close(); Files.deleteIfExists(Paths.get(getSchematicPath(), playerSchematicId)); - Create.logger.warn("Cancelled Schematic Upload: " + playerSchematicId); + Create.LOGGER.warn("Cancelled Schematic Upload: " + playerSchematicId); } catch (IOException e) { - Create.logger.error("Exception Thrown when cancelling Upload: " + playerSchematicId); + Create.LOGGER.error("Exception Thrown when cancelling Upload: " + playerSchematicId); e.printStackTrace(); } @@ -249,7 +249,7 @@ public class ServerSchematicLoader { World world = removed.world; BlockPos pos = removed.tablePos; - Create.logger.info("New Schematic Uploaded: " + playerSchematicId); + Create.LOGGER.info("New Schematic Uploaded: " + playerSchematicId); if (pos == null) return; @@ -264,7 +264,7 @@ public class ServerSchematicLoader { table.inventory.setStackInSlot(1, SchematicItem.create(schematic, player.getGameProfile().getName())); } catch (IOException e) { - Create.logger.error("Exception Thrown when finishing Upload: " + playerSchematicId); + Create.LOGGER.error("Exception Thrown when finishing Upload: " + playerSchematicId); e.printStackTrace(); } } @@ -278,7 +278,7 @@ public class ServerSchematicLoader { // Unsupported Format if (!schematic.endsWith(".nbt")) { - Create.logger.warn("Attempted Schematic Upload with non-supported Format: {}", playerSchematicId); + Create.LOGGER.warn("Attempted Schematic Upload with non-supported Format: {}", playerSchematicId); return; } @@ -286,7 +286,7 @@ public class ServerSchematicLoader { Path path = schematicPath.resolve(playerSchematicId).normalize(); if (!path.startsWith(schematicPath)) { - Create.logger.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); + Create.LOGGER.warn("Attempted Schematic Upload with directory escape: {}", playerSchematicId); return; } @@ -326,7 +326,7 @@ public class ServerSchematicLoader { e.printStackTrace(); } } catch (IOException e) { - Create.logger.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId); + Create.LOGGER.error("Exception Thrown in direct Schematic Upload: " + playerSchematicId); e.printStackTrace(); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java index fe9bf1dea..2d0ba889c 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableContainer.java @@ -8,6 +8,7 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; @@ -21,8 +22,8 @@ public class SchematicTableContainer extends Container { private Slot outputSlot; private PlayerEntity player; - public SchematicTableContainer(int id, PlayerInventory inv, PacketBuffer extraData) { - super(AllContainerTypes.SCHEMATIC_TABLE.type, id); + public SchematicTableContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id); player = inv.player; ClientWorld world = Minecraft.getInstance().world; TileEntity tileEntity = world.getTileEntity(extraData.readBlockPos()); @@ -33,23 +34,27 @@ public class SchematicTableContainer extends Container { } } - public SchematicTableContainer(int id, PlayerInventory inv, SchematicTableTileEntity te) { - super(AllContainerTypes.SCHEMATIC_TABLE.type, id); + public SchematicTableContainer(ContainerType type, int id, PlayerInventory inv, SchematicTableTileEntity te) { + super(type, id); this.player = inv.player; this.te = te; init(); } + public static SchematicTableContainer create(int id, PlayerInventory inv, SchematicTableTileEntity te) { + return new SchematicTableContainer(AllContainerTypes.SCHEMATIC_TABLE.get(), id, inv, te); + } + protected void init() { - inputSlot = new SlotItemHandler(te.inventory, 0, -35, 41) { + inputSlot = new SlotItemHandler(te.inventory, 0, 21, 57) { @Override public boolean isItemValid(ItemStack stack) { return AllItems.EMPTY_SCHEMATIC.isIn(stack) || AllItems.SCHEMATIC_AND_QUILL.isIn(stack) - || AllItems.SCHEMATIC.isIn(stack); + || AllItems.SCHEMATIC.isIn(stack); } }; - outputSlot = new SlotItemHandler(te.inventory, 1, 110, 41) { + outputSlot = new SlotItemHandler(te.inventory, 1, 166, 57) { @Override public boolean isItemValid(ItemStack stack) { return false; @@ -62,12 +67,12 @@ public class SchematicTableContainer extends Container { // player Slots for (int row = 0; row < 3; ++row) { for (int col = 0; col < 9; ++col) { - this.addSlot(new Slot(player.inventory, col + row * 9 + 9, 12 + col * 18, 102 + row * 18)); + this.addSlot(new Slot(player.inventory, col + row * 9 + 9, 38 + col * 18, 105 + row * 18)); } } for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) { - this.addSlot(new Slot(player.inventory, hotbarSlot, 12 + hotbarSlot * 18, 160)); + this.addSlot(new Slot(player.inventory, hotbarSlot, 38 + hotbarSlot * 18, 163)); } detectAndSendChanges(); diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java index 93b98c4b7..2cd8049db 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableScreen.java @@ -1,12 +1,12 @@ package com.simibubi.create.content.schematics.block; -import static com.simibubi.create.foundation.gui.AllGuiTextures.SCHEMATIC_TABLE; import static com.simibubi.create.foundation.gui.AllGuiTextures.SCHEMATIC_TABLE_PROGRESS; import java.nio.file.Paths; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import com.google.common.collect.ImmutableList; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllBlocks; @@ -22,7 +22,6 @@ import com.simibubi.create.foundation.gui.widgets.ScrollInput; import com.simibubi.create.foundation.gui.widgets.SelectionScrollInput; import com.simibubi.create.foundation.utility.Lang; -import net.minecraft.client.gui.IHasContainer; import net.minecraft.client.renderer.Rectangle2d; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.item.ItemStack; @@ -31,17 +30,17 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; -public class SchematicTableScreen extends AbstractSimiContainerScreen - implements IHasContainer { +public class SchematicTableScreen extends AbstractSimiContainerScreen { + + protected AllGuiTextures background; + private List extraAreas = Collections.emptyList(); private ScrollInput schematicsArea; private IconButton confirmButton; private IconButton folderButton; private IconButton refreshButton; private Label schematicsLabel; - private List extraAreas; - private final ITextComponent title = Lang.translate("gui.schematicTable.title"); private final ITextComponent uploading = Lang.translate("gui.schematicTable.uploading"); private final ITextComponent finished = Lang.translate("gui.schematicTable.finished"); private final ITextComponent refresh = Lang.translate("gui.schematicTable.refresh"); @@ -57,74 +56,74 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen availableSchematics = CreateClient.SCHEMATIC_SENDER.getAvailableSchematics(); - CreateClient.schematicSender.refresh(); - List availableSchematics = CreateClient.schematicSender.getAvailableSchematics(); - - schematicsLabel = new Label(mainLeft + 49, mainTop + 26, StringTextComponent.EMPTY).withShadow(); + schematicsLabel = new Label(guiLeft + 49, guiTop + 26, StringTextComponent.EMPTY).withShadow(); schematicsLabel.text = StringTextComponent.EMPTY; if (!availableSchematics.isEmpty()) { schematicsArea = - new SelectionScrollInput(mainLeft + 45, mainTop + 21, 139, 18).forOptions(availableSchematics) + new SelectionScrollInput(guiLeft + 45, guiTop + 21, 139, 18).forOptions(availableSchematics) .titled(availableSchematicsTitle.copy()) .writingTo(schematicsLabel); widgets.add(schematicsArea); widgets.add(schematicsLabel); } - confirmButton = new IconButton(mainLeft + 44, mainTop + 56, AllIcons.I_CONFIRM); + confirmButton = new IconButton(guiLeft + 44, guiTop + 56, AllIcons.I_CONFIRM); - folderButton = new IconButton(mainLeft + 21, mainTop + 21, AllIcons.I_OPEN_FOLDER); + folderButton = new IconButton(guiLeft + 21, guiTop + 21, AllIcons.I_OPEN_FOLDER); folderButton.setToolTip(folder); - refreshButton = new IconButton(mainLeft + 207, mainTop + 21, AllIcons.I_REFRESH); + refreshButton = new IconButton(guiLeft + 207, guiTop + 21, AllIcons.I_REFRESH); refreshButton.setToolTip(refresh); widgets.add(confirmButton); widgets.add(folderButton); widgets.add(refreshButton); - extraAreas = new ArrayList<>(); - extraAreas.add(new Rectangle2d(mainLeft, mainTop, SCHEMATIC_TABLE.width, SCHEMATIC_TABLE.height)); + extraAreas = ImmutableList.of( + new Rectangle2d(guiLeft + background.width, guiTop + background.height - 40, 48, 48), + new Rectangle2d(refreshButton.x, refreshButton.y, 16, 16) + ); } @Override - protected void renderWindow(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) { + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + int invLeft = guiLeft - windowXOffset + (xSize - AllGuiTextures.PLAYER_INVENTORY.width) / 2; + int invTop = guiTop + background.height + 4; - int x = guiLeft + 20; - int y = guiTop; + AllGuiTextures.PLAYER_INVENTORY.draw(ms, this, invLeft, invTop); + textRenderer.draw(ms, playerInventory.getDisplayName(), invLeft + 8, invTop + 6, 0x404040); - int mainLeft = guiLeft - 56; - int mainTop = guiTop - 16; - - AllGuiTextures.PLAYER_INVENTORY.draw(matrixStack, this, x - 16, y + 70 + 14); - textRenderer.draw(matrixStack, playerInventory.getDisplayName(), x - 15 + 7, y + 64 + 26, 0x666666); - - SCHEMATIC_TABLE.draw(matrixStack, this, mainLeft, mainTop); + background.draw(ms, this, guiLeft, guiTop); + ITextComponent titleText; if (container.getTileEntity().isUploading) - textRenderer.drawWithShadow(matrixStack, uploading, mainLeft + 11, mainTop + 3, 0xffffff); + titleText = uploading; else if (container.getSlot(1) .getHasStack()) - textRenderer.drawWithShadow(matrixStack, finished, mainLeft + 11, mainTop + 3, 0xffffff); + titleText = finished; else - textRenderer.drawWithShadow(matrixStack, title, mainLeft + 11, mainTop + 3, 0xffffff); + titleText = title; + drawCenteredText(ms, textRenderer, titleText, guiLeft + (background.width - 8) / 2, guiTop + 3, 0xFFFFFF); + if (schematicsArea == null) - textRenderer.drawWithShadow(matrixStack, noSchematics, mainLeft + 54, mainTop + 26, 0xd3d3d3); + textRenderer.drawWithShadow(ms, noSchematics, guiLeft + 54, guiTop + 26, 0xD3D3D3); GuiGameElement.of(renderedItem) - .at(mainLeft + 217, mainTop + 50, -150) + .at(guiLeft + background.width, guiTop + background.height - 40, -200) .scale(3) - .render(matrixStack); + .render(ms); client.getTextureManager() .bindTexture(SCHEMATIC_TABLE_PROGRESS.location); @@ -132,7 +131,7 @@ public class SchematicTableScreen extends AbstractSimiContainerScreen getExtraAreas() { return extraAreas; } + } diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java index 4479525fc..d75bb645b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicTableTileEntity.java @@ -1,6 +1,7 @@ package com.simibubi.create.content.schematics.block; import com.simibubi.create.foundation.tileEntity.SyncedTileEntity; +import com.simibubi.create.foundation.utility.Lang; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; @@ -13,7 +14,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.tileentity.ITickableTileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; import net.minecraftforge.items.ItemStackHandler; public class SchematicTableTileEntity extends SyncedTileEntity implements ITickableTileEntity, INamedContainerProvider { @@ -110,13 +110,13 @@ public class SchematicTableTileEntity extends SyncedTileEntity implements ITicka } @Override - public Container createMenu(int p_createMenu_1_, PlayerInventory p_createMenu_2_, PlayerEntity p_createMenu_3_) { - return new SchematicTableContainer(p_createMenu_1_, p_createMenu_2_, this); + public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { + return SchematicTableContainer.create(id, inv, this); } @Override public ITextComponent getDisplayName() { - return new StringTextComponent(getType().getRegistryName().toString()); + return Lang.translate("gui.schematicTable.title"); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java index 8fd5a6b07..a49ab9b44 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonContainer.java @@ -7,6 +7,7 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; @@ -18,8 +19,8 @@ public class SchematicannonContainer extends Container { private SchematicannonTileEntity te; private PlayerEntity player; - public SchematicannonContainer(int id, PlayerInventory inv, PacketBuffer buffer) { - super(AllContainerTypes.SCHEMATICANNON.type, id); + public SchematicannonContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer buffer) { + super(type, id); player = inv.player; ClientWorld world = Minecraft.getInstance().world; TileEntity tileEntity = world.getTileEntity(buffer.readBlockPos()); @@ -30,15 +31,19 @@ public class SchematicannonContainer extends Container { } } - public SchematicannonContainer(int id, PlayerInventory inv, SchematicannonTileEntity te) { - super(AllContainerTypes.SCHEMATICANNON.type, id); + public SchematicannonContainer(ContainerType type, int id, PlayerInventory inv, SchematicannonTileEntity te) { + super(type, id); player = inv.player; this.te = te; init(); } + public static SchematicannonContainer create(int id, PlayerInventory inv, SchematicannonTileEntity te) { + return new SchematicannonContainer(AllContainerTypes.SCHEMATICANNON.get(), id, inv, te); + } + protected void init() { - int x = 20; + int x = 0; int y = 0; addSlot(new SlotItemHandler(te.inventory, 0, x + 15, y + 65)); @@ -50,9 +55,9 @@ public class SchematicannonContainer extends Container { // player Slots for (int row = 0; row < 3; ++row) for (int col = 0; col < 9; ++col) - addSlot(new Slot(player.inventory, col + row * 9 + 9, -2 + col * 18, 163 + row * 18)); - for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) - addSlot(new Slot(player.inventory, hotbarSlot, -2 + hotbarSlot * 18, 221)); + addSlot(new Slot(player.inventory, col + row * 9 + 9, 37 + col * 18, 161 + row * 18)); + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + addSlot(new Slot(player.inventory, hotbarSlot, 37 + hotbarSlot * 18, 219)); detectAndSendChanges(); } diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java index b91ca03a0..98db7d37b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java +++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonInstance.java @@ -1,13 +1,12 @@ package com.simibubi.create.content.schematics.block; +import com.jozufozu.flywheel.backend.instancing.IDynamicInstance; +import com.jozufozu.flywheel.backend.instancing.InstanceMaterial; +import com.jozufozu.flywheel.backend.instancing.MaterialManager; +import com.jozufozu.flywheel.backend.instancing.tile.TileEntityInstance; +import com.jozufozu.flywheel.core.materials.ModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlockPartials; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.instancing.IDynamicInstance; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderer; -import com.simibubi.create.foundation.render.backend.instancing.RenderMaterial; -import com.simibubi.create.foundation.render.backend.instancing.TileEntityInstance; import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -18,10 +17,10 @@ public class SchematicannonInstance extends TileEntityInstance modelManager, SchematicannonTileEntity tile) { + public SchematicannonInstance(MaterialManager modelManager, SchematicannonTileEntity tile) { super(modelManager, tile); - RenderMaterial> mat = getTransformMaterial(); + InstanceMaterial mat = getTransformMaterial(); connector = mat.getModel(AllBlockPartials.SCHEMATICANNON_CONNECTOR, blockState).createInstance(); pipe = mat.getModel(AllBlockPartials.SCHEMATICANNON_PIPE, blockState).createInstance(); 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 6ac93df76..13d701138 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 @@ -2,6 +2,7 @@ package com.simibubi.create.content.schematics.block; import java.util.Random; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.AllBlockPartials; @@ -9,7 +10,6 @@ import com.simibubi.create.content.schematics.block.LaunchedItem.ForBlockState; import com.simibubi.create.content.schematics.block.LaunchedItem.ForEntity; import com.simibubi.create.foundation.render.PartialBufferer; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer; import net.minecraft.block.BlockState; @@ -46,7 +46,7 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer extraAreas; + private List extraAreas = Collections.emptyList(); protected List placementSettingWidgets; - private final ITextComponent title = Lang.translate("gui.schematicannon.title"); private final ITextComponent listPrinter = Lang.translate("gui.schematicannon.listPrinter"); private final String _gunpowderLevel = "gui.schematicannon.gunpowderLevel"; private final String _shotsRemaining = "gui.schematicannon.shotsRemaining"; @@ -80,21 +78,21 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen(); } @Override protected void init() { - setWindowSize(BG_TOP.width + 50, BG_BOTTOM.height + BG_TOP.height + 80); + setWindowSize(BG_TOP.width, BG_TOP.height + BG_BOTTOM.height + 2 + AllGuiTextures.PLAYER_INVENTORY.height); + setWindowOffset(30 - (2 + 80) / 2, 0); super.init(); - - int x = guiLeft + 20; - int y = guiTop; - widgets.clear(); + int x = guiLeft; + int y = guiTop; + // Play Pause Stop playButton = new IconButton(x + 75, y + 86, AllIcons.I_PLAY); playIndicator = new Indicator(x + 75, y + 79, StringTextComponent.EMPTY); @@ -106,17 +104,18 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen(); - extraAreas.add(new Rectangle2d(guiLeft + 240, guiTop + 88, 84, 113)); - confirmButton = new IconButton(x + 180, guiTop + 117, AllIcons.I_CONFIRM); widgets.add(confirmButton); - showSettingsButton = new IconButton(guiLeft + 29, guiTop + 117, AllIcons.I_PLACEMENT_SETTINGS); + showSettingsButton = new IconButton(guiLeft + 9, guiTop + 117, AllIcons.I_PLACEMENT_SETTINGS); showSettingsButton.setToolTip(Lang.translate(_showSettings)); widgets.add(showSettingsButton); - showSettingsIndicator = new Indicator(guiLeft + 29, guiTop + 111, StringTextComponent.EMPTY); + showSettingsIndicator = new Indicator(guiLeft + 9, guiTop + 111, StringTextComponent.EMPTY); widgets.add(showSettingsIndicator); + extraAreas = ImmutableList.of( + new Rectangle2d(guiLeft + BG_TOP.width, guiTop + BG_TOP.height + BG_BOTTOM.height - 62, 84, 92) + ); + tick(); } @@ -127,7 +126,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreenat(guiLeft + 230, guiTop + 110, -200) + .at(guiLeft + BG_TOP.width, guiTop + BG_TOP.height + BG_BOTTOM.height - 48, -200) .scale(5) - .render(matrixStack); + .render(ms); - textRenderer.drawWithShadow(matrixStack, title, guiLeft + 80, guiTop + 3, 0xfefefe); + drawCenteredText(ms, textRenderer, title, guiLeft + (BG_TOP.width - 8) / 2, guiTop + 3, 0xFFFFFF); ITextComponent msg = Lang.translate("schematicannon.status." + te.statusMsg); int stringWidth = textRenderer.getWidth(msg); if (te.missingItem != null) { - stringWidth += 15; + stringWidth += 16; GuiGameElement.of(te.missingItem) - .at(guiLeft + 150, guiTop + 46, 100) + .at(guiLeft + 128, guiTop + 49, 100) .scale(1) - .render(matrixStack); + .render(ms); } - textRenderer.drawWithShadow(matrixStack, msg, guiLeft + 20 + 102 - stringWidth / 2, guiTop + 50, 0xCCDDFF); - textRenderer.draw(matrixStack, playerInventory.getDisplayName(), guiLeft - 10 + 7, guiTop + 145 + 6, 0x666666); - - // to see or debug the bounds of the extra area uncomment the following lines - // Rectangle2d r = extraAreas.get(0); - // fill(r.getX() + r.getWidth(), r.getY() + r.getHeight(), r.getX(), r.getY(), - // 0xd3d3d3d3); + textRenderer.drawWithShadow(ms, msg, guiLeft + 103 - stringWidth / 2, guiTop + 53, 0xCCDDFF); } protected void renderBlueprintHighlight(MatrixStack matrixStack) { - AllGuiTextures.SCHEMATICANNON_HIGHLIGHT.draw(matrixStack, this, guiLeft + 20 + 10, guiTop + 60); + AllGuiTextures.SCHEMATICANNON_HIGHLIGHT.draw(matrixStack, this, guiLeft + 10, guiTop + 60); } protected void renderPrintingProgress(MatrixStack matrixStack, float progress) { @@ -297,7 +295,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen= fuelX && mouseY >= fuelY && mouseX <= fuelX + AllGuiTextures.SCHEMATICANNON_FUEL.width && mouseY <= fuelY + AllGuiTextures.SCHEMATICANNON_FUEL.height) { List tooltip = getFuelLevelTooltip(te); @@ -348,14 +346,14 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen= missingBlockX && mouseY >= missingBlockY && mouseX <= missingBlockX + 16 && mouseY <= missingBlockY + 16) { renderTooltip(matrixStack, te.missingItem, mouseX, mouseY); } } - int paperX = guiLeft + 132, paperY = guiTop + 19; + int paperX = guiLeft + 112, paperY = guiTop + 19; if (mouseX >= paperX && mouseY >= paperY && mouseX <= paperX + 16 && mouseY <= paperY + 16) renderTooltip(matrixStack, listPrinter, mouseX, mouseY); @@ -393,7 +391,7 @@ public class SchematicannonScreen extends AbstractSimiContainerScreen> attachedInventories; public List flyingBlocks; @@ -142,9 +131,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC inventory = new SchematicannonInventory(this); statusMsg = "idle"; state = State.STOPPED; - printingEntityIndex = -1; replaceMode = 2; checklist = new MaterialChecklist(); + printer = new SchematicPrinter(); } public void findInventories() { @@ -173,8 +162,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC protected void fromTag(BlockState blockState, CompoundNBT compound, boolean clientPacket) { if (!clientPacket) { inventory.deserializeNBT(compound.getCompound("Inventory")); - if (compound.contains("CurrentPos")) - currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos")); } // Gui information @@ -185,7 +172,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC state = State.valueOf(compound.getString("State")); blocksPlaced = compound.getInt("AmountPlaced"); blocksToPlace = compound.getInt("AmountToPlace"); - printingEntityIndex = compound.getInt("EntityProgress"); missingItem = null; if (compound.contains("MissingItem")) @@ -198,8 +184,8 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC replaceTileEntities = options.getBoolean("ReplaceTileEntities"); // Printer & Flying Blocks - if (compound.contains("Target")) - target = NBTUtil.readBlockPos(compound.getCompound("Target")); + if (compound.contains("Printer")) + printer.fromTag(compound.getCompound("Printer"), clientPacket); if (compound.contains("FlyingBlocks")) readFlyingBlocks(compound); @@ -247,8 +233,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC compound.put("Inventory", inventory.serializeNBT()); if (state == State.RUNNING) { compound.putBoolean("Running", true); - if (currentPos != null) - compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos)); } } @@ -260,7 +244,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC compound.putString("State", state.name()); compound.putInt("AmountPlaced", blocksPlaced); compound.putInt("AmountToPlace", blocksToPlace); - compound.putInt("EntityProgress", printingEntityIndex); if (missingItem != null) compound.put("MissingItem", missingItem.serializeNBT()); @@ -273,12 +256,14 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC compound.put("Options", options); // Printer & Flying Blocks - if (target != null) - compound.put("Target", NBTUtil.writeBlockPos(target)); - ListNBT tagBlocks = new ListNBT(); + CompoundNBT printerData = new CompoundNBT(); + printer.write(printerData); + compound.put("Printer", printerData); + + ListNBT tagFlyingBlocks = new ListNBT(); for (LaunchedItem b : flyingBlocks) - tagBlocks.add(b.serializeNBT()); - compound.put("FlyingBlocks", tagBlocks); + tagFlyingBlocks.add(b.serializeNBT()); + compound.put("FlyingBlocks", tagFlyingBlocks); super.write(compound, clientPacket); } @@ -293,7 +278,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC } firstRenderTick = true; - previousTarget = target; + previousTarget = printer.getCurrentTarget(); tickFlyingBlocks(); if (world.isRemote) @@ -331,7 +316,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC // Skip if not Active if (state == State.STOPPED) { - if (schematicLoaded) + if (printer.isLoaded()) resetPrinter(); return; } @@ -347,7 +332,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC return; // Initialize Printer - if (!schematicLoaded) { + if (!printer.isLoaded()) { initializePrinter(blueprint); return; } @@ -367,7 +352,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC return; } - // Update Target if (hasCreativeCrate) { if (missingItem != null) { missingItem = null; @@ -375,23 +359,17 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC } } + // Update Target if (missingItem == null && !positionNotLoaded) { - do { - advanceCurrentPos(); - if (state == State.STOPPED) - return; - - } while (!blockReader.getBounds() - .isVecInside(currentPos)); - + if (!printer.advanceCurrentPos()) { + finishedPrinting(); + return; + } sendUpdate = true; - target = schematicAnchor.add(currentPos); } - boolean entityMode = printingEntityIndex >= 0; - // Check block - if (!getWorld().isAreaLoaded(target, 0)) { + if (!getWorld().isAreaLoaded(printer.getCurrentTarget(), 0)) { positionNotLoaded = true; statusMsg = "targetNotLoaded"; state = State.PAUSED; @@ -403,32 +381,19 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC } } - boolean shouldSkip = false; - BlockState blockState = Blocks.AIR.getDefaultState(); - ItemRequirement requirement; - - if (entityMode) { - requirement = ItemRequirement.of(blockReader.getEntities() - .collect(Collectors.toList()) - .get(printingEntityIndex)); - - } else { - blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target)); - requirement = ItemRequirement.of(blockState); - shouldSkip = !shouldPlace(target, blockState); - } - - if (shouldSkip || requirement.isInvalid()) { + // Get item requirement + ItemRequirement requirement = printer.getCurrentRequirement(); + if (requirement.isInvalid() || !printer.shouldPlaceCurrent(world, this::shouldPlace)) { statusMsg = "searching"; blockSkipped = true; return; } // Find item - List requiredItems = requirement.getRequiredItems(); + List requiredItems = requirement.getRequiredItems(); if (!requirement.isEmpty()) { - for (ItemStack required : requiredItems) { - if (!grabItemsFromAttachedInventories(required, requirement.getUsage(), true)) { + for (ItemRequirement.StackRequirement required : requiredItems) { + if (!grabItemsFromAttachedInventories(required.item, required.usage, true)) { if (skipMissing) { statusMsg = "skipping"; blockSkipped = true; @@ -439,47 +404,29 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC return; } - missingItem = required; + missingItem = required.item; state = State.PAUSED; statusMsg = "missingBlock"; return; } } - for (ItemStack required : requiredItems) - grabItemsFromAttachedInventories(required, requirement.getUsage(), false); + for (ItemRequirement.StackRequirement required : requiredItems) + grabItemsFromAttachedInventories(required.item, required.usage, false); } // Success state = State.RUNNING; - if (blockState.getBlock() != Blocks.AIR || entityMode) + ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item; + printer.handleCurrentTarget((target, blockState, tile) -> { + // Launch block + statusMsg = blockState.getBlock() != Blocks.AIR ? "placing" : "clearing"; + launchBlockOrBelt(target, icon, blockState, tile); + }, (target, entity) -> { + // Launch entity statusMsg = "placing"; - else - statusMsg = "clearing"; - - ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0); - if (entityMode) - launchEntity(target, icon, blockReader.getEntities() - .collect(Collectors.toList()) - .get(printingEntityIndex)); - else if (AllBlocks.BELT.has(blockState)) { - TileEntity te = blockReader.getTileEntity(currentPos.add(schematicAnchor)); - blockState = stripBeltIfNotLast(blockState); - if (te instanceof BeltTileEntity && AllBlocks.BELT.has(blockState)) - launchBelt(target, blockState, ((BeltTileEntity) te).beltLength); - else - launchBlock(target, icon, blockState, null); - } else { - CompoundNBT data = null; - if (AllBlockTags.SAFE_NBT.matches(blockState)) { - TileEntity tile = blockReader.getTileEntity(target); - if (tile != null) { - data = tile.write(new CompoundNBT()); - data = NBTProcessors.process(tile, data, true); - } - } - launchBlock(target, icon, blockState, data); - } + launchEntity(target, icon, entity); + }); printerCooldown = config().schematicannonDelay.get(); fuelLevel -= getFuelUsageRate(); @@ -487,35 +434,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC missingItem = null; } - public BlockState stripBeltIfNotLast(BlockState blockState) { - // is highest belt? - boolean isLastSegment = false; - Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING); - BeltSlope slope = blockState.get(BeltBlock.SLOPE); - boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE; - boolean start = blockState.get(BeltBlock.PART) == BeltPart.START; - boolean end = blockState.get(BeltBlock.PART) == BeltPart.END; - - switch (slope) { - case DOWNWARD: - isLastSegment = start; - break; - case UPWARD: - isLastSegment = end; - break; - case HORIZONTAL: - case VERTICAL: - default: - isLastSegment = positive && end || !positive && start; - } - if (!isLastSegment) - blockState = (blockState.get(BeltBlock.PART) == BeltPart.MIDDLE) ? Blocks.AIR.getDefaultState() - : AllBlocks.SHAFT.getDefaultState() - .with(AbstractShaftBlock.AXIS, facing.rotateY() - .getAxis()); - return blockState; - } - public double getFuelUsageRate() { return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f; } @@ -537,38 +455,29 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC } // Load blocks into reader - Template activeTemplate = SchematicItem.loadSchematic(blueprint); - BlockPos anchor = NBTUtil.readBlockPos(blueprint.getTag() - .getCompound("Anchor")); + printer.loadSchematic(blueprint, world, true); - if (activeTemplate.getSize() - .equals(BlockPos.ZERO)) { + if (printer.isWorldEmpty()) { state = State.STOPPED; statusMsg = "schematicExpired"; inventory.setStackInSlot(0, ItemStack.EMPTY); inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get())); + printer.resetSchematic(); return; } - if (!anchor.withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) { + if (!printer.getAnchor().withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) { state = State.STOPPED; statusMsg = "targetOutsideRange"; + printer.resetSchematic(); return; } - schematicAnchor = anchor; - blockReader = new SchematicWorld(schematicAnchor, world); - PlacementSettings settings = SchematicItem.getSettings(blueprint); - activeTemplate.place(blockReader, schematicAnchor, settings, blockReader.getRandom()); - schematicLoaded = true; state = State.PAUSED; statusMsg = "ready"; - printingEntityIndex = -1; updateChecklist(); sendUpdate = true; blocksToPlace += blocksPlaced; - MutableBoundingBox bounds = blockReader.getBounds(); - currentPos = currentPos != null ? currentPos.west() : new BlockPos(bounds.minX - 1, bounds.minY, bounds.minZ); } protected ItemStack getItemForBlock(BlockState blockState) { @@ -646,46 +555,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC return success; } - protected void advanceCurrentPos() { - List entities = blockReader.getEntities() - .collect(Collectors.toList()); - if (printingEntityIndex != -1) { - printingEntityIndex++; - - // End of entities reached - if (printingEntityIndex >= entities.size()) { - finishedPrinting(); - return; - } - - currentPos = entities.get(printingEntityIndex) - .getBlockPos() - .subtract(schematicAnchor); - return; - } - - MutableBoundingBox bounds = blockReader.getBounds(); - currentPos = currentPos.offset(Direction.EAST); - BlockPos posInBounds = currentPos.add(-bounds.minX, -bounds.minY, -bounds.minZ); - - if (posInBounds.getX() > bounds.getXSize()) - currentPos = new BlockPos(bounds.minX, currentPos.getY(), currentPos.getZ() + 1).west(); - if (posInBounds.getZ() > bounds.getZSize()) - currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, bounds.minZ).west(); - - // End of blocks reached - if (currentPos.getY() > bounds.getYSize()) { - printingEntityIndex = 0; - if (entities.isEmpty()) { - finishedPrinting(); - return; - } - currentPos = entities.get(0) - .getBlockPos() - .subtract(schematicAnchor); - } - } - public void finishedPrinting() { inventory.setStackInSlot(0, ItemStack.EMPTY); inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get(), inventory.getStackInSlot(1) @@ -693,80 +562,54 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC state = State.STOPPED; statusMsg = "finished"; resetPrinter(); - target = getPos().add(1, 0, 0); AllSoundEvents.SCHEMATICANNON_FINISH.playOnServer(world, pos); sendUpdate = true; } protected void resetPrinter() { - schematicLoaded = false; - schematicAnchor = null; - currentPos = null; - blockReader = null; + printer.resetSchematic(); missingItem = null; sendUpdate = true; - printingEntityIndex = -1; schematicProgress = 0; blocksPlaced = 0; blocksToPlace = 0; } - protected boolean shouldPlace(BlockPos pos, BlockState state) { - if (world == null) - return false; - BlockState toReplace = world.getBlockState(pos); - boolean placingAir = state.getBlock() - .isAir(state, world, pos); - - BlockState toReplaceOther = null; - if (state.contains(BlockStateProperties.BED_PART) && state.contains(BlockStateProperties.HORIZONTAL_FACING) - && state.get(BlockStateProperties.BED_PART) == BedPart.FOOT) - toReplaceOther = world.getBlockState(pos.offset(state.get(BlockStateProperties.HORIZONTAL_FACING))); - if (state.contains(BlockStateProperties.DOUBLE_BLOCK_HALF) - && state.get(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER) - toReplaceOther = world.getBlockState(pos.up()); - - if (!world.isBlockPresent(pos)) - return false; - if (!world.getWorldBorder() - .contains(pos)) - return false; - if (toReplace == state) - return false; - if (toReplace.getBlockHardness(world, pos) == -1 - || (toReplaceOther != null && toReplaceOther.getBlockHardness(world, pos) == -1)) - return false; + protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te, + BlockState toReplace, BlockState toReplaceOther, boolean isNormalCube) { if (pos.withinDistance(getPos(), 2f)) return false; if (!replaceTileEntities - && (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity()))) + && (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity()))) return false; - if (shouldIgnoreBlockState(state)) + if (shouldIgnoreBlockState(state, te)) return false; + boolean placingAir = state.getBlock().isAir(state, world, pos); + if (replaceMode == 3) return true; if (replaceMode == 2 && !placingAir) return true; if (replaceMode == 1 - && (state.isNormalCube(blockReader, pos.subtract(schematicAnchor)) || (!toReplace.isNormalCube(world, pos) + && (isNormalCube || (!toReplace.isNormalCube(world, pos) && (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)))) - && !placingAir) + && !placingAir) return true; if (replaceMode == 0 && !toReplace.isNormalCube(world, pos) - && (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)) && !placingAir) + && (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)) && !placingAir) return true; return false; } - protected boolean shouldIgnoreBlockState(BlockState state) { + protected boolean shouldIgnoreBlockState(BlockState state, TileEntity te) { // Block doesnt have a mapping (Water, lava, etc) if (state.getBlock() == Blocks.STRUCTURE_VOID) return true; - ItemRequirement requirement = ItemRequirement.of(state); + ItemRequirement requirement = ItemRequirement.of(state, te); if (requirement.isEmpty()) return false; if (requirement.isInvalid()) @@ -774,7 +617,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC // Block doesnt need to be placed twice (Doors, beds, double plants) if (state.contains(BlockStateProperties.DOUBLE_BLOCK_HALF) - && state.get(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.UPPER) + && state.get(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.UPPER) return true; if (state.contains(BlockStateProperties.BED_PART) && state.get(BlockStateProperties.BED_PART) == BedPart.HEAD) return true; @@ -828,7 +671,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC return; } - if (!schematicLoaded) { + if (!printer.isLoaded()) { if (!blueprint.isEmpty()) initializePrinter(blueprint); return; @@ -843,8 +686,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC dontUpdateChecklist = true; inventory.extractItem(BookInput, 1, false); ItemStack stack = checklist.createItem(); - stack.setCount(inventory.getStackInSlot(BookOutput) - .getCount() + 1); + stack.setCount(inventory.getStackInSlot(BookOutput).getCount() + 1); inventory.setStackInSlot(BookOutput, stack); sendUpdate = true; return; @@ -854,6 +696,58 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC sendUpdate = true; } + public static BlockState stripBeltIfNotLast(BlockState blockState) { + // is highest belt? + boolean isLastSegment = false; + Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING); + BeltSlope slope = blockState.get(BeltBlock.SLOPE); + boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE; + boolean start = blockState.get(BeltBlock.PART) == BeltPart.START; + boolean end = blockState.get(BeltBlock.PART) == BeltPart.END; + + switch (slope) { + case DOWNWARD: + isLastSegment = start; + break; + case UPWARD: + isLastSegment = end; + break; + case HORIZONTAL: + case VERTICAL: + default: + isLastSegment = positive && end || !positive && start; + } + if (!isLastSegment) + blockState = (blockState.get(BeltBlock.PART) == BeltPart.MIDDLE) ? Blocks.AIR.getDefaultState() + : AllBlocks.SHAFT.getDefaultState() + .with(AbstractShaftBlock.AXIS, facing.rotateY() + .getAxis()); + return blockState; + } + + protected void launchBlockOrBelt(BlockPos target, ItemStack icon, BlockState blockState, TileEntity tile) { + if (AllBlocks.BELT.has(blockState)) { + blockState = stripBeltIfNotLast(blockState); + if (tile instanceof BeltTileEntity && AllBlocks.BELT.has(blockState)) + launchBelt(target, blockState, ((BeltTileEntity) tile).beltLength); + else + launchBlock(target, icon, blockState, null); + } else { + CompoundNBT data = null; + if (tile != null) { + if (AllBlockTags.SAFE_NBT.matches(blockState)) { + data = tile.write(new CompoundNBT()); + data = NBTProcessors.process(tile, data, true); + } else if (tile instanceof IPartialSafeNBT) { + data = new CompoundNBT(); + ((IPartialSafeNBT) tile).writeSafe(data, false); + data = NBTProcessors.process(tile, data, true); + } + } + launchBlock(target, icon, blockState, data); + } + } + protected void launchBelt(BlockPos target, BlockState state, int length) { blocksPlaced++; ItemStack connector = AllItems.BELT_CONNECTOR.asStack(); @@ -862,8 +756,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC } protected void launchBlock(BlockPos target, ItemStack stack, BlockState state, @Nullable CompoundNBT data) { - if (state.getBlock() - .isAir(state, world, target)) + if (!state.getBlock().isAir(state, world, target)) blocksPlaced++; flyingBlocks.add(new LaunchedItem.ForBlockState(this.getPos(), target, stack, state, data)); playFiringSound(); @@ -886,13 +779,12 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC @Override public Container createMenu(int id, PlayerInventory inv, PlayerEntity player) { - return new SchematicannonContainer(id, inv, this); + return SchematicannonContainer.create(id, inv, this); } @Override public ITextComponent getDisplayName() { - return new StringTextComponent(getType().getRegistryName() - .toString()); + return Lang.translate("gui.schematicannon.title"); } public void updateChecklist() { @@ -900,35 +792,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC checklist.damageRequired.clear(); checklist.blocksNotLoaded = false; - if (schematicLoaded) { + if (printer.isLoaded()) { blocksToPlace = blocksPlaced; - for (BlockPos pos : blockReader.getAllPositions()) { - BlockState required = blockReader.getBlockState(pos.add(schematicAnchor)); - - if (!getWorld().isAreaLoaded(pos.add(schematicAnchor), 0)) { - checklist.warnBlockNotLoaded(); - continue; - } - if (!shouldPlace(pos.add(schematicAnchor), required)) - continue; - ItemRequirement requirement = ItemRequirement.of(required); - if (requirement.isEmpty()) - continue; - if (requirement.isInvalid()) - continue; - checklist.require(requirement); - blocksToPlace++; - } - blockReader.getEntities() - .forEach(entity -> { - ItemRequirement requirement = ItemRequirement.of(entity); - if (requirement.isEmpty()) - return; - if (requirement.isInvalid()) - return; - checklist.require(requirement); - }); - + blocksToPlace += printer.markAllBlockRequirements(checklist, world, this::shouldPlace); + printer.markAllEntityRequirements(checklist); } checklist.gathered.clear(); findInventories(); @@ -957,7 +824,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC } @Override - public boolean shouldRenderAsTE() { + public boolean shouldRenderNormally() { return true; } } 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 aee90c939..af0624b67 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 @@ -239,7 +239,7 @@ public class SchematicAndQuillHandler { if (!convertImmediately) return; if (!Files.exists(path)) { - Create.logger.fatal("Missing Schematic file: " + path.toString()); + Create.LOGGER.fatal("Missing Schematic file: " + path.toString()); return; } try { @@ -248,14 +248,14 @@ public class SchematicAndQuillHandler { AllPackets.channel.sendToServer(new InstantSchematicPacket(filename, origin, bounds)); } catch (IOException e) { - Create.logger.fatal("Error finding Schematic file: " + path.toString()); + Create.LOGGER.fatal("Error finding Schematic file: " + path.toString()); e.printStackTrace(); return; } } private Outliner outliner() { - return CreateClient.outliner; + return CreateClient.OUTLINER; } } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java index b775572c0..818327e76 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicEditScreen.java @@ -50,14 +50,14 @@ public class SchematicEditScreen extends AbstractSimiScreen { setWindowSize(background.width + 50, background.height); int x = guiLeft; int y = guiTop; - handler = CreateClient.schematicHandler; + handler = CreateClient.SCHEMATIC_HANDLER; xInput = new TextFieldWidget(textRenderer, x + 50, y + 26, 34, 10, StringTextComponent.EMPTY); yInput = new TextFieldWidget(textRenderer, x + 90, y + 26, 34, 10, StringTextComponent.EMPTY); zInput = new TextFieldWidget(textRenderer, x + 130, y + 26, 34, 10, StringTextComponent.EMPTY); BlockPos anchor = handler.getTransformation() - .getAnchor(); + .getAnchor(); if (handler.isDeployed()) { xInput.setText("" + anchor.getX()); yInput.setText("" + anchor.getY()); 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 d2eaa4595..9bea80f55 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 @@ -191,12 +191,11 @@ public class SchematicHandler { return; if (activeSchematicItem != null) this.overlay.renderOn(ms, activeHotbarSlot); - currentTool.getTool() .renderOverlay(ms, buffer); selectionScreen.renderPassive(ms, partialTicks); } - + public void onMouseInput(int button, boolean pressed) { if (!active) return; diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java index 8b765eca9..33f531cbe 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicHotbarSlotOverlay.java @@ -14,11 +14,10 @@ public class SchematicHotbarSlotOverlay extends AbstractGui { MainWindow mainWindow = Minecraft.getInstance().getWindow(); int x = mainWindow.getScaledWidth() / 2 - 88; int y = mainWindow.getScaledHeight() - 19; - RenderSystem.enableAlphaTest(); RenderSystem.enableDepthTest(); - RenderSystem.enableBlend(); + matrixStack.push(); AllGuiTextures.SCHEMATIC_SLOT.draw(matrixStack, this, x + 20 * slot, y); - RenderSystem.disableAlphaTest(); + matrixStack.pop(); } } diff --git a/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java b/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java index 1738b233e..ce7cd33df 100644 --- a/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java +++ b/src/main/java/com/simibubi/create/content/schematics/client/SchematicPromptScreen.java @@ -90,7 +90,7 @@ public class SchematicPromptScreen extends AbstractSimiScreen { return true; } if (abort.isHovered()) { - CreateClient.schematicAndQuillHandler.discard(); + CreateClient.SCHEMATIC_AND_QUILL_HANDLER.discard(); Minecraft.getInstance().player.closeScreen(); return true; } @@ -102,7 +102,7 @@ public class SchematicPromptScreen extends AbstractSimiScreen { } private void confirm(boolean convertImmediately) { - CreateClient.schematicAndQuillHandler.saveSchematic(nameField.getText(), convertImmediately); + CreateClient.SCHEMATIC_AND_QUILL_HANDLER.saveSchematic(nameField.getText(), convertImmediately); Minecraft.getInstance().player.closeScreen(); } 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 a585b429d..75f55c7ba 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 @@ -78,8 +78,7 @@ public class SchematicRenderer { SuperByteBuffer superByteBuffer = bufferCache.get(layer); superByteBuffer.renderInto(ms, buffer.getBuffer(layer)); } - TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, new MatrixStack(), - buffer); + TileEntityRenderHelper.renderTileEntities(schematic, schematic.getRenderedTileEntities(), ms, buffer); } protected void redraw(Minecraft minecraft) { 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 189642d36..7c3c6c6a2 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 @@ -213,7 +213,7 @@ public class SchematicTransformation { z.start(pos.getZ()); moveTo(pos); } - + public void moveTo(BlockPos pos) { moveTo(pos.getX(), pos.getY(), pos.getZ()); } 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 0a60b3433..bbfa5163c 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 @@ -45,7 +45,7 @@ public abstract class SchematicToolBase implements ISchematicTool { @Override public void init() { - schematicHandler = CreateClient.schematicHandler; + schematicHandler = CreateClient.SCHEMATIC_HANDLER; selectedPos = null; selectedFace = null; schematicSelected = false; diff --git a/src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java b/src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java index 90a184ddb..9ca103e6b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java +++ b/src/main/java/com/simibubi/create/content/schematics/filtering/SchematicInstances.java @@ -1,6 +1,5 @@ package com.simibubi.create.content.schematics.filtering; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; 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 7633d85b6..eca91e789 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 @@ -100,11 +100,16 @@ public class SchematicItem extends Item { } public static PlacementSettings getSettings(ItemStack blueprint) { + return getSettings(blueprint, true); + } + + public static PlacementSettings getSettings(ItemStack blueprint, boolean processNBT) { CompoundNBT tag = blueprint.getTag(); PlacementSettings settings = new PlacementSettings(); settings.setRotation(Rotation.valueOf(tag.getString("Rotation"))); settings.setMirror(Mirror.valueOf(tag.getString("Mirror"))); - settings.addProcessor(SchematicProcessor.INSTANCE); + if (processNBT) + settings.addProcessor(SchematicProcessor.INSTANCE); return settings; } diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java index 30a4fdcba..00255c435 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/InstantSchematicPacket.java @@ -40,10 +40,10 @@ public class InstantSchematicPacket extends SimplePacketBase { context.get() .enqueueWork(() -> { ServerPlayerEntity player = context.get() - .getSender(); + .getSender(); if (player == null) return; - Create.schematicReceiver.handleInstantSchematic(player, name, player.world, origin, bounds); + Create.SCHEMATIC_RECEIVER.handleInstantSchematic(player, name, player.world, origin, bounds); }); context.get() .setPacketHandled(true); diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java index d429ddda8..01cc59d07 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicPlacePacket.java @@ -2,16 +2,15 @@ package com.simibubi.create.content.schematics.packet; import java.util.function.Supplier; -import com.simibubi.create.content.schematics.SchematicProcessor; -import com.simibubi.create.content.schematics.item.SchematicItem; +import com.simibubi.create.content.schematics.SchematicPrinter; import com.simibubi.create.foundation.networking.SimplePacketBase; +import com.simibubi.create.foundation.utility.BlockHelper; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NBTUtil; +import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.PacketBuffer; -import net.minecraft.world.gen.feature.template.PlacementSettings; -import net.minecraft.world.gen.feature.template.Template; +import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkEvent.Context; public class SchematicPlacePacket extends SimplePacketBase { @@ -35,13 +34,22 @@ public class SchematicPlacePacket extends SimplePacketBase { ServerPlayerEntity player = context.get().getSender(); if (player == null) return; - Template t = SchematicItem.loadSchematic(stack); - PlacementSettings settings = SchematicItem.getSettings(stack); - if (player.canUseCommandBlock()) - settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor - settings.setIgnoreEntities(false); - t.place(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")), - settings, player.getRNG()); + + World world = player.getServerWorld(); + SchematicPrinter printer = new SchematicPrinter(); + printer.loadSchematic(stack, world, !player.canUseCommandBlock()); + + while (printer.advanceCurrentPos()) { + if (!printer.shouldPlaceCurrent(world)) + continue; + + printer.handleCurrentTarget((pos, state, tile) -> { + CompoundNBT tileData = tile != null ? tile.write(new CompoundNBT()) : null; + BlockHelper.placeSchematicBlock(world, state, pos, null, tileData); + }, (pos, entity) -> { + world.addEntity(entity); + }); + } }); context.get().setPacketHandled(true); } diff --git a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java index b8c37ac39..bde22038b 100644 --- a/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java +++ b/src/main/java/com/simibubi/create/content/schematics/packet/SchematicUploadPacket.java @@ -72,13 +72,13 @@ public class SchematicUploadPacket extends SimplePacketBase { return; if (code == BEGIN) { BlockPos pos = ((SchematicTableContainer) player.openContainer).getTileEntity() - .getPos(); - Create.schematicReceiver.handleNewUpload(player, schematic, size, pos); + .getPos(); + Create.SCHEMATIC_RECEIVER.handleNewUpload(player, schematic, size, pos); } - if (code == WRITE) - Create.schematicReceiver.handleWriteRequest(player, schematic, data); - if (code == FINISH) - Create.schematicReceiver.handleFinishedUpload(player, schematic); + if (code == WRITE) + Create.SCHEMATIC_RECEIVER.handleWriteRequest(player, schematic, data); + if (code == FINISH) + Create.SCHEMATIC_RECEIVER.handleFinishedUpload(player, schematic); }); context.get() .setPacketHandled(true); diff --git a/src/main/java/com/simibubi/create/events/ClientEvents.java b/src/main/java/com/simibubi/create/events/ClientEvents.java index aa9db5918..925c761d8 100644 --- a/src/main/java/com/simibubi/create/events/ClientEvents.java +++ b/src/main/java/com/simibubi/create/events/ClientEvents.java @@ -3,6 +3,7 @@ package com.simibubi.create.events; import java.util.ArrayList; import java.util.List; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderDispatcher; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.AllFluids; @@ -21,15 +22,18 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.CapabilityMinecartController; import com.simibubi.create.content.contraptions.components.turntable.TurntableHandler; +import com.simibubi.create.content.contraptions.goggles.GoggleOverlayRenderer; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorHandler; import com.simibubi.create.content.curiosities.armor.CopperBacktankArmorLayer; +import com.simibubi.create.content.curiosities.tools.BlueprintOverlayRenderer; import com.simibubi.create.content.curiosities.tools.ExtendoGripRenderHandler; import com.simibubi.create.content.curiosities.zapper.ZapperItem; import com.simibubi.create.content.curiosities.zapper.ZapperRenderHandler; import com.simibubi.create.content.curiosities.zapper.terrainzapper.WorldshaperRenderHandler; import com.simibubi.create.content.logistics.block.depot.EjectorTargetHandler; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmInteractionPointHandler; +import com.simibubi.create.content.logistics.item.LinkedControllerClientHandler; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.ui.BaseConfigScreen; import com.simibubi.create.foundation.fluid.FluidHelper; @@ -38,9 +42,6 @@ import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.LeftClickPacket; import com.simibubi.create.foundation.ponder.PonderTooltipHandler; -import com.simibubi.create.foundation.render.KineticRenderer; -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.sound.SoundScapes; import com.simibubi.create.foundation.tileEntity.behaviour.edgeInteraction.EdgeInteractionRenderer; @@ -101,18 +102,19 @@ public class ClientEvents { return; if (event.phase == Phase.START) { + LinkedControllerClientHandler.tick(); AirCurrent.tickClientPlayerSounds(); return; } + SoundScapes.tick(); AnimationTickHolder.tick(); - FastRenderDispatcher.tick(); ScrollValueHandler.tick(); - CreateClient.schematicSender.tick(); - CreateClient.schematicAndQuillHandler.tick(); - CreateClient.schematicHandler.tick(); + CreateClient.SCHEMATIC_SENDER.tick(); + CreateClient.SCHEMATIC_AND_QUILL_HANDLER.tick(); + CreateClient.SCHEMATIC_HANDLER.tick(); ContraptionHandler.tick(world); CapabilityMinecartController.tick(world); @@ -137,9 +139,10 @@ public class ClientEvents { ArmInteractionPointHandler.tick(); EjectorTargetHandler.tick(); PlacementHelpers.tick(); - CreateClient.outliner.tickOutlines(); - CreateClient.ghostBlocks.tickGhosts(); + CreateClient.OUTLINER.tickOutlines(); + CreateClient.GHOST_BLOCKS.tickGhosts(); ContraptionRenderDispatcher.tick(); + BlueprintOverlayRenderer.tick(); } @SubscribeEvent @@ -151,11 +154,8 @@ public class ClientEvents { public static void onLoadWorld(WorldEvent.Load event) { IWorld world = event.getWorld(); if (world.isRemote() && world instanceof ClientWorld && !(world instanceof WrappedClientWorld)) { - CreateClient.invalidateRenderers(world); + CreateClient.invalidateRenderers(); AnimationTickHolder.reset(); - KineticRenderer renderer = CreateClient.kineticRenderer.get(world); - renderer.invalidate(); - ((ClientWorld) world).loadedTileEntityList.forEach(renderer::add); } /* @@ -170,7 +170,7 @@ public class ClientEvents { public static void onUnloadWorld(WorldEvent.Unload event) { if (event.getWorld() .isRemote()) { - CreateClient.invalidateRenderers(event.getWorld()); + CreateClient.invalidateRenderers(); AnimationTickHolder.reset(); } } @@ -178,7 +178,7 @@ public class ClientEvents { @SubscribeEvent public static void onRenderWorld(RenderWorldLastEvent event) { Vector3d cameraPos = Minecraft.getInstance().gameRenderer.getActiveRenderInfo() - .getProjectedView(); + .getProjectedView(); float pt = AnimationTickHolder.getPartialTicks(); MatrixStack ms = event.getMatrixStack(); @@ -187,17 +187,15 @@ public class ClientEvents { SuperRenderTypeBuffer buffer = SuperRenderTypeBuffer.getInstance(); CouplingRenderer.renderAll(ms, buffer); - CreateClient.schematicHandler.render(ms, buffer); - CreateClient.ghostBlocks.renderAll(ms, buffer); + CreateClient.SCHEMATIC_HANDLER.render(ms, buffer); + CreateClient.GHOST_BLOCKS.renderAll(ms, buffer); - CreateClient.outliner.renderOutlines(ms, buffer, pt); + CreateClient.OUTLINER.renderOutlines(ms, buffer, pt); // LightVolumeDebugger.render(ms, buffer); buffer.draw(); RenderSystem.enableCull(); ms.pop(); - - RenderWork.runAll(); } @SubscribeEvent @@ -220,7 +218,10 @@ public class ClientEvents { public static void onRenderHotbar(MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay, float partialTicks) { - CreateClient.schematicHandler.renderOverlay(ms, buffer, light, overlay, partialTicks); + CreateClient.SCHEMATIC_HANDLER.renderOverlay(ms, buffer, light, overlay, partialTicks); + LinkedControllerClientHandler.renderOverlay(ms, buffer, light, overlay, partialTicks); + BlueprintOverlayRenderer.renderOverlay(ms, buffer, light, overlay, partialTicks); + GoggleOverlayRenderer.renderOverlay(ms, buffer, light, overlay, partialTicks); } @SubscribeEvent @@ -335,8 +336,8 @@ public class ClientEvents { } public static void loadCompleted(FMLLoadCompleteEvent event) { - ModContainer createContainer = ModList.get().getModContainerById("create").orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted")); - createContainer.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, previousScreen) -> new BaseConfigScreen(previousScreen)); + ModContainer createContainer = ModList.get().getModContainerById(Create.ID).orElseThrow(() -> new IllegalStateException("Create Mod Container missing after loadCompleted")); + createContainer.registerExtensionPoint(ExtensionPoint.CONFIGGUIFACTORY, () -> (mc, previousScreen) -> BaseConfigScreen.forCreate(previousScreen)); } } diff --git a/src/main/java/com/simibubi/create/events/CommonEvents.java b/src/main/java/com/simibubi/create/events/CommonEvents.java index dfcb926a4..6664931dd 100644 --- a/src/main/java/com/simibubi/create/events/CommonEvents.java +++ b/src/main/java/com/simibubi/create/events/CommonEvents.java @@ -10,7 +10,7 @@ import com.simibubi.create.content.contraptions.fluids.recipe.PotionMixingRecipe import com.simibubi.create.content.contraptions.wrench.WrenchItem; import com.simibubi.create.content.curiosities.zapper.ZapperInteractionHandler; import com.simibubi.create.content.curiosities.zapper.ZapperItem; -import com.simibubi.create.content.schematics.ServerSchematicLoader; +import com.simibubi.create.content.logistics.item.LinkedControllerServerHandler; import com.simibubi.create.foundation.command.AllCommands; import com.simibubi.create.foundation.fluid.FluidHelper; import com.simibubi.create.foundation.utility.Iterate; @@ -54,10 +54,8 @@ public class CommonEvents { public static void onServerTick(ServerTickEvent event) { if (event.phase == Phase.START) return; - if (Create.schematicReceiver == null) - Create.schematicReceiver = new ServerSchematicLoader(); - Create.schematicReceiver.tick(); - Create.lagger.tick(); + Create.SCHEMATIC_RECEIVER.tick(); + Create.LAGGER.tick(); ServerSpeedProvider.serverTick(); } @@ -96,6 +94,7 @@ public class CommonEvents { ContraptionHandler.tick(world); CapabilityMinecartController.tick(world); CouplingPhysics.tick(world); + LinkedControllerServerHandler.tick(world); } @SubscribeEvent @@ -133,21 +132,21 @@ public class CommonEvents { @SubscribeEvent public static void serverStopped(FMLServerStoppingEvent event) { - Create.schematicReceiver.shutdown(); + Create.SCHEMATIC_RECEIVER.shutdown(); } @SubscribeEvent public static void onLoadWorld(WorldEvent.Load event) { IWorld world = event.getWorld(); - Create.redstoneLinkNetworkHandler.onLoadWorld(world); - Create.torquePropagator.onLoadWorld(world); + Create.REDSTONE_LINK_NETWORK_HANDLER.onLoadWorld(world); + Create.TORQUE_PROPAGATOR.onLoadWorld(world); } @SubscribeEvent public static void onUnloadWorld(WorldEvent.Unload event) { IWorld world = event.getWorld(); - Create.redstoneLinkNetworkHandler.onUnloadWorld(world); - Create.torquePropagator.onUnloadWorld(world); + Create.REDSTONE_LINK_NETWORK_HANDLER.onUnloadWorld(world); + Create.TORQUE_PROPAGATOR.onUnloadWorld(world); WorldAttached.invalidateWorld(world); } diff --git a/src/main/java/com/simibubi/create/events/InputEvents.java b/src/main/java/com/simibubi/create/events/InputEvents.java index 7447b0a94..6cdcb3ff7 100644 --- a/src/main/java/com/simibubi/create/events/InputEvents.java +++ b/src/main/java/com/simibubi/create/events/InputEvents.java @@ -23,7 +23,7 @@ public class InputEvents { if (Minecraft.getInstance().currentScreen != null) return; - CreateClient.schematicHandler.onKeyInput(key, pressed); + CreateClient.SCHEMATIC_HANDLER.onKeyInput(key, pressed); } @SubscribeEvent @@ -33,9 +33,9 @@ public class InputEvents { double delta = event.getScrollDelta(); // CollisionDebugger.onScroll(delta); - boolean cancelled = CreateClient.schematicHandler.mouseScrolled(delta) - || CreateClient.schematicAndQuillHandler.mouseScrolled(delta) || FilteringHandler.onScroll(delta) - || ScrollValueHandler.onScroll(delta); + boolean cancelled = CreateClient.SCHEMATIC_HANDLER.mouseScrolled(delta) + || CreateClient.SCHEMATIC_AND_QUILL_HANDLER.mouseScrolled(delta) || FilteringHandler.onScroll(delta) + || ScrollValueHandler.onScroll(delta); event.setCanceled(cancelled); } @@ -47,8 +47,8 @@ public class InputEvents { int button = event.getButton(); boolean pressed = !(event.getAction() == 0); - CreateClient.schematicHandler.onMouseInput(button, pressed); - CreateClient.schematicAndQuillHandler.onMouseInput(button, pressed); + CreateClient.SCHEMATIC_HANDLER.onMouseInput(button, pressed); + CreateClient.SCHEMATIC_AND_QUILL_HANDLER.onMouseInput(button, pressed); } } diff --git a/src/main/java/com/simibubi/create/foundation/BreakProgressHook.java b/src/main/java/com/simibubi/create/foundation/BreakProgressHook.java new file mode 100644 index 000000000..34c16f20e --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/BreakProgressHook.java @@ -0,0 +1,22 @@ +package com.simibubi.create.foundation; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; +import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; + +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; + +public class BreakProgressHook { + + public static void whenBreaking(ClientWorld world, WorldRenderer renderer, int playerEntityId, BlockPos pos, int progress) { + if (AllBlocks.BELT.has(world.getBlockState(pos))) { + BeltTileEntity belt = (BeltTileEntity) world.getTileEntity(pos); + + for (BlockPos beltPos : BeltBlock.getBeltChain(world, belt.getController())) { + renderer.sendBlockBreakProgress(beltPos.hashCode(), beltPos, progress); + } + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java b/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java index 30cdb88eb..ed9a32a7e 100644 --- a/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java +++ b/src/main/java/com/simibubi/create/foundation/ResourceReloadHandler.java @@ -3,6 +3,7 @@ package com.simibubi.create.foundation; import com.simibubi.create.CreateClient; import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation; import com.simibubi.create.foundation.block.render.SpriteShifter; +import com.simibubi.create.foundation.sound.SoundScapes; import com.simibubi.create.foundation.utility.ISimpleReloadListener; import net.minecraft.profiler.IProfiler; @@ -15,6 +16,7 @@ public class ResourceReloadHandler implements ISimpleReloadListener { SpriteShifter.reloadUVs(); CreateClient.invalidateRenderers(); IHaveGoggleInformation.numberFormat.update(); + SoundScapes.invalidateAll(); } } diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java index 96392244e..18fcb1deb 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllAdvancements.java @@ -16,7 +16,7 @@ import com.simibubi.create.AllBlocks; import com.simibubi.create.AllFluids; import com.simibubi.create.AllItems; import com.simibubi.create.Create; -import com.simibubi.create.content.logistics.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.Advancement.Builder; diff --git a/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java b/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java index 1e0c67527..959043354 100644 --- a/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java +++ b/src/main/java/com/simibubi/create/foundation/advancement/AllTriggers.java @@ -4,7 +4,7 @@ import java.util.LinkedList; import java.util.List; import java.util.function.Predicate; -import com.simibubi.create.content.logistics.InWorldProcessing; +import com.simibubi.create.content.contraptions.processing.InWorldProcessing; import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.block.Block; diff --git a/src/main/java/com/simibubi/create/foundation/block/DyedBlockList.java b/src/main/java/com/simibubi/create/foundation/block/DyedBlockList.java new file mode 100644 index 000000000..f0a5d97f6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/block/DyedBlockList.java @@ -0,0 +1,33 @@ +package com.simibubi.create.foundation.block; + +import java.util.Arrays; +import java.util.function.Function; + +import com.tterrag.registrate.util.entry.BlockEntry; + +import net.minecraft.block.Block; +import net.minecraft.item.DyeColor; + +public class DyedBlockList { + + private static final int COLOR_AMOUNT = DyeColor.values().length; + + private final BlockEntry[] values = new BlockEntry[COLOR_AMOUNT]; + + public DyedBlockList(Function> filler) { + for (DyeColor color : DyeColor.values()) { + values[color.ordinal()] = filler.apply(color); + } + } + + @SuppressWarnings("unchecked") + public BlockEntry get(DyeColor color) { + return (BlockEntry) values[color.ordinal()]; + } + + @SuppressWarnings("unchecked") + public BlockEntry[] toArray() { + return (BlockEntry[]) Arrays.copyOf(values, values.length); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/block/ITE.java b/src/main/java/com/simibubi/create/foundation/block/ITE.java index 8054544e8..16eae3ba0 100644 --- a/src/main/java/com/simibubi/create/foundation/block/ITE.java +++ b/src/main/java/com/simibubi/create/foundation/block/ITE.java @@ -2,102 +2,44 @@ package com.simibubi.create.foundation.block; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.Function; -import com.simibubi.create.Create; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.utility.WorldHelper; +import javax.annotation.Nullable; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.ResourceLocation; +import net.minecraft.util.ActionResultType; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockReader; -import net.minecraft.world.IWorld; public interface ITE { Class getTileEntityClass(); default void withTileEntityDo(IBlockReader world, BlockPos pos, Consumer action) { - try { - action.accept(getTileEntity(world, pos)); - } catch (TileEntityException e) { - } + getTileEntityOptional(world, pos).ifPresent(action); + } + + default ActionResultType onTileEntityUse(IBlockReader world, BlockPos pos, Function action) { + return getTileEntityOptional(world, pos).map(action) + .orElse(ActionResultType.PASS); } default Optional getTileEntityOptional(IBlockReader world, BlockPos pos) { - try { - return Optional.of(getTileEntity(world, pos)); - } catch (TileEntityException e) { - } - return Optional.empty(); + return Optional.ofNullable(getTileEntity(world, pos)); } + @Nullable @SuppressWarnings("unchecked") - default T getTileEntity(IBlockReader worldIn, BlockPos pos) throws TileEntityException { + default T getTileEntity(IBlockReader worldIn, BlockPos pos) { TileEntity tileEntity = worldIn.getTileEntity(pos); Class expectedClass = getTileEntityClass(); - IWorld world = null; - if (worldIn instanceof IWorld) - world = (IWorld) worldIn; - if (tileEntity == null) - throw new MissingTileEntityException(world, pos, expectedClass); + return null; if (!expectedClass.isInstance(tileEntity)) - throw new InvalidTileEntityException(world, pos, expectedClass, tileEntity.getClass()); + return null; return (T) tileEntity; } - static class TileEntityException extends Throwable { - private static final long serialVersionUID = 1L; - - public TileEntityException(IWorld world, BlockPos pos, Class teClass) { - super(makeBaseMessage(world, pos, teClass)); - } - - public TileEntityException(String message) { - super(message); - report(this); - } - - static String makeBaseMessage(IWorld world, BlockPos pos, Class expectedTeClass) { - return String.format("[%s] @(%d, %d, %d), expecting a %s", getDimensionName(world), pos.getX(), pos.getY(), - pos.getZ(), expectedTeClass.getSimpleName()); - } - - static String getDimensionName(IWorld world) { - String notAvailable = "Dim N/A"; - if (world == null) - return notAvailable; - ResourceLocation registryName = WorldHelper.getDimensionID(world); - if (registryName == null) - return notAvailable; - return registryName.toString(); - } - } - - static class MissingTileEntityException extends TileEntityException { - private static final long serialVersionUID = 1L; - - public MissingTileEntityException(IWorld world, BlockPos pos, Class teClass) { - super("Missing TileEntity: " + makeBaseMessage(world, pos, teClass)); - } - - } - - static class InvalidTileEntityException extends TileEntityException { - private static final long serialVersionUID = 1L; - - public InvalidTileEntityException(IWorld world, BlockPos pos, Class expectedTeClass, Class foundTeClass) { - super("Wrong TileEntity: " + makeBaseMessage(world, pos, expectedTeClass) + ", found " - + foundTeClass.getSimpleName()); - } - } - - static void report(TileEntityException e) { - if (AllConfigs.COMMON.logTeErrors.get()) - Create.logger.debug("TileEntityException thrown!", e); - } - } diff --git a/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java b/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java index 0337a5d08..9d3dbf59b 100644 --- a/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java +++ b/src/main/java/com/simibubi/create/foundation/block/ItemUseOverrides.java @@ -13,15 +13,15 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockRayTraceResult; import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -@Mod.EventBusSubscriber +@EventBusSubscriber public class ItemUseOverrides { - private static final Set overrides = new HashSet<>(); + private static final Set OVERRIDES = new HashSet<>(); public static void addBlock(Block block) { - overrides.add(block.getRegistryName()); + OVERRIDES.add(block.getRegistryName()); } @SubscribeEvent @@ -30,15 +30,15 @@ public class ItemUseOverrides { return; BlockState state = event.getWorld() - .getBlockState(event.getPos()); + .getBlockState(event.getPos()); ResourceLocation id = state.getBlock() - .getRegistryName(); + .getRegistryName(); - if (!overrides.contains(id)) + if (!OVERRIDES.contains(id)) return; BlockRayTraceResult blockTrace = - new BlockRayTraceResult(VecHelper.getCenterOf(event.getPos()), event.getFace(), event.getPos(), true); + new BlockRayTraceResult(VecHelper.getCenterOf(event.getPos()), event.getFace(), event.getPos(), true); ActionResultType result = state.onUse(event.getWorld(), event.getPlayer(), event.getHand(), blockTrace); if (!result.isAccepted()) @@ -46,6 +46,6 @@ public class ItemUseOverrides { event.setCanceled(true); event.setCancellationResult(result); - } + } diff --git a/src/main/java/com/simibubi/create/foundation/block/render/ColoredVertexModel.java b/src/main/java/com/simibubi/create/foundation/block/render/ColoredVertexModel.java index c860bb29e..e4be4b2ba 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/ColoredVertexModel.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/ColoredVertexModel.java @@ -4,8 +4,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -import com.simibubi.create.foundation.block.IBlockVertexColor; - import net.minecraft.block.BlockState; import net.minecraft.client.renderer.model.BakedQuad; import net.minecraft.client.renderer.model.IBakedModel; diff --git a/src/main/java/com/simibubi/create/foundation/block/IBlockVertexColor.java b/src/main/java/com/simibubi/create/foundation/block/render/IBlockVertexColor.java similarity index 67% rename from src/main/java/com/simibubi/create/foundation/block/IBlockVertexColor.java rename to src/main/java/com/simibubi/create/foundation/block/render/IBlockVertexColor.java index 1a4f91dae..f754ed13c 100644 --- a/src/main/java/com/simibubi/create/foundation/block/IBlockVertexColor.java +++ b/src/main/java/com/simibubi/create/foundation/block/render/IBlockVertexColor.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.block; +package com.simibubi.create.foundation.block.render; @FunctionalInterface public interface IBlockVertexColor { 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 81b4a5f5a..9f393940b 100644 --- a/src/main/java/com/simibubi/create/foundation/command/AllCommands.java +++ b/src/main/java/com/simibubi/create/foundation/command/AllCommands.java @@ -23,7 +23,6 @@ public class AllCommands { LiteralCommandNode createRoot = dispatcher.register(Commands.literal("create") .requires(cs -> cs.hasPermissionLevel(0)) // general purpose - .then(new ToggleExperimentalRenderingCommand().register()) .then(new ToggleDebugCommand().register()) .then(FabulousWarningCommand.register()) .then(OverlayConfigCommand.register()) @@ -33,6 +32,7 @@ public class AllCommands { .then(ConfigCommand.register()) .then(PonderCommand.register()) .then(CloneCommand.register()) + .then(GlueCommand.register()) // utility .then(util) diff --git a/src/main/java/com/simibubi/create/foundation/command/ChunkUtilCommand.java b/src/main/java/com/simibubi/create/foundation/command/ChunkUtilCommand.java index 4a67e3d82..e999333ca 100644 --- a/src/main/java/com/simibubi/create/foundation/command/ChunkUtilCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/ChunkUtilCommand.java @@ -23,20 +23,20 @@ public class ChunkUtilCommand { ColumnPos columnPos = ColumnPosArgument.fromBlockPos(ctx, "pos"); ChunkPos chunkPos = new ChunkPos(columnPos.x >> 4, columnPos.z >> 4); ServerChunkProvider chunkProvider = ctx.getSource() - .getWorld() - .getChunkProvider(); + .getWorld() + .getChunkProvider(); - boolean success = Create.chunkUtil.reloadChunk(chunkProvider, chunkPos); + boolean success = Create.CHUNK_UTIL.reloadChunk(chunkProvider, chunkPos); if (success) { ctx.getSource() - .sendFeedback(new StringTextComponent("scheduled unload for chunk " - + chunkPos.toString() + ", might need to repeat command"), true); + .sendFeedback(new StringTextComponent("scheduled unload for chunk " + + chunkPos.toString() + ", might need to repeat command"), true); return 1; } else { ctx.getSource() - .sendFeedback( - new StringTextComponent( + .sendFeedback( + new StringTextComponent( "unable to schedule unload, is chunk " + chunkPos.toString() + " loaded?"), true); return 0; @@ -49,19 +49,19 @@ public class ChunkUtilCommand { ColumnPos columnPos = ColumnPosArgument.fromBlockPos(ctx, "pos"); ChunkPos chunkPos = new ChunkPos(columnPos.x >> 4, columnPos.z >> 4); ServerChunkProvider chunkProvider = ctx.getSource() - .getWorld() - .getChunkProvider(); + .getWorld() + .getChunkProvider(); - boolean success = Create.chunkUtil.unloadChunk(chunkProvider, chunkPos); + boolean success = Create.CHUNK_UTIL.unloadChunk(chunkProvider, chunkPos); ctx.getSource() - .sendFeedback( - new StringTextComponent("added chunk " + chunkPos.toString() + " to unload list"), - true); + .sendFeedback( + new StringTextComponent("added chunk " + chunkPos.toString() + " to unload list"), + true); if (success) { ctx.getSource() - .sendFeedback(new StringTextComponent("scheduled unload for chunk " - + chunkPos.toString() + ", might need to repeat command"), true); + .sendFeedback(new StringTextComponent("scheduled unload for chunk " + + chunkPos.toString() + ", might need to repeat command"), true); return 1; } else { ctx.getSource() @@ -75,11 +75,11 @@ public class ChunkUtilCommand { .then(Commands.literal("clear") .executes(ctx -> { // chunk clear - int count = Create.chunkUtil.clear(ctx.getSource() - .getWorld() - .getChunkProvider()); + int count = Create.CHUNK_UTIL.clear(ctx.getSource() + .getWorld() + .getChunkProvider()); ctx.getSource() - .sendFeedback(new StringTextComponent("removed " + count + " entries from unload list"), false); + .sendFeedback(new StringTextComponent("removed " + count + " entries from unload list"), false); return 1; })); diff --git a/src/main/java/com/simibubi/create/foundation/command/ConfigCommand.java b/src/main/java/com/simibubi/create/foundation/command/ConfigCommand.java index 24a45110a..5115d9d6f 100644 --- a/src/main/java/com/simibubi/create/foundation/command/ConfigCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/ConfigCommand.java @@ -1,14 +1,25 @@ package com.simibubi.create.foundation.command; +import com.mojang.brigadier.Command; +import com.mojang.brigadier.arguments.StringArgumentType; +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.config.ui.ConfigHelper; +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.fml.config.ModConfig; import net.minecraftforge.fml.network.PacketDistributor; -import com.mojang.brigadier.Command; -import com.mojang.brigadier.builder.ArgumentBuilder; -import com.simibubi.create.foundation.networking.AllPackets; - +/** + * Examples: + * /create config client - to open Create's ConfigGui with the client config already selected + * /create config "botania:common" - to open Create's ConfigGui with Botania's common config already selected + * /create config "create:client.client.rainbowDebug" set false - to disable Create's rainbow debug for the sender + */ public class ConfigCommand { public static ArgumentBuilder register() { @@ -21,7 +32,59 @@ public class ConfigCommand { ); return Command.SINGLE_SUCCESS; - }); + }) + .then(Commands.argument("path", StringArgumentType.string()) + .executes(ctx -> { + ServerPlayerEntity player = ctx.getSource().asPlayer(); + AllPackets.channel.send( + PacketDistributor.PLAYER.with(() -> player), + new SConfigureConfigPacket(SConfigureConfigPacket.Actions.configScreen.name(), StringArgumentType.getString(ctx, "path")) + ); + + return Command.SINGLE_SUCCESS; + }) + .then(Commands.literal("set") + .requires(cs -> cs.hasPermissionLevel(2)) + .then(Commands.argument("value", StringArgumentType.string()) + .executes(ctx -> { + String path = StringArgumentType.getString(ctx, "path"); + String value = StringArgumentType.getString(ctx, "value"); + + + ConfigHelper.ConfigPath configPath; + try { + configPath = ConfigHelper.ConfigPath.parse(path); + } catch (IllegalArgumentException e) { + ctx.getSource().sendErrorMessage(new StringTextComponent(e.getMessage())); + return 0; + } + + if (configPath.getType() == ModConfig.Type.CLIENT) { + ServerPlayerEntity player = ctx.getSource().asPlayer(); + AllPackets.channel.send( + PacketDistributor.PLAYER.with(() -> player), + new SConfigureConfigPacket("SET" + path, value) + ); + + return Command.SINGLE_SUCCESS; + } + + try { + ConfigHelper.setConfigValue(configPath, value); + ctx.getSource().sendFeedback(new StringTextComponent("Great Success!"), false); + return Command.SINGLE_SUCCESS; + } catch (ConfigHelper.InvalidValueException e) { + ctx.getSource().sendErrorMessage(new StringTextComponent("Config could not be set the the specified value!")); + return 0; + } catch (Exception e) { + ctx.getSource().sendErrorMessage(new StringTextComponent("Something went wrong while trying to set config value. Check the server logs for more information")); + Create.LOGGER.warn("Exception during server-side config value set:", e); + return 0; + } + }) + ) + ) + ); } } diff --git a/src/main/java/com/simibubi/create/foundation/command/GlueCommand.java b/src/main/java/com/simibubi/create/foundation/command/GlueCommand.java new file mode 100644 index 000000000..269d52023 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/command/GlueCommand.java @@ -0,0 +1,32 @@ +package com.simibubi.create.foundation.command; + +import com.mojang.brigadier.builder.ArgumentBuilder; +import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; + +import net.minecraft.command.CommandSource; +import net.minecraft.command.Commands; +import net.minecraft.command.arguments.BlockPosArgument; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.server.ServerWorld; + +public class GlueCommand { + public static ArgumentBuilder register() { + return Commands.literal("glue") + .requires(cs -> cs.hasPermissionLevel(0)) + .then(Commands.argument("pos", BlockPosArgument.blockPos()) + //.then(Commands.argument("direction", EnumArgument.enumArgument(Direction.class)) + .executes(ctx -> { + BlockPos pos = BlockPosArgument.getBlockPos(ctx, "pos"); + + ServerWorld world = ctx.getSource().getWorld(); + SuperGlueEntity entity = new SuperGlueEntity(world, pos, Direction.UP); + + entity.playPlaceSound(); + world.addEntity(entity); + + return 1; + })); + + } +} 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 a66bbb06e..900e250fe 100644 --- a/src/main/java/com/simibubi/create/foundation/command/HighlightPacket.java +++ b/src/main/java/com/simibubi/create/foundation/command/HighlightPacket.java @@ -48,13 +48,13 @@ public class HighlightPacket extends SimplePacketBase { if (Minecraft.getInstance().world == null || !Minecraft.getInstance().world.isBlockPresent(pos)) return; - CreateClient.outliner.showAABB("highlightCommand", VoxelShapes.fullCube() - .getBoundingBox() - .offset(pos), 200) - .lineWidth(1 / 32f) - .colored(0xEeEeEe) - // .colored(0x243B50) - .withFaceTexture(AllSpecialTextures.SELECTION); + CreateClient.OUTLINER.showAABB("highlightCommand", VoxelShapes.fullCube() + .getBoundingBox() + .offset(pos), 200) + .lineWidth(1 / 32f) + .colored(0xEeEeEe) + // .colored(0x243B50) + .withFaceTexture(AllSpecialTextures.SELECTION); } } diff --git a/src/main/java/com/simibubi/create/foundation/command/KillTPSCommand.java b/src/main/java/com/simibubi/create/foundation/command/KillTPSCommand.java index 22ecbce81..46e18f681 100644 --- a/src/main/java/com/simibubi/create/foundation/command/KillTPSCommand.java +++ b/src/main/java/com/simibubi/create/foundation/command/KillTPSCommand.java @@ -16,32 +16,32 @@ public class KillTPSCommand { .executes(ctx -> { // killtps no arguments ctx.getSource() - .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.slowed_by.0", - Create.lagger.isLagging() ? Create.lagger.getTickTime() : 0), true); - if (Create.lagger.isLagging()) + .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.slowed_by.0", + Create.LAGGER.isLagging() ? Create.LAGGER.getTickTime() : 0), true); + if (Create.LAGGER.isLagging()) ctx.getSource() - .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.0"), - true); + .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.0"), + true); else ctx.getSource() - .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.1"), - true); + .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.1"), + true); return 1; }) .then(Commands.literal("start") .executes(ctx -> { // killtps start no time - int tickTime = Create.lagger.getTickTime(); + int tickTime = Create.LAGGER.getTickTime(); if (tickTime > 0) { - Create.lagger.setLagging(true); + Create.LAGGER.setLagging(true); ctx.getSource() - .sendFeedback((Lang - .createTranslationTextComponent("command.killTPSCommand.status.slowed_by.1", tickTime)), - true); + .sendFeedback((Lang + .createTranslationTextComponent("command.killTPSCommand.status.slowed_by.1", tickTime)), + true); ctx.getSource() - .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.0"), - true); + .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.0"), + true); } else { ctx.getSource() .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.1"), @@ -55,27 +55,27 @@ public class KillTPSCommand { .executes(ctx -> { // killtps start tickTime int tickTime = IntegerArgumentType.getInteger(ctx, - Lang.translate("command.killTPSCommand.argument.tickTime") - .getUnformattedComponentText()); - Create.lagger.setTickTime(tickTime); - Create.lagger.setLagging(true); + Lang.translate("command.killTPSCommand.argument.tickTime") + .getUnformattedComponentText()); + Create.LAGGER.setTickTime(tickTime); + Create.LAGGER.setLagging(true); ctx.getSource() - .sendFeedback((Lang - .createTranslationTextComponent("command.killTPSCommand.status.slowed_by.1", tickTime)), - true); + .sendFeedback((Lang + .createTranslationTextComponent("command.killTPSCommand.status.slowed_by.1", tickTime)), + true); ctx.getSource() - .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.0"), - true); + .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.usage.0"), + true); return 1; }))) .then(Commands.literal("stop") .executes(ctx -> { // killtps stop - Create.lagger.setLagging(false); + Create.LAGGER.setLagging(false); ctx.getSource() - .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.slowed_by.2"), - false); + .sendFeedback(Lang.createTranslationTextComponent("command.killTPSCommand.status.slowed_by.2"), + false); return 1; })); diff --git a/src/main/java/com/simibubi/create/foundation/command/SConfigureConfigPacket.java b/src/main/java/com/simibubi/create/foundation/command/SConfigureConfigPacket.java index c1dcd3105..73ffd6168 100644 --- a/src/main/java/com/simibubi/create/foundation/command/SConfigureConfigPacket.java +++ b/src/main/java/com/simibubi/create/foundation/command/SConfigureConfigPacket.java @@ -9,13 +9,13 @@ import com.simibubi.create.Create; import com.simibubi.create.content.contraptions.goggles.GoggleConfigScreen; import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.ui.BaseConfigScreen; +import com.simibubi.create.foundation.config.ui.ConfigHelper; +import com.simibubi.create.foundation.config.ui.SubMenuConfigScreen; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.networking.SimplePacketBase; import com.simibubi.create.foundation.ponder.PonderRegistry; import com.simibubi.create.foundation.ponder.PonderUI; import com.simibubi.create.foundation.ponder.content.PonderIndexScreen; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; -import com.simibubi.create.foundation.render.backend.OptifineHandler; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.player.ClientPlayerEntity; @@ -30,6 +30,7 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.common.ForgeConfig; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.network.NetworkEvent; public class SConfigureConfigPacket extends SimplePacketBase { @@ -57,6 +58,11 @@ public class SConfigureConfigPacket extends SimplePacketBase { public void handle(Supplier ctx) { ctx.get() .enqueueWork(() -> DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> { + if (option.startsWith("SET")) { + trySetConfig(option.substring(3), value); + return; + } + try { Actions.valueOf(option) .performAction(value); @@ -70,13 +76,42 @@ public class SConfigureConfigPacket extends SimplePacketBase { .setPacketHandled(true); } + private static void trySetConfig(String option, String value) { + ClientPlayerEntity player = Minecraft.getInstance().player; + if (player == null) + return; + + ConfigHelper.ConfigPath configPath; + try { + configPath = ConfigHelper.ConfigPath.parse(option); + } catch (IllegalArgumentException e) { + player.sendStatusMessage(new StringTextComponent(e.getMessage()), false); + return; + } + + if (configPath.getType() != ModConfig.Type.CLIENT) { + Create.LOGGER.warn("Received type-mismatched config packet on client"); + return; + } + + try { + ConfigHelper.setConfigValue(configPath, value); + player.sendStatusMessage(new StringTextComponent("Great Success!"), false); + } catch (ConfigHelper.InvalidValueException e) { + player.sendStatusMessage(new StringTextComponent("Config could not be set the the specified value!"), false); + } catch (Exception e) { + player.sendStatusMessage(new StringTextComponent("Something went wrong while trying to set config value. Check the client logs for more information"), false); + Create.LOGGER.warn("Exception during client-side config value set:", e); + } + + } + public enum Actions { configScreen(() -> Actions::configScreen), rainbowDebug(() -> Actions::rainbowDebug), overlayScreen(() -> Actions::overlayScreen), fixLighting(() -> Actions::experimentalLighting), overlayReset(() -> Actions::overlayReset), - experimentalRendering(() -> Actions::experimentalRendering), openPonder(() -> Actions::openPonder), fabulousWarning(() -> Actions::fabulousWarning) @@ -95,7 +130,25 @@ public class SConfigureConfigPacket extends SimplePacketBase { @OnlyIn(Dist.CLIENT) private static void configScreen(String value) { - ScreenOpener.open(new BaseConfigScreen(null)); + if (value.equals("")) { + ScreenOpener.open(BaseConfigScreen.forCreate(null)); + return; + } + + ClientPlayerEntity player = Minecraft.getInstance().player; + ConfigHelper.ConfigPath configPath; + try { + configPath = ConfigHelper.ConfigPath.parse(value); + } catch (IllegalArgumentException e) { + player.sendStatusMessage(new StringTextComponent(e.getMessage()), false); + return; + } + + try { + ScreenOpener.open(SubMenuConfigScreen.find(configPath)); + } catch (Exception e) { + player.sendStatusMessage(new StringTextComponent("Unable to find the specified config"), false); + } } @OnlyIn(Dist.CLIENT) @@ -117,33 +170,6 @@ public class SConfigureConfigPacket extends SimplePacketBase { player.sendStatusMessage(text, false); } - @OnlyIn(Dist.CLIENT) - private static void experimentalRendering(String value) { - ClientPlayerEntity player = Minecraft.getInstance().player; - if (player == null || "".equals(value)) - return; - - if (value.equals("info")) { - ITextComponent text = new StringTextComponent("Experimental Rendering is currently: ") - .append(boolToText(AllConfigs.CLIENT.experimentalRendering.get())); - player.sendStatusMessage(text, false); - return; - } - - boolean parsedBoolean = Boolean.parseBoolean(value); - boolean cannotUseER = OptifineHandler.usingShaders() && parsedBoolean; - - AllConfigs.CLIENT.experimentalRendering.set(parsedBoolean); - - ITextComponent text = boolToText(AllConfigs.CLIENT.experimentalRendering.get()) - .append(new StringTextComponent(" Experimental Rendering").formatted(TextFormatting.WHITE)); - ITextComponent error = new StringTextComponent("Experimental Rendering does not support Optifine Shaders") - .formatted(TextFormatting.RED); - - player.sendStatusMessage(cannotUseER ? error : text, false); - FastRenderDispatcher.refresh(); - } - @OnlyIn(Dist.CLIENT) private static void overlayReset(String value) { AllConfigs.CLIENT.overlayOffsetX.set(0); @@ -170,7 +196,7 @@ public class SConfigureConfigPacket extends SimplePacketBase { ResourceLocation id = new ResourceLocation(value); if (!PonderRegistry.all.containsKey(id)) { - Create.logger.error("Could not find ponder scenes for item: " + id); + Create.LOGGER.error("Could not find ponder scenes for item: " + id); return; } diff --git a/src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java b/src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java deleted file mode 100644 index 19c761f74..000000000 --- a/src/main/java/com/simibubi/create/foundation/command/ToggleExperimentalRenderingCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.simibubi.create.foundation.command; - -import com.simibubi.create.foundation.networking.AllPackets; - -import net.minecraft.entity.player.ServerPlayerEntity; -import net.minecraftforge.fml.network.PacketDistributor; - -public class ToggleExperimentalRenderingCommand extends ConfigureConfigCommand { - - public ToggleExperimentalRenderingCommand() { - super("experimentalRendering"); - } - - @Override - protected void sendPacket(ServerPlayerEntity player, String option) { - AllPackets.channel.send( - PacketDistributor.PLAYER.with(() -> player), - new SConfigureConfigPacket(SConfigureConfigPacket.Actions.experimentalRendering.name(), option) - ); - } -} 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 ce9017241..ebe8f1e31 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CClient.java +++ b/src/main/java/com/simibubi/create/foundation/config/CClient.java @@ -19,6 +19,20 @@ public class CClient extends ConfigBase { 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 ConfigInt mainMenuConfigButtonRow = i(2, 0, 4, "mainMenuConfigButtonRow", + "Choose the menu row that the Create config button appears on in the main menu", + "Set to 0 to disable the button altogether"); + public ConfigInt mainMenuConfigButtonOffsetX = i(-4, Integer.MIN_VALUE, Integer.MAX_VALUE, "mainMenuConfigButtonOffsetX", + "Offset the Create config button in the main menu by this many pixels on the X axis", + "The sign (+/-) of this value determines what side of the row the button appears on (right/left)"); + + public ConfigInt ingameMenuConfigButtonRow = i(3, 0, 5, "ingameMenuConfigButtonRow", + "Choose the menu row that the Create config button appears on in the in-game menu", + "Set to 0 to disable the button altogether"); + public ConfigInt ingameMenuConfigButtonOffsetX = i(-4, Integer.MIN_VALUE, Integer.MAX_VALUE, "ingameMenuConfigButtonOffsetX", + "Offset the Create config button in the in-game menu by this many pixels on the X axis", + "The sign (+/-) of this value determines what side of the row the button appears on (right/left)"); + public ConfigBool ignoreFabulousWarning = b(false, "ignoreFabulousWarning", "Setting this to true will prevent Create from sending you a warning when playing with Fabulous graphics enabled"); diff --git a/src/main/java/com/simibubi/create/foundation/config/CCommon.java b/src/main/java/com/simibubi/create/foundation/config/CCommon.java index d95a92f60..beeb7f897 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CCommon.java +++ b/src/main/java/com/simibubi/create/foundation/config/CCommon.java @@ -3,7 +3,6 @@ package com.simibubi.create.foundation.config; public class CCommon extends ConfigBase { public CWorldGen worldGen = nested(0, CWorldGen::new, Comments.worldGen); - public ConfigBool logTeErrors = b(false, "logTeErrors", Comments.logTeErrors); @Override public String getName() { @@ -12,7 +11,6 @@ public class CCommon extends ConfigBase { private static class Comments { static String worldGen = "Modify Create's impact on your terrain"; - static String logTeErrors = "Forward caught TileEntityExceptions to the log at debug level."; } } diff --git a/src/main/java/com/simibubi/create/foundation/config/CKinetics.java b/src/main/java/com/simibubi/create/foundation/config/CKinetics.java index ec9218eb1..b5fe5002d 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CKinetics.java +++ b/src/main/java/com/simibubi/create/foundation/config/CKinetics.java @@ -33,6 +33,8 @@ public class CKinetics extends ConfigBase { public ConfigInt maxPistonPoles = i(64, 1, "maxPistonPoles", Comments.maxPistonPoles); public ConfigInt maxRopeLength = i(128, 1, "maxRopeLength", Comments.maxRopeLength); public ConfigInt maxCartCouplingLength = i(32, 1, "maxCartCouplingLength", Comments.maxCartCouplingLength); + public ConfigEnum spawnerMovement = + e(SpawnerMovementSetting.NO_PICKUP, "movableSpawners", Comments.spawnerMovement); public CStress stressValues = nested(1, CStress::new, Comments.stress); @@ -92,10 +94,15 @@ public class CKinetics extends ConfigBase { static String maxEjectorDistance = "Max Distance in blocks a Weighted Ejector can throw"; static String ejectorScanInterval = "Time in ticks until the next item launched by an ejector scans blocks for potential collisions"; + static String spawnerMovement = "Configure how Spawner blocks can be moved by contraptions."; } - public static enum DeployerAggroSetting { + public enum DeployerAggroSetting { ALL, CREEPERS, NONE } + public enum SpawnerMovementSetting { + MOVABLE, NO_PICKUP, UNMOVABLE + } + } diff --git a/src/main/java/com/simibubi/create/foundation/config/CRecipes.java b/src/main/java/com/simibubi/create/foundation/config/CRecipes.java index eec2389e7..ec1b46489 100644 --- a/src/main/java/com/simibubi/create/foundation/config/CRecipes.java +++ b/src/main/java/com/simibubi/create/foundation/config/CRecipes.java @@ -7,6 +7,8 @@ public class CRecipes extends ConfigBase { public ConfigBool allowShapedSquareInPress = b(true, "allowShapedSquareInPress", Comments.allowShapedSquareInPress); public ConfigBool allowRegularCraftingInCrafter = b(true, "allowRegularCraftingInCrafter", Comments.allowRegularCraftingInCrafter); + public ConfigBool allowBiggerFireworksInCrafter = + b(false, "allowBiggerFireworksInCrafter", Comments.allowBiggerFireworksInCrafter); public ConfigBool allowStonecuttingOnSaw = b(true, "allowStonecuttingOnSaw", Comments.allowStonecuttingOnSaw); public ConfigBool allowWoodcuttingOnSaw = b(true, "allowWoodcuttingOnSaw", Comments.allowWoodcuttingOnSaw); public ConfigInt lightSourceCountForRefinedRadiance = @@ -28,6 +30,8 @@ public class CRecipes extends ConfigBase { "When true, allows any single-ingredient 2x2 or 3x3 crafting recipes to be processed by a Mechanical Press + Basin."; static String allowRegularCraftingInCrafter = "When true, allows any standard crafting recipes to be processed by Mechanical Crafters."; + static String allowBiggerFireworksInCrafter = + "When true, allows Firework Rockets with more than 9 ingredients to be crafted using Mechanical Crafters."; static String allowStonecuttingOnSaw = "When true, allows any stonecutting recipes to be processed by a Mechanical Saw."; static String allowWoodcuttingOnSaw = diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java index 915abcb38..01119459e 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/BaseConfigScreen.java @@ -1,59 +1,182 @@ package com.simibubi.create.foundation.config.ui; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import com.simibubi.create.Create; import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.TextStencilElement; import com.simibubi.create.foundation.gui.Theme; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.gui.widgets.BoxWidget; +import com.simibubi.create.foundation.item.TooltipHelper; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; import net.minecraft.util.text.StringTextComponent; import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.fml.config.ModConfig; public class BaseConfigScreen extends ConfigScreen { + private static final DelegatedStencilElement.ElementRenderer DISABLED_RENDERER = (ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE, true), Theme.i(Theme.Key.BUTTON_DISABLE, false) | 0x40_000000); + + public static BaseConfigScreen forCreate(Screen parent) { + return new BaseConfigScreen(parent) + .withTitles("Client Settings", "World Generation Settings", "Gameplay Settings") + .withSpecs(AllConfigs.CLIENT.specification, AllConfigs.COMMON.specification, AllConfigs.SERVER.specification); + } + BoxWidget clientConfigWidget; BoxWidget commonConfigWidget; BoxWidget serverConfigWidget; + BoxWidget goBack; - public BaseConfigScreen(Screen parent) { + ForgeConfigSpec clientSpec; + ForgeConfigSpec commonSpec; + ForgeConfigSpec serverSpec; + String clientTile = "CLIENT CONFIG"; + String commonTile = "COMMON CONFIG"; + String serverTile = "SERVER CONFIG"; + String modID = Create.ID; + protected boolean returnOnClose; + + /** + * If you are a Create Addon dev and want to make use of the same GUI + * for your mod's config, use this Constructor to create a entry point + * + * @param parent the previously opened screen + * @param modID the modID of your addon/mod + */ + public BaseConfigScreen(Screen parent, @Nonnull String modID) { + this(parent); + this.modID = modID; + } + + private BaseConfigScreen(Screen parent) { super(parent); } + /** + * If you have static references to your Configs or ConfigSpecs (like Create does in {@link AllConfigs}), + * please use {@link #withSpecs(ForgeConfigSpec, ForgeConfigSpec, ForgeConfigSpec)} instead + */ + public BaseConfigScreen searchForSpecsInModContainer() { + try { + clientSpec = ConfigHelper.findConfigSpecFor(ModConfig.Type.CLIENT, this.modID); + } catch (Exception e) { + Create.LOGGER.warn("Unable to find ClientConfigSpec for mod: " + this.modID); + } + + try { + commonSpec = ConfigHelper.findConfigSpecFor(ModConfig.Type.COMMON, this.modID); + } catch (Exception e) { + Create.LOGGER.warn("Unable to find CommonConfigSpec for mod: " + this.modID, e); + } + + try { + serverSpec = ConfigHelper.findConfigSpecFor(ModConfig.Type.SERVER, this.modID); + } catch (Exception e) { + Create.LOGGER.warn("Unable to find ServerConfigSpec for mod: " + this.modID, e); + } + + return this; + } + + public BaseConfigScreen withSpecs(@Nullable ForgeConfigSpec client, @Nullable ForgeConfigSpec common, @Nullable ForgeConfigSpec server) { + clientSpec = client; + commonSpec = common; + serverSpec = server; + return this; + } + + public BaseConfigScreen withTitles(@Nullable String client, @Nullable String common, @Nullable String server) { + if (client != null) + clientTile = client; + + if (common != null) + commonTile = common; + + if (server != null) + serverTile = server; + + return this; + } + @Override protected void init() { widgets.clear(); super.init(); + returnOnClose = true; - TextStencilElement text = new TextStencilElement(client.fontRenderer, new StringTextComponent("Client Settings").formatted(TextFormatting.BOLD)).centered(true, true); - widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16) - .showingElement(text) - .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, AllConfigs.CLIENT.specification))) - ); - text.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget)); + TextStencilElement clientText = new TextStencilElement(client.fontRenderer, new StringTextComponent(clientTile)).centered(true, true); + widgets.add(clientConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 - 30, 200, 16).showingElement(clientText)); - TextStencilElement text2 = new TextStencilElement(client.fontRenderer, new StringTextComponent("World Generation Settings").formatted(TextFormatting.BOLD)).centered(true, true); - widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16) - .showingElement(text2) - .withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, AllConfigs.COMMON.specification))) - ); - text2.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget)); + if (clientSpec != null) { + clientConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.CLIENT, clientSpec))); + clientText.withElementRenderer(BoxWidget.gradientFactory.apply(clientConfigWidget)); + } else { + clientConfigWidget.active = false; + clientConfigWidget.updateColorsFromState(); + clientText.withElementRenderer(DISABLED_RENDERER); + } - TextStencilElement text3 = new TextStencilElement(client.fontRenderer, new StringTextComponent("Gameplay Settings").formatted(TextFormatting.BOLD)).centered(true, true); - widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16) - .showingElement(text3) - ); + TextStencilElement commonText = new TextStencilElement(client.fontRenderer, new StringTextComponent(commonTile)).centered(true, true); + widgets.add(commonConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15, 200, 16).showingElement(commonText)); - if (Minecraft.getInstance().world != null) { - serverConfigWidget.withCallback(() -> ScreenOpener.open(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, AllConfigs.SERVER.specification))); - text3.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget)); + if (commonSpec != null) { + commonConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.COMMON, commonSpec))); + commonText.withElementRenderer(BoxWidget.gradientFactory.apply(commonConfigWidget)); + } else { + commonConfigWidget.active = false; + commonConfigWidget.updateColorsFromState(); + commonText.withElementRenderer(DISABLED_RENDERER); + } + + TextStencilElement serverText = new TextStencilElement(client.fontRenderer, new StringTextComponent(serverTile)).centered(true, true); + widgets.add(serverConfigWidget = new BoxWidget(width / 2 - 100, height / 2 - 15 + 30, 200, 16).showingElement(serverText)); + + if (serverSpec != null && Minecraft.getInstance().world != null) { + serverConfigWidget.withCallback(() -> linkTo(new SubMenuConfigScreen(this, ModConfig.Type.SERVER, serverSpec))); + serverText.withElementRenderer(BoxWidget.gradientFactory.apply(serverConfigWidget)); } else { serverConfigWidget.active = false; serverConfigWidget.updateColorsFromState(); - text3.withElementRenderer((ms, width, height, alpha) -> UIRenderHelper.angledGradient(ms, 0, 0, height / 2, height, width, Theme.i(Theme.Key.BUTTON_DISABLE, true), Theme.i(Theme.Key.BUTTON_DISABLE, false) | 0x40_000000)); + serverText.withElementRenderer(DISABLED_RENDERER); + serverConfigWidget.active = true; + serverConfigWidget.getToolTip() + .add(new StringTextComponent("Stored individually per World")); + serverConfigWidget.getToolTip() + .addAll(TooltipHelper.cutTextComponent( + new StringTextComponent( + "Gameplay settings can only be accessed from the in-game menu after joining a World or Server."), + TextFormatting.GRAY, TextFormatting.GRAY)); } + + ConfigScreen.modID = this.modID; + + goBack = new BoxWidget(width / 2 - 134, height / 2, 20, 20).withPadding(2, 2) + .withCallback(this::onClose); + goBack.showingElement(AllIcons.I_CONFIG_BACK.asStencil() + .withElementRenderer(BoxWidget.gradientFactory.apply(goBack))); + goBack.getToolTip() + .add(new StringTextComponent("Go Back")); + widgets.add(goBack); } + + private void linkTo(Screen screen) { + returnOnClose = false; + ScreenOpener.open(screen); + } + + @Override + public void onClose() { + super.onClose(); + ScreenOpener.open(parent); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java b/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java index c1a475d29..b472b0a70 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/CConfigureConfigPacket.java @@ -1,54 +1,65 @@ package com.simibubi.create.foundation.config.ui; +import java.util.Objects; import java.util.function.Supplier; -import com.simibubi.create.foundation.command.SConfigureConfigPacket; -import com.simibubi.create.foundation.config.AllConfigs; -import com.simibubi.create.foundation.networking.AllPackets; +import com.simibubi.create.Create; import com.simibubi.create.foundation.networking.SimplePacketBase; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.network.PacketBuffer; import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.network.NetworkEvent; -import net.minecraftforge.fml.network.PacketDistributor; public class CConfigureConfigPacket extends SimplePacketBase { + private String modID; private String path; private String value; - public CConfigureConfigPacket(String path, T value) { + public CConfigureConfigPacket(String modID, String path, T value) { + this.modID = Objects.requireNonNull(modID); this.path = path; this.value = serialize(value); } public CConfigureConfigPacket(PacketBuffer buffer) { + this.modID = buffer.readString(32767); this.path = buffer.readString(32767); this.value = buffer.readString(32767); } @Override public void write(PacketBuffer buffer) { + buffer.writeString(modID); buffer.writeString(path); buffer.writeString(value); } @Override public void handle(Supplier context) { - ServerPlayerEntity sender = context.get().getSender(); - if (sender == null || !sender.hasPermissionLevel(2)) - return; + context.get().enqueueWork(() -> { + try { + ServerPlayerEntity sender = context.get().getSender(); + if (sender == null || !sender.hasPermissionLevel(2)) + return; - ForgeConfigSpec.ValueSpec valueSpec = AllConfigs.SERVER.specification.getRaw(path); - ForgeConfigSpec.ConfigValue configValue = AllConfigs.SERVER.specification.getValues().get(path); + ForgeConfigSpec spec = ConfigHelper.findConfigSpecFor(ModConfig.Type.SERVER, modID); + ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(path); + ForgeConfigSpec.ConfigValue configValue = spec.getValues().get(path); - T v = (T) deserialize(configValue.get(), value); - if (!valueSpec.test(v)) - return; + T v = (T) deserialize(configValue.get(), value); + if (!valueSpec.test(v)) + return; - configValue.set(v); + configValue.set(v); + } catch (Exception e) { + Create.LOGGER.warn("Unable to handle ConfigureConfig Packet. ", e); + } + }); + context.get().setPacketHandled(true); } public String serialize(T value) { @@ -66,7 +77,7 @@ public class CConfigureConfigPacket extends SimplePacketBase { throw new IllegalArgumentException("unknown type " + value + ": " + value.getClass().getSimpleName()); } - public Object deserialize(Object type, String sValue) { + public static Object deserialize(Object type, String sValue) { if (type instanceof Boolean) return Boolean.parseBoolean(sValue); if (type instanceof Enum) diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java new file mode 100644 index 000000000..57a52417f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigHelper.java @@ -0,0 +1,142 @@ +package com.simibubi.create.foundation.config.ui; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import javax.annotation.Nonnull; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.config.AllConfigs; + +import net.minecraftforge.common.ForgeConfigSpec; +import net.minecraftforge.fml.ModContainer; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; +import net.minecraftforge.fml.config.ModConfig; + +public class ConfigHelper { + + private static final LoadingCache> configCache = CacheBuilder.newBuilder().expireAfterAccess(15, TimeUnit.SECONDS).build( + new CacheLoader>() { + @Override + public EnumMap load(@Nonnull String key) { + return findModConfigsUncached(key); + } + } + ); + + private static EnumMap findModConfigsUncached(String modID) { + ModContainer modContainer = ModList.get().getModContainerById(modID).orElseThrow(() -> new IllegalArgumentException("Unable to find ModContainer for id: " + modID)); + EnumMap configs = ObfuscationReflectionHelper.getPrivateValue(ModContainer.class, modContainer, "configs"); + return Objects.requireNonNull(configs); + } + + public static ForgeConfigSpec findConfigSpecFor(ModConfig.Type type, String modID) { + if (!modID.equals(Create.ID)) + return configCache.getUnchecked(modID).get(type).getSpec(); + + switch (type) { + case COMMON: + return AllConfigs.COMMON.specification; + case CLIENT: + return AllConfigs.CLIENT.specification; + case SERVER: + return AllConfigs.SERVER.specification; + } + + return null; + } + + //Directly set a value + public static void setConfigValue(ConfigPath path, String value) throws InvalidValueException { + ForgeConfigSpec spec = findConfigSpecFor(path.getType(), path.getModID()); + List pathList = Arrays.asList(path.getPath()); + ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(pathList); + ForgeConfigSpec.ConfigValue configValue = spec.getValues().get(pathList); + T v = (T) CConfigureConfigPacket.deserialize(configValue.get(), value); + if (!valueSpec.test(v)) + throw new InvalidValueException(); + + configValue.set(v); + } + + //Add a value to the current UI's changes list + public static void setValue(String path, ForgeConfigSpec.ConfigValue configValue, T value) { + if (value.equals(configValue.get())) { + ConfigScreen.changes.remove(path); + } else { + ConfigScreen.changes.put(path, value); + } + } + + //Get a value from the current UI's changes list or the config value, if its unchanged + public static T getValue(String path, ForgeConfigSpec.ConfigValue configValue) { + //noinspection unchecked + return (T) ConfigScreen.changes.getOrDefault(path, configValue.get()); + } + + public static class ConfigPath { + private String modID = Create.ID; + private ModConfig.Type type = ModConfig.Type.CLIENT; + private String[] path; + + public static ConfigPath parse(String string) { + ConfigPath cp = new ConfigPath(); + String p = string; + int index = string.indexOf(":"); + if (index >= 0) { + p = string.substring(index + 1); + if (index >= 1) { + cp.modID = string.substring(0, index); + } + } + String[] split = p.split("\\."); + try { + cp.type = ModConfig.Type.valueOf(split[0].toUpperCase(Locale.ROOT)); + } catch (Exception e) { + throw new IllegalArgumentException("path must start with either 'client.', 'common.' or 'server.'"); + } + + cp.path = new String[split.length - 1]; + System.arraycopy(split, 1, cp.path, 0, cp.path.length); + + return cp; + } + + public ConfigPath setID(String modID) { + this.modID = modID; + return this; + } + + public ConfigPath setType(ModConfig.Type type) { + this.type = type; + return this; + } + + public ConfigPath setPath(String[] path) { + this.path = path; + return this; + } + + public String getModID() { + return modID; + } + + public ModConfig.Type getType() { + return type; + } + + public String[] getPath() { + return path; + } + } + + public static class InvalidValueException extends Exception {} +} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java index 98086a786..6bcbc4880 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreen.java @@ -8,18 +8,27 @@ import java.util.stream.Collectors; import javax.annotation.Nonnull; import org.apache.commons.lang3.StringUtils; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.gl.versioned.GlCompat; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.AllBlocks; import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock; import com.simibubi.create.foundation.gui.AbstractSimiScreen; import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.StencilElement; +import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.utility.animation.Force; import com.simibubi.create.foundation.utility.animation.PhysicalFloat; import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.FramebufferConstants; import net.minecraft.util.Direction; public abstract class ConfigScreen extends AbstractSimiScreen { @@ -41,6 +50,7 @@ public abstract class ConfigScreen extends AbstractSimiScreen { public static final PhysicalFloat cogSpin = PhysicalFloat.create().withDrag(0.3).addForce(new Force.Static(.2f)); public static final BlockState cogwheelState = AllBlocks.LARGE_COGWHEEL.getDefaultState().with(CogWheelBlock.AXIS, Direction.Axis.Y); public static final Map changes = new HashMap<>(); + public static String modID = null; protected final Screen parent; public ConfigScreen(Screen parent) { @@ -83,7 +93,37 @@ public abstract class ConfigScreen extends AbstractSimiScreen { } @Override - protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) {} + protected void prepareFrame() { + Framebuffer thisBuffer = UIRenderHelper.framebuffer; + Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer(); + + GlCompat functions = Backend.getInstance().compat; + functions.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, mainBuffer.framebufferObject); + functions.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, thisBuffer.framebufferObject); + functions.blit.blitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR); + + functions.fbo.bindFramebuffer(FramebufferConstants.FRAME_BUFFER, thisBuffer.framebufferObject); + GL11.glClear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT); + + } + + @Override + protected void endFrame() { + + Framebuffer thisBuffer = UIRenderHelper.framebuffer; + Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer(); + + GlCompat functions = Backend.getInstance().compat; + functions.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, thisBuffer.framebufferObject); + functions.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject); + functions.blit.blitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR); + + functions.fbo.bindFramebuffer(FramebufferConstants.FRAME_BUFFER, mainBuffer.framebufferObject); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + } @Override public boolean mouseScrolled(double mouseX, double mouseY, double delta) { diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java index a0d23b7a1..2b01b9647 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/ConfigScreenList.java @@ -135,7 +135,8 @@ public class ConfigScreenList extends ExtendedList { @Override public void render(MatrixStack ms, int index, int y, int x, int width, int height, int mouseX, int mouseY, boolean p_230432_9_, float partialTicks) { - UIRenderHelper.streak(ms, 0, x, y + height / 2, height - 6, width, 0xdd_000000); + UIRenderHelper.streak(ms, 0, x - 10, y + height / 2, height - 6, width / 8 * 7, 0xdd_000000); + UIRenderHelper.streak(ms, 180, x + (int) (width * 1.35f) + 10, y + height / 2, height - 6, width / 8 * 7, 0xdd_000000); IFormattableTextComponent component = label.getComponent(); FontRenderer font = Minecraft.getInstance().fontRenderer; if (font.getWidth(component) > getLabelWidth(width) - 10) { diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/OpenCreateMenuButton.java b/src/main/java/com/simibubi/create/foundation/config/ui/OpenCreateMenuButton.java new file mode 100644 index 000000000..6d12dc3f8 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/config/ui/OpenCreateMenuButton.java @@ -0,0 +1,114 @@ +package com.simibubi.create.foundation.config.ui; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.AllItems; +import com.simibubi.create.foundation.config.AllConfigs; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.gui.mainMenu.CreateMainMenuScreen; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.IngameMenuScreen; +import net.minecraft.client.gui.screen.MainMenuScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.StringTextComponent; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; + +public class OpenCreateMenuButton extends Button { + + public static ItemStack icon = AllItems.GOGGLES.asStack(); + + public OpenCreateMenuButton(int x, int y) { + super(x, y, 20, 20, StringTextComponent.EMPTY, OpenCreateMenuButton::click); + } + + @Override + public void render(MatrixStack mstack, int mouseX, int mouseY, float pticks) { + super.render(mstack, mouseX, mouseY, pticks); + Minecraft.getInstance().getItemRenderer().renderItemIntoGUI(icon, x + 2, y + 2); + } + + public static void click(Button b) { + ScreenOpener.open(new CreateMainMenuScreen(Minecraft.getInstance().currentScreen)); + } + + public static class SingleMenuRow { + public final String left, right; + public SingleMenuRow(String left, String right) { + this.left = I18n.format(left); + this.right = I18n.format(right); + } + public SingleMenuRow(String center) { + this(center, center); + } + } + + public static class MenuRows { + public static final MenuRows MAIN_MENU = new MenuRows(Arrays.asList( + new SingleMenuRow("menu.singleplayer"), + new SingleMenuRow("menu.multiplayer"), + new SingleMenuRow("fml.menu.mods", "menu.online"), + new SingleMenuRow("narrator.button.language", "narrator.button.accessibility") + )); + + public static final MenuRows INGAME_MENU = new MenuRows(Arrays.asList( + new SingleMenuRow("menu.returnToGame"), + new SingleMenuRow("gui.advancements", "gui.stats"), + new SingleMenuRow("menu.sendFeedback", "menu.reportBugs"), + new SingleMenuRow("menu.options", "menu.shareToLan"), + new SingleMenuRow("menu.returnToMenu") + )); + + protected final List leftButtons, rightButtons; + + public MenuRows(List variants) { + leftButtons = variants.stream().map(r -> r.left).collect(Collectors.toList()); + rightButtons = variants.stream().map(r -> r.right).collect(Collectors.toList()); + } + } + + @EventBusSubscriber(value = Dist.CLIENT) + public static class OpenConfigButtonHandler { + + @SubscribeEvent + public static void onGuiInit(GuiScreenEvent.InitGuiEvent event) { + Screen gui = event.getGui(); + + MenuRows menu = null; + int rowIdx = 0, offsetX = 0; + if (gui instanceof MainMenuScreen) { + menu = MenuRows.MAIN_MENU; + rowIdx = AllConfigs.CLIENT.mainMenuConfigButtonRow.get(); + offsetX = AllConfigs.CLIENT.mainMenuConfigButtonOffsetX.get(); + } else if (gui instanceof IngameMenuScreen) { + menu = MenuRows.INGAME_MENU; + rowIdx = AllConfigs.CLIENT.ingameMenuConfigButtonRow.get(); + offsetX = AllConfigs.CLIENT.ingameMenuConfigButtonOffsetX.get(); + } + + if (rowIdx != 0 && menu != null) { + boolean onLeft = offsetX < 0; + String target = (onLeft ? menu.leftButtons : menu.rightButtons).get(rowIdx - 1); + + int offsetX_ = offsetX; + event.getWidgetList().stream() + .filter(w -> w.getMessage().getString().equals(target)) + .findFirst() + .ifPresent(w -> event.addWidget( + new OpenCreateMenuButton(w.x + offsetX_ + (onLeft ? -20 : w.getWidth()), w.y) + )); + } + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java index e27502281..34d68af65 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/SubMenuConfigScreen.java @@ -1,6 +1,11 @@ package com.simibubi.create.foundation.config.ui; -import java.awt.Color; +import java.awt.*; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.function.Consumer; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -9,7 +14,9 @@ import org.lwjgl.glfw.GLFW; import com.electronwill.nightconfig.core.AbstractConfig; import com.electronwill.nightconfig.core.UnmodifiableConfig; +import com.google.common.collect.Lists; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.config.ui.ConfigScreenList.LabeledEntry; import com.simibubi.create.foundation.config.ui.entries.BooleanEntry; import com.simibubi.create.foundation.config.ui.entries.EnumEntry; import com.simibubi.create.foundation.config.ui.entries.NumberEntry; @@ -17,6 +24,7 @@ import com.simibubi.create.foundation.config.ui.entries.SubMenuEntry; import com.simibubi.create.foundation.config.ui.entries.ValueEntry; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.ConfirmationScreen; +import com.simibubi.create.foundation.gui.ConfirmationScreen.Response; import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.ScreenOpener; import com.simibubi.create.foundation.gui.Theme; @@ -50,6 +58,37 @@ public class SubMenuConfigScreen extends ConfigScreen { protected int listWidth; protected String title; + public static SubMenuConfigScreen find(ConfigHelper.ConfigPath path) { + ForgeConfigSpec spec = ConfigHelper.findConfigSpecFor(path.getType(), path.getModID()); + UnmodifiableConfig values = spec.getValues(); + BaseConfigScreen base = new BaseConfigScreen(null, path.getModID()).searchForSpecsInModContainer(); + SubMenuConfigScreen screen = new SubMenuConfigScreen(base, "root", path.getType(), spec, values); + List remainingPath = Lists.newArrayList(path.getPath()); + + path: while (!remainingPath.isEmpty()) { + String next = remainingPath.remove(0); + for (Map.Entry entry : values.valueMap().entrySet()) { + String key = entry.getKey(); + Object obj = entry.getValue(); + if (!key.equalsIgnoreCase(next)) + continue; + + if (!(obj instanceof AbstractConfig)) { + //highlight entry + continue; + } + + values = (UnmodifiableConfig) obj; + screen = new SubMenuConfigScreen(screen, toHumanReadable(key), path.getType(), spec, values); + continue path; + } + + break; + } + + ConfigScreen.modID = path.getModID(); + return screen; + } public SubMenuConfigScreen(Screen parent, String title, ModConfig.Type type, ForgeConfigSpec configSpec, UnmodifiableConfig configGroup) { super(parent); @@ -81,7 +120,7 @@ public class SubMenuConfigScreen extends ConfigScreen { ForgeConfigSpec.ConfigValue configValue = values.get(path); configValue.set(value); if (type == ModConfig.Type.SERVER) { - AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(path, value)); + AllPackets.channel.sendToServer(new CConfigureConfigPacket<>(ConfigScreen.modID, path, value)); } }); clearChanges(); @@ -92,11 +131,10 @@ public class SubMenuConfigScreen extends ConfigScreen { if (obj instanceof AbstractConfig) { resetConfig((UnmodifiableConfig) obj); } else if (obj instanceof ForgeConfigSpec.ConfigValue) { - ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue) obj; - ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw(configValue.getPath()); + ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue) obj; + ForgeConfigSpec.ValueSpec valueSpec = spec.getRaw((List) configValue.getPath()); - if (!configValue.get().equals(valueSpec.getDefault())) - changes.put(String.join(".", configValue.getPath()), valueSpec.getDefault()); + ConfigHelper.setValue(String.join(".", configValue.getPath()), configValue, valueSpec.getDefault()); } }); @@ -127,8 +165,8 @@ public class SubMenuConfigScreen extends ConfigScreen { .withPadding(2, 2) .withCallback((x, y) -> new ConfirmationScreen() - .at(x, y) - .withText(ITextProperties.plain("You are about to reset all settings for the " + type.toString() + " config. Are you sure?")) + .centered() + .withText(ITextProperties.plain("Resetting all settings of the " + type.toString() + " config. Are you sure?")) .withAction(success -> { if (success) resetConfig(spec.getValues()); @@ -138,7 +176,7 @@ public class SubMenuConfigScreen extends ConfigScreen { resetAll.showingElement(AllIcons.I_CONFIG_RESET.asStencil().withElementRenderer(BoxWidget.gradientFactory.apply(resetAll))); resetAll.getToolTip().add(new StringTextComponent("Reset All")); - resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all configs to their default value.", TextFormatting.GRAY, TextFormatting.GRAY)); + resetAll.getToolTip().addAll(TooltipHelper.cutStringTextComponent("Click here to reset all settings to their default value.", TextFormatting.GRAY, TextFormatting.GRAY)); saveChanges = new BoxWidget(listL - 30, yCenter - 25, 20, 20) .withPadding(2, 2) @@ -147,8 +185,8 @@ public class SubMenuConfigScreen extends ConfigScreen { return; new ConfirmationScreen() - .at(x, y) - .withText(ITextProperties.plain("You are about to change " + changes.size() + " value" + (changes.size() != 1 ? "s" : "") + ". Are you sure?")) + .centered() + .withText(ITextProperties.plain("Saving " + changes.size() + " changed value" + (changes.size() != 1 ? "s" : "") + "")) .withAction(success -> { if (success) saveChanges(); @@ -166,8 +204,8 @@ public class SubMenuConfigScreen extends ConfigScreen { return; new ConfirmationScreen() - .at(x, y) - .withText(ITextProperties.plain("You are about to discard " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + ". Are you sure?")) + .centered() + .withText(ITextProperties.plain("Discarding " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + "")) .withAction(success -> { if (success) clearChanges(); @@ -200,6 +238,10 @@ public class SubMenuConfigScreen extends ConfigScreen { if (obj instanceof AbstractConfig) { SubMenuEntry entry = new SubMenuEntry(this, humanKey, spec, (UnmodifiableConfig) obj); list.children().add(entry); + if (configGroup.valueMap() + .size() == 1) + ScreenOpener.open( + new SubMenuConfigScreen(parent, humanKey, type, spec, (UnmodifiableConfig) obj)); } else if (obj instanceof ForgeConfigSpec.ConfigValue) { ForgeConfigSpec.ConfigValue configValue = (ForgeConfigSpec.ConfigValue) obj; @@ -225,9 +267,25 @@ public class SubMenuConfigScreen extends ConfigScreen { } }); + Collections.sort(list.children(), + (e, e2) -> { + int group = (e2 instanceof SubMenuEntry ? 1 : 0) - (e instanceof SubMenuEntry ? 1 : 0); + if (group == 0 && e instanceof LabeledEntry && e2 instanceof LabeledEntry) { + LabeledEntry le = (LabeledEntry) e; + LabeledEntry le2 = (LabeledEntry) e2; + return le.label.getComponent() + .getString() + .compareTo(le2.label.getComponent() + .getString()); + } + return group; + }); + //extras for server configs if (type != ModConfig.Type.SERVER) return; + if (client.isSingleplayer()) + return; list.isForServer = true; boolean canEdit = client != null && client.player != null && client.player.hasPermissionLevel(2); @@ -241,6 +299,7 @@ public class SubMenuConfigScreen extends ConfigScreen { .withPadding(2, 2) .showingElement(stencil); + if (!canEdit) { list.children().forEach(e -> e.setEditable(false)); resetAll.active = false; @@ -248,7 +307,7 @@ public class SubMenuConfigScreen extends ConfigScreen { stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, red)); serverLocked.withBorderColors(red); serverLocked.getToolTip().add(new StringTextComponent("Locked").formatted(TextFormatting.BOLD)); - serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You don't have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY)); + serverLocked.getToolTip().addAll(TooltipHelper.cutStringTextComponent("You do not have enough permissions to edit the server config. You can still look at the current values here though.", TextFormatting.GRAY, TextFormatting.GRAY)); } else { stencil.withStencilRenderer((ms, w, h, alpha) -> AllIcons.I_CONFIG_UNLOCKED.draw(ms, 0, 0)); stencil.withElementRenderer((ms, w, h, alpha) -> UIRenderHelper.angledGradient(ms, 90, 8, 0, 16, 16, green)); @@ -264,8 +323,8 @@ public class SubMenuConfigScreen extends ConfigScreen { protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { super.renderWindow(ms, mouseX, mouseY, partialTicks); - int x = width/2; - drawCenteredString(ms, client.fontRenderer, "Editing config: " + type.toString() + "@" + title, x, 15, Theme.i(Theme.Key.TEXT)); + int x = width / 2; + drawCenteredString(ms, client.fontRenderer, ConfigScreen.modID + " > " + type.toString().toLowerCase(Locale.ROOT) + " > " + title, x, 15, Theme.i(Theme.Key.TEXT)); list.render(ms, mouseX, mouseY, partialTicks); } @@ -304,42 +363,49 @@ public class SubMenuConfigScreen extends ConfigScreen { } private void attemptBackstep() { - if (!changes.isEmpty() && parent instanceof BaseConfigScreen) { - new ConfirmationScreen() - .centered() - .addText(ITextProperties.plain("You still have " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + " for this config.")) - .addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?")) - .withAction(success -> { - if (!success) - return; - - changes.clear(); - ScreenOpener.open(parent); - }) - .open(this); - } else { + if (changes.isEmpty() || !(parent instanceof BaseConfigScreen)) { ScreenOpener.open(parent); + return; } + + Consumer action = success -> { + if (success == Response.Cancel) + return; + if (success == Response.Confirm) + saveChanges(); + changes.clear(); + ScreenOpener.open(parent); + }; + + showLeavingPrompt(action); } @Override public void onClose() { if (changes.isEmpty()) { super.onClose(); + ScreenOpener.open(parent); return; } - new ConfirmationScreen() - .centered() - .addText(ITextProperties.plain("You still have " + changes.size() + " unsaved change" + (changes.size() != 1 ? "s" : "") + " for this config.")) - .addText(ITextProperties.plain("Leaving this screen will discard them without saving. Are you sure?")) - .withAction(success -> { - if (!success) - return; + Consumer action = success -> { + if (success == Response.Cancel) + return; + if (success == Response.Confirm) + saveChanges(); + changes.clear(); + super.onClose(); + }; - changes.clear(); - super.onClose(); - }) + showLeavingPrompt(action); + } + + public void showLeavingPrompt(Consumer action) { + new ConfirmationScreen().centered() + .addText(ITextProperties.plain("Leaving with " + changes.size() + " unsaved change" + + (changes.size() != 1 ? "s" : "") + " for this config")) + .withThreeActions(action) .open(this); } + } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java index 08d7e8288..3d7590762 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/EnumEntry.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.config.ui.entries; +import java.util.Locale; + import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.BoxElement; @@ -78,9 +80,9 @@ public class EnumEntry extends ValueEntry> { cycleLeft.y = y + 10; cycleLeft.render(ms, mouseX, mouseY, partialTicks); - valueText.at(cycleLeft.x + cycleWidth - 8, y + 11, 200) - .withBounds(width - getLabelWidth(width) - 2 * cycleWidth - resetWidth - 4, 16) - .render(ms); + valueText.at(cycleLeft.x + cycleWidth - 8, y + 10, 200) + .withBounds(width - getLabelWidth(width) - 2 * cycleWidth - resetWidth - 4, 16) + .render(ms); cycleRight.x = x + width - cycleWidth * 2 - resetWidth + 10; cycleRight.y = y + 10; @@ -97,6 +99,10 @@ public class EnumEntry extends ValueEntry> { @Override public void onValueChange(Enum newValue) { super.onValueChange(newValue); - valueText.withText(newValue.name()); + valueText.withText(newValue.name() + .substring(0, 1) + + newValue.name() + .substring(1) + .toLowerCase(Locale.ROOT)); } } diff --git a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java index 6f6f89093..52a0d3fa1 100644 --- a/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java +++ b/src/main/java/com/simibubi/create/foundation/config/ui/entries/ValueEntry.java @@ -10,12 +10,15 @@ import javax.annotation.Nonnull; import org.apache.commons.lang3.ArrayUtils; +import com.google.common.base.Predicates; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.foundation.config.ui.ConfigHelper; import com.simibubi.create.foundation.config.ui.ConfigScreen; import com.simibubi.create.foundation.config.ui.ConfigScreenList; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.widgets.BoxWidget; +import com.simibubi.create.foundation.item.TooltipHelper; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.StringTextComponent; @@ -51,7 +54,7 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { listeners.add(resetButton); List path = value.getPath(); - labelTooltip.add(new StringTextComponent(path.get(path.size()-1)).formatted(TextFormatting.GRAY)); + labelTooltip.add(new StringTextComponent(label).formatted(TextFormatting.WHITE)); String comment = spec.getComment(); if (comment == null || comment.isEmpty()) return; @@ -75,8 +78,14 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { u = "in SU"; unit = u; } - //add comment to tooltip - labelTooltip.addAll(Arrays.stream(commentLines).map(StringTextComponent::new).collect(Collectors.toList())); + // add comment to tooltip + labelTooltip.addAll(Arrays.stream(commentLines) + .filter(Predicates.not(s -> s.startsWith("Range"))) + .map(StringTextComponent::new) + .flatMap(stc -> TooltipHelper.cutTextComponent(stc, TextFormatting.GRAY, TextFormatting.GRAY) + .stream()) + .collect(Collectors.toList())); + labelTooltip.add(new StringTextComponent(ConfigScreen.modID + ":" + path.get(path.size() - 1)).formatted(TextFormatting.DARK_GRAY)); } @Override @@ -115,20 +124,13 @@ public class ValueEntry extends ConfigScreenList.LabeledEntry { } public void setValue(@Nonnull T value) { - if (value.equals(this.value.get())) { - ConfigScreen.changes.remove(path); - onValueChange(value); - return; - } - - ConfigScreen.changes.put(path, value); + ConfigHelper.setValue(path, this.value, value); onValueChange(value); } @Nonnull public T getValue() { - //noinspection unchecked - return (T) ConfigScreen.changes.getOrDefault(path, this.value.get()); + return ConfigHelper.getValue(path, this.value); } protected boolean isCurrentValueChanged() { diff --git a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java index 2fd69e79f..5a110f8b7 100644 --- a/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java +++ b/src/main/java/com/simibubi/create/foundation/data/BuilderTransformers.java @@ -212,7 +212,7 @@ public class BuilderTransformers { }); }) .item() - .properties(p -> type.equals("creative") ? p : p.rarity(Rarity.EPIC)) + .properties(p -> type.equals("creative") ? p.rarity(Rarity.EPIC) : p) .transform(ModelGen.customItemModel("crate", type, "single")); } diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java b/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java new file mode 100644 index 000000000..1cd900123 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/data/CreateEntityBuilder.java @@ -0,0 +1,57 @@ +package com.simibubi.create.foundation.data; + +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.entity.IEntityInstanceFactory; +import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory; +import com.tterrag.registrate.AbstractRegistrate; +import com.tterrag.registrate.builders.BuilderCallback; +import com.tterrag.registrate.builders.EntityBuilder; + +import com.tterrag.registrate.util.OneTimeEventReceiver; +import com.tterrag.registrate.util.nullness.NonNullSupplier; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; + +@ParametersAreNonnullByDefault +public class CreateEntityBuilder extends EntityBuilder { + + @Nullable + private NonNullSupplier> instanceFactory; + + public static EntityBuilder create(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, EntityType.IFactory factory, EntityClassification classification) { + return (new CreateEntityBuilder<>(owner, parent, name, callback, factory, classification)).defaultLang(); + } + + public CreateEntityBuilder(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, EntityType.IFactory factory, EntityClassification classification) { + super(owner, parent, name, callback, factory, classification); + } + + public CreateEntityBuilder instance(NonNullSupplier> instanceFactory) { + if (this.instanceFactory == null) { + DistExecutor.runWhenOn(Dist.CLIENT, () -> this::registerInstance); + } + + this.instanceFactory = instanceFactory; + + return this; + } + + protected void registerInstance() { + OneTimeEventReceiver.addModListener(FMLClientSetupEvent.class, $ -> { + NonNullSupplier> instanceFactory = this.instanceFactory; + if (instanceFactory != null) { + InstancedRenderRegistry.getInstance().register(getEntry(), instanceFactory.get()); + } + + }); + } + +} 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 06851d0f3..bb0f1ae73 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateRegistrate.java @@ -14,10 +14,11 @@ import com.simibubi.create.CreateClient; import com.simibubi.create.content.AllSections; import com.simibubi.create.content.contraptions.fluids.VirtualFluid; import com.simibubi.create.content.contraptions.relays.encased.CasingConnectivity; -import com.simibubi.create.foundation.block.IBlockVertexColor; import com.simibubi.create.foundation.block.connected.CTModel; import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour; -import com.simibubi.create.foundation.block.render.CustomRenderedItemModel; +import com.simibubi.create.foundation.block.render.ColoredVertexModel; +import com.simibubi.create.foundation.block.render.IBlockVertexColor; +import com.simibubi.create.foundation.item.render.CustomRenderedItemModel; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BlockBuilder; import com.tterrag.registrate.builders.Builder; @@ -33,14 +34,14 @@ import com.tterrag.registrate.util.nullness.NonNullUnaryOperator; import net.minecraft.block.AbstractBlock.Properties; import net.minecraft.block.Block; -import net.minecraft.client.renderer.color.IBlockColor; -import net.minecraft.client.renderer.color.IItemColor; import net.minecraft.client.renderer.model.IBakedModel; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; import net.minecraft.fluid.Fluid; import net.minecraft.item.Item; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; -import net.minecraft.util.IItemProvider; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fluids.FluidAttributes; @@ -113,7 +114,7 @@ public class CreateRegistrate extends AbstractRegistrate { public CreateTileEntityBuilder tileEntity(String name, NonNullFunction, ? extends T> factory) { - return this.tileEntity(this.self(), name, (NonNullFunction) factory); + return this.tileEntity(this.self(), name, factory); } @Override @@ -124,6 +125,17 @@ public class CreateRegistrate extends AbstractRegistrate { }); } + @Override + public CreateEntityBuilder entity(String name, EntityType.IFactory factory, EntityClassification classification) { + return this.entity(self(), name, factory, classification); + } + + public CreateEntityBuilder entity(P parent, String name, EntityType.IFactory factory, EntityClassification classification) { + return (CreateEntityBuilder) this.entry(name, (callback) -> { + return CreateEntityBuilder.create(this, parent, name, callback, factory, classification); + }); + } + /* Palettes */ public BlockBuilder baseBlock(String name, @@ -172,30 +184,22 @@ public class CreateRegistrate extends AbstractRegistrate { } public static NonNullConsumer casingConnectivity( - BiConsumer consumer) { + BiConsumer consumer) { return entry -> onClient(() -> () -> registerCasingConnectivity(entry, consumer)); } - public static NonNullConsumer blockModel( - Supplier> func) { - return entry -> onClient(() -> () -> registerBlockModel(entry, func)); - } - - public static NonNullConsumer blockColors(Supplier> colorFunc) { - return entry -> onClient(() -> () -> registerBlockColor(entry, colorFunc)); - } - public static NonNullConsumer blockVertexColors(IBlockVertexColor colorFunc) { return entry -> onClient(() -> () -> registerBlockVertexColor(entry, colorFunc)); } - public static NonNullConsumer itemModel( - Supplier> func) { - return entry -> onClient(() -> () -> registerItemModel(entry, func)); + public static NonNullConsumer blockModel( + Supplier> func) { + return entry -> onClient(() -> () -> registerBlockModel(entry, func)); } - public static NonNullConsumer itemColors(Supplier> colorFunc) { - return entry -> onClient(() -> () -> registerItemColor(entry, colorFunc)); + public static NonNullConsumer itemModel( + Supplier> func) { + return entry -> onClient(() -> () -> registerItemModel(entry, func)); } public static NonNullUnaryOperator> customRenderedItem( @@ -213,20 +217,26 @@ public class CreateRegistrate extends AbstractRegistrate { @OnlyIn(Dist.CLIENT) private static void registerCTBehviour(Block entry, ConnectedTextureBehaviour behavior) { CreateClient.getCustomBlockModels() - .register(entry.delegate, model -> new CTModel(model, behavior)); + .register(entry.delegate, model -> new CTModel(model, behavior)); } @OnlyIn(Dist.CLIENT) private static void registerCasingConnectivity(T entry, - BiConsumer consumer) { + BiConsumer consumer) { consumer.accept(entry, CreateClient.getCasingConnectivity()); } @OnlyIn(Dist.CLIENT) - private static void registerBlockModel(Block entry, - Supplier> func) { + private static void registerBlockVertexColor(Block entry, IBlockVertexColor colorFunc) { CreateClient.getCustomBlockModels() - .register(entry.delegate, func.get()); + .register(entry.delegate, model -> new ColoredVertexModel(model, colorFunc)); + } + + @OnlyIn(Dist.CLIENT) + private static void registerBlockModel(Block entry, + Supplier> func) { + CreateClient.getCustomBlockModels() + .register(entry.delegate, func.get()); } @OnlyIn(Dist.CLIENT) @@ -243,24 +253,4 @@ public class CreateRegistrate extends AbstractRegistrate { .register(entry.delegate, func.get()); } - @OnlyIn(Dist.CLIENT) - private static void registerBlockColor(Block entry, Supplier> colorFunc) { - CreateClient.getColorHandler() - .register(entry, colorFunc.get() - .get()); - } - - @OnlyIn(Dist.CLIENT) - private static void registerBlockVertexColor(Block entry, IBlockVertexColor colorFunc) { - CreateClient.getColorHandler() - .register(entry, colorFunc); - } - - @OnlyIn(Dist.CLIENT) - private static void registerItemColor(IItemProvider entry, Supplier> colorFunc) { - CreateClient.getColorHandler() - .register(entry, colorFunc.get() - .get()); - } - } diff --git a/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java b/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java index 64286f525..38d854f8c 100644 --- a/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/data/CreateTileEntityBuilder.java @@ -2,8 +2,8 @@ package com.simibubi.create.foundation.data; import javax.annotation.Nullable; -import com.simibubi.create.foundation.render.backend.instancing.IRendererFactory; -import com.simibubi.create.foundation.render.backend.instancing.InstancedTileRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.InstancedRenderRegistry; +import com.jozufozu.flywheel.backend.instancing.tile.ITileInstanceFactory; import com.tterrag.registrate.AbstractRegistrate; import com.tterrag.registrate.builders.BuilderCallback; import com.tterrag.registrate.builders.TileEntityBuilder; @@ -20,7 +20,7 @@ import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; public class CreateTileEntityBuilder extends TileEntityBuilder { @Nullable - private NonNullSupplier> instanceFactory; + private NonNullSupplier> instanceFactory; public static TileEntityBuilder create(AbstractRegistrate owner, P parent, String name, BuilderCallback callback, NonNullFunction, ? extends T> factory) { @@ -32,7 +32,7 @@ public class CreateTileEntityBuilder extends TileEntity super(owner, parent, name, callback, factory); } - public CreateTileEntityBuilder instance(NonNullSupplier> instanceFactory) { + public CreateTileEntityBuilder instance(NonNullSupplier> instanceFactory) { if (this.instanceFactory == null) { DistExecutor.runWhenOn(Dist.CLIENT, () -> this::registerInstance); } @@ -43,10 +43,10 @@ public class CreateTileEntityBuilder extends TileEntity } protected void registerInstance() { - OneTimeEventReceiver.addModListener(FMLClientSetupEvent.class, ($) -> { - NonNullSupplier> instanceFactory = this.instanceFactory; + OneTimeEventReceiver.addModListener(FMLClientSetupEvent.class, $ -> { + NonNullSupplier> instanceFactory = this.instanceFactory; if (instanceFactory != null) { - InstancedTileRenderRegistry.instance.register(getEntry(), instanceFactory.get()); + InstancedRenderRegistry.getInstance().register(getEntry(), instanceFactory.get()); } }); diff --git a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java b/src/main/java/com/simibubi/create/foundation/data/LangMerger.java index a4426a706..b1f717bfa 100644 --- a/src/main/java/com/simibubi/create/foundation/data/LangMerger.java +++ b/src/main/java/com/simibubi/create/foundation/data/LangMerger.java @@ -119,7 +119,7 @@ public class LangMerger implements IDataProvider { private void collectExistingEntries(Path path) throws IOException { if (!Files.exists(path)) { - Create.logger.warn("Nothing to merge! It appears no lang was generated before me."); + Create.LOGGER.warn("Nothing to merge! It appears no lang was generated before me."); return; } @@ -237,7 +237,7 @@ public class LangMerger implements IDataProvider { Files.createDirectories(target.getParent()); try (BufferedWriter bufferedwriter = Files.newBufferedWriter(target)) { - Create.logger.info(message); + Create.LOGGER.info(message); bufferedwriter.write(data); bufferedwriter.close(); } diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java b/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java index d26ee4d42..3f5f87671 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/CreateRecipeProvider.java @@ -29,7 +29,7 @@ public abstract class CreateRecipeProvider extends RecipeProvider { @Override protected void registerRecipes(Consumer p_200404_1_) { all.forEach(c -> c.register(p_200404_1_)); - Create.logger.info(getName() + " registered " + all.size() + " recipe" + (all.size() == 1 ? "" : "s")); + Create.LOGGER.info(getName() + " registered " + all.size() + " recipe" + (all.size() == 1 ? "" : "s")); } @FunctionalInterface diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java index ca9740ab9..a42bd4893 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/PressingRecipeGen.java @@ -14,7 +14,7 @@ public class PressingRecipeGen extends ProcessingRecipeGen { SUGAR_CANE = create(() -> Items.SUGAR_CANE, b -> b.output(Items.PAPER)), - PATH = create("path", b -> b.require(Ingredient.fromItems(Items.GRASS_BLOCK, Items.DIRT, Items.PODZOL)) + PATH = create("path", b -> b.require(Ingredient.fromItems(Items.GRASS_BLOCK, Items.DIRT)) .output(Items.GRASS_PATH)), IRON = create("iron_ingot", b -> b.require(I.iron()) diff --git a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java index 4f6998cc9..7c7e9050b 100644 --- a/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java +++ b/src/main/java/com/simibubi/create/foundation/data/recipe/StandardRecipeGen.java @@ -957,9 +957,10 @@ public class StandardRecipeGen extends CreateRecipeProvider { COPPER_BACKTANK = create(AllItems.COPPER_BACKTANK).unlockedByTag(I::copper) .viaShaped(b -> b.key('G', I.shaft()) .key('A', I.andesite()) + .key('B', I.copperBlock()) .key('P', I.copper()) .patternLine("AGA") - .patternLine("PPP") + .patternLine("PBP") .patternLine(" P ")), DIVING_BOOTS = create(AllItems.DIVING_BOOTS).unlockedByTag(I::copper) @@ -968,6 +969,17 @@ public class StandardRecipeGen extends CreateRecipeProvider { .patternLine("P P") .patternLine("P P") .patternLine("G G")), + + LINKED_CONTROLLER = create(AllItems.LINKED_CONTROLLER).unlockedBy(AllBlocks.REDSTONE_LINK::get) + .viaShaped(b -> b.key('S', ItemTags.WOODEN_BUTTONS) + .key('P', AllBlocks.REDSTONE_LINK.get()) + .patternLine("SSS") + .patternLine(" P ") + .patternLine("SSS")), + + CRAFTING_BLUEPRINT = create(AllItems.CRAFTING_BLUEPRINT).unlockedBy(() -> Items.CRAFTING_TABLE) + .viaShapeless(b -> b.addIngredient(Items.PAINTING) + .addIngredient(Items.CRAFTING_TABLE)), SLIME_BALL = create(() -> Items.SLIME_BALL).unlockedBy(AllItems.DOUGH::get) .viaShapeless(b -> b.addIngredient(AllItems.DOUGH.get()) diff --git a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java index 23d8a0624..9870a7fb7 100644 --- a/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/fluid/FluidRenderer.java @@ -2,15 +2,18 @@ package com.simibubi.create.foundation.fluid; import java.util.function.Function; +import com.jozufozu.flywheel.event.RenderLayerEvent; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack.Entry; import com.mojang.blaze3d.vertex.IVertexBuilder; +import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.MatrixStacker; import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.texture.TextureAtlasSprite; @@ -23,11 +26,39 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3i; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.common.Mod; +@Mod.EventBusSubscriber public class FluidRenderer { + // If we draw to BufferBuilder that minecraft provides for RenderType.getTranslucent(), minecraft draws the contents + // to the wrong framebuffer. If we tried to inject a custom RenderType into RenderTypeBuffers, we'd have the same + // issue. This is because minecraft calls IRenderTypeBuffer.Impl::draw just before clearing the transparency + // framebuffer, so anything we put into the normal RenderTypeBuffers will never be seen. By using our own + // BufferBuilder, we can avoid getting our contents wiped. Then, using Flywheel's renderLayer hook, we can draw our + // buffer at the same time the transparent world layer is drawn. + private static final BufferBuilder _builder = new BufferBuilder(RenderType.getTranslucent().getExpectedBufferSize()); + + private static BufferBuilder getBuilder() { + if (!_builder.isBuilding()) { + RenderType type = RenderType.getTranslucent(); + + _builder.begin(type.getDrawMode(), type.getVertexFormat()); + } + + return _builder; + } + + @SubscribeEvent + public static void renderLayer(RenderLayerEvent event) { + if (event.type == RenderType.getTranslucent()) { + event.type.draw(_builder, 0, 0, 0); + } + } + public static void renderFluidStream(FluidStack fluidStack, Direction direction, float radius, float progress, boolean inbound, IRenderTypeBuffer buffer, MatrixStack ms, int light) { Fluid fluid = fluidStack.getFluid(); @@ -38,7 +69,10 @@ public class FluidRenderer { TextureAtlasSprite stillTexture = spriteAtlas.apply(fluidAttributes.getStillTexture(fluidStack)); int color = fluidAttributes.getColor(fluidStack); - IVertexBuilder builder = buffer.getBuffer(RenderType.getTranslucent()); + IVertexBuilder builder = getBuilder(); + if (buffer instanceof SuperRenderTypeBuffer) + builder = ((SuperRenderTypeBuffer) buffer).getLateBuffer(RenderType.getTranslucent()); + MatrixStacker msr = MatrixStacker.of(ms); int blockLightIn = (light >> 4) & 0xf; int luminosity = Math.max(blockLightIn, fluidAttributes.getLuminosity(fluidStack)); @@ -86,7 +120,9 @@ public class FluidRenderer { .apply(fluidAttributes.getStillTexture(fluidStack)); int color = fluidAttributes.getColor(fluidStack); - IVertexBuilder builder = buffer.getBuffer(RenderType.getTranslucent()); + IVertexBuilder builder = getBuilder(); + if (buffer instanceof SuperRenderTypeBuffer) + builder = ((SuperRenderTypeBuffer) buffer).getLateBuffer(RenderType.getTranslucent()); MatrixStacker msr = MatrixStacker.of(ms); Vector3d center = new Vector3d(xMin + (xMax - xMin) / 2, yMin + (yMax - yMin) / 2, zMin + (zMax - zMin) / 2); diff --git a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java index d76463414..06300938c 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiContainerScreen.java @@ -33,6 +33,8 @@ import net.minecraftforge.api.distmarker.OnlyIn; public abstract class AbstractSimiContainerScreen extends ContainerScreen { protected List widgets; + protected int windowXOffset; + protected int windowYOffset; public AbstractSimiContainerScreen(T container, PlayerInventory inv, ITextComponent title) { super(container, inv, title); @@ -44,6 +46,18 @@ public abstract class AbstractSimiContainerScreen extends C this.ySize = height; } + protected void setWindowOffset(int xOffset, int yOffset) { + windowXOffset = xOffset; + windowYOffset = yOffset; + } + + @Override + protected void init() { + super.init(); + guiLeft += windowXOffset; + guiTop += windowYOffset; + } + @Override protected void drawForeground(MatrixStack p_230451_1_, int p_230451_2_, int p_230451_3_) { // no-op to prevent screen- and inventory-title from being rendered at incorrect location @@ -263,4 +277,16 @@ public abstract class AbstractSimiContainerScreen extends C public List getExtraAreas() { return Collections.emptyList(); } + + @Deprecated + protected void debugWindowArea(MatrixStack matrixStack) { + fill(matrixStack, guiLeft + xSize, guiTop + ySize, guiLeft, guiTop, 0xd3d3d3d3); + } + + @Deprecated + protected void debugExtraAreas(MatrixStack matrixStack) { + for (Rectangle2d area : getExtraAreas()) { + fill(matrixStack, area.getX() + area.getWidth(), area.getY() + area.getHeight(), area.getX(), area.getY(), 0xd3d3d3d3); + } + } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java index b064ccbfa..4a78dc36e 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AbstractSimiScreen.java @@ -43,20 +43,30 @@ public abstract class AbstractSimiScreen extends Screen { @Override public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { partialTicks = partialTicks == 10 ? 0 - : Minecraft.getInstance() + : Minecraft.getInstance() .getRenderPartialTicks(); ms.push(); + prepareFrame(); + renderWindowBackground(ms, mouseX, mouseY, partialTicks); renderWindow(ms, mouseX, mouseY, partialTicks); for (Widget widget : widgets) widget.render(ms, mouseX, mouseY, partialTicks); renderWindowForeground(ms, mouseX, mouseY, partialTicks); + endFrame(); + ms.pop(); } + protected void prepareFrame() { + } + + protected void endFrame() { + } + protected void renderWindowBackground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { renderBackground(ms); } 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 db6fdea92..84197e65f 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -20,6 +20,8 @@ public enum AllGuiTextures implements IScreenRenderable { TERRAINZAPPER("curiosities.png", 234, 103), TERRAINZAPPER_INACTIVE_PARAM("curiosities.png", 238, 0, 18, 18), + LOGO("logo.png", 256, 256), + SCHEMATIC("schematics.png", 192, 121), SCHEMATIC_SLOT("widgets.png", 54, 0, 16, 16), SCHEMATIC_PROMPT("schematics_2.png", 213, 77), @@ -58,6 +60,15 @@ public enum AllGuiTextures implements IScreenRenderable { SEQUENCER_EMPTY("sequencer.png", 0, 102, 162, 22), SEQUENCER_AWAIT("sequencer.png", 0, 160, 162, 22), + LINKED_CONTROLLER("curiosities2.png", 179, 109), + BLUEPRINT("curiosities2.png", 0, 109, 179, 109), + + PROJECTOR("projector.png", 235, 185), + PROJECTOR_FILTER_STRENGTH("projector.png", 0, 14, 162, 22), + PROJECTOR_FILTER("projector.png", 0, 36, 162, 22), + PROJECTOR_END("projector.png", 0, 58, 162, 22), + PROJECTOR_EMPTY("projector.png", 0, 80, 162, 22), + // JEI JEI_SLOT("jei/widgets.png", 18, 18), JEI_CHANCE_SLOT("jei/widgets.png", 20, 156, 18, 18), @@ -82,6 +93,11 @@ public enum AllGuiTextures implements IScreenRenderable { INDICATOR_YELLOW("widgets.png", 54, 18, 18, 6), INDICATOR_RED("widgets.png", 72, 18, 18, 6), + HOTSLOT_ARROW("widgets.png", 24, 51, 20, 12), + HOTSLOT("widgets.png", 0, 68, 22, 22), + HOTSLOT_ACTIVE("widgets.png", 0, 46, 22, 22), + HOTSLOT_SUPER_ACTIVE("widgets.png", 27, 67, 24, 24), + SPEECH_TOOLTIP_BACKGROUND("widgets.png", 0, 24, 8, 8), SPEECH_TOOLTIP_COLOR("widgets.png", 8, 24, 8, 8), diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java index e6b6cc573..3351867e7 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllIcons.java @@ -22,24 +22,24 @@ public class AllIcons implements IScreenRenderable { private int iconX; private int iconY; - public static final AllIcons - I_ADD = newRow(), - I_TRASH = next(), - I_3x3 = next(), + public static final AllIcons + I_ADD = newRow(), + I_TRASH = next(), + I_3x3 = next(), I_TARGET = next(), - I_PRIORITY_VERY_LOW = next(), - I_PRIORITY_LOW = next(), - I_PRIORITY_HIGH = next(), + I_PRIORITY_VERY_LOW = next(), + I_PRIORITY_LOW = next(), + I_PRIORITY_HIGH = next(), I_PRIORITY_VERY_HIGH = next(), - I_BLACKLIST = next(), - I_WHITELIST = next(), - I_WHITELIST_OR = next(), + I_BLACKLIST = next(), + I_WHITELIST = next(), + I_WHITELIST_OR = next(), I_WHITELIST_AND = next(), - I_WHITELIST_NOT = next(), - I_RESPECT_NBT = next(), + I_WHITELIST_NOT = next(), + I_RESPECT_NBT = next(), I_IGNORE_NBT = next(); - public static final AllIcons + public static final AllIcons I_CONFIRM = newRow(), I_NONE = next(), I_OPEN_FOLDER = next(), @@ -55,8 +55,8 @@ public class AllIcons implements IScreenRenderable { I_CART_ROTATE = next(), I_CART_ROTATE_PAUSED = next(), I_CART_ROTATE_LOCKED = next(); - - public static final AllIcons + + public static final AllIcons I_DONT_REPLACE = newRow(), I_REPLACE_SOLID = next(), I_REPLACE_ANY = next(), @@ -73,8 +73,8 @@ public class AllIcons implements IScreenRenderable { I_LMB = next(), I_SCROLL = next(), I_RMB = next(); - - public static final AllIcons + + public static final AllIcons I_TOOL_DEPLOY = newRow(), I_SKIP_MISSING = next(), I_SKIP_TILES = next(), @@ -86,7 +86,7 @@ public class AllIcons implements IScreenRenderable { I_TUNNEL_PREFER_NEAREST = next(), I_TUNNEL_RANDOMIZE = next(), I_TUNNEL_SYNCHRONIZE = next(), - + I_TOOL_MOVE_XZ = newRow(), I_TOOL_MOVE_Y = next(), I_TOOL_ROTATE = next(), @@ -94,10 +94,10 @@ public class AllIcons implements IScreenRenderable { I_ARM_ROUND_ROBIN = next(), I_ARM_FORCED_ROUND_ROBIN = next(), I_ARM_PREFER_FIRST = next(), - + I_ADD_INVERTED_ATTRIBUTE = next(), I_FLIP = next(), - + I_PLAY = newRow(), I_PAUSE = next(), I_STOP = next(), @@ -106,17 +106,17 @@ public class AllIcons implements IScreenRenderable { I_HOUR_HAND_FIRST = next(), I_MINUTE_HAND_FIRST = next(), I_HOUR_HAND_FIRST_24 = next(), - + I_PATTERN_SOLID = newRow(), I_PATTERN_CHECKERED = next(), I_PATTERN_CHECKERED_INVERSED = next(), I_PATTERN_CHANCE_25 = next(), - + I_PATTERN_CHANCE_50 = newRow(), I_PATTERN_CHANCE_75 = next(), I_FOLLOW_DIAGONAL = next(), I_FOLLOW_MATERIAL = next(), - + I_SCHEMATIC = newRow(), I_MTD_LEFT = newRow(), @@ -136,7 +136,15 @@ public class AllIcons implements IScreenRenderable { I_CONFIG_PREV = next(), I_CONFIG_NEXT = next(), I_DISABLE = next(), - I_CONFIG_OPEN = next(); + I_CONFIG_OPEN = next(), + + I_FX_SURFACE_OFF = newRow(), + I_FX_SURFACE_ON = next(), + I_FX_FIELD_OFF = next(), + I_FX_FIELD_ON = next(), + I_FX_BLEND = next(), + I_FX_BLEND_OFF = next(); + ; public AllIcons(int x, int y) { iconX = x * 16; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java b/src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java new file mode 100644 index 000000000..4714c273c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/ClearContainerPacket.java @@ -0,0 +1,36 @@ +package com.simibubi.create.foundation.gui; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class ClearContainerPacket extends SimplePacketBase { + + public ClearContainerPacket() {} + + public ClearContainerPacket(PacketBuffer buffer) {} + + @Override + public void write(PacketBuffer buffer) {} + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + if (!(player.openContainer instanceof IClearableContainer)) + return; + ((IClearableContainer) player.openContainer).clearContents(); + }); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java index e7b5b48cf..f0de70016 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ConfirmationScreen.java @@ -20,21 +20,28 @@ import net.minecraft.util.text.Style; public class ConfirmationScreen extends AbstractSimiScreen { private Screen source; - private Consumer action = _success -> {}; + private Consumer action = _success -> { + }; private List text = new ArrayList<>(); private boolean centered = false; private int x; private int y; private int textWidth; private int textHeight; + private boolean tristate; private BoxWidget confirm; + private BoxWidget confirmDontSave; private BoxWidget cancel; private BoxElement textBackground; + public enum Response { + Confirm, ConfirmDontSave, Cancel + } + /* - * Removes text lines from the back of the list - * */ + * Removes text lines from the back of the list + * */ public ConfirmationScreen removeTextLines(int amount) { if (amount > text.size()) return clearText(); @@ -70,7 +77,13 @@ public class ConfirmationScreen extends AbstractSimiScreen { } public ConfirmationScreen withAction(Consumer action) { + this.action = r -> action.accept(r == Response.Confirm); + return this; + } + + public ConfirmationScreen withThreeActions(Consumer action) { this.action = action; + this.tristate = true; return this; } @@ -99,6 +112,14 @@ public class ConfirmationScreen extends AbstractSimiScreen { textHeight = text.size() * (client.fontRenderer.FONT_HEIGHT + 1) + 4; textWidth = 300; + if (centered) { + x = width/2 - textWidth/2 - 2; + y = height/2 - textHeight/2 - 16; + } else { + x = Math.max(0, x - textWidth / 2); + y = Math.max(0, y -= textHeight); + } + if (x + textWidth > width) { x = width - textWidth; } @@ -107,37 +128,46 @@ public class ConfirmationScreen extends AbstractSimiScreen { y = height - textHeight - 30; } - if (centered) { - x = width/2 - textWidth/2 - 2; - y = height/2 - textHeight/2 - 16; + int buttonX = x + textWidth / 2 - 6 - (int) (70 * (tristate ? 1.5f : 1)); + + TextStencilElement confirmText = + new TextStencilElement(client.fontRenderer, tristate ? "Save" : "Confirm").centered(true, true); + confirm = new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.Confirm)); + confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm))); + widgets.add(confirm); + + buttonX += 12 + 70; + + if (tristate) { + TextStencilElement confirmDontSaveText = + new TextStencilElement(client.fontRenderer, "Don't Save").centered(true, true); + confirmDontSave = + new BoxWidget(buttonX, y + textHeight + 6, 70, 16).withCallback(() -> accept(Response.ConfirmDontSave)); + confirmDontSave.showingElement( + confirmDontSaveText.withElementRenderer(BoxWidget.gradientFactory.apply(confirmDontSave))); + widgets.add(confirmDontSave); + buttonX += 12 + 70; } - TextStencilElement confirmText = new TextStencilElement(client.fontRenderer, "Confirm").centered(true, true); - confirm = new BoxWidget(x + 4, y + textHeight + 2 , textWidth/2 - 10, 20) - .withCallback(() -> accept(true)); - confirm.showingElement(confirmText.withElementRenderer(BoxWidget.gradientFactory.apply(confirm))); - TextStencilElement cancelText = new TextStencilElement(client.fontRenderer, "Cancel").centered(true, true); - cancel = new BoxWidget(x + textWidth/2 + 6, y + textHeight + 2, textWidth/2 - 10, 20) - .withCallback(() -> accept(false)); + cancel = new BoxWidget(buttonX, y + textHeight + 6, 70, 16) + .withCallback(() -> accept(Response.Cancel)); cancel.showingElement(cancelText.withElementRenderer(BoxWidget.gradientFactory.apply(cancel))); - - widgets.add(confirm); widgets.add(cancel); textBackground = new BoxElement() .gradientBorder(Theme.p(Theme.Key.BUTTON_DISABLE)) - .withBounds(textWidth, textHeight) - .at(x, y); + .withBounds(width + 10, textHeight + 35) + .at(-5, y - 5); } @Override public void onClose() { - accept(false); + accept(Response.Cancel); } - private void accept(boolean success) { + private void accept(Response success) { client.currentScreen = source; action.accept(success); } @@ -154,11 +184,12 @@ public class ConfirmationScreen extends AbstractSimiScreen { for (ITextProperties line : text) { lineY = lineY + offset; - if (line == null) continue; - - client.fontRenderer.draw(ms, line.getString(), x, lineY, 0xeaeaea); + int textX = x; + if (text.size() == 1) + x = (width - client.fontRenderer.getWidth(line)) / 2; + client.fontRenderer.draw(ms, line.getString(), textX, lineY, 0xeaeaea); } ms.pop(); @@ -172,7 +203,7 @@ public class ConfirmationScreen extends AbstractSimiScreen { ms.push(); UIRenderHelper.framebuffer.bindFramebuffer(true); - source.render(ms, mouseX, mouseY, 10); + source.render(ms, 0, 0, 10); // zero mouse coords to prevent further tooltips UIRenderHelper.framebuffer.unbindFramebuffer(); Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer(); ms.pop(); @@ -180,7 +211,7 @@ public class ConfirmationScreen extends AbstractSimiScreen { //fixme replace with glVersioned-backend calls once they are merged from jozu's branch GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, UIRenderHelper.framebuffer.framebufferObject); GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject); - GL30.glBlitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL30.GL_LINEAR); + GL30.glBlitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL30.GL_LINEAR); mainBuffer.bindFramebuffer(true); this.fillGradient(ms, 0, 0, this.width, this.height, 0x70101010, 0x80101010); diff --git a/src/main/java/com/simibubi/create/foundation/gui/GhostItemContainer.java b/src/main/java/com/simibubi/create/foundation/gui/GhostItemContainer.java new file mode 100644 index 000000000..34b710559 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/GhostItemContainer.java @@ -0,0 +1,149 @@ +package com.simibubi.create.foundation.gui; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.container.ClickType; +import net.minecraft.inventory.container.Container; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.inventory.container.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.ItemStackHandler; + +public abstract class GhostItemContainer extends Container implements IClearableContainer { + + public PlayerEntity player; + public PlayerInventory playerInventory; + public ItemStackHandler ghostInventory; + public T contentHolder; + + protected GhostItemContainer(ContainerType type, int id, PlayerInventory inv, PacketBuffer extraData) { + super(type, id); + init(inv, createOnClient(extraData)); + } + + protected GhostItemContainer(ContainerType type, int id, PlayerInventory inv, T contentHolder) { + super(type, id); + init(inv, contentHolder); + } + + @OnlyIn(Dist.CLIENT) + protected abstract T createOnClient(PacketBuffer extraData); + + protected abstract void addSlots(); + + protected abstract ItemStackHandler createGhostInventory(); + + protected abstract void readData(T contentHolder); + + protected abstract void saveData(T contentHolder); + + protected abstract boolean allowRepeats(); + + protected void init(PlayerInventory inv, T contentHolder) { + player = inv.player; + playerInventory = inv; + this.contentHolder = contentHolder; + ghostInventory = createGhostInventory(); + readData(contentHolder); + addSlots(); + detectAndSendChanges(); + } + + @Override + public void clearContents() { + for (int i = 0; i < ghostInventory.getSlots(); i++) + ghostInventory.setStackInSlot(i, ItemStack.EMPTY); + } + + protected void addPlayerSlots(int x, int y) { + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new Slot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new Slot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + @Override + public boolean canMergeSlot(ItemStack stack, Slot slotIn) { + return slotIn.inventory == playerInventory; + } + + @Override + public boolean canDragIntoSlot(Slot slotIn) { + if (allowRepeats()) + return true; + return slotIn.inventory == playerInventory; + } + + @Override + public boolean canInteractWith(PlayerEntity playerIn) { + return true; + } + + @Override + public ItemStack slotClick(int slotId, int dragType, ClickType clickTypeIn, PlayerEntity player) { + ItemStack held = playerInventory.getItemStack(); + if (slotId < 36) + return super.slotClick(slotId, dragType, clickTypeIn, player); + if (clickTypeIn == ClickType.THROW) + return ItemStack.EMPTY; + + int slot = slotId - 36; + if (clickTypeIn == ClickType.CLONE) { + if (player.isCreative() && held.isEmpty()) { + ItemStack stackInSlot = ghostInventory.getStackInSlot(slot) + .copy(); + stackInSlot.setCount(stackInSlot.getMaxStackSize()); + playerInventory.setItemStack(stackInSlot); + return ItemStack.EMPTY; + } + return ItemStack.EMPTY; + } + + if (held.isEmpty()) { + ghostInventory.setStackInSlot(slot, ItemStack.EMPTY); + getSlot(slotId).onSlotChanged(); + return ItemStack.EMPTY; + } + + ItemStack insert = held.copy(); + insert.setCount(1); + ghostInventory.setStackInSlot(slot, insert); + getSlot(slotId).onSlotChanged(); + return held; + } + + @Override + public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { + if (index < 36) { + ItemStack stackToInsert = playerInventory.getStackInSlot(index); + for (int i = 0; i < ghostInventory.getSlots(); i++) { + ItemStack stack = ghostInventory.getStackInSlot(i); + if (!allowRepeats() && ItemHandlerHelper.canItemStacksStack(stack, stackToInsert)) + break; + if (stack.isEmpty()) { + ItemStack copy = stackToInsert.copy(); + copy.setCount(1); + ghostInventory.insertItem(i, copy, false); + getSlot(i + 36).onSlotChanged(); + break; + } + } + } else { + ghostInventory.extractItem(index - 36, 1, false); + getSlot(index).onSlotChanged(); + } + return ItemStack.EMPTY; + } + + @Override + public void onContainerClosed(PlayerEntity playerIn) { + super.onContainerClosed(playerIn); + saveData(contentHolder); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/GhostItemSubmitPacket.java b/src/main/java/com/simibubi/create/foundation/gui/GhostItemSubmitPacket.java new file mode 100644 index 000000000..54df945ac --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/GhostItemSubmitPacket.java @@ -0,0 +1,53 @@ +package com.simibubi.create.foundation.gui; + +import java.util.function.Supplier; + +import com.simibubi.create.foundation.networking.SimplePacketBase; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class GhostItemSubmitPacket extends SimplePacketBase { + + private final ItemStack item; + private final int slot; + + public GhostItemSubmitPacket(ItemStack item, int slot) { + this.item = item; + this.slot = slot; + } + + public GhostItemSubmitPacket(PacketBuffer buffer) { + item = buffer.readItemStack(); + slot = buffer.readInt(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeItemStack(item); + buffer.writeInt(slot); + } + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + ServerPlayerEntity player = context.get() + .getSender(); + if (player == null) + return; + + if (player.openContainer instanceof GhostItemContainer) { + GhostItemContainer c = (GhostItemContainer) player.openContainer; + c.ghostInventory.setStackInSlot(slot, item); + c.getSlot(36 + slot).onSlotChanged(); + } + + }); + context.get() + .setPacketHandled(true); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/GuiGameElement.java b/src/main/java/com/simibubi/create/foundation/gui/GuiGameElement.java index 79405d4c4..e1dfe6fb3 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/GuiGameElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/GuiGameElement.java @@ -2,6 +2,8 @@ package com.simibubi.create.foundation.gui; import javax.annotation.Nullable; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager.DestFactor; @@ -9,10 +11,8 @@ import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.IVertexBuilder; import com.simibubi.create.foundation.fluid.FluidRenderer; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.VecHelper; -import com.simibubi.create.foundation.utility.VirtualEmptyModelData; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -35,12 +35,15 @@ import net.minecraft.inventory.container.PlayerContainer; import net.minecraft.item.ItemStack; import net.minecraft.util.IItemProvider; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector2f; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraftforge.fluids.FluidStack; public class GuiGameElement { + public static Vector2f defaultBlockLighting = new Vector2f(30.0f, 7.5f); + public static GuiRenderBuilder of(ItemStack stack) { return new GuiItemRenderBuilder(stack); } @@ -64,11 +67,13 @@ public class GuiGameElement { } public static abstract class GuiRenderBuilder extends RenderElement { - double xLocal, yLocal, zLocal; - double xRot, yRot, zRot; - double scale = 1; - int color = 0xFFFFFF; - Vector3d rotationOffset = Vector3d.ZERO; + protected double xLocal, yLocal, zLocal; + protected double xRot, yRot, zRot; + protected double scale = 1; + protected int color = 0xFFFFFF; + protected Vector3d rotationOffset = Vector3d.ZERO; + protected boolean hasCustomLighting = false; + protected float lightingXRot, lightingYRot; public GuiRenderBuilder atLocal(double x, double y, double z) { this.xLocal = x; @@ -104,33 +109,25 @@ public class GuiGameElement { return this; } - public abstract void render(MatrixStack matrixStack); + public GuiRenderBuilder lighting(float xRot, float yRot) { + hasCustomLighting = true; + lightingXRot = xRot; + lightingYRot = yRot; + return this; + } - @Deprecated - protected void prepare() {} + public abstract void render(MatrixStack matrixStack); protected void prepareMatrix(MatrixStack matrixStack) { matrixStack.push(); - RenderSystem.enableBlend(); - RenderSystem.enableRescaleNormal(); - RenderSystem.enableAlphaTest(); - RenderHelper.enableGuiDepthLighting(); - RenderSystem.alphaFunc(516, 0.1F); - RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); - } - - @Deprecated - protected void transform() { - RenderSystem.translated(x, y, 0); - RenderSystem.scaled(scale, scale, scale); - RenderSystem.translated(xLocal, yLocal, zLocal); - RenderSystem.scaled(1, -1, 1); - RenderSystem.translated(rotationOffset.x, rotationOffset.y, rotationOffset.z); - RenderSystem.rotatef((float) zRot, 0, 0, 1); - RenderSystem.rotatef((float) xRot, 1, 0, 0); - RenderSystem.rotatef((float) yRot, 0, 1, 0); - RenderSystem.translated(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z); + RenderSystem.alphaFunc(516, 0.1F); + RenderSystem.enableAlphaTest(); + RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); + RenderSystem.enableBlend(); + RenderSystem.enableDepthTest(); + RenderSystem.enableRescaleNormal(); + prepareLighting(matrixStack); } protected void transformMatrix(MatrixStack matrixStack) { @@ -145,13 +142,18 @@ public class GuiGameElement { matrixStack.translate(-rotationOffset.x, -rotationOffset.y, -rotationOffset.z); } - @Deprecated - protected void cleanUp() {} - protected void cleanUpMatrix(MatrixStack matrixStack) { matrixStack.pop(); - RenderSystem.disableAlphaTest(); RenderSystem.disableRescaleNormal(); + RenderSystem.disableAlphaTest(); + cleanUpLighting(matrixStack); + } + + protected void prepareLighting(MatrixStack matrixStack) { + RenderHelper.enableGuiDepthLighting(); + } + + protected void cleanUpLighting(MatrixStack matrixStack) { } } @@ -197,6 +199,20 @@ public class GuiGameElement { 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); buffer.draw(); } + + @Override + protected void prepareLighting(MatrixStack matrixStack) { + if (hasCustomLighting) { + UIRenderHelper.setupSimpleCustomLighting(lightingXRot, lightingYRot); + } else { + UIRenderHelper.setupSimpleCustomLighting(defaultBlockLighting.x, defaultBlockLighting.y); + } + } + + @Override + protected void cleanUpLighting(MatrixStack matrixStack) { + RenderHelper.enableGuiDepthLighting(); + } } public static class GuiBlockStateRenderBuilder extends GuiBlockModelRenderBuilder { @@ -214,8 +230,8 @@ public class GuiGameElement { RenderHelper.disableGuiDepthLighting(); blockRenderer.renderBlock(blockState, ms, buffer, 0xF000F0, OverlayTexture.DEFAULT_UV, VirtualEmptyModelData.INSTANCE); - RenderHelper.enable(); buffer.draw(); + RenderHelper.enableGuiDepthLighting(); return; } @@ -273,6 +289,7 @@ public class GuiGameElement { .setBlurMipmapDirect(false, false); RenderSystem.enableRescaleNormal(); RenderSystem.enableAlphaTest(); + RenderSystem.enableCull(); RenderSystem.defaultAlphaFunc(); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, @@ -281,19 +298,19 @@ public class GuiGameElement { matrixStack.translate((float) 0, (float) 0, 100.0F + renderer.zLevel); matrixStack.translate(8.0F, -8.0F, 0.0F); matrixStack.scale(16.0F, 16.0F, 16.0F); - IRenderTypeBuffer.Impl irendertypebuffer$impl = Minecraft.getInstance() + IRenderTypeBuffer.Impl buffer = Minecraft.getInstance() .getBufferBuilders() .getEntityVertexConsumers(); - boolean flag = !bakedModel.isSideLit(); - if (flag) { + boolean flatLighting = !bakedModel.isSideLit(); + if (flatLighting) { RenderHelper.disableGuiDepthLighting(); } renderer.renderItem(stack, ItemCameraTransforms.TransformType.GUI, false, matrixStack, - irendertypebuffer$impl, 15728880, OverlayTexture.DEFAULT_UV, bakedModel); - irendertypebuffer$impl.draw(); + buffer, 0xF000F0, OverlayTexture.DEFAULT_UV, bakedModel); + buffer.draw(); RenderSystem.enableDepthTest(); - if (flag) { + if (flatLighting) { RenderHelper.enableGuiDepthLighting(); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java b/src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java new file mode 100644 index 000000000..eea746881 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/IClearableContainer.java @@ -0,0 +1,13 @@ +package com.simibubi.create.foundation.gui; + +import com.simibubi.create.foundation.networking.AllPackets; + +public interface IClearableContainer { + + default void sendClearPacket() { + AllPackets.channel.sendToServer(new ClearContainerPacket()); + } + + public void clearContents(); + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java index 26677e053..22c70b75f 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/StencilElement.java @@ -47,5 +47,6 @@ public abstract class StencilElement extends RenderElement { protected void cleanUp(MatrixStack ms) { GL11.glDisable(GL11.GL_STENCIL_TEST); + } } diff --git a/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java b/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java index c5d87543c..cdea4f887 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java +++ b/src/main/java/com/simibubi/create/foundation/gui/TextStencilElement.java @@ -53,7 +53,7 @@ public class TextStencilElement extends DelegatedStencilElement { x = width / 2f - font.getWidth(component) / 2f; if (centerVertically) - y = height / 2f - font.FONT_HEIGHT / 2f; + y = height / 2f - (font.FONT_HEIGHT - 1) / 2f; font.draw(ms, component, x, y, 0xff_000000); } @@ -65,7 +65,7 @@ public class TextStencilElement extends DelegatedStencilElement { x = width / 2f - font.getWidth(component) / 2f; if (centerVertically) - y = height / 2f - font.FONT_HEIGHT / 2f; + y = height / 2f - (font.FONT_HEIGHT - 1) / 2f; ms.push(); ms.translate(x, y, 0); diff --git a/src/main/java/com/simibubi/create/foundation/gui/Theme.java b/src/main/java/com/simibubi/create/foundation/gui/Theme.java index 0f6f0155e..57b2b6412 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/Theme.java +++ b/src/main/java/com/simibubi/create/foundation/gui/Theme.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.gui; -import java.awt.Color; +import java.awt.*; import java.util.HashMap; import java.util.Map; @@ -18,6 +18,12 @@ public class Theme { custom = theme; } + public static void reload() { + base.init(); + if (custom != null) + custom.init(); + } + private static ColorHolder resolve(String key) { ColorHolder h = null; @@ -58,25 +64,29 @@ public class Theme { } protected void init() { - put(Key.BUTTON_IDLE, new Color(0x60_c0c0ff, true), new Color(0x30_c0c0ff, true)); - put(Key.BUTTON_HOVER, new Color(0xa0_c0c0ff, true), new Color(0x50_c0c0ff, true)); - put(Key.BUTTON_CLICK, new Color(0xff_4b4bff), new Color(0xff_3b3bdd)); - put(Key.BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x20_909090, true)); + put(Key.BUTTON_IDLE, new Color(0xdd_8ab6d6, true), new Color(0x90_8ab6d6, true)); + put(Key.BUTTON_HOVER, new Color(0xff_9ABBD3, true), new Color(0xd0_9ABBD3, true)); + put(Key.BUTTON_CLICK, new Color(0xff_ffffff), new Color(0xee_ffffff)); + put(Key.BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x60_909090, true)); put(Key.BUTTON_SUCCESS, new Color(0xcc_88f788, true), new Color(0xcc_20cc20, true)); put(Key.BUTTON_FAIL, new Color(0xcc_f78888, true), new Color(0xcc_cc2020, true)); put(Key.TEXT, new Color(0xff_eeeeee), new Color(0xff_a3a3a3)); put(Key.TEXT_DARKER, new Color(0xff_a3a3a3), new Color(0xff_808080)); - put(Key.TEXT_ACCENT_STRONG, new Color(0xff_7b7ba3), new Color(0xff_616192)); + put(Key.TEXT_ACCENT_STRONG, new Color(0xff_8ab6d6), new Color(0xff_8ab6d6)); put(Key.TEXT_ACCENT_SLIGHT, new Color(0xff_ddeeff), new Color(0xff_a0b0c0)); put(Key.STREAK, new Color(0x101010, false)); + put(Key.PONDER_BUTTON_IDLE, new Color(0x60_c0c0ff, true), new Color(0x30_c0c0ff, true)); + put(Key.PONDER_BUTTON_HOVER, new Color(0xf0_c0c0ff, true), new Color(0xa0_c0c0ff, true)); + put(Key.PONDER_BUTTON_CLICK, new Color(0xff_ffffff), new Color(0xdd_ffffff)); + put(Key.PONDER_BUTTON_DISABLE, new Color(0x80_909090, true), new Color(0x20_909090, true)); put(Key.PONDER_BACKGROUND_TRANSPARENT, new Color(0xdd_000000, true)); put(Key.PONDER_BACKGROUND_FLAT, new Color(0xff_000000, false)); put(Key.PONDER_IDLE, new Color(0x40ffeedd, true), new Color(0x20ffeedd, true)); put(Key.PONDER_HOVER, new Color(0x70ffffff, true), new Color(0x30ffffff, true)); put(Key.PONDER_HIGHLIGHT, new Color(0xf0ffeedd, true), new Color(0x60ffeedd, true)); put(Key.TEXT_WINDOW_BORDER, new Color(0x607a6000, true), new Color(0x207a6000, true)); - put(Key.PONDER_BACK_ARROW, new Color(0x70aa9999, true), new Color(0x30aa9999, true)); + put(Key.PONDER_BACK_ARROW, new Color(0xf0aa9999, true), new Color(0x30aa9999, true)); put(Key.PONDER_PROGRESSBAR, new Color(0x80ffeedd, true), new Color(0x50ffeedd, true)); put(Key.PONDER_MISSING_CREATE, new Color(0x70_984500, true), new Color(0x70_692400, true)); put(Key.PONDER_MISSING_VANILLA, new Color(0x50_5000ff, true), new Color(0x50_300077, true)); @@ -130,6 +140,11 @@ public class Theme { public static Key PONDER_MISSING_CREATE = new Key(); public static Key PONDER_MISSING_VANILLA = new Key(); + public static Key PONDER_BUTTON_IDLE = new Key(); + public static Key PONDER_BUTTON_HOVER = new Key(); + public static Key PONDER_BUTTON_CLICK = new Key(); + public static Key PONDER_BUTTON_DISABLE = new Key(); + private static int index = 0; private final String s; diff --git a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java index 5efe5c936..cb77c8b7d 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java +++ b/src/main/java/com/simibubi/create/foundation/gui/ToolSelectionScreen.java @@ -136,6 +136,7 @@ public class ToolSelectionScreen extends Screen { matrixStack.pop(); } + RenderSystem.enableBlend(); matrixStack.pop(); } diff --git a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java index be3e6b11c..23adb2cc2 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/gui/UIRenderHelper.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.gui; -import java.awt.Color; +import java.awt.*; import javax.annotation.Nonnull; @@ -10,6 +10,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.systems.RenderSystem; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.MainWindow; import net.minecraft.client.Minecraft; @@ -24,23 +25,33 @@ import net.minecraftforge.fml.client.gui.GuiUtils; public class UIRenderHelper { - public static void enableStencil() { - RenderSystem.recordRenderCall(() -> Minecraft.getInstance().getFramebuffer().enableStencil()); - } - + /** + * An FBO that has a stencil buffer for use wherever stencil are necessary. Forcing the main FBO to have a stencil + * buffer will cause GL error spam when using fabulous graphics. + */ public static Framebuffer framebuffer; + public static void updateWindowSize(MainWindow mainWindow) { + if (framebuffer != null) + framebuffer.func_216491_a(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC); + } + public static void init() { RenderSystem.recordRenderCall(() -> { MainWindow mainWindow = Minecraft.getInstance() .getWindow(); - framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true, - Minecraft.IS_RUNNING_ON_MAC); - framebuffer.setFramebufferColor(0, 0, 0, 0); - framebuffer.enableStencil(); + framebuffer = createFramebuffer(mainWindow); }); } + private static Framebuffer createFramebuffer(MainWindow mainWindow) { + Framebuffer framebuffer = new Framebuffer(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), true, + Minecraft.IS_RUNNING_ON_MAC); + framebuffer.setFramebufferColor(0, 0, 0, 0); + framebuffer.enableStencil(); + return framebuffer; + } + public static void drawFramebuffer(float alpha) { MainWindow window = Minecraft.getInstance() .getWindow(); @@ -69,10 +80,10 @@ public class UIRenderHelper { } public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length) {streak(ms, angle, x, y, breadth, length, Theme.i(Theme.Key.STREAK));} - // angle in degrees; 0° -> fading to the right // x and y specify the middle point of the starting edge // breadth is the total width of the streak + public static void streak(MatrixStack ms, float angle, int x, int y, int breadth, int length, int color) { int a1 = 0xa0 << 24; int a2 = 0x80 << 24; @@ -257,4 +268,14 @@ public class UIRenderHelper { RenderSystem.enableAlphaTest(); WorldVertexBufferUploader.draw(bufferbuilder); } + + public static void setupSimpleCustomLighting(float xRot, float yRot) { + Matrix4f lightingMatrix = new Matrix4f(); + lightingMatrix.loadIdentity(); + lightingMatrix.multiply(Vector3f.POSITIVE_Y.getDegreesQuaternion(yRot)); + lightingMatrix.multiply(Vector3f.POSITIVE_X.getDegreesQuaternion(xRot)); + lightingMatrix.multiply(Matrix4f.translate(0, 0, 1)); + RenderSystem.setupLevelDiffuseLighting(VecHelper.ZERO_3F, VecHelper.ZERO_3F, lightingMatrix); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java b/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java new file mode 100644 index 000000000..8688b3492 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/gui/mainMenu/CreateMainMenuScreen.java @@ -0,0 +1,195 @@ +package com.simibubi.create.foundation.gui.mainMenu; + +import java.awt.Color; + +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.Create; +import com.simibubi.create.foundation.config.ui.BaseConfigScreen; +import com.simibubi.create.foundation.gui.AbstractSimiScreen; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.BoxElement; +import com.simibubi.create.foundation.gui.GuiGameElement; +import com.simibubi.create.foundation.gui.ScreenOpener; +import com.simibubi.create.foundation.utility.Iterate; +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.MatrixStacker; + +import net.minecraft.client.gui.screen.ConfirmOpenLinkScreen; +import net.minecraft.client.gui.screen.MainMenuScreen; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.button.Button; +import net.minecraft.client.renderer.RenderSkybox; +import net.minecraft.client.renderer.RenderSkyboxCube; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.Util; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; + +public class CreateMainMenuScreen extends AbstractSimiScreen { + + protected final Screen parent; + protected boolean returnOnClose; + + private static final RenderSkyboxCube PANORAMA_RESOURCES = + new RenderSkyboxCube(Create.asResource("textures/gui/title/background/panorama")); + private static final ResourceLocation PANORAMA_OVERLAY_TEXTURES = + new ResourceLocation("textures/gui/title/background/panorama_overlay.png"); + private RenderSkybox vanillaPanorama = new RenderSkybox(MainMenuScreen.PANORAMA_RESOURCES); + private RenderSkybox panorama = new RenderSkybox(PANORAMA_RESOURCES); + private long firstRenderTime; + + public CreateMainMenuScreen(Screen parent) { + this.parent = parent; + returnOnClose = true; + if (parent instanceof MainMenuScreen) + vanillaPanorama = ObfuscationReflectionHelper.getPrivateValue(MainMenuScreen.class, (MainMenuScreen) parent, + "field_209101_K"); + } + + @Override + public void render(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + if (firstRenderTime == 0L) + this.firstRenderTime = Util.milliTime(); + super.render(ms, mouseX, mouseY, partialTicks); + } + + @Override + protected void renderWindow(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + float f = (float) (Util.milliTime() - this.firstRenderTime) / 1000.0F; + float alpha = MathHelper.clamp(f, 0.0F, 1.0F); + + if (parent instanceof MainMenuScreen) { + if (alpha < 1) + vanillaPanorama.render(partialTicks, 1); + panorama.render(partialTicks, alpha); + + client.getTextureManager() + .bindTexture(PANORAMA_OVERLAY_TEXTURES); + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + drawTexture(ms, 0, 0, this.width, this.height, 0.0F, 0.0F, 16, 128, 16, 128); + } + + RenderSystem.enableDepthTest(); + + for (int side : Iterate.positiveAndNegative) { + ms.push(); + ms.translate(width / 2, 60, 200); + ms.scale(24 * side, 24 * side, 32); + ms.translate(-1.75 * ((alpha * alpha) / 2f + .5f), .25f, 0); + MatrixStacker.of(ms) + .rotateX(45); + GuiGameElement.of(AllBlocks.LARGE_COGWHEEL.getDefaultState()) + .rotateBlock(0, Util.milliTime() / 32f * side, 0) + .render(ms); + ms.translate(-1, 0, -1); + GuiGameElement.of(AllBlocks.COGWHEEL.getDefaultState()) + .rotateBlock(0, Util.milliTime() / -16f * side + 22.5f, 0) + .render(ms); + ms.pop(); + } + + ms.push(); + ms.translate(width / 2 - 32, 32, -10); + ms.push(); + ms.scale(0.25f, 0.25f, 0.25f); + AllGuiTextures.LOGO.draw(ms, 0, 0); + ms.pop(); + new BoxElement().withBackground(0x88_000000) + .flatBorder(new Color(0x01_000000, true)) + .at(-32, 56, 100) + .withBounds(128, 11) + .render(ms); + ms.pop(); + + ms.push(); + ms.translate(0, 0, 200); + drawCenteredText(ms, textRenderer, new StringTextComponent(Create.NAME).formatted(TextFormatting.BOLD) + .append(new StringTextComponent(" v" + Create.VERSION).formatted(TextFormatting.BOLD, TextFormatting.WHITE)), + width / 2, 89, 0xff_E4BB67); + ms.pop(); + + RenderSystem.disableDepthTest(); + } + + protected void init() { + super.init(); + returnOnClose = true; + this.addButtons(); + } + + private void addButtons() { + buttons.clear(); + + int yStart = height / 4 + (parent instanceof MainMenuScreen ? 40 : 40); + int center = width / 2; + int bHeight = 20; + int bShortWidth = 98; + int bLongWidth = 200; + + addButton(new Button(center - 100, yStart + 92, bLongWidth, bHeight, Lang.translate("menu.return"), + $ -> onClose())); + addButton(new Button(center - 100, yStart + 24 + -16, bLongWidth, bHeight, Lang.translate("menu.configure"), + $ -> linkTo(BaseConfigScreen.forCreate(this)))); + + Button gettingStarted = new Button(center + 2, yStart + 48 + -16, bShortWidth, bHeight, + Lang.translate("menu.getting_started"), $ -> { + }); + gettingStarted.active = false; + addButton(gettingStarted); + + String projectLink = "https://www.curseforge.com/minecraft/mc-mods/create"; + String issueTrackerLink = "https://github.com/Creators-of-Create/Create/issues"; + String supportLink = "https://github.com/Creators-of-Create/Create/wiki/Supporting-the-Project"; + + addButton(new Button(center - 100, yStart + 48 + -16, bShortWidth, bHeight, Lang.translate("menu.project_page"), + $ -> linkTo(projectLink))); + addButton(new Button(center + 2, yStart + 68, bShortWidth, bHeight, Lang.translate("menu.report_bugs"), + $ -> linkTo(issueTrackerLink))); + addButton(new Button(center - 100, yStart + 68, bShortWidth, bHeight, Lang.translate("menu.support"), + $ -> linkTo(supportLink))); + } + + @Override + protected void renderWindowForeground(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + super.renderWindowForeground(ms, mouseX, mouseY, partialTicks); + buttons.forEach(w -> w.render(ms, mouseX, mouseY, partialTicks)); + } + + public void tick() { + super.tick(); + } + + private void linkTo(Screen screen) { + returnOnClose = false; + ScreenOpener.open(screen); + } + + private void linkTo(String url) { + returnOnClose = false; + ScreenOpener.open(new ConfirmOpenLinkScreen((p_213069_2_) -> { + if (p_213069_2_) + Util.getOSType() + .openURI(url); + this.client.displayGuiScreen(this); + }, url, true)); + } + + @Override + public boolean isPauseScreen() { + return true; + } + + @Override + public void onClose() { + super.onClose(); + ScreenOpener.open(parent); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/BoxWidget.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/BoxWidget.java index 07b35d4f9..0623d96f9 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/BoxWidget.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/BoxWidget.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.gui.widgets; -import java.awt.Color; +import java.awt.*; import java.util.function.Function; import javax.annotation.Nonnull; @@ -9,6 +9,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.BoxElement; import com.simibubi.create.foundation.gui.DelegatedStencilElement; import com.simibubi.create.foundation.gui.Theme; +import com.simibubi.create.foundation.gui.Theme.Key; import com.simibubi.create.foundation.gui.UIRenderHelper; import com.simibubi.create.foundation.utility.ColorHelper; import com.simibubi.create.foundation.utility.Couple; @@ -24,9 +25,11 @@ public class BoxWidget extends ElementWidget { protected Color customBorderBot; protected boolean animateColors = true; protected LerpedFloat colorAnimation = LerpedFloat.linear(); + protected Color gradientColor1, gradientColor2; - private Color colorTarget1 = Theme.c(Theme.Key.BUTTON_IDLE, true), colorTarget2 = Theme.c(Theme.Key.BUTTON_IDLE, false); private Color previousColor1, previousColor2; + private Color colorTarget1 = Theme.c(getIdleTheme(), true); + private Color colorTarget2 = Theme.c(getIdleTheme(), false); public BoxWidget() { this(0, 0); @@ -84,8 +87,8 @@ public class BoxWidget extends ElementWidget { public void onClick(double x, double y) { super.onClick(x, y); - gradientColor1 = Theme.c(Theme.Key.BUTTON_CLICK, true); - gradientColor2 = Theme.c(Theme.Key.BUTTON_CLICK, true); + gradientColor1 = Theme.c(getClickTheme(), true); + gradientColor2 = Theme.c(getClickTheme(), false); startGradientAnimation(getColorForState(true), getColorForState(false), true, 0.15); } @@ -175,23 +178,40 @@ public class BoxWidget extends ElementWidget { } private void startGradientAnimation(Color c1, Color c2, boolean positive) { - startGradientAnimation(c1, c2, positive, 0.3); + startGradientAnimation(c1, c2, positive, 0.6); } private Color getColorForState(boolean first) { if (!active) - return Theme.p(Theme.Key.BUTTON_DISABLE).get(first); + return Theme.p(getDisabledTheme()).get(first); if (hovered) { if (first) - return customBorderTop != null ? customBorderTop.darker() : Theme.c(Theme.Key.BUTTON_HOVER, true); + return customBorderTop != null ? customBorderTop.darker() : Theme.c(getHoverTheme(), true); else - return customBorderBot != null ? customBorderBot.darker() : Theme.c(Theme.Key.BUTTON_HOVER, false); + return customBorderBot != null ? customBorderBot.darker() : Theme.c(getHoverTheme(), false); } if (first) - return customBorderTop != null ? customBorderTop : Theme.c(Theme.Key.BUTTON_IDLE, true); + return customBorderTop != null ? customBorderTop : Theme.c(getIdleTheme(), true); else - return customBorderBot != null ? customBorderBot : Theme.c(Theme.Key.BUTTON_IDLE, false); + return customBorderBot != null ? customBorderBot : Theme.c(getIdleTheme(), false); } + + public Key getDisabledTheme() { + return Theme.Key.BUTTON_DISABLE; + } + + public Key getIdleTheme() { + return Theme.Key.BUTTON_IDLE; + } + + public Key getHoverTheme() { + return Theme.Key.BUTTON_HOVER; + } + + public Key getClickTheme() { + return Theme.Key.BUTTON_CLICK; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java b/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java index dcd54ac69..3b553b729 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java +++ b/src/main/java/com/simibubi/create/foundation/gui/widgets/IconButton.java @@ -52,4 +52,7 @@ public class IconButton extends AbstractSimiWidget { toolTip.add(text); } + public void setIcon(AllIcons icon) { + this.icon = icon; + } } diff --git a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java index e8a901d58..155f4758c 100644 --- a/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/ItemHelper.java @@ -161,7 +161,7 @@ public class ItemHelper { continue; if (!test.test(stack)) continue; - if (!extracting.isEmpty() && !ItemHandlerHelper.canItemStacksStack(stack, extracting)) { + if (!extracting.isEmpty() && !canItemStackAmountsStack(stack, extracting)) { potentialOtherMatch = true; continue; } @@ -174,8 +174,7 @@ public class ItemHelper { if (!simulate && hasEnoughItems) inv.extractItem(slot, stack.getCount(), false); - if (extracting.getCount() >= maxExtractionCount - || extracting.getCount() >= extracting.getMaxStackSize()) { + if (extracting.getCount() >= maxExtractionCount) { if (checkHasEnoughItems) { hasEnoughItems = true; checkHasEnoughItems = false; @@ -225,7 +224,7 @@ public class ItemHelper { if (!test.test(stack)) continue; - if (!extracting.isEmpty() && !ItemHandlerHelper.canItemStacksStack(stack, extracting)) + if (!extracting.isEmpty() && !canItemStackAmountsStack(stack, extracting)) continue; if (extracting.isEmpty()) @@ -235,13 +234,17 @@ public class ItemHelper { if (!simulate) inv.extractItem(slot, stack.getCount(), false); - if (extracting.getCount() >= maxExtractionCount || extracting.getCount() >= extracting.getMaxStackSize()) + if (extracting.getCount() >= maxExtractionCount) break; } return extracting; } + public static boolean canItemStackAmountsStack(ItemStack a, ItemStack b) { + return ItemHandlerHelper.canItemStacksStack(a, b) && a.getCount() + b.getCount() <= a.getMaxStackSize(); + } + public static ItemStack findFirstMatch(IItemHandler inv, Predicate test) { int slot = findFirstMatchingSlotIndex(inv, test); if (slot == -1) diff --git a/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java b/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java index 452af3c6c..ff99d550b 100644 --- a/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java +++ b/src/main/java/com/simibubi/create/foundation/item/TooltipHelper.java @@ -9,7 +9,6 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; import com.google.common.base.Strings; @@ -33,9 +32,7 @@ import net.minecraft.util.IItemProvider; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.Style; import net.minecraft.util.text.TextFormatting; -import net.minecraft.util.text.TextProcessing; import net.minecraftforge.client.MinecraftForgeClient; public class TooltipHelper { @@ -277,10 +274,6 @@ public class TooltipHelper { private static ItemDescription buildToolTip(String translationKey, ItemStack stack) { AllSections module = AllSections.of(stack); - if (I18n.format(translationKey) - .equals("WIP")) - return new WipScription(module.getTooltipPalette()); - ItemDescription tooltip = new ItemDescription(module.getTooltipPalette()); String summaryKey = translationKey + ".summary"; @@ -328,14 +321,14 @@ public class TooltipHelper { return item.getTranslationKey(stack) + ".tooltip"; } - private static int getComponentLength(ITextComponent component) { - AtomicInteger l = new AtomicInteger(); - TextProcessing.visitFormatted(component, Style.EMPTY, (s, style, charConsumer) -> { - l.getAndIncrement(); - return true; - }); - return l.get(); - } +// private static int getComponentLength(ITextComponent component) { +// AtomicInteger l = new AtomicInteger(); +// TextProcessing.visitFormatted(component, Style.EMPTY, (s, style, charConsumer) -> { +// l.getAndIncrement(); +// return true; +// }); +// return l.get(); +// } public static String getUnformattedDeepText(ITextComponent component) { StringBuilder b = new StringBuilder(); diff --git a/src/main/java/com/simibubi/create/foundation/item/WipScription.java b/src/main/java/com/simibubi/create/foundation/item/WipScription.java deleted file mode 100644 index d16d0b914..000000000 --- a/src/main/java/com/simibubi/create/foundation/item/WipScription.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.simibubi.create.foundation.item; - -import java.util.List; -import java.util.Random; - -import com.simibubi.create.foundation.utility.Lang; - -import net.minecraft.client.resources.I18n; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.StringTextComponent; -import net.minecraft.util.text.TextFormatting; - -public class WipScription extends ItemDescription { - - public WipScription(Palette palette) { - super(palette); - add(getLines(), Lang.translate("tooltip.workInProgress") - .formatted(TextFormatting.RED)); - - int descriptions = 0; - while (I18n.hasKey("create.tooltip.randomWipDescription" + descriptions++)) - ; - - if (--descriptions > 0) { - int index = new Random().nextInt(descriptions); - ITextComponent translate = Lang.translate("tooltip.randomWipDescription" + index); - List lines = getLines(); - lines.addAll(TooltipHelper.cutTextComponent(translate, TextFormatting.DARK_RED, TextFormatting.DARK_RED)); - } - } - - @Override - public List addInformation(List tooltip) { - tooltip.set(0, decorateName(tooltip.get(0))); - tooltip.addAll(getLines()); - return tooltip; - } - - public static ITextComponent decorateName(ITextComponent name) { - return StringTextComponent.EMPTY.copy() - .append(name.copy() - .formatted(TextFormatting.GRAY, TextFormatting.STRIKETHROUGH)) - .append(" ") - .append(Lang.translate("tooltip.wip") - .formatted(TextFormatting.GOLD)); - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/item/CustomItemModels.java b/src/main/java/com/simibubi/create/foundation/item/render/CustomItemModels.java similarity index 96% rename from src/main/java/com/simibubi/create/foundation/item/CustomItemModels.java rename to src/main/java/com/simibubi/create/foundation/item/render/CustomItemModels.java index 805d8e3f6..8f7ed04f6 100644 --- a/src/main/java/com/simibubi/create/foundation/item/CustomItemModels.java +++ b/src/main/java/com/simibubi/create/foundation/item/render/CustomItemModels.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.item; +package com.simibubi.create.foundation.item.render; import java.util.ArrayList; import java.util.IdentityHashMap; diff --git a/src/main/java/com/simibubi/create/foundation/block/render/CustomRenderedItemModel.java b/src/main/java/com/simibubi/create/foundation/item/render/CustomRenderedItemModel.java similarity index 96% rename from src/main/java/com/simibubi/create/foundation/block/render/CustomRenderedItemModel.java rename to src/main/java/com/simibubi/create/foundation/item/render/CustomRenderedItemModel.java index 6df4c426b..6ef18e8cd 100644 --- a/src/main/java/com/simibubi/create/foundation/block/render/CustomRenderedItemModel.java +++ b/src/main/java/com/simibubi/create/foundation/item/render/CustomRenderedItemModel.java @@ -1,4 +1,4 @@ -package com.simibubi.create.foundation.block.render; +package com.simibubi.create.foundation.item.render; import java.util.HashMap; import java.util.List; @@ -16,7 +16,6 @@ import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.ModelBakeEvent; import net.minecraftforge.client.model.BakedModelWrapper; -@SuppressWarnings("deprecation") public abstract class CustomRenderedItemModel extends BakedModelWrapper { protected String basePath; @@ -67,6 +66,7 @@ public abstract class CustomRenderedItemModel extends BakedModelWrapper> 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/FixNormalScalingMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/FixNormalScalingMixin.java new file mode 100644 index 000000000..46b35d6e3 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/FixNormalScalingMixin.java @@ -0,0 +1,36 @@ +package com.simibubi.create.foundation.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.At.Shift; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.mojang.blaze3d.matrix.MatrixStack; + +@Mixin(MatrixStack.class) +public class FixNormalScalingMixin { + /** + * Minecraft negates the normal matrix if all scales are equal and negative, but + * does not return afterward. This allows the rest of the method's logic to be + * applied, which negates the matrix again, resulting in the matrix being the + * same as in the beginning. + */ + @Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/vector/Matrix3f;multiply(F)V", shift = Shift.AFTER), method = "scale(FFF)V", cancellable = true) + private void returnAfterNegate(float x, float y, float z, CallbackInfo ci) { + ci.cancel(); + } + + /** + * Minecraft takes the inverse cube root of the product of all scales to provide a + * rough estimate for normalization so that it does not need to be done later. It + * does not make sense for this "normalization factor" to be negative though, as + * that would invert all normals. Additionally, Minecraft's fastInverseCbrt method + * does not work for negative numbers. + */ + @ModifyArg(at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;fastInverseCbrt(F)F"), method = "scale(FFF)V") + private float absInvCbrtInput(float input) { + return Math.abs(input); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/FogColorTrackerMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/FogColorTrackerMixin.java deleted file mode 100644 index d4cb97910..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/FogColorTrackerMixin.java +++ /dev/null @@ -1,21 +0,0 @@ -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 deleted file mode 100644 index 440a3f68b..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/LightUpdateMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -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.CreateClient; -import com.simibubi.create.foundation.render.backend.light.LightUpdater; - -import net.minecraft.client.multiplayer.ClientChunkProvider; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.SectionPos; -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); - ClientWorld world = (ClientWorld) thi.getWorld(); - - 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) - .forEach(tile -> { - CreateClient.kineticRenderer.get(world) - .onLightUpdate(tile); - }); - } - - LightUpdater.getInstance() - .onLightUpdate(world, type, pos.asLong()); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.java new file mode 100644 index 000000000..151a0a7c6 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/mixin/ModelDataRefreshMixin.java @@ -0,0 +1,37 @@ +package com.simibubi.create.foundation.mixin; + +import com.simibubi.create.content.schematics.SchematicWorld; + +import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.client.model.ModelDataManager; + +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 net.minecraft.client.Minecraft; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +@Mixin(ModelDataManager.class) +public class ModelDataRefreshMixin { + + /** + * Normally ModelDataManager will throw an exception if a tile entity tries + * to refresh its model data from a world the client isn't currently in, + * but we need that to not happen for tile entities in fake schematic + * worlds, so in those cases just do nothing instead. + */ + @Inject(at = @At("HEAD"), method = "requestModelDataRefresh", cancellable = true, remap = false) + private static void requestModelDataRefresh(TileEntity te, CallbackInfo ci) { + if (te != null) { + World world = te.getWorld(); + if (world != Minecraft.getInstance().world && world instanceof SchematicWorld) + ci.cancel(); + } + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java deleted file mode 100644 index 06ddf0c30..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/NetworkLightUpdateMixin.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.simibubi.create.foundation.mixin; - -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.CreateClient; -import com.simibubi.create.foundation.render.backend.RenderWork; -import com.simibubi.create.foundation.render.backend.light.LightUpdater; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.network.play.ClientPlayNetHandler; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.network.play.server.SUpdateLightPacket; -import net.minecraft.world.chunk.Chunk; - -@Mixin(ClientPlayNetHandler.class) -public class NetworkLightUpdateMixin { - - @Inject(at = @At("TAIL"), method = "handleUpdateLight") - private void onLightPacket(SUpdateLightPacket packet, CallbackInfo ci) { - RenderWork.enqueue(() -> { - ClientWorld world = Minecraft.getInstance().world; - - if (world == null) - return; - - int chunkX = packet.getChunkX(); - int chunkZ = packet.getChunkZ(); - - Chunk chunk = world.getChunkProvider() - .getChunk(chunkX, chunkZ, false); - - if (chunk != null) { - chunk.getTileEntityMap() - .values() - .forEach(tile -> { - CreateClient.kineticRenderer.get(world) - .onLightUpdate(tile); - }); - } - - LightUpdater.getInstance() - .onLightPacket(world, chunkX, chunkZ); - }); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java deleted file mode 100644 index da41425e6..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/RenderHooksMixin.java +++ /dev/null @@ -1,93 +0,0 @@ -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.KineticRenderer; -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.block.BlockState; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.LightTexture; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.WorldRenderer; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3d; -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("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(Backend.projectionMatrix); - - FastRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ); - - ContraptionRenderDispatcher.renderLayer(type, viewProjection, camX, camY, camZ); - - GL20.glUseProgram(0); - } - - @Inject(at = @At(value = "INVOKE", target = "net.minecraft.client.renderer.WorldRenderer.updateChunks(J)V"), method = "render") - private void setupFrame(MatrixStack p_228426_1_, float p_228426_2_, long p_228426_3_, boolean p_228426_5_, - ActiveRenderInfo info, GameRenderer p_228426_7_, LightTexture p_228426_8_, Matrix4f p_228426_9_, - CallbackInfo ci) { - Vector3d cameraPos = info.getProjectedView(); - double camX = cameraPos.getX(); - double camY = cameraPos.getY(); - double camZ = cameraPos.getZ(); - - CreateClient.kineticRenderer.get(world) - .beginFrame(info, camX, camY, camZ); - ContraptionRenderDispatcher.beginFrame(info, camX, camY, camZ); - } - - @Inject(at = @At("TAIL"), method = "scheduleBlockRerenderIfNeeded") - private void checkUpdate(BlockPos pos, BlockState lastState, BlockState newState, CallbackInfo ci) { - CreateClient.kineticRenderer.get(world) - .update(world.getTileEntity(pos)); - } - - @Inject(at = @At("TAIL"), method = "loadRenderers") - private void refresh(CallbackInfo ci) { - ContraptionRenderDispatcher.invalidateAll(); - OptifineHandler.refresh(); - Backend.refresh(); - - if (Backend.canUseInstancing() && world != null) { - KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world); - kineticRenderer.invalidate(); - world.loadedTileEntityList.forEach(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 deleted file mode 100644 index d779d6582..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/ShaderCloseMixin.java +++ /dev/null @@ -1,35 +0,0 @@ -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/mixin/StoreProjectionMatrixMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/StoreProjectionMatrixMixin.java deleted file mode 100644 index 7b1d5c7cd..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/StoreProjectionMatrixMixin.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.simibubi.create.foundation.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -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.foundation.render.backend.Backend; - -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.util.math.vector.Matrix4f; - -@Mixin(GameRenderer.class) -public class StoreProjectionMatrixMixin { - - @Unique - private boolean shouldCopy = false; - - /** - * We only want to copy the projection matrix if it is going to be used to render the world. - * We don't care about the mat for your hand. - */ - @Inject(method = "renderWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/GameRenderer;loadProjectionMatrix(Lnet/minecraft/util/math/vector/Matrix4f;)V")) - private void projectionMatrixReady(float p_228378_1_, long p_228378_2_, MatrixStack p_228378_4_, CallbackInfo ci) { - shouldCopy = true; - } - - @Inject(method = "loadProjectionMatrix", at = @At("TAIL")) - private void onProjectionMatrixLoad(Matrix4f projection, CallbackInfo ci) { - if (shouldCopy) { - Backend.projectionMatrix = projection.copy(); - shouldCopy = false; - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/TileRemoveMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/TileRemoveMixin.java deleted file mode 100644 index b2907a127..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/TileRemoveMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -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.CreateClient; - -import net.minecraft.client.world.ClientWorld; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; - -@Mixin(TileEntity.class) -public class TileRemoveMixin { - - @Shadow - @Nullable - protected World world; - - @Inject(at = @At("TAIL"), method = "remove") - private void onRemove(CallbackInfo ci) { - if (world instanceof ClientWorld) - CreateClient.kineticRenderer.get(this.world) - .remove((TileEntity) (Object) this); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/TileWorldHookMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/TileWorldHookMixin.java deleted file mode 100644 index a50fbc6ec..000000000 --- a/src/main/java/com/simibubi/create/foundation/mixin/TileWorldHookMixin.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.simibubi.create.foundation.mixin; - -import java.util.Set; - -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.CallbackInfoReturnable; - -import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.render.KineticRenderer; - -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -@Mixin(value = World.class, priority = 1100) // this and create.mixins.json have high priority to load after Performant -public class TileWorldHookMixin { - - final World self = (World) (Object) this; - - @Shadow - @Final - public boolean isRemote; - - @Shadow - @Final - protected Set tileEntitiesToBeRemoved; - - @Inject(at = @At("TAIL"), method = "addTileEntity") - private void onAddTile(TileEntity te, CallbackInfoReturnable cir) { - if (isRemote) { - CreateClient.kineticRenderer.get(self) - .queueAdd(te); - } - } - - /** - * Without this we don't unload instances when a chunk unloads. - */ - @Inject(at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V", ordinal = 0), method = "tickBlockEntities") - private void onChunkUnload(CallbackInfo ci) { - if (isRemote) { - KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(self); - for (TileEntity tile : tileEntitiesToBeRemoved) { - kineticRenderer.remove(tile); - } - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java b/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java index 5008129b3..21ed291ff 100644 --- a/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java +++ b/src/main/java/com/simibubi/create/foundation/mixin/WindowResizeMixin.java @@ -22,8 +22,7 @@ public class WindowResizeMixin { @Inject(at = @At("TAIL"), method = "updateWindowSize") private void updateWindowSize(CallbackInfo ci) { - if (UIRenderHelper.framebuffer != null) - UIRenderHelper.framebuffer.func_216491_a(mainWindow.getFramebufferWidth(), mainWindow.getFramebufferHeight(), Minecraft.IS_RUNNING_ON_MAC); + UIRenderHelper.updateWindowSize(mainWindow); } } 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 faa37475d..3bd14eedd 100644 --- a/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java +++ b/src/main/java/com/simibubi/create/foundation/networking/AllPackets.java @@ -21,13 +21,17 @@ import com.simibubi.create.content.contraptions.components.structureMovement.tra import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartControllerUpdatePacket; import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket; import com.simibubi.create.content.contraptions.relays.advanced.sequencer.ConfigureSequencedGearshiftPacket; +import com.simibubi.create.content.curiosities.projector.ConfigureProjectorPacket; import com.simibubi.create.content.curiosities.symmetry.SymmetryEffectPacket; +import com.simibubi.create.content.curiosities.tools.BlueprintAssignCompleteRecipePacket; import com.simibubi.create.content.curiosities.tools.ExtendoGripInteractionPacket; import com.simibubi.create.content.curiosities.zapper.ZapperBeamPacket; import com.simibubi.create.content.logistics.block.depot.EjectorElytraPacket; import com.simibubi.create.content.logistics.block.depot.EjectorPlacementPacket; import com.simibubi.create.content.logistics.block.depot.EjectorTriggerPacket; import com.simibubi.create.content.logistics.block.mechanicalArm.ArmPlacementPacket; +import com.simibubi.create.content.logistics.item.LinkedControllerBindPacket; +import com.simibubi.create.content.logistics.item.LinkedControllerInputPacket; 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; @@ -38,9 +42,11 @@ 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.SConfigureConfigPacket; import com.simibubi.create.foundation.command.HighlightPacket; +import com.simibubi.create.foundation.command.SConfigureConfigPacket; import com.simibubi.create.foundation.config.ui.CConfigureConfigPacket; +import com.simibubi.create.foundation.gui.ClearContainerPacket; +import com.simibubi.create.foundation.gui.GhostItemSubmitPacket; 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; @@ -64,9 +70,11 @@ public enum AllPackets { CONFIGURE_FLEXCRATE(ConfigureFlexcratePacket.class, ConfigureFlexcratePacket::new, PLAY_TO_SERVER), CONFIGURE_STOCKSWITCH(ConfigureStockswitchPacket.class, ConfigureStockswitchPacket::new, PLAY_TO_SERVER), CONFIGURE_SEQUENCER(ConfigureSequencedGearshiftPacket.class, ConfigureSequencedGearshiftPacket::new, - PLAY_TO_SERVER), + PLAY_TO_SERVER), + CONFIGURE_PROJECTOR(ConfigureProjectorPacket.class, ConfigureProjectorPacket::new, PLAY_TO_SERVER), PLACE_SCHEMATIC(SchematicPlacePacket.class, SchematicPlacePacket::new, PLAY_TO_SERVER), UPLOAD_SCHEMATIC(SchematicUploadPacket.class, SchematicUploadPacket::new, PLAY_TO_SERVER), + CLEAR_CONTAINER(ClearContainerPacket.class, ClearContainerPacket::new, PLAY_TO_SERVER), CONFIGURE_FILTER(FilterScreenPacket.class, FilterScreenPacket::new, PLAY_TO_SERVER), CONFIGURE_FILTERING_AMOUNT(FilteringCountUpdatePacket.class, FilteringCountUpdatePacket::new, PLAY_TO_SERVER), CONFIGURE_SCROLLABLE(ScrollValueUpdatePacket.class, ScrollValueUpdatePacket::new, PLAY_TO_SERVER), @@ -81,7 +89,11 @@ public enum AllPackets { PLACE_EJECTOR(EjectorPlacementPacket.class, EjectorPlacementPacket::new, PLAY_TO_SERVER), TRIGGER_EJECTOR(EjectorTriggerPacket.class, EjectorTriggerPacket::new, PLAY_TO_SERVER), EJECTOR_ELYTRA(EjectorElytraPacket.class, EjectorElytraPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_INPUT(LinkedControllerInputPacket.class, LinkedControllerInputPacket::new, PLAY_TO_SERVER), + LINKED_CONTROLLER_BIND(LinkedControllerBindPacket.class, LinkedControllerBindPacket::new, PLAY_TO_SERVER), C_CONFIGURE_CONFIG(CConfigureConfigPacket.class, CConfigureConfigPacket::new, PLAY_TO_SERVER), + SUBMIT_GHOST_ITEM(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new, PLAY_TO_SERVER), + BLUEPRINT_COMPLETE_RECIPE(BlueprintAssignCompleteRecipePacket.class, BlueprintAssignCompleteRecipePacket::new, PLAY_TO_SERVER), // Server to Client SYMMETRY_EFFECT(SymmetryEffectPacket.class, SymmetryEffectPacket::new, PLAY_TO_CLIENT), @@ -100,6 +112,7 @@ public enum AllPackets { BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT), TUNNEL_FLAP(TunnelFlapPacket.class, TunnelFlapPacket::new, PLAY_TO_CLIENT), FUNNEL_FLAP(FunnelFlapPacket.class, FunnelFlapPacket::new, PLAY_TO_CLIENT), + PERSISTENT_DATA(ISyncPersistentData.Packet.class, ISyncPersistentData.Packet::new, PLAY_TO_CLIENT), ; diff --git a/src/main/java/com/simibubi/create/foundation/networking/ISyncPersistentData.java b/src/main/java/com/simibubi/create/foundation/networking/ISyncPersistentData.java new file mode 100644 index 000000000..f8d30dd44 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/networking/ISyncPersistentData.java @@ -0,0 +1,64 @@ +package com.simibubi.create.foundation.networking; + +import java.util.Iterator; +import java.util.function.Supplier; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent.Context; +import net.minecraftforge.fml.network.PacketDistributor; + +public interface ISyncPersistentData { + + void onPersistentDataUpdated(); + + default void syncPersistentDataWithTracking(Entity self) { + AllPackets.channel.send(PacketDistributor.TRACKING_ENTITY.with(() -> self), new Packet(self)); + } + + public static class Packet extends SimplePacketBase { + + private int entityId; + private Entity entity; + private CompoundNBT readData; + + public Packet(Entity entity) { + this.entity = entity; + this.entityId = entity.getEntityId(); + } + + public Packet(PacketBuffer buffer) { + entityId = buffer.readInt(); + readData = buffer.readCompoundTag(); + } + + @Override + public void write(PacketBuffer buffer) { + buffer.writeInt(entityId); + buffer.writeCompoundTag(entity.getPersistentData()); + } + + @Override + public void handle(Supplier context) { + context.get() + .enqueueWork(() -> { + Entity entityByID = Minecraft.getInstance().world.getEntityByID(entityId); + if (!(entityByID instanceof ISyncPersistentData)) + return; + CompoundNBT data = entityByID.getPersistentData(); + for (Iterator iterator = data.keySet() + .iterator(); iterator.hasNext(); ) { + data.remove(iterator.next()); + } + data.merge(readData); + ((ISyncPersistentData) entityByID).onPersistentDataUpdated(); + }); + context.get() + .setPacketHandled(true); + } + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java index d2c25f25f..bcaf05352 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderProgressBar.java @@ -95,12 +95,12 @@ public class PonderProgressBar extends AbstractSimiWidget { new BoxElement() .withBackground(Theme.c(Theme.Key.PONDER_BACKGROUND_FLAT)) .gradientBorder(Theme.p(Theme.Key.PONDER_IDLE)) - .at(x, y, 250) + .at(x, y, 300) .withBounds(width, height) .render(ms); ms.push(); - ms.translate(x - 2, y - 2, 150); + ms.translate(x - 2, y - 2, 200); ms.push(); ms.scale((width + 4) * progress.getValue(partialTicks), 1, 1); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistry.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistry.java index 412eb6ae8..06348383c 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistry.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderRegistry.java @@ -113,7 +113,7 @@ public class PonderRegistry { InputStream resourceAsStream = Create.class.getClassLoader() .getResourceAsStream(filepath); if (resourceAsStream == null) { - Create.logger.error("Ponder schematic missing: " + path); + Create.LOGGER.error("Ponder schematic missing: " + path); return t; } try (DataInputStream stream = @@ -121,7 +121,7 @@ public class PonderRegistry { CompoundNBT nbt = CompressedStreamTools.read(stream, new NBTSizeTracker(0x20000000L)); t.read(nbt); } catch (IOException e) { - Create.logger.warn("Failed to read ponder schematic", e); + Create.LOGGER.warn("Failed to read ponder schematic", e); } return t; } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java index b3a9173b2..a970431bd 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderScene.java @@ -233,8 +233,9 @@ public class PonderScene { for (RenderType type : RenderType.getBlockLayers()) forEachVisible(PonderSceneElement.class, e -> e.renderLayer(world, buffer, type, ms, pt)); + forEachVisible(PonderSceneElement.class, e -> e.renderLast(world, buffer, ms, pt)); - info.set(transform.xRotation.getValue(pt), transform.yRotation.getValue(pt)); + info.set(transform.xRotation.getValue(pt) + 90, transform.yRotation.getValue(pt) + 180); world.renderEntities(ms, buffer, info, pt); world.renderParticles(ms, buffer, info, pt); outliner.renderOutlines(ms, buffer, pt); @@ -524,4 +525,4 @@ public class PonderScene { this.finished = finished; } -} \ No newline at end of file +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java index 7f0e951fd..cd8f2fe1d 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderUI.java @@ -2,7 +2,7 @@ package com.simibubi.create.foundation.ponder; import static com.simibubi.create.foundation.ponder.PonderLocalization.LANG_PREFIX; -import java.awt.Color; +import java.awt.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -536,6 +536,8 @@ public class PonderUI extends NavigatableSimiScreen { } protected void renderWidgets(MatrixStack ms, int mouseX, int mouseY, float partialTicks) { + RenderSystem.disableDepthTest(); + float fade = fadeIn.getValue(partialTicks); float lazyIndexValue = lazyIndex.getValue(partialTicks); float indexDiff = Math.abs(lazyIndexValue - index); @@ -549,7 +551,7 @@ public class PonderUI extends NavigatableSimiScreen { { // Chapter title ms.push(); - ms.translate(0, 0, 100); + ms.translate(0, 0, 400); int x = 31 + 20 + 8; int y = 31; @@ -693,7 +695,7 @@ public class PonderUI extends NavigatableSimiScreen { chase.tickChaser(); - if (highlightAll || sceneTags.contains(this.tags.get(i))) + if (highlightAll) button.flash(); else button.dim(); @@ -735,6 +737,8 @@ public class PonderUI extends NavigatableSimiScreen { if (PonderIndex.EDITOR_MODE && userMode.isHovered()) drawCenteredString(ms, textRenderer, "Editor View", userMode.x + 10, tooltipY, tooltipColor); ms.pop(); + + RenderSystem.enableDepthTest(); } private void renderOverlay(MatrixStack ms, int i, float partialTicks) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java index b6f5b5f84..83a8d7f46 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorld.java @@ -9,6 +9,7 @@ import java.util.Map; import javax.annotation.Nullable; import com.mojang.blaze3d.matrix.MatrixStack; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; import com.simibubi.create.content.contraptions.relays.belt.BeltBlock; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.schematics.SchematicWorld; @@ -104,15 +105,26 @@ public class PonderWorld extends SchematicWorld { originalEntities.forEach(e -> EntityType.loadEntityUnchecked(e.serializeNBT(), this) .ifPresent(entities::add)); particles.clearEffects(); - fixBeltTileEntities(); + fixControllerTileEntities(); } public void restoreBlocks(Selection selection) { selection.forEach(p -> { if (originalBlocks.containsKey(p)) blocks.put(p, originalBlocks.get(p)); + if (originalTileEntities.containsKey(p)) { + TileEntity te = TileEntity.createFromTag(originalBlocks.get(p), originalTileEntities.get(p) + .write(new CompoundNBT())); + onTEadded(te, te.getPos()); + tileEntities.put(p, te); + } }); - scene.forEach(WorldSectionElement.class, WorldSectionElement::queueRedraw); + redraw(); + } + + private void redraw() { + if (scene != null) + scene.forEach(WorldSectionElement.class, WorldSectionElement::queueRedraw); } public void pushFakeLight(int light) { @@ -226,6 +238,11 @@ public class PonderWorld extends SchematicWorld { : iparticlefactory.makeParticle(data, asClientWorld.getValue(), x, y, z, mx, my, mz); } + @Override + public boolean setBlockState(BlockPos pos, BlockState arg1, int arg2) { + return super.setBlockState(pos, arg1, arg2); + } + public void addParticle(Particle p) { if (p != null) particles.addParticle(p); @@ -240,20 +257,34 @@ public class PonderWorld extends SchematicWorld { smartTileEntity.markVirtual(); } - public void fixBeltTileEntities() { + public void fixControllerTileEntities() { for (TileEntity tileEntity : tileEntities.values()) { - if (!(tileEntity instanceof BeltTileEntity)) - continue; - BeltTileEntity beltTileEntity = (BeltTileEntity) tileEntity; - if (!beltTileEntity.isController()) - continue; - BlockPos controllerPos = tileEntity.getPos(); - for (BlockPos blockPos : BeltBlock.getBeltChain(this, controllerPos)) { - TileEntity tileEntity2 = getTileEntity(blockPos); - if (!(tileEntity2 instanceof BeltTileEntity)) + if (tileEntity instanceof BeltTileEntity) { + BeltTileEntity beltTileEntity = (BeltTileEntity) tileEntity; + if (!beltTileEntity.isController()) continue; - BeltTileEntity belt2 = (BeltTileEntity) tileEntity2; - belt2.setController(controllerPos); + BlockPos controllerPos = tileEntity.getPos(); + for (BlockPos blockPos : BeltBlock.getBeltChain(this, controllerPos)) { + TileEntity tileEntity2 = getTileEntity(blockPos); + if (!(tileEntity2 instanceof BeltTileEntity)) + continue; + BeltTileEntity belt2 = (BeltTileEntity) tileEntity2; + belt2.setController(controllerPos); + } + } + if (tileEntity instanceof FluidTankTileEntity) { + FluidTankTileEntity fluidTankTileEntity = (FluidTankTileEntity) tileEntity; + BlockPos lastKnown = fluidTankTileEntity.getLastKnownPos(); + BlockPos current = fluidTankTileEntity.getPos(); + if (lastKnown == null || current == null) + continue; + if (fluidTankTileEntity.isController()) + continue; + if (!lastKnown.equals(current)) { + BlockPos newControllerPos = fluidTankTileEntity.getController() + .add(current.subtract(lastKnown)); + fluidTankTileEntity.setController(newControllerPos); + } } } } @@ -303,6 +334,11 @@ public class PonderWorld extends SchematicWorld { return state; } + @Override + public boolean isBlockLoaded(BlockPos pos) { + return true; // fix particle lighting + } + @Override public boolean chunkExists(int x, int y) { return true; // fix particle lighting diff --git a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java index 3ff9774bb..6fad6cdb3 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/PonderWorldParticles.java @@ -73,13 +73,11 @@ public class PonderWorldParticles { RenderSystem.pushMatrix(); RenderSystem.multMatrix(ms.peek() .getModel()); - // check ParticleManager#renderParticles for a replacement if RenderSystem#multMatrix gets removed - for (IParticleRenderType iparticlerendertype : this.byType.keySet()) { // Forge: allow custom - // IParticleRenderType's + for (IParticleRenderType iparticlerendertype : this.byType.keySet()) { if (iparticlerendertype == IParticleRenderType.NO_RENDER) continue; - enable.run(); // Forge: MC-168672 Make sure all render types have the correct GL state. + enable.run(); Iterable iterable = this.byType.get(iparticlerendertype); if (iterable != null) { RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); @@ -96,6 +94,7 @@ public class PonderWorldParticles { RenderSystem.popMatrix(); RenderSystem.depthMask(true); + RenderSystem.depthFunc(515); RenderSystem.disableBlend(); RenderSystem.defaultAlphaFunc(); lightTexture.disableLightmap(); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java index 2767b1b02..eaf8c3532 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/SceneBuilder.java @@ -14,6 +14,8 @@ import com.simibubi.create.content.contraptions.components.crafter.ConnectedInpu import com.simibubi.create.content.contraptions.components.crafter.MechanicalCrafterTileEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueEntity; import com.simibubi.create.content.contraptions.components.structureMovement.glue.SuperGlueItem; +import com.simibubi.create.content.contraptions.fluids.FluidPropagator; +import com.simibubi.create.content.contraptions.fluids.PumpTileEntity; import com.simibubi.create.content.contraptions.particle.RotationIndicatorParticleData; import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity; import com.simibubi.create.content.contraptions.relays.gauge.SpeedGaugeTileEntity; @@ -739,6 +741,10 @@ public class SceneBuilder { }); } + public void propagatePipeChange(BlockPos pos) { + modifyTileEntity(pos, PumpTileEntity.class, te -> te.onSpeedChanged(0)); + } + public void setFilterData(Selection selection, Class teType, ItemStack filter) { modifyTileNBT(selection, teType, nbt -> { nbt.put("Filter", filter.serializeNBT()); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java index 843f8a622..34d878e95 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BearingScenes.java @@ -46,6 +46,7 @@ public class BearingScenes { scene.overlay.showSelectionWithText(util.select.position(anchorPos), 60) .colored(PonderPalette.GREEN) .pointAt(util.vector.blockSurface(windmill, Direction.WEST)) + .attachKeyFrame() .placeNearTarget() .text("Windmill Bearings attach to the block in front of them"); scene.idle(50); @@ -88,6 +89,7 @@ public class BearingScenes { scene.overlay.showText(60) .pointAt(util.vector.blockSurface(anchorPos, Direction.NORTH)) + .attachKeyFrame() .placeNearTarget() .text("If enough Sail-like blocks are attached to the block, it can act as a Windmill"); scene.idle(70); @@ -109,6 +111,7 @@ public class BearingScenes { scene.overlay.showText(60) .pointAt(util.vector.topOf(windmill)) .placeNearTarget() + .attachKeyFrame() .text("Activated with Right-Click, the Windmill Bearing will start providing Rotational Force"); scene.idle(70); @@ -125,6 +128,7 @@ public class BearingScenes { scene.overlay.showCenteredScrollInput(windmill, Direction.WEST, 50); scene.overlay.showText(60) .pointAt(surface) + .attachKeyFrame() .placeNearTarget() .text("Use a Wrench to configure its rotation direction"); scene.idle(36); @@ -184,6 +188,7 @@ public class BearingScenes { scene.overlay.showOutline(PonderPalette.BLUE, bearingPos, util.select.fromTo(3, 2, 1, 3, 3, 2), 80); scene.overlay.showSelectionWithText(util.select.fromTo(3, 2, 4, 3, 3, 5), 80) .colored(PonderPalette.BLUE) + .attachKeyFrame() .text("Any Structure can count as a valid Windmill, as long as it contains at least 8 sail-like Blocks."); scene.idle(90); @@ -225,6 +230,7 @@ public class BearingScenes { .colored(PonderPalette.GREEN) .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) .placeNearTarget() + .attachKeyFrame() .text("Mechanical Bearings attach to the block in front of them"); scene.idle(50); @@ -245,6 +251,7 @@ public class BearingScenes { scene.overlay.showText(80) .pointAt(util.vector.topOf(bearingPos.up())) .placeNearTarget() + .attachKeyFrame() .text("Upon receiving Rotational Force, it will assemble it into a Rotating Contraption"); scene.idle(37 * 2); scene.world.setKineticSpeed(all, 0); @@ -273,6 +280,7 @@ public class BearingScenes { scene.overlay.showText(120) .pointAt(util.vector.topOf(bearingPos.up())) .placeNearTarget() + .attachKeyFrame() .sharedText("movement_anchors"); scene.idle(37 * 4); @@ -331,6 +339,7 @@ public class BearingScenes { .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) .placeNearTarget() .colored(PonderPalette.RED) + .attachKeyFrame() .text("When Stopped, the Bearing will place the structure at the nearest grid-aligned Angle"); scene.idle(110); @@ -343,6 +352,7 @@ public class BearingScenes { scene.overlay.showText(60) .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) .placeNearTarget() + .attachKeyFrame() .sharedText("behaviour_modify_wrench"); scene.idle(70); @@ -389,6 +399,7 @@ public class BearingScenes { scene.overlay.showSelectionWithText(util.select.position(bearingPos), 60) .text("Whenever Mechanical Bearings are themselves part of a moving Structure..") + .attachKeyFrame() .placeNearTarget(); scene.idle(70); @@ -410,6 +421,7 @@ public class BearingScenes { scene.overlay.showSelectionWithText(util.select.position(bearingPos.north()), 60) .colored(PonderPalette.GREEN) .text("Once again, the bearing will attach to the block in front of it") + .attachKeyFrame() .placeNearTarget(); scene.idle(70); @@ -455,6 +467,7 @@ public class BearingScenes { .colored(PonderPalette.GREEN) .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) .placeNearTarget() + .attachKeyFrame() .text("Clockwork Bearings attach to blocks in front of them"); scene.idle(50); @@ -472,6 +485,7 @@ public class BearingScenes { scene.overlay.showText(80) .pointAt(util.vector.blockSurface(bearingPos.north(), Direction.NORTH)) .placeNearTarget() + .attachKeyFrame() .text("Upon receiving Rotational Force, the structure will be rotated according to the hour of the day"); scene.idle(90); @@ -501,6 +515,7 @@ public class BearingScenes { scene.overlay.showText(60) .pointAt(util.vector.blockSurface(bearingPos, Direction.WEST)) .placeNearTarget() + .attachKeyFrame() .text("Right-Click the bearing to start or stop animating the structure"); scene.idle(70); @@ -513,6 +528,7 @@ public class BearingScenes { scene.idle(15); scene.overlay.showSelectionWithText(util.select.fromTo(3, 3, 1, 3, 4, 2), 80) .placeNearTarget() + .attachKeyFrame() .sharedText("movement_anchors"); scene.idle(90); @@ -525,6 +541,7 @@ public class BearingScenes { scene.overlay.showSelectionWithText(util.select.position(bearingPos.north(3)), 80) .placeNearTarget() .colored(PonderPalette.BLUE) + .attachKeyFrame() .text("In front of the Hour Hand, a second structure can be added"); scene.idle(90); scene.overlay.showControls(clickTheBearingSide.rightClick(), 20); @@ -618,7 +635,7 @@ public class BearingScenes { .placeNearTarget(); scene.idle(40); scene.world.configureCenterOfRotation(plank, util.vector.centerOf(bearingPos)); - + if (!frame) { scene.world.rotateBearing(bearingPos, 180, 75); scene.world.rotateSection(plank, 0, 180, 0, 75); @@ -628,26 +645,26 @@ public class BearingScenes { scene.rotateCameraY(-30); scene.idle(10); InputWindowElement input = - new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.NORTH), Pointing.RIGHT) - .withItem(new ItemStack(Items.BLUE_DYE)); + new InputWindowElement(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.NORTH), Pointing.RIGHT) + .withItem(new ItemStack(Items.BLUE_DYE)); scene.overlay.showControls(input, 30); scene.idle(7); - scene.world.setBlock(util.grid.at(2, 3, 1), AllBlocks.DYED_SAILS[DyeColor.BLUE.ordinal()].getDefaultState() - .with(SailBlock.FACING, Direction.WEST), false); + scene.world.setBlock(util.grid.at(2, 3, 1), AllBlocks.DYED_SAILS.get(DyeColor.BLUE).getDefaultState() + .with(SailBlock.FACING, Direction.WEST), false); scene.idle(10); scene.overlay.showText(40) - .colored(PonderPalette.BLUE) - .text("Right-Click with Dye to paint them") - .attachKeyFrame() - .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.WEST)) - .placeNearTarget(); + .colored(PonderPalette.BLUE) + .text("Right-Click with Dye to paint them") + .attachKeyFrame() + .pointAt(util.vector.blockSurface(util.grid.at(2, 3, 1), Direction.WEST)) + .placeNearTarget(); scene.idle(20); scene.overlay.showControls(input, 30); scene.idle(7); scene.world.replaceBlocks(util.select.fromTo(2, 2, 1, 2, 4, 1), - AllBlocks.DYED_SAILS[DyeColor.BLUE.ordinal()].getDefaultState() - .with(SailBlock.FACING, Direction.WEST), - false); + AllBlocks.DYED_SAILS.get(DyeColor.BLUE).getDefaultState() + .with(SailBlock.FACING, Direction.WEST), + false); scene.idle(20); scene.world.rotateBearing(bearingPos, 90, 33); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java index dbaeb1718..a2d45e769 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/BeltScenes.java @@ -87,6 +87,7 @@ public class BeltScenes { scene.overlay.showText(80) .text("Right-Clicking two shafts with a belt item will connect them together") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.topOf(2, 1, 2)); scene.idle(90); @@ -100,6 +101,7 @@ public class BeltScenes { scene.overlay.showText(80) .colored(PonderPalette.RED) .text("Accidental selections can be canceled with Right-Click while Sneaking") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.centerOf(backEnd.south(1))); scene.idle(43); @@ -118,6 +120,7 @@ public class BeltScenes { scene.overlay.showText(43) .text("Additional Shafts can be added throughout the Belt") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(shaftLocation, Direction.NORTH)); scene.idle(50); @@ -146,6 +149,7 @@ public class BeltScenes { scene.idle(10); scene.overlay.showText(50) .text("Added shafts can be removed using the wrench") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(shaftLocation, Direction.NORTH)); scene.idle(70); @@ -212,6 +216,7 @@ public class BeltScenes { .colored(PonderPalette.GREEN) .placeNearTarget() .pointAt(to) + .attachKeyFrame() .text("1. They can connect horizontally"); scene.idle(20); @@ -236,6 +241,7 @@ public class BeltScenes { .colored(PonderPalette.GREEN) .placeNearTarget() .pointAt(to) + .attachKeyFrame() .text("2. They can connect diagonally"); scene.idle(20); @@ -258,6 +264,7 @@ public class BeltScenes { .colored(PonderPalette.GREEN) .placeNearTarget() .pointAt(to) + .attachKeyFrame() .text("3. They can connect vertically"); scene.idle(20); @@ -282,6 +289,7 @@ public class BeltScenes { .colored(PonderPalette.GREEN) .placeNearTarget() .pointAt(to) + .attachKeyFrame() .text("4. And they can connect vertical shafts horizontally"); scene.idle(20); @@ -375,6 +383,7 @@ public class BeltScenes { scene.overlay.showText(60) .placeNearTarget() .pointAt(topOf.subtract(0, 0.1, 0)) + .attachKeyFrame() .text("Right-Click with an empty hand to take items off a belt"); scene.idle(20); scene.world.removeItemsFromBelt(util.grid.at(3, 2, 2)); @@ -425,6 +434,7 @@ public class BeltScenes { scene.overlay.showText(80) .text("Brass or Andesite Casing can be used to decorate Mechanical Belts") + .attachKeyFrame() .pointAt(util.vector.centerOf(beltPos2)); scene.idle(40); @@ -455,6 +465,7 @@ public class BeltScenes { scene.world.modifyBlock(pos, s -> s.with(BeltBlock.CASING, true), true); } scene.idle(30); + scene.addKeyframe(); scene.overlay .showControls(new InputWindowElement(util.vector.topOf(beltPos.south()), Pointing.DOWN).rightClick() diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java index 168e171c2..b20d88216 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/ChainDriveScenes.java @@ -50,6 +50,7 @@ public class ChainDriveScenes { scene.idle(20); scene.overlay.showText(60) .text("Chain Drives relay rotation to each other in a row") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 4), Direction.WEST)); scene.idle(60); @@ -65,12 +66,14 @@ public class ChainDriveScenes { scene.idle(20); scene.overlay.showText(60) .text("All shafts connected like this will rotate in the same direction") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(util.grid.at(2, 1, 1), Direction.WEST)); scene.idle(50); scene.world.hideSection(shafts, Direction.WEST); scene.idle(25); + scene.addKeyframe(); scene.overlay.showControls(new InputWindowElement(util.vector.topOf(rotatedECD), Pointing.DOWN).rightClick() .withWrench(), 30); scene.idle(7); @@ -116,7 +119,8 @@ public class ChainDriveScenes { scene.idle(10); scene.overlay.showText(60) - .text("Unpowered Chain Gearshifts behave exacly like Chain Drives") + .text("Unpowered Chain Gearshifts behave exactly like Chain Drives") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(eastDrive, Direction.NORTH)); scene.idle(60); @@ -153,6 +157,7 @@ public class ChainDriveScenes { scene.overlay.showText(80) .text("When Powered, the speed transmitted to other Chain Drives in the row is doubled") + .attachKeyFrame() .placeNearTarget() .colored(PonderPalette.FAST) .pointAt(util.vector.blockSurface(eastDrive.west(2), Direction.WEST)); @@ -197,6 +202,7 @@ public class ChainDriveScenes { scene.overlay.showText(80) .text("Whenever the Powered Gearshift is not at the source, its speed will be halved instead") + .attachKeyFrame() .placeNearTarget() .colored(PonderPalette.SLOW) .pointAt(util.vector.blockSurface(eastDrive.west(2), Direction.WEST)); @@ -215,6 +221,7 @@ public class ChainDriveScenes { scene.overlay.showText(100) .text("In both cases, Chain Drives in the row always run at 2x the speed of the Powered Gearshift") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(eastDrive.west(2), Direction.WEST)); scene.idle(100); @@ -240,6 +247,7 @@ public class ChainDriveScenes { scene.overlay.showText(100) .text("Using analog signals, the ratio can be adjusted more precisely between 1 and 2") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(eastDrive.west(2), Direction.WEST)); scene.idle(40); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/DebugScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/DebugScenes.java index 30199ef5c..5261f9437 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/DebugScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/DebugScenes.java @@ -45,6 +45,7 @@ public class DebugScenes { add(DebugScenes::birbScene); add(DebugScenes::sectionsScene); add(DebugScenes::itemScene); + add(DebugScenes::pipeScene); } private static void add(PonderStoryBoard sb) { @@ -433,5 +434,17 @@ public class DebugScenes { scene.world.modifyEntities(ItemEntity.class, Entity::remove); } + + public static void pipeScene(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("debug_pipes", "Manipulating Items"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(10); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + + + + } } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/DeployerScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/DeployerScenes.java index 49af64c7c..89d1a3f96 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/DeployerScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/DeployerScenes.java @@ -1,10 +1,13 @@ package com.simibubi.create.foundation.ponder.content; +import com.simibubi.create.AllItems; import com.simibubi.create.content.contraptions.components.deployer.DeployerTileEntity; +import com.simibubi.create.content.curiosities.tools.SandPaperItem; import com.simibubi.create.foundation.ponder.ElementLink; import com.simibubi.create.foundation.ponder.SceneBuilder; import com.simibubi.create.foundation.ponder.SceneBuildingUtil; import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.elements.BeltItemElement; import com.simibubi.create.foundation.ponder.elements.EntityElement; import com.simibubi.create.foundation.ponder.elements.InputWindowElement; import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; @@ -303,6 +306,122 @@ public class DeployerScenes { } } + public static void processing(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("deployer_processing", "Processing Items using Deployers"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + + ElementLink depot = + scene.world.showIndependentSection(util.select.position(2, 1, 1), Direction.DOWN); + scene.world.moveSection(depot, util.vector.of(0, 0, 1), 0); + scene.idle(10); + + Selection pressS = util.select.position(2, 3, 2); + BlockPos pressPos = util.grid.at(2, 3, 2); + BlockPos depotPos = util.grid.at(2, 1, 1); + scene.world.setKineticSpeed(pressS, 0); + scene.world.showSection(pressS, Direction.DOWN); + scene.idle(10); + + scene.world.showSection(util.select.fromTo(2, 1, 3, 2, 1, 5), Direction.NORTH); + scene.idle(3); + scene.world.showSection(util.select.position(2, 2, 3), Direction.SOUTH); + scene.idle(3); + scene.world.showSection(util.select.position(2, 3, 3), Direction.NORTH); + scene.world.setKineticSpeed(pressS, -32); + scene.effects.indicateSuccess(pressPos); + scene.idle(10); + + ItemStack tool = AllItems.SAND_PAPER.asStack(); + scene.overlay.showControls(new InputWindowElement(util.vector.blockSurface(pressPos.down(), Direction.EAST) + .add(0, 0.15, 0), Pointing.RIGHT).withItem(tool), 30); + scene.idle(7); + scene.world.modifyTileNBT(pressS, DeployerTileEntity.class, nbt -> nbt.put("HeldItem", tool.serializeNBT())); + scene.idle(25); + + Vector3d pressSide = util.vector.blockSurface(pressPos, Direction.WEST); + scene.overlay.showText(60) + .pointAt(pressSide) + .placeNearTarget() + .attachKeyFrame() + .text("With a fitting held item, Deployers can process items provided beneath them"); + scene.idle(80); + + scene.overlay.showText(60) + .pointAt(pressSide.subtract(0, 2, 0)) + .placeNearTarget() + .text("The Input items can be dropped or placed on a Depot under the Deployer"); + scene.idle(50); + ItemStack quartz = AllItems.ROSE_QUARTZ.asStack(); + scene.world.createItemOnBeltLike(depotPos, Direction.NORTH, quartz); + Vector3d depotCenter = util.vector.centerOf(depotPos.south()); + scene.overlay.showControls(new InputWindowElement(depotCenter, Pointing.UP).withItem(quartz), 30); + scene.idle(10); + + Vector3d targetV = util.vector.centerOf(pressPos) + .subtract(0, 1.65, 0); + + scene.world.moveDeployer(pressPos, 1, 30); + scene.idle(30); + scene.world.moveDeployer(pressPos, -1, 30); + scene.debug.enqueueCallback(s -> SandPaperItem.spawnParticles(targetV, quartz, s.getWorld())); + // particle + scene.world.removeItemsFromBelt(depotPos); + ItemStack polished = AllItems.POLISHED_ROSE_QUARTZ.asStack(); + scene.world.createItemOnBeltLike(depotPos, Direction.UP, polished); + scene.idle(10); + scene.overlay.showControls(new InputWindowElement(depotCenter, Pointing.UP).withItem(polished), 50); + scene.idle(60); + + scene.world.hideIndependentSection(depot, Direction.NORTH); + scene.idle(5); + scene.world.showSection(util.select.fromTo(0, 1, 3, 0, 2, 3), Direction.DOWN); + scene.idle(10); + scene.world.showSection(util.select.fromTo(4, 1, 2, 0, 2, 2), Direction.SOUTH); + scene.idle(20); + BlockPos beltPos = util.grid.at(0, 1, 2); + scene.overlay.showText(40) + .pointAt(util.vector.blockSurface(beltPos, Direction.WEST)) + .placeNearTarget() + .attachKeyFrame() + .text("When items are provided on a belt..."); + scene.idle(30); + + ElementLink ingot = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, quartz); + scene.idle(15); + ElementLink ingot2 = scene.world.createItemOnBelt(beltPos, Direction.SOUTH, quartz); + scene.idle(15); + scene.world.stallBeltItem(ingot, true); + scene.world.moveDeployer(pressPos, 1, 30); + + scene.overlay.showText(50) + .pointAt(pressSide) + .placeNearTarget() + .attachKeyFrame() + .text("The Deployer will hold and process them automatically"); + + scene.idle(30); + scene.world.moveDeployer(pressPos, -1, 30); + scene.debug.enqueueCallback(s -> SandPaperItem.spawnParticles(targetV, quartz, s.getWorld())); + scene.world.removeItemsFromBelt(pressPos.down(2)); + ingot = scene.world.createItemOnBelt(pressPos.down(2), Direction.UP, polished); + scene.world.stallBeltItem(ingot, true); + scene.idle(15); + scene.world.stallBeltItem(ingot, false); + scene.idle(15); + scene.world.stallBeltItem(ingot2, true); + scene.world.moveDeployer(pressPos, 1, 30); + scene.idle(30); + scene.world.moveDeployer(pressPos, -1, 30); + scene.debug.enqueueCallback(s -> SandPaperItem.spawnParticles(targetV, quartz, s.getWorld())); + scene.world.removeItemsFromBelt(pressPos.down(2)); + ingot2 = scene.world.createItemOnBelt(pressPos.down(2), Direction.UP, polished); + scene.world.stallBeltItem(ingot2, true); + scene.idle(15); + scene.world.stallBeltItem(ingot2, false); + } + public static void redstone(SceneBuilder scene, SceneBuildingUtil util) { scene.title("deployer_redstone", "Controlling Deployers with Redstone"); scene.configureBasePlate(0, 0, 5); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java index 6a22d56ed..04ac6a0fe 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/FanScenes.java @@ -53,6 +53,7 @@ public class FanScenes { scene.overlay.showText(80) .text("Encased Fans use Rotational Force to create an Air Current") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.topOf(fanPos)); scene.idle(90); @@ -61,6 +62,7 @@ public class FanScenes { Selection reverse = util.select.fromTo(3, 1, 5, 1, 1, 4); scene.world.toggleRedstonePower(util.select.fromTo(leverPos, leverPos.down())); scene.effects.indicateRedstone(leverPos); + scene.addKeyframe(); scene.world.modifyKineticSpeed(reverse, f -> -f); scene.effects.rotationDirectionIndicator(fanPos.south()); scene.special.rotateParrot(flappyBirb, 0, 215 * 2, 0, 30); @@ -127,6 +129,7 @@ public class FanScenes { .colored(PonderPalette.WHITE) .pointAt(itemVec) .placeNearTarget() + .attachKeyFrame() .text("Items caught in the area will be smelted"); scene.idle(60); @@ -157,6 +160,7 @@ public class FanScenes { scene.overlay.showSelectionWithText(util.select.fromTo(blockPos, blockPos.west(2)), 60) .colored(PonderPalette.BLACK) + .attachKeyFrame() .text("Instead, a setup for Smoking using Fire should be used for them"); scene.idle(80); @@ -173,6 +177,7 @@ public class FanScenes { scene.overlay.showSelectionWithText(util.select.fromTo(blockPos, blockPos.west(2)), 60) .colored(PonderPalette.MEDIUM) + .attachKeyFrame() .text("Air Flows passing through water create a Washing Setup"); scene.idle(70); @@ -204,6 +209,7 @@ public class FanScenes { .colored(PonderPalette.RED) .pointAt(util.vector.topOf(blockPos.east())) .placeNearTarget() + .attachKeyFrame() .text("The Speed of the Fan does NOT affect the processing speed, only its range"); scene.world.destroyBlock(util.grid.at(1, 1, 2)); scene.idle(110); @@ -237,6 +243,7 @@ public class FanScenes { scene.effects.emitParticles(depotTop, Emitter.simple(ParticleTypes.SPIT, Vector3d.ZERO), .5f, 30); scene.overlay.showText(90) .pointAt(depotTop) + .attachKeyFrame() .text("Fan Processing can also be applied to Items on Depots and Belts"); scene.idle(100); @@ -272,11 +279,12 @@ public class FanScenes { scene.world.showSection(util.select.layersFrom(2), Direction.DOWN); scene.idle(10); BlockPos rightFan = util.grid.at(1, 2, 2); - scene.overlay.showText(80) + scene.overlay.showText(70) .text("Fans facing down into a source of heat can provide Rotational Force") .placeNearTarget() .pointAt(util.vector.blockSurface(rightFan, Direction.WEST)); scene.idle(80); + scene.addKeyframe(); for (BlockPos pos : new BlockPos[] { rightFan, util.grid.at(3, 2, 2) }) { scene.idle(10); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java index 030f0ce6e..366547173 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/FunnelScenes.java @@ -130,6 +130,7 @@ public class FunnelScenes { scene.world.showSection(topFunnelSelection, Direction.DOWN); scene.overlay.showText(80) .text("Placed normally, it pulls items from the inventory.") + .attachKeyFrame() .pointAt(topCenter) .placeNearTarget(); scene.idle(45); @@ -150,6 +151,7 @@ public class FunnelScenes { scene.overlay.showControls(controlsSneak, 35); scene.overlay.showText(80) .text("Placed while sneaking, it puts items into the inventory.") + .attachKeyFrame() .pointAt(topCenter) .placeNearTarget(); scene.idle(45); @@ -169,6 +171,7 @@ public class FunnelScenes { scene.idle(10); scene.overlay.showText(80) .text("Using a wrench, the funnel can be flipped after placement.") + .attachKeyFrame() .pointAt(topCenter) .placeNearTarget(); @@ -216,6 +219,7 @@ public class FunnelScenes { scene.world.showSection(beltFunnelSetup, Direction.DOWN); scene.overlay.showText(140) .text("Funnels on belts will extract/insert depending on its movement direction.") + .attachKeyFrame() .pointAt(topOfBeltFunnel); scene.idle(15); @@ -263,6 +267,7 @@ public class FunnelScenes { scene.idle(8); scene.overlay.showText(360) .text("Funnels should also interact nicely with a handful of other components.") + .attachKeyFrame() .independent(0); scene.idle(40); @@ -368,6 +373,7 @@ public class FunnelScenes { scene.overlay.showText(60) .text("Andesite Funnels can only ever extract single items.") + .attachKeyFrame() .pointAt(util.vector.topOf(andesiteFunnel)) .placeNearTarget(); scene.idle(10); @@ -378,6 +384,7 @@ public class FunnelScenes { scene.overlay.showText(60) .text("Brass Funnels can extract up to a full stack.") + .attachKeyFrame() .pointAt(util.vector.topOf(brassFunnel)) .placeNearTarget(); scene.idle(10); @@ -393,6 +400,7 @@ public class FunnelScenes { scene.idle(10); scene.overlay.showText(80) .text("Scrolling on the filter slot allows for precise control over the extracted stack size.") + .attachKeyFrame() .pointAt(filterSlot.getCenter()) .placeNearTarget(); scene.idle(90); @@ -436,6 +444,7 @@ public class FunnelScenes { scene.idle(10); scene.overlay.showText(80) .text("Using items on the filter slot will restrict the funnel to only transfer matching stacks.") + .attachKeyFrame() .pointAt(filterSlot.getCenter()) .placeNearTarget(); scene.world.setFilterData(util.select.position(brassFunnel), FunnelTileEntity.class, emerald); @@ -470,6 +479,7 @@ public class FunnelScenes { scene.overlay.showSelectionWithText(funnelSelect, 40) .colored(PonderPalette.RED) .text("Funnels cannot ever transfer between closed inventories directly.") + .attachKeyFrame() .placeNearTarget(); scene.idle(50); @@ -483,6 +493,7 @@ public class FunnelScenes { scene.overlay.showText(40) .colored(PonderPalette.GREEN) .text("Chutes or Smart chutes might be more suitable for such purposes.") + .attachKeyFrame() .pointAt(util.vector.centerOf(funnelPos)) .placeNearTarget(); scene.idle(50); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java index 3bc0ccf90..3f68a5bfc 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/KineticsScenes.java @@ -26,6 +26,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; import net.minecraft.block.FurnaceBlock; import net.minecraft.block.RedstoneWireBlock; +import net.minecraft.item.DyeColor; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.particles.ParticleTypes; @@ -230,6 +231,7 @@ public class KineticsScenes { scene.overlay.showText(60) .text("Shifting from large to small cogs, the conveyed speed will be doubled") .colored(PonderPalette.GREEN) + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 3), Direction.NORTH)); scene.idle(10); @@ -268,6 +270,7 @@ public class KineticsScenes { scene.overlay.showText(80) .text("Shifting the opposite way, the conveyed speed will be halved") .colored(PonderPalette.RED) + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 3), Direction.NORTH)); scene.idle(10); @@ -338,6 +341,7 @@ public class KineticsScenes { .colored(PonderPalette.GREEN) .pointAt(util.vector.topOf(3, 2, 3)) .placeNearTarget() + .attachKeyFrame() .text("A gearbox is the more compact equivalent of this setup"); scene.idle(90); @@ -410,6 +414,7 @@ public class KineticsScenes { scene.overlay.showText(50) .colored(PonderPalette.RED) .text("When powered by Redstone, it breaks the connection") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.topOf(clutch)); @@ -455,6 +460,7 @@ public class KineticsScenes { .colored(PonderPalette.RED) .placeNearTarget() .text("When powered by Redstone, it reverses the transmission") + .attachKeyFrame() .pointAt(util.vector.topOf(gearshift)); for (int i = 0; i < 3; i++) { @@ -502,6 +508,7 @@ public class KineticsScenes { scene.overlay.showText(50) .text("Scrolling on the back panel changes the RPM of the motors' rotational output") + .attachKeyFrame() .placeNearTarget() .pointAt(blockSurface); scene.idle(10); @@ -573,6 +580,7 @@ public class KineticsScenes { scene.rotateCameraY(-30); scene.overlay.showText(70) .text("The Wheels' blades should be oriented against the flow") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.topOf(wheel)); scene.idle(80); @@ -598,6 +606,7 @@ public class KineticsScenes { scene.overlay.showText(70) .colored(PonderPalette.RED) .text("Facing the opposite way, they will not be as effective") + .attachKeyFrame() .placeNearTarget() .pointAt(util.vector.topOf(wheel)); scene.idle(80); @@ -629,15 +638,15 @@ public class KineticsScenes { scene.idle(20); Vector3d centerOf = util.vector.centerOf(2, 2, 2); scene.overlay.showControls(new InputWindowElement(centerOf, Pointing.DOWN).rightClick() - .withItem(new ItemStack(Items.BLUE_DYE)), 40); + .withItem(new ItemStack(Items.BLUE_DYE)), 40); scene.idle(7); - scene.world.modifyBlock(util.grid.at(2, 2, 2), s -> AllBlocks.DYED_VALVE_HANDLES.get(11).getDefaultState() - .with(ValveHandleBlock.FACING, Direction.UP), true); + scene.world.modifyBlock(util.grid.at(2, 2, 2), s -> AllBlocks.DYED_VALVE_HANDLES.get(DyeColor.BLUE).getDefaultState() + .with(ValveHandleBlock.FACING, Direction.UP), true); scene.idle(10); scene.overlay.showText(70) - .text("Valve handles can be dyed for aesthetic purposes") - .placeNearTarget() - .pointAt(centerOf); + .text("Valve handles can be dyed for aesthetic purposes") + .placeNearTarget() + .pointAt(centerOf); } private static void manualSource(SceneBuilder scene, SceneBuildingUtil util, boolean handCrank) { @@ -673,6 +682,7 @@ public class KineticsScenes { scene.idle(10); scene.overlay.showText(50) .text("Hold Right-Click to rotate it Counter-Clockwise") + .attachKeyFrame() .placeNearTarget() .pointAt(centerOf); scene.idle(70); @@ -696,6 +706,7 @@ public class KineticsScenes { scene.idle(10); scene.overlay.showText(90) .text("Sneak and Hold Right-Click to rotate it Clockwise") + .attachKeyFrame() .placeNearTarget() .pointAt(centerOf); scene.idle(90); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java index cecbcfeef..11ebe967b 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/MovementActorScenes.java @@ -49,6 +49,7 @@ public class MovementActorScenes { .pointAt(util.vector.topOf(bearing.up(2))) .colored(PonderPalette.RED) .placeNearTarget() + .attachKeyFrame() .text("Inventories on moving contraptions cannot be accessed by players."); scene.idle(70); @@ -61,6 +62,7 @@ public class MovementActorScenes { .pointAt(util.vector.topOf(psi)) .colored(PonderPalette.GREEN) .placeNearTarget() + .attachKeyFrame() .text("This component can interact with storage without the need to stop the contraption."); scene.idle(90); @@ -69,6 +71,7 @@ public class MovementActorScenes { scene.overlay.showSelectionWithText(util.select.position(psi.west()), 50) .colored(PonderPalette.RED) .placeNearTarget() + .attachKeyFrame() .text("Place a second one with a gap of 1 or 2 blocks inbetween"); scene.idle(55); @@ -97,6 +100,7 @@ public class MovementActorScenes { scene.overlay.showSelectionWithText(util.select.position(psi2), 70) .placeNearTarget() .colored(PonderPalette.GREEN) + .attachKeyFrame() .text("While engaged, the stationary interface will represent ALL inventories on the contraption"); scene.idle(80); @@ -106,6 +110,7 @@ public class MovementActorScenes { scene.overlay.showText(70) .placeNearTarget() .pointAt(util.vector.topOf(hopper)) + .attachKeyFrame() .text("Items can now be inserted..."); ItemStack itemStack = AllItems.COPPER_INGOT.asStack(); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java index 28706d1fa..65e73a6cf 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PistonScenes.java @@ -58,6 +58,7 @@ public class PistonScenes { scene.overlay.showText(55) .pointAt(util.vector.topOf(piston)) .placeNearTarget() + .attachKeyFrame() .text("Mechanical Pistons can move blocks in front of them"); scene.idle(65); @@ -93,6 +94,7 @@ public class PistonScenes { scene.overlay.showText(60) .pointAt(util.vector.topOf(piston)) .placeNearTarget() + .attachKeyFrame() .text("Sticky Mechanical Pistons can pull the attached blocks back"); scene.idle(20); scene.world.setBlock(util.grid.at(2, 1, 1), Blocks.OAK_PLANKS.getDefaultState(), false); @@ -108,6 +110,7 @@ public class PistonScenes { ElementLink chassis = scene.world.showIndependentSection(util.select.fromTo(2, 2, 0, 2, 3, 2), Direction.DOWN); scene.world.moveSection(chassis, util.vector.of(0, -1, 1), 0); + scene.addKeyframe(); scene.idle(5); scene.world.showSectionAndMerge(util.select.position(1, 2, 0), Direction.EAST, chassis); scene.idle(15); @@ -154,6 +157,7 @@ public class PistonScenes { scene.overlay.showSelectionWithText(util.select.position(piston), 50) .colored(PonderPalette.RED) .placeNearTarget() + .attachKeyFrame() .text("Without attached Poles, a Mechanical Piston cannot move"); scene.idle(60); @@ -172,6 +176,7 @@ public class PistonScenes { 100); scene.overlay.showSelectionWithText(util.select.fromTo(piston.west(), piston.west(2)), 100) .text("The Length of pole added at its back determines the Extension Range") + .attachKeyFrame() .placeNearTarget() .colored(PonderPalette.GREEN); scene.idle(110); @@ -238,6 +243,7 @@ public class PistonScenes { scene.idle(10); scene.overlay.showSelectionWithText(rose, 70) .text("Whenever Pistons stop moving, the moved structure reverts to blocks") + .attachKeyFrame() .colored(PonderPalette.RED); scene.idle(80); @@ -259,6 +265,7 @@ public class PistonScenes { scene.overlay.showText(70) .pointAt(util.vector.topOf(piston)) .placeNearTarget() + .attachKeyFrame() .sharedText("behaviour_modify_wrench"); scene.idle(80); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java index 71fb38cb2..f8e914b0e 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PonderIndex.java @@ -3,12 +3,20 @@ package com.simibubi.create.foundation.ponder.content; import com.simibubi.create.AllBlocks; import com.simibubi.create.AllItems; import com.simibubi.create.foundation.ponder.PonderRegistry; +import com.simibubi.create.foundation.ponder.content.fluid.DrainScenes; +import com.simibubi.create.foundation.ponder.content.fluid.FluidMovementActorScenes; +import com.simibubi.create.foundation.ponder.content.fluid.FluidTankScenes; +import com.simibubi.create.foundation.ponder.content.fluid.HosePulleyScenes; +import com.simibubi.create.foundation.ponder.content.fluid.PipeScenes; +import com.simibubi.create.foundation.ponder.content.fluid.PumpScenes; +import com.simibubi.create.foundation.ponder.content.fluid.SpoutScenes; import net.minecraft.block.Blocks; +import net.minecraft.item.DyeColor; public class PonderIndex { - public static final boolean EDITOR_MODE = false; + public static final boolean EDITOR_MODE = true; public static void register() { // Register storyboards here @@ -54,24 +62,24 @@ public class PonderIndex { .addStoryBoard("fan/source", FanScenes::source, PonderTag.KINETIC_SOURCES); PonderRegistry.addStoryBoard(AllBlocks.CREATIVE_MOTOR, "creative_motor", KineticsScenes::creativeMotor, - PonderTag.KINETIC_SOURCES); + PonderTag.KINETIC_SOURCES); PonderRegistry.addStoryBoard(AllBlocks.WATER_WHEEL, "water_wheel", KineticsScenes::waterWheel, - PonderTag.KINETIC_SOURCES); + PonderTag.KINETIC_SOURCES); PonderRegistry.addStoryBoard(AllBlocks.HAND_CRANK, "hand_crank", KineticsScenes::handCrank, - PonderTag.KINETIC_SOURCES); + PonderTag.KINETIC_SOURCES); PonderRegistry.addStoryBoard(AllBlocks.COPPER_VALVE_HANDLE, "valve_handle", KineticsScenes::valveHandle, - PonderTag.KINETIC_SOURCES); - PonderRegistry.forComponents(AllBlocks.DYED_VALVE_HANDLES) - .addStoryBoard("valve_handle", KineticsScenes::valveHandle); + PonderTag.KINETIC_SOURCES); + PonderRegistry.forComponents(AllBlocks.DYED_VALVE_HANDLES.toArray()) + .addStoryBoard("valve_handle", KineticsScenes::valveHandle); PonderRegistry.addStoryBoard(AllBlocks.ENCASED_CHAIN_DRIVE, "chain_drive/relay", - ChainDriveScenes::chainDriveAsRelay, PonderTag.KINETIC_RELAYS); + ChainDriveScenes::chainDriveAsRelay, PonderTag.KINETIC_RELAYS); PonderRegistry.forComponents(AllBlocks.ENCASED_CHAIN_DRIVE, AllBlocks.ADJUSTABLE_CHAIN_GEARSHIFT) - .addStoryBoard("chain_drive/gearshift", ChainDriveScenes::adjustableChainGearshift); + .addStoryBoard("chain_drive/gearshift", ChainDriveScenes::adjustableChainGearshift); PonderRegistry.forComponents(AllBlocks.FURNACE_ENGINE) - .addStoryBoard("furnace_engine", KineticsScenes::furnaceEngine); + .addStoryBoard("furnace_engine", KineticsScenes::furnaceEngine); PonderRegistry.forComponents(AllBlocks.FLYWHEEL) .addStoryBoard("furnace_engine", KineticsScenes::flywheel); PonderRegistry.forComponents(AllBlocks.ROTATION_SPEED_CONTROLLER) @@ -223,6 +231,7 @@ public class PonderIndex { PonderRegistry.forComponents(AllBlocks.DEPLOYER) .addStoryBoard("deployer/filter", DeployerScenes::filter, PonderTag.KINETIC_APPLIANCES) .addStoryBoard("deployer/modes", DeployerScenes::modes) + .addStoryBoard("deployer/processing", DeployerScenes::processing) .addStoryBoard("deployer/redstone", DeployerScenes::redstone) .addStoryBoard("deployer/contraption", DeployerScenes::contraption, PonderTag.CONTRAPTION_ACTOR); PonderRegistry.forComponents(AllBlocks.MECHANICAL_HARVESTER) @@ -230,6 +239,41 @@ public class PonderIndex { PonderRegistry.forComponents(AllBlocks.MECHANICAL_PLOUGH) .addStoryBoard("plough", MovementActorScenes::plough); + // Fluids + + PonderRegistry.forComponents(AllBlocks.FLUID_PIPE) + .addStoryBoard("fluid_pipe/flow", PipeScenes::flow, PonderTag.FLUIDS) + .addStoryBoard("fluid_pipe/interaction", PipeScenes::interaction) + .addStoryBoard("fluid_pipe/encasing", PipeScenes::encasing); + PonderRegistry.forComponents(AllBlocks.COPPER_CASING) + .addStoryBoard("fluid_pipe/encasing", PipeScenes::encasing); + PonderRegistry.forComponents(AllBlocks.MECHANICAL_PUMP) + .addStoryBoard("debug/scene_1", PumpScenes::flow, PonderTag.FLUIDS, PonderTag.KINETIC_APPLIANCES) + .addStoryBoard("debug/scene_1", PumpScenes::speed); + PonderRegistry.forComponents(AllBlocks.FLUID_VALVE) + .addStoryBoard("debug/scene_1", PipeScenes::valve, PonderTag.FLUIDS, PonderTag.KINETIC_APPLIANCES); + PonderRegistry.forComponents(AllBlocks.SMART_FLUID_PIPE) + .addStoryBoard("debug/scene_1", PipeScenes::smart, PonderTag.FLUIDS); + PonderRegistry.forComponents(AllBlocks.FLUID_TANK) + .addStoryBoard("debug/scene_1", FluidTankScenes::storage, PonderTag.FLUIDS) + .addStoryBoard("debug/scene_1", FluidTankScenes::sizes); + PonderRegistry.forComponents(AllBlocks.CREATIVE_FLUID_TANK) + .addStoryBoard("debug/scene_1", FluidTankScenes::creative, PonderTag.FLUIDS, PonderTag.CREATIVE) + .addStoryBoard("debug/scene_1", FluidTankScenes::sizes); + PonderRegistry.forComponents(AllBlocks.HOSE_PULLEY) + .addStoryBoard("debug/scene_1", HosePulleyScenes::intro, PonderTag.FLUIDS, PonderTag.KINETIC_APPLIANCES) + .addStoryBoard("debug/scene_1", HosePulleyScenes::level) + .addStoryBoard("debug/scene_1", HosePulleyScenes::infinite); + PonderRegistry.forComponents(AllBlocks.SPOUT) + .addStoryBoard("debug/scene_1", SpoutScenes::filling, PonderTag.FLUIDS) + .addStoryBoard("debug/scene_1", SpoutScenes::access); + PonderRegistry.forComponents(AllBlocks.ITEM_DRAIN) + .addStoryBoard("debug/scene_1", DrainScenes::emptying, PonderTag.FLUIDS); + PonderRegistry.forComponents(AllBlocks.PORTABLE_FLUID_INTERFACE) + .addStoryBoard("debug/scene_1", FluidMovementActorScenes::transfer, PonderTag.FLUIDS, + PonderTag.CONTRAPTION_ACTOR) + .addStoryBoard("debug/scene_1", FluidMovementActorScenes::redstone); + // Redstone PonderRegistry.forComponents(AllBlocks.PULSE_REPEATER) .addStoryBoard("pulse_repeater", RedstoneScenes::pulseRepeater); @@ -398,17 +442,17 @@ public class PonderIndex { .add(Blocks.HONEY_BLOCK); PonderRegistry.tags.forTag(PonderTag.CONTRAPTION_ACTOR) - .add(AllBlocks.MECHANICAL_HARVESTER) - .add(AllBlocks.MECHANICAL_PLOUGH) - .add(AllBlocks.MECHANICAL_DRILL) - .add(AllBlocks.MECHANICAL_SAW) - .add(AllBlocks.DEPLOYER) - .add(AllBlocks.PORTABLE_STORAGE_INTERFACE) - .add(AllBlocks.PORTABLE_FLUID_INTERFACE) - .add(AllBlocks.MECHANICAL_BEARING) - .add(AllBlocks.ANDESITE_FUNNEL) - .add(AllBlocks.BRASS_FUNNEL) - .add(AllBlocks.SEATS[0]) + .add(AllBlocks.MECHANICAL_HARVESTER) + .add(AllBlocks.MECHANICAL_PLOUGH) + .add(AllBlocks.MECHANICAL_DRILL) + .add(AllBlocks.MECHANICAL_SAW) + .add(AllBlocks.DEPLOYER) + .add(AllBlocks.PORTABLE_STORAGE_INTERFACE) + .add(AllBlocks.PORTABLE_FLUID_INTERFACE) + .add(AllBlocks.MECHANICAL_BEARING) + .add(AllBlocks.ANDESITE_FUNNEL) + .add(AllBlocks.BRASS_FUNNEL) + .add(AllBlocks.SEATS.get(DyeColor.WHITE)) .add(AllBlocks.REDSTONE_CONTACT) .add(Blocks.BELL) .add(Blocks.DISPENSER) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java index 8b11d693e..b228d4f60 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/PulleyScenes.java @@ -44,6 +44,7 @@ public class PulleyScenes { scene.idle(45); scene.overlay.showText(60) .pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST)) + .attachKeyFrame() .text("Rope Pulleys can move blocks vertically when given Rotational Force") .placeNearTarget(); scene.idle(70); @@ -81,6 +82,7 @@ public class PulleyScenes { scene.overlay.showText(80) .pointAt(util.vector.blockSurface(util.grid.at(1, 2, 2), Direction.NORTH)) .placeNearTarget() + .attachKeyFrame() .sharedText("movement_anchors"); scene.idle(90); @@ -136,6 +138,7 @@ public class PulleyScenes { scene.idle(10); scene.overlay.showSelectionWithText(util.select.position(flowerPos), 70) .text("Whenever Pulleys stop moving, the moved structure reverts to blocks") + .attachKeyFrame() .placeNearTarget() .colored(PonderPalette.RED); scene.idle(80); @@ -157,6 +160,7 @@ public class PulleyScenes { scene.overlay.showText(70) .pointAt(util.vector.topOf(pulleyPos)) .placeNearTarget() + .attachKeyFrame() .sharedText("behaviour_modify_wrench"); scene.idle(80); @@ -202,6 +206,7 @@ public class PulleyScenes { scene.overlay.showText(50) .pointAt(util.vector.blockSurface(pulleyPos, Direction.WEST)) .placeNearTarget() + .attachKeyFrame() .text("Whenever Pulleys are themselves being moved by a Contraption..."); scene.idle(60); @@ -215,6 +220,7 @@ public class PulleyScenes { scene.overlay.showSelectionWithText(util.select.fromTo(1, 1, 1, 1, 1, 2), 50) .colored(PonderPalette.GREEN) .placeNearTarget() + .attachKeyFrame() .text("...its attached structure will be dragged with it"); scene.idle(60); scene.overlay.showText(80) diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/DrainScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/DrainScenes.java new file mode 100644 index 000000000..4804f5edc --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/DrainScenes.java @@ -0,0 +1,31 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; + +import net.minecraft.util.Direction; + +public class DrainScenes { + + public static void emptying(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("item_drain", "Emptying Fluid Containers using Item Drains"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Item Drains can extract fluids from any fluid container items + * + * Right-click it to pour fluids from your held item into it + * + * When items are inserted from the side... + * + * ...they tumble across the surface, emptying out their contained fluid if possible + * + * Pipe Networks can now pull the fluid from the drains' internal buffer + */ + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidMovementActorScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidMovementActorScenes.java new file mode 100644 index 000000000..57d390b44 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidMovementActorScenes.java @@ -0,0 +1,53 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; + +import net.minecraft.util.Direction; + +public class FluidMovementActorScenes { + + public static void transfer(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("portable_fluid_interface", "Contraption Fluid Exchange"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Fluid Tanks on moving contraptions cannot be accessed by any pipes + * + * This component can interact with fluid tanks without the need to stop the + * contraption + * + * Place a second one with a gap of 1 or 2 blocks inbetween + * + * Whenever they pass by each other, they will engage in a connection + * + * While engaged, the stationary interface will represent ALL Fluid Tanks on the + * contraption + * + * Fluid can now be inserted... + * + * ...or extracted from the contraption + * + * After no contents have been exchanged for a while, the contraption will + * continue on its way + */ + + } + + public static void redstone(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("portable_fluid_interface_redstone", "Redstone Control"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Redstone power will prevent the stationary interface from engaging + */ + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidTankScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidTankScenes.java new file mode 100644 index 000000000..3610e3b4f --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/FluidTankScenes.java @@ -0,0 +1,69 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; + +import net.minecraft.util.Direction; + +public class FluidTankScenes { + + public static void storage(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fluid_tank_storage", "Storing Fluids in Fluid Tanks"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Fluid Tanks can be used to store large amounts of fluid + * + * Pipe networks can push and pull fluids from any side + * + * Comparators can read the current fill level of a fluid tank + * + * In Survival Mode, Fluids cannot be added or taken manually + * + * You can use Basins, Item Drains and Spouts to drain or fill fluid containing items + */ + + } + + public static void sizes(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fluid_tank_sizes", "Dimensions of a Fluid tank"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Fluid Tanks can be combined to increase the total capacity + * + * The base shape can be a square up to 3 blocks wide... + * + * ...and grow in height by more than 30 additional layers + * + * Using a Wrench, the tanks' window can be toggled + */ + + } + + public static void creative(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("creative_fluid_tank", "Creative Fluid Tanks"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Creative Fluid Tanks can be used to provide a bottomless supply of fluid + * + * Right-Click with a fluid containing item to configure it + * + * Pipe Networks can now endlessly draw the assigned fluid from this tank + * + * Any Fluids pipes push into a Creative Fluid Tank will be voided + */ + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/HosePulleyScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/HosePulleyScenes.java new file mode 100644 index 000000000..92c7086d1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/HosePulleyScenes.java @@ -0,0 +1,73 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; + +import net.minecraft.util.Direction; + +public class HosePulleyScenes { + + public static void intro(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("hose_pulley", "Source Filling and Draining using Hose Pulleys"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Hose Pulleys can be used to fill or drain large bodies of Fluid + * + * With the Kinetic Input, the height of the pulleys' hose can be controlled + * + * The Pulley will retract when the input rotation is inverted + * + * Once the hose is in position, an attached pipe network can either provide fluid to the Hose Pulley... + * + * ...or pull from it, draining the pool instead + * + * Fill and Drain speed of the pulley depend entirely on the fluid networks' throughput + */ + + } + + public static void level(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("hose_pulley_level", "Fill and Drain level of Hose Pulleys"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * While fully retracted, the Hose Pulley cannot operate + * + * Draining runs from top to bottom + * + * The surface level will end up just below where the hose ends + * + * Filling runs from bottom to top + * + * The filled pool will not grow beyond the layer above the hose end + */ + + } + + public static void infinite(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("hose_pulley_infinite", "Passively Filling and Draining large bodies of Fluid"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * When deploying the Hose Pulley into a large enough ocean... + * + * It will simply provide/dispose fluids without affecting the source + * + * Pipe networks can limitlessly pull or push fluids to and from such pulleys + * + * After such a state is reached, your goggles will display an indicator when looking at it + */ + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PipeScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PipeScenes.java new file mode 100644 index 000000000..1cf206d1a --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PipeScenes.java @@ -0,0 +1,405 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.content.contraptions.fluids.PumpBlock; +import com.simibubi.create.content.contraptions.fluids.actors.ItemDrainTileEntity; +import com.simibubi.create.content.contraptions.fluids.pipes.AxisPipeBlock; +import com.simibubi.create.content.contraptions.fluids.pipes.FluidPipeBlock; +import com.simibubi.create.content.contraptions.fluids.tank.FluidTankTileEntity; +import com.simibubi.create.foundation.ponder.ElementLink; +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; +import com.simibubi.create.foundation.ponder.Selection; +import com.simibubi.create.foundation.ponder.content.PonderPalette; +import com.simibubi.create.foundation.ponder.elements.InputWindowElement; +import com.simibubi.create.foundation.ponder.elements.WorldSectionElement; +import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour; +import com.simibubi.create.foundation.utility.Pointing; + +import net.minecraft.block.BeehiveBlock; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.fluid.Fluids; +import net.minecraft.item.ItemStack; +import net.minecraft.state.BooleanProperty; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +public class PipeScenes { + + public static void flow(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fluid_pipe_flow", "Moving Fluids using Copper Pipes"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + scene.idle(5); + + BlockState pipeState = AllBlocks.FLUID_PIPE.getDefaultState() + .with(FluidPipeBlock.UP, false) + .with(FluidPipeBlock.DOWN, false); + + scene.world.setBlock(util.grid.at(2, 1, 1), pipeState.with(FluidPipeBlock.NORTH, false) + .with(FluidPipeBlock.SOUTH, false), false); + scene.world.setBlock(util.grid.at(1, 1, 2), pipeState.with(FluidPipeBlock.WEST, false) + .with(FluidPipeBlock.EAST, false), false); + + Selection largeCog = util.select.position(5, 0, 1); + Selection kinetics = util.select.fromTo(5, 1, 0, 3, 1, 0); + Selection tank = util.select.fromTo(4, 1, 2, 4, 2, 2); + Selection tank2 = util.select.fromTo(0, 1, 3, 0, 2, 3); + + Selection strayPipes = util.select.fromTo(2, 1, 2, 2, 2, 2) + .add(util.select.fromTo(1, 2, 2, 1, 3, 2)); + + scene.world.showSection(tank, Direction.DOWN); + scene.idle(5); + scene.world.showSection(tank2, Direction.DOWN); + FluidStack content = new FluidStack(Fluids.LAVA, 10000); + scene.world.modifyTileEntity(util.grid.at(4, 1, 2), FluidTankTileEntity.class, te -> te.getTankInventory() + .fill(content, FluidAction.EXECUTE)); + scene.idle(10); + + for (int i = 4; i >= 1; i--) { + scene.world.showSection(util.select.position(i, 1, 1), i == 4 ? Direction.SOUTH : Direction.EAST); + scene.idle(3); + } + + scene.overlay.showText(60) + .text("Fluid Pipes can connect two or more fluid sources and targets") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(1, 1, 1)); + + for (int i = 2; i <= 3; i++) { + scene.world.showSection(util.select.position(1, 1, i), Direction.NORTH); + scene.idle(3); + } + + scene.idle(60); + + scene.overlay.showControls(new InputWindowElement(util.vector.centerOf(2, 1, 1), Pointing.DOWN).rightClick() + .withWrench(), 40); + scene.idle(7); + scene.world.restoreBlocks(util.select.position(2, 1, 1)); + scene.overlay.showText(70) + .attachKeyFrame() + .pointAt(util.vector.centerOf(2, 1, 1)) + .placeNearTarget() + .text("Using a wrench, a straight pipe segment can be given a window"); + scene.idle(40); + + scene.overlay.showControls(new InputWindowElement(util.vector.centerOf(1, 1, 2), Pointing.DOWN).rightClick() + .withWrench(), 10); + scene.idle(7); + scene.world.restoreBlocks(util.select.position(1, 1, 2)); + scene.idle(40); + + Vector3d center = util.vector.centerOf(2, 1, 2); + AxisAlignedBB bb = new AxisAlignedBB(center, center).grow(1 / 6f); + AxisAlignedBB bb1 = bb.offset(-0.5, 0, 0); + AxisAlignedBB bb2 = bb.offset(0, 0, -0.5); + + scene.world.showSection(strayPipes, Direction.DOWN); + scene.idle(10); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb1, bb, 1); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb2, bb, 1); + scene.idle(1); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb1, bb1, 50); + scene.overlay.chaseBoundingBoxOutline(PonderPalette.RED, bb2, bb2, 50); + scene.idle(10); + scene.overlay.showText(55) + .attachKeyFrame() + .pointAt(util.vector.centerOf(2, 1, 2)) + .placeNearTarget() + .colored(PonderPalette.RED) + .text("Windowed pipes will not connect to any other adjacent pipe segments"); + scene.idle(60); + scene.world.hideSection(strayPipes, Direction.UP); + scene.idle(10); + + BlockPos pumpPos = util.grid.at(3, 1, 1); + scene.world.setBlock(pumpPos, AllBlocks.MECHANICAL_PUMP.getDefaultState() + .with(PumpBlock.FACING, Direction.WEST), true); + scene.idle(10); + scene.world.showSection(largeCog, Direction.UP); + scene.world.showSection(kinetics, Direction.SOUTH); + scene.idle(10); + scene.world.setKineticSpeed(util.select.position(pumpPos), 32); + scene.world.propagatePipeChange(pumpPos); + + scene.overlay.showText(70) + .attachKeyFrame() + .pointAt(util.vector.topOf(pumpPos)) + .placeNearTarget() + .text("Powered by Mechanical Pumps, the Pipes can transport Fluids"); + scene.idle(85); + scene.overlay.showSelectionWithText(tank, 40) + .colored(PonderPalette.RED) + .placeNearTarget() + .text("No fluid is being extracted at first"); + scene.idle(90); + + scene.overlay.showOutline(PonderPalette.GREEN, new Object(), tank, 100); + scene.idle(5); + scene.overlay.showOutline(PonderPalette.GREEN, new Object(), tank2, 100); + scene.idle(5); + scene.overlay.showText(100) + .attachKeyFrame() + .independent() + .text("Once the flow connects them, the endpoints gradually transfer their contents"); + scene.overlay.showLine(PonderPalette.GREEN, util.vector.blockSurface(util.grid.at(4, 2, 2), Direction.WEST), + util.vector.blockSurface(util.grid.at(0, 2, 3), Direction.EAST), 80); + + scene.world.multiplyKineticSpeed(util.select.everywhere(), 2); + scene.world.propagatePipeChange(pumpPos); + scene.effects.rotationSpeedIndicator(pumpPos); + + scene.idle(120); + + scene.overlay.showText(60) + .text("Thus, the Pipe blocks themselves never 'physically' contain any fluid") + .placeNearTarget() + .pointAt(util.vector.topOf(1, 1, 1)); + scene.idle(50); + } + + public static void interaction(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("fluid_pipe_interaction", "Draining and Filling fluid containers"); + scene.configureBasePlate(0, 1, 5); + scene.showBasePlate(); + scene.idle(5); + + BlockPos pumpPos = util.grid.at(2, 1, 4); + Selection largeCog = util.select.position(5, 0, 4); + Selection kinetics = util.select.fromTo(5, 1, 5, 2, 1, 5); + Selection pipes = util.select.fromTo(1, 1, 4, 3, 1, 3) + .add(util.select.position(3, 1, 2)); + Selection tank = util.select.fromTo(4, 1, 3, 4, 2, 3); + Selection drain = util.select.position(1, 1, 2); + Selection basin = util.select.position(3, 1, 1); + + Selection waterSourceS = util.select.position(1, 1, 1); + Selection waterTargetS = util.select.position(4, 1, 1); + Selection waterTarget2S = util.select.fromTo(4, 0, 0, 4, 1, 0); + + scene.world.setKineticSpeed(util.select.position(pumpPos), 0); + + scene.world.showSection(pipes, Direction.DOWN); + scene.idle(10); + scene.world.showSection(basin, Direction.SOUTH); + scene.idle(5); + scene.world.showSection(drain, Direction.SOUTH); + scene.idle(5); + scene.world.showSection(tank, Direction.WEST); + + scene.overlay.showText(60) + .text("Endpoints of a pipe network can interact with a variety of blocks") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(1, 1, 3), Direction.NORTH)); + scene.idle(60); + scene.world.showSection(largeCog, Direction.UP); + scene.idle(5); + scene.world.showSection(kinetics, Direction.NORTH); + scene.idle(10); + scene.world.setKineticSpeed(util.select.position(pumpPos), 64); + BlockPos drainPos = util.grid.at(1, 1, 2); + scene.world.modifyTileEntity(drainPos, ItemDrainTileEntity.class, + te -> te.getBehaviour(SmartFluidTankBehaviour.TYPE) + .allowInsertion() + .getPrimaryHandler() + .fill(new FluidStack(Fluids.WATER, 1500), FluidAction.EXECUTE)); + + scene.idle(50); + scene.overlay.showOutline(PonderPalette.MEDIUM, new Object(), drain, 40); + scene.idle(5); + scene.overlay.showOutline(PonderPalette.MEDIUM, new Object(), tank, 40); + scene.idle(5); + scene.overlay.showOutline(PonderPalette.MEDIUM, new Object(), basin, 40); + scene.idle(5); + + scene.overlay.showText(60) + .text("Any block with fluid storage capabilities can be filled or drained") + .attachKeyFrame() + .colored(PonderPalette.MEDIUM) + .placeNearTarget() + .pointAt(util.vector.blockSurface(drainPos, Direction.UP)); + scene.idle(100); + + scene.world.hideSection(drain, Direction.NORTH); + scene.idle(5); + scene.world.hideSection(tank, Direction.EAST); + scene.idle(5); + scene.world.setBlock(drainPos, Blocks.AIR.getDefaultState(), false); + scene.world.propagatePipeChange(pumpPos); + scene.world.hideSection(basin, Direction.NORTH); + scene.idle(5); + scene.world.setBlock(util.grid.at(3, 1, 1), Blocks.AIR.getDefaultState(), false); + scene.idle(5); + scene.world.setBlock(util.grid.at(3, 1, 3), AllBlocks.GLASS_FLUID_PIPE.getDefaultState() + .with(AxisPipeBlock.AXIS, Axis.Z), false); + scene.idle(10); + scene.world.multiplyKineticSpeed(util.select.everywhere(), 2); + scene.world.propagatePipeChange(pumpPos); + ElementLink water = scene.world.showIndependentSection(waterSourceS, Direction.DOWN); + scene.world.moveSection(water, util.vector.of(0, 0, 1), 0); + scene.idle(10); + scene.world.setBlock(drainPos, Blocks.WATER.getDefaultState(), false); + scene.idle(20); + + scene.overlay.showText(60) + .text("Source blocks right in front of an open end can be picked up...") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(drainPos, Direction.SOUTH)); + + scene.idle(40); + scene.world.setBlock(drainPos.north(), Blocks.AIR.getDefaultState(), false); + scene.idle(40); + ElementLink target = scene.world.showIndependentSection(waterTargetS, Direction.UP); + scene.world.moveSection(target, util.vector.of(-1, 0, 0), 0); + scene.idle(5); + scene.world.showSectionAndMerge(waterTarget2S, Direction.UP, target); + + scene.overlay.showText(60) + .text("...while spilling into empty spaces can create fluid sources") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 2), Direction.NORTH)); + + scene.idle(80); + scene.world.hideIndependentSection(target, Direction.DOWN); + scene.idle(5); + scene.world.setBlock(drainPos, Blocks.BEE_NEST.getDefaultState() + .with(BeehiveBlock.HONEY_LEVEL, 5), false); + scene.world.showSection(drain, Direction.DOWN); + scene.world.setBlock(util.grid.at(3, 1, 2), AllBlocks.FLUID_TANK.getDefaultState(), false); + scene.world.propagatePipeChange(pumpPos); + scene.idle(15); + + scene.overlay.showText(60) + .text("Pipes can also extract fluids from a handful of other blocks directly") + .attachKeyFrame() + .placeNearTarget() + .pointAt(util.vector.topOf(drainPos)); + + scene.idle(60); + scene.world.setBlock(drainPos, Blocks.BEE_NEST.getDefaultState() + .with(BeehiveBlock.HONEY_LEVEL, 0), false); + } + + public static void encasing(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("encased_fluid_pipe", "Encasing Fluid Pipes"); + scene.configureBasePlate(0, 0, 5); + scene.showBasePlate(); + scene.idle(5); + scene.world.showSection(util.select.position(2, 0, 5), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layer(1), Direction.DOWN); + scene.idle(15); + + BlockState copperEncased = AllBlocks.ENCASED_FLUID_PIPE.getDefaultState() + .with(FluidPipeBlock.SOUTH, true) + .with(FluidPipeBlock.WEST, true); + ItemStack casingItem = AllBlocks.COPPER_CASING.asStack(); + + scene.overlay.showControls(new InputWindowElement(util.vector.topOf(3, 1, 1), Pointing.DOWN).rightClick() + .withItem(casingItem), 60); + scene.idle(7); + scene.world.setBlock(util.grid.at(3, 1, 1), copperEncased, true); + scene.idle(10); + + scene.overlay.showText(60) + .placeNearTarget() + .text("Copper Casing can be used to decorate Fluid Pipes") + .attachKeyFrame() + .pointAt(util.vector.topOf(3, 1, 1)); + + scene.idle(70); + scene.world.destroyBlock(util.grid.at(2, 1, 1)); + scene.world.modifyBlock(util.grid.at(1, 1, 1), s -> s.with(FluidPipeBlock.EAST, false) + .with(FluidPipeBlock.NORTH, true), false); + scene.idle(5); + + scene.overlay.showLine(PonderPalette.RED, util.vector.of(1.5, 1.75, 1), util.vector.of(1.5, 1.75, 2), 80); + scene.idle(5); + scene.addKeyframe(); + scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(3.5, 2, 1.5), util.vector.of(3.5, 2, 2), 80); + scene.overlay.showLine(PonderPalette.GREEN, util.vector.of(3, 2, 1.5), util.vector.of(3.5, 2, 1.5), 80); + + scene.idle(25); + scene.overlay.showText(60) + .placeNearTarget() + .text("Aside from being conceiled, Encased Pipes are locked into their connectivity state") + .pointAt(util.vector.blockSurface(util.grid.at(3, 1, 1), Direction.WEST)); + + scene.idle(70); + BlockState defaultState = AllBlocks.FLUID_PIPE.getDefaultState(); + for (BooleanProperty booleanProperty : FluidPipeBlock.FACING_TO_PROPERTY_MAP.values()) + defaultState = defaultState.with(booleanProperty, false); + + scene.world.setBlock(util.grid.at(3, 2, 1), defaultState.with(FluidPipeBlock.EAST, true) + .with(FluidPipeBlock.WEST, true), false); + scene.world.setBlock(util.grid.at(1, 2, 1), defaultState.with(FluidPipeBlock.UP, true) + .with(FluidPipeBlock.DOWN, true), false); + scene.world.showSection(util.select.layer(2), Direction.DOWN); + scene.idle(10); + scene.world.modifyBlock(util.grid.at(1, 1, 1), s -> s.with(FluidPipeBlock.UP, true) + .with(FluidPipeBlock.NORTH, false), false); + scene.idle(20); + + scene.overlay.showText(60) + .placeNearTarget() + .colored(PonderPalette.RED) + .text("It will no longer react to any neighbouring blocks being added or removed") + .attachKeyFrame() + .pointAt(util.vector.centerOf(3, 2, 1)); + scene.idle(20); + } + + public static void valve(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("valve_pipe", "Controlling Fluid flow using Valves"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Valve pipes propagate flows in a straight line + * + * When given Rotational Force in the closing direction, the valve will stop the + * fluid flow + * + * It can be re-opened by reversing the input rotation + */ + } + + public static void smart(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("smart_pipe", "Controlling Fluid flow using Smart Pipes"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Smart pipes propagate flows in a straight line + * + * When placed directly at the source, they can specify the type of fluid to + * extract + * + * Simply Right-Click their filter slot with any item containing the desired + * fluid + * + * When placed further down a pipe network, smart pipes will only let matching + * fluids continue past + * + * In this configuration, their filter has no impact on whether a fluid can + * enter the pipe network + */ + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PumpScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PumpScenes.java new file mode 100644 index 000000000..b9847c45d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/PumpScenes.java @@ -0,0 +1,53 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; + +import net.minecraft.util.Direction; + +public class PumpScenes { + + public static void flow(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_pump_flow", "Fluid Transportation using Mechanical Pumps"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Mechanical Pumps govern the flow of their attached pipe networks + * + * When powered, their arrow indicates the direction of flow + * + * The network behind is now pulling fluids... + * + * ...while the network in front is transferring it outward + * + * Reversing the input rotation reverses the direction of flow + * + * Use a Wrench to reverse the orientation of pumps manually + */ + } + + public static void speed(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("mechanical_pump_speed", "Throughput of Mechanical Pumps"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * Regardless of speed, Mechanical Pumps affect pipes up to 16 blocks away + * + * Speeding up the input rotation changes the speed of flows building... + * + * ...aswell as how quickly fluids are transferred + * + * Parallel pumps combine their speed within shared pipe connections + * + * Alternating their orientation can help lining up their flow directions + */ + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/SpoutScenes.java b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/SpoutScenes.java new file mode 100644 index 000000000..e3a567914 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/ponder/content/fluid/SpoutScenes.java @@ -0,0 +1,44 @@ +package com.simibubi.create.foundation.ponder.content.fluid; + +import com.simibubi.create.foundation.ponder.SceneBuilder; +import com.simibubi.create.foundation.ponder.SceneBuildingUtil; + +import net.minecraft.util.Direction; + +public class SpoutScenes { + + public static void filling(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("spout_filling", "Filling Items using a Spout"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * The Spout can fill fluid holding items provided beneath it + * + * The Input items can be placed on a Depot under the Spout + * + * When items are provided on a belt... + * + * The Spout will hold and process them automatically + */ + + } + + public static void access(SceneBuilder scene, SceneBuildingUtil util) { + scene.title("spout_access", "Moving fluids into Spouts"); + scene.configureBasePlate(0, 0, 5); + scene.world.showSection(util.select.layer(0), Direction.UP); + scene.idle(5); + scene.world.showSection(util.select.layersFrom(1), Direction.DOWN); + + /* + * The internal fluid tank of a spout cannot be accessed manually + * + * Instead, use an Item Drain or Basin to manually add fluid to your machines + */ + + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java index 7456ff92b..b43efb782 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/ParrotElement.java @@ -143,7 +143,7 @@ public class ParrotElement extends AnimatedSceneElement { ParrotEntity create(PonderWorld world) { ParrotEntity entity = new ParrotEntity(EntityType.PARROT, world); - int nextInt = Create.random.nextInt(5); + int nextInt = Create.RANDOM.nextInt(5); entity.setVariant(nextInt == 1 ? 0 : nextInt); // blue parrots are kinda hard to see return entity; } diff --git a/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java b/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java index 2f9c86278..9646753ee 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/elements/WorldSectionElement.java @@ -60,6 +60,7 @@ public class WorldSectionElement extends AnimatedSceneElement { public static final Compartment> DOC_WORLD_SECTION = new Compartment<>(); List renderedTileEntities; + List tickableTileEntities; Selection section; boolean redraw; @@ -256,27 +257,33 @@ public class WorldSectionElement extends AnimatedSceneElement { loadTEsIfMissing(scene.getWorld()); renderedTileEntities.removeIf(te -> scene.getWorld() .getTileEntity(te.getPos()) != te); - renderedTileEntities.forEach(te -> { + tickableTileEntities.removeIf(te -> scene.getWorld() + .getTileEntity(te.getPos()) != te); + tickableTileEntities.forEach(te -> { if (te instanceof ITickableTileEntity) ((ITickableTileEntity) te).tick(); }); } - + @Override public void whileSkipping(PonderScene scene) { - if (redraw) + if (redraw) { renderedTileEntities = null; + tickableTileEntities = null; + } redraw = false; } protected void loadTEsIfMissing(PonderWorld world) { if (renderedTileEntities != null) return; + tickableTileEntities = new ArrayList<>(); renderedTileEntities = new ArrayList<>(); section.forEach(pos -> { TileEntity tileEntity = world.getTileEntity(pos); if (tileEntity == null) return; + tickableTileEntities.add(tileEntity); renderedTileEntities.add(tileEntity); tileEntity.updateContainingBlockInfo(); }); @@ -294,8 +301,10 @@ public class WorldSectionElement extends AnimatedSceneElement { int light = -1; if (fade != 1) light = (int) (MathHelper.lerp(fade, 5, 14)); - if (redraw) + if (redraw) { renderedTileEntities = null; + tickableTileEntities = null; + } transformMS(ms, pt); world.pushFakeLight(light); renderTileEntities(world, ms, buffer, pt); @@ -329,15 +338,15 @@ public class WorldSectionElement extends AnimatedSceneElement { protected void renderStructure(PonderWorld world, MatrixStack ms, IRenderTypeBuffer buffer, RenderType type, float fade) { - SuperByteBufferCache bufferCache = CreateClient.bufferCache; + SuperByteBufferCache bufferCache = CreateClient.BUFFER_CACHE; int code = hashCode() ^ world.hashCode(); Pair key = Pair.of(code, RenderType.getBlockLayers() - .indexOf(type)); + .indexOf(type)); if (redraw) bufferCache.invalidate(DOC_WORLD_SECTION, key); SuperByteBuffer contraptionBuffer = - bufferCache.get(DOC_WORLD_SECTION, key, () -> buildStructureBuffer(world, type)); + bufferCache.get(DOC_WORLD_SECTION, key, () -> buildStructureBuffer(world, type)); if (contraptionBuffer.isEmpty()) return; @@ -352,7 +361,7 @@ public class WorldSectionElement extends AnimatedSceneElement { if (selectedBlock == null) return; BlockState blockState = world.getBlockState(selectedBlock); - if (blockState.isAir(world, selectedBlock)) + if (blockState.isAir()) return; VoxelShape shape = blockState.getShape(world, selectedBlock, ISelectionContext.forEntity(Minecraft.getInstance().player)); @@ -369,7 +378,7 @@ public class WorldSectionElement extends AnimatedSceneElement { private void renderTileEntities(PonderWorld world, MatrixStack ms, IRenderTypeBuffer buffer, float pt) { loadTEsIfMissing(world); - TileEntityRenderHelper.renderTileEntities(world, renderedTileEntities, ms, new MatrixStack(), buffer, pt); + TileEntityRenderHelper.renderTileEntities(world, renderedTileEntities, ms, buffer, pt); } private SuperByteBuffer buildStructureBuffer(PonderWorld world, RenderType layer) { diff --git a/src/main/java/com/simibubi/create/foundation/ponder/instructions/EmitParticlesInstruction.java b/src/main/java/com/simibubi/create/foundation/ponder/instructions/EmitParticlesInstruction.java index 176e79b05..ff4fa77b9 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/instructions/EmitParticlesInstruction.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/instructions/EmitParticlesInstruction.java @@ -23,9 +23,9 @@ public class EmitParticlesInstruction extends TickingInstruction { } public static Emitter withinBlockSpace(T data, Vector3d motion) { - return (w, x, y, z) -> w.addParticle(data, Math.floor(x) + Create.random.nextFloat(), - Math.floor(y) + Create.random.nextFloat(), Math.floor(z) + Create.random.nextFloat(), motion.x, - motion.y, motion.z); + return (w, x, y, z) -> w.addParticle(data, Math.floor(x) + Create.RANDOM.nextFloat(), + Math.floor(y) + Create.RANDOM.nextFloat(), Math.floor(z) + Create.RANDOM.nextFloat(), motion.x, + motion.y, motion.z); } static ParticleManager paticleManager() { @@ -47,7 +47,7 @@ public class EmitParticlesInstruction extends TickingInstruction { public void tick(PonderScene scene) { super.tick(scene); int runs = (int) runsPerTick; - if (Create.random.nextFloat() < (runsPerTick - runs)) + if (Create.RANDOM.nextFloat() < (runsPerTick - runs)) runs++; for (int i = 0; i < runs; i++) emitter.create(scene.getWorld(), anchor.x, anchor.y, anchor.z); diff --git a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java index 2533e3e9a..e3e675053 100644 --- a/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java +++ b/src/main/java/com/simibubi/create/foundation/ponder/ui/PonderButton.java @@ -1,6 +1,6 @@ package com.simibubi.create.foundation.ponder.ui; -import java.awt.Color; +import java.awt.*; import javax.annotation.Nonnull; @@ -8,6 +8,7 @@ import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.gui.GuiGameElement; import com.simibubi.create.foundation.gui.RenderElement; import com.simibubi.create.foundation.gui.Theme; +import com.simibubi.create.foundation.gui.Theme.Key; import com.simibubi.create.foundation.gui.widgets.BoxWidget; import com.simibubi.create.foundation.gui.widgets.ElementWidget; import com.simibubi.create.foundation.utility.AnimationTickHolder; @@ -74,12 +75,12 @@ public class PonderButton extends BoxWidget { float flashValue = flash.getValue(partialTicks); if (flashValue > .1f) { - float sin = 0.5f + 0.5f * MathHelper.sin((AnimationTickHolder.getTicks(true) + partialTicks) / 6f); + float sin = 0.5f + 0.5f * MathHelper.sin((AnimationTickHolder.getTicks(true) + partialTicks) / 5f); sin *= flashValue; Color c1 = gradientColor1; Color c2 = gradientColor2; - Color nc1 = new Color(c1.getRed(), c1.getGreen(), c1.getBlue(), MathHelper.clamp(c1.getAlpha() + 50, 0, 255)); - Color nc2 = new Color(c2.getRed(), c2.getGreen(), c2.getBlue(), MathHelper.clamp(c2.getAlpha() + 50, 0, 255)); + Color nc1 = new Color(255, 255, 255, MathHelper.clamp(c1.getAlpha() + 150, 0, 255)); + Color nc2 = new Color(155, 155, 155, MathHelper.clamp(c2.getAlpha() + 150, 0, 255)); gradientColor1 = ColorHelper.mixColors(c1, nc1, sin); gradientColor2 = ColorHelper.mixColors(c2, nc2, sin); } @@ -94,7 +95,7 @@ public class PonderButton extends BoxWidget { return; if (shortcut != null) { - ms.translate(0, 0, z+50); + ms.translate(0, 0, z + 50); drawCenteredText(ms, Minecraft.getInstance().fontRenderer, shortcut.getBoundKeyLocalizedText(), x + width / 2 + 8, y + height - 6, ColorHelper.applyAlpha(Theme.i(Theme.Key.TEXT_DARKER), fadeValue)); } } @@ -102,4 +103,25 @@ public class PonderButton extends BoxWidget { public ItemStack getItem() { return item; } + + @Override + public Key getDisabledTheme() { + return Theme.Key.PONDER_BUTTON_DISABLE; + } + + @Override + public Key getIdleTheme() { + return Theme.Key.PONDER_BUTTON_IDLE; + } + + @Override + public Key getHoverTheme() { + return Theme.Key.PONDER_BUTTON_HOVER; + } + + @Override + public Key getClickTheme() { + return Theme.Key.PONDER_BUTTON_CLICK; + } + } diff --git a/src/main/java/com/simibubi/create/foundation/render/AllInstanceFormats.java b/src/main/java/com/simibubi/create/foundation/render/AllInstanceFormats.java new file mode 100644 index 000000000..2ae42930c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/AllInstanceFormats.java @@ -0,0 +1,33 @@ +package com.simibubi.create.foundation.render; + +import com.jozufozu.flywheel.backend.gl.attrib.CommonAttributes; +import com.jozufozu.flywheel.backend.gl.attrib.VertexFormat; +import com.jozufozu.flywheel.core.Formats; + +public class AllInstanceFormats { + + public static VertexFormat ROTATING = kineticInstance() + .addAttributes(CommonAttributes.NORMAL) + .build(); + + public static VertexFormat BELT = kineticInstance() + .addAttributes(CommonAttributes.QUATERNION, CommonAttributes.UV, CommonAttributes.VEC4, + CommonAttributes.NORMALIZED_BYTE) + .build(); + + public static VertexFormat ACTOR = VertexFormat.builder() + .addAttributes(CommonAttributes.VEC3, CommonAttributes.LIGHT, CommonAttributes.FLOAT, + CommonAttributes.NORMAL, CommonAttributes.QUATERNION, CommonAttributes.NORMAL, + CommonAttributes.FLOAT) + .build(); + + public static VertexFormat FLAP = VertexFormat.builder() + .addAttributes(CommonAttributes.VEC3, CommonAttributes.LIGHT, CommonAttributes.VEC3, CommonAttributes.VEC3, + CommonAttributes.FLOAT, CommonAttributes.FLOAT, CommonAttributes.FLOAT, CommonAttributes.FLOAT) + .build(); + + private static VertexFormat.Builder kineticInstance() { + return Formats.litInstance() + .addAttributes(CommonAttributes.VEC3, CommonAttributes.FLOAT, CommonAttributes.FLOAT); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java new file mode 100644 index 000000000..3a0c1dbcf --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/AllMaterialSpecs.java @@ -0,0 +1,47 @@ +package com.simibubi.create.foundation.render; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.instancing.InstanceData; +import com.jozufozu.flywheel.backend.instancing.MaterialSpec; +import com.jozufozu.flywheel.core.Formats; +import com.jozufozu.flywheel.event.GatherContextEvent; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.base.RotatingData; +import com.simibubi.create.content.contraptions.components.actors.ActorData; +import com.simibubi.create.content.contraptions.relays.belt.BeltData; +import com.simibubi.create.content.logistics.block.FlapData; + +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class AllMaterialSpecs { + public static void init() { + // noop, make sure the static field are loaded. + } + + public static final MaterialSpec ROTATING = new MaterialSpec<>(Locations.ROTATING, AllProgramSpecs.ROTATING, Formats.UNLIT_MODEL, AllInstanceFormats.ROTATING, RotatingData::new); + public static final MaterialSpec BELTS = new MaterialSpec<>(Locations.BELTS, AllProgramSpecs.BELT, Formats.UNLIT_MODEL, AllInstanceFormats.BELT, BeltData::new); + public static final MaterialSpec ACTORS = new MaterialSpec<>(Locations.ACTORS, AllProgramSpecs.ACTOR, Formats.UNLIT_MODEL, AllInstanceFormats.ACTOR, ActorData::new); + public static final MaterialSpec FLAPS = new MaterialSpec<>(Locations.FLAPS, AllProgramSpecs.FLAPS, Formats.UNLIT_MODEL, AllInstanceFormats.FLAP, FlapData::new); + + public static MaterialSpec register(MaterialSpec spec) { + return Backend.getInstance().register(spec); + } + + @SubscribeEvent + public static void flwInit(GatherContextEvent event) { + register(ROTATING); + register(BELTS); + register(ACTORS); + register(FLAPS); + } + + public static class Locations { + public static final ResourceLocation ROTATING = new ResourceLocation(Create.ID, "rotating"); + public static final ResourceLocation BELTS = new ResourceLocation(Create.ID, "belts"); + public static final ResourceLocation ACTORS = new ResourceLocation(Create.ID, "actors"); + public static final ResourceLocation FLAPS = new ResourceLocation(Create.ID, "flaps"); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java index 840732670..6df22f622 100644 --- a/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java +++ b/src/main/java/com/simibubi/create/foundation/render/AllProgramSpecs.java @@ -1,139 +1,19 @@ 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.KineticAttributes; -import com.simibubi.create.content.contraptions.base.RotatingAttributes; -import com.simibubi.create.content.contraptions.components.actors.ActorVertexAttributes; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionAttributes; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionProgram; -import com.simibubi.create.content.contraptions.relays.belt.BeltAttributes; -import com.simibubi.create.content.logistics.block.FlapAttributes; -import com.simibubi.create.foundation.render.backend.core.BasicAttributes; -import com.simibubi.create.foundation.render.backend.core.ModelAttributes; -import com.simibubi.create.foundation.render.backend.core.OrientedAttributes; -import com.simibubi.create.foundation.render.backend.core.TransformAttributes; -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.ShaderConstants; import net.minecraft.util.ResourceLocation; public class AllProgramSpecs { - public static void init() { - // noop, make sure the static field are loaded. - } - public static final ProgramSpec MODEL = register(ProgramSpec.builder("model", BasicProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(TransformAttributes.class) - .setVert(Locations.MODEL_VERT) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); + public static final ResourceLocation ROTATING = loc("rotating"); + public static final ResourceLocation CHROMATIC = loc("chromatic"); + public static final ResourceLocation BELT = loc("belt"); + public static final ResourceLocation FLAPS = loc("flap"); + public static final ResourceLocation STRUCTURE = loc("contraption_structure"); + public static final ResourceLocation ACTOR = loc("contraption_actor"); - public static final ProgramSpec ORIENTED = register(ProgramSpec.builder("oriented", BasicProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(OrientedAttributes.class) - .setVert(Locations.ORIENTED) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); - - public static final ProgramSpec ROTATING = register(ProgramSpec.builder("rotating", BasicProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(KineticAttributes.class) - .addAttributes(RotatingAttributes.class) - .setVert(Locations.ROTATING) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); - - public static final ProgramSpec BELT = register(ProgramSpec.builder("belt", BasicProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(KineticAttributes.class) - .addAttributes(BeltAttributes.class) - .setVert(Locations.BELT) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); - - public static final ProgramSpec FLAPS = register(ProgramSpec.builder("flap", BasicProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(FlapAttributes.class) - .setVert(Locations.FLAP) - .setFrag(Locations.MODEL_FRAG) - .createProgramSpec()); - public static final ProgramSpec C_STRUCTURE = register(ProgramSpec.builder("contraption_structure", ContraptionProgram::new) - .addAttributes(ContraptionAttributes.class) - .setVert(Locations.CONTRAPTION_STRUCTURE) - .setFrag(Locations.CONTRAPTION) - .createProgramSpec()); - public static final ProgramSpec C_MODEL = register(ProgramSpec.builder("contraption_model", ContraptionProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(TransformAttributes.class) - .setVert(Locations.MODEL_VERT) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_ORIENTED = register(ProgramSpec.builder("contraption_oriented", ContraptionProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(OrientedAttributes.class) - .setVert(Locations.ORIENTED) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_ROTATING = register(ProgramSpec.builder("contraption_rotating", ContraptionProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(KineticAttributes.class) - .addAttributes(RotatingAttributes.class) - .setVert(Locations.ROTATING) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_BELT = register(ProgramSpec.builder("contraption_belt", ContraptionProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(BasicAttributes.class) - .addAttributes(KineticAttributes.class) - .addAttributes(BeltAttributes.class) - .setVert(Locations.BELT) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_FLAPS = register(ProgramSpec.builder("contraption_flap", ContraptionProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(FlapAttributes.class) - .setVert(Locations.FLAP) - .setFrag(Locations.CONTRAPTION) - .setDefines(ShaderConstants.define("CONTRAPTION")) - .createProgramSpec()); - public static final ProgramSpec C_ACTOR = register(ProgramSpec.builder("contraption_actor", ContraptionProgram::new) - .addAttributes(ModelAttributes.class) - .addAttributes(ActorVertexAttributes.class) - .setVert(Locations.CONTRAPTION_ACTOR) - .setFrag(Locations.CONTRAPTION) - .createProgramSpec()); - - - public static class Locations { - public static final ResourceLocation MODEL_FRAG = loc("model.frag"); - public static final ResourceLocation MODEL_VERT = loc("model.vert"); - public static final ResourceLocation ORIENTED = loc("oriented.vert"); - public static final ResourceLocation CONTRAPTION = loc("contraption.frag"); - - public static final ResourceLocation ROTATING = loc("rotating.vert"); - public static final ResourceLocation BELT = loc("belt.vert"); - public static final ResourceLocation FLAP = loc("flap.vert"); - public static final ResourceLocation CONTRAPTION_STRUCTURE = loc("contraption_structure.vert"); - public static final ResourceLocation CONTRAPTION_ACTOR = loc("contraption_actor.vert"); - - - private static ResourceLocation loc(String name) { - return new ResourceLocation(Create.ID, name); - } + private static ResourceLocation loc(String name) { + return new ResourceLocation(Create.ID, name); } } diff --git a/src/main/java/com/simibubi/create/foundation/render/Compartment.java b/src/main/java/com/simibubi/create/foundation/render/Compartment.java index 01087fc22..59a601df4 100644 --- a/src/main/java/com/simibubi/create/foundation/render/Compartment.java +++ b/src/main/java/com/simibubi/create/foundation/render/Compartment.java @@ -2,7 +2,7 @@ package com.simibubi.create.foundation.render; import org.apache.commons.lang3.tuple.Pair; -import com.simibubi.create.foundation.render.backend.core.PartialModel; +import com.jozufozu.flywheel.core.PartialModel; import net.minecraft.block.BlockState; import net.minecraft.util.Direction; diff --git a/src/main/java/com/simibubi/create/foundation/render/CreateContexts.java b/src/main/java/com/simibubi/create/foundation/render/CreateContexts.java new file mode 100644 index 000000000..15ecb3b4c --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/CreateContexts.java @@ -0,0 +1,45 @@ +package com.simibubi.create.foundation.render; + +import java.util.stream.Stream; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.SpecMetaRegistry; +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.loading.ModelTemplate; +import com.jozufozu.flywheel.core.WorldContext; +import com.jozufozu.flywheel.event.GatherContextEvent; +import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionProgram; +import com.simibubi.create.foundation.render.effects.EffectsContext; + +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) +public class CreateContexts { + private static final ResourceLocation CONTRAPTION = new ResourceLocation("create", "context/contraption"); + + public static EffectsContext EFFECTS; + public static WorldContext CWORLD; + public static WorldContext STRUCTURE; + + @SubscribeEvent + public static void flwInit(GatherContextEvent event) { + Backend backend = event.getBackend(); + + SpecMetaRegistry.register(RainbowDebugStateProvider.INSTANCE); + + EFFECTS = backend.register(new EffectsContext(backend)); + CWORLD = backend.register(contraptionContext(backend)); + STRUCTURE = backend.register(contraptionContext(backend) + .withSpecStream(() -> Stream.of(AllProgramSpecs.STRUCTURE)) + .withTemplateFactory(ModelTemplate::new)); + } + + private static WorldContext contraptionContext(Backend backend) { + return new WorldContext<>(backend, ContraptionProgram::new) + .withName(CONTRAPTION) + .withBuiltin(ShaderType.FRAGMENT, CONTRAPTION, "/builtin.frag") + .withBuiltin(ShaderType.VERTEX, CONTRAPTION, "/builtin.vert"); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java b/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java deleted file mode 100644 index 451122105..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/KineticRenderer.java +++ /dev/null @@ -1,84 +0,0 @@ -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.RotatingModel; -import com.simibubi.create.content.contraptions.relays.belt.BeltInstancedModel; -import com.simibubi.create.content.logistics.block.FlapModel; -import com.simibubi.create.foundation.render.backend.MaterialTypes; -import com.simibubi.create.foundation.render.backend.core.OrientedModel; -import com.simibubi.create.foundation.render.backend.core.TransformedModel; -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.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.vector.Matrix4f; - -public class KineticRenderer extends InstancedTileRenderer { - public static int MAX_ORIGIN_DISTANCE = 100; - - public BlockPos originCoordinate = BlockPos.ZERO; - - @Override - public void registerMaterials() { - materials.put(MaterialTypes.TRANSFORMED, - new RenderMaterial<>(this, AllProgramSpecs.MODEL, TransformedModel::new)); - materials.put(MaterialTypes.ORIENTED, new RenderMaterial<>(this, AllProgramSpecs.ORIENTED, OrientedModel::new)); - - materials.put(KineticRenderMaterials.BELTS, - new RenderMaterial<>(this, AllProgramSpecs.BELT, BeltInstancedModel::new)); - materials.put(KineticRenderMaterials.ROTATING, - new RenderMaterial<>(this, AllProgramSpecs.ROTATING, RotatingModel::new)); - materials.put(KineticRenderMaterials.FLAPS, new RenderMaterial<>(this, AllProgramSpecs.FLAPS, FlapModel::new)); - } - - @Override - public BlockPos getOriginCoordinate() { - return originCoordinate; - } - - @Override - public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) { - int cX = MathHelper.floor(cameraX); - int cY = MathHelper.floor(cameraY); - int cZ = MathHelper.floor(cameraZ); - - int dX = Math.abs(cX - originCoordinate.getX()); - int dY = Math.abs(cY - originCoordinate.getY()); - int dZ = Math.abs(cZ - originCoordinate.getZ()); - - if (dX > MAX_ORIGIN_DISTANCE || dY > MAX_ORIGIN_DISTANCE || dZ > MAX_ORIGIN_DISTANCE) { - - originCoordinate = new BlockPos(cX, cY, cZ); - - ArrayList instancedTiles = new ArrayList<>(instances.keySet()); - invalidate(); - instancedTiles.forEach(this::add); - } - - super.beginFrame(info, cameraX, cameraY, cameraZ); - } - - @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/PartialBufferer.java b/src/main/java/com/simibubi/create/foundation/render/PartialBufferer.java index 4ed176c64..7a8af4c23 100644 --- a/src/main/java/com/simibubi/create/foundation/render/PartialBufferer.java +++ b/src/main/java/com/simibubi/create/foundation/render/PartialBufferer.java @@ -4,9 +4,9 @@ import static net.minecraft.state.properties.BlockStateProperties.FACING; import java.util.function.Supplier; +import com.jozufozu.flywheel.core.PartialModel; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.CreateClient; -import com.simibubi.create.foundation.render.backend.core.PartialModel; import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.MatrixStacker; @@ -16,7 +16,7 @@ import net.minecraft.util.Direction; public class PartialBufferer { public static SuperByteBuffer get(PartialModel partial, BlockState referenceState) { - return CreateClient.bufferCache.renderPartial(partial, referenceState); + return CreateClient.BUFFER_CACHE.renderPartial(partial, referenceState); } public static SuperByteBuffer getFacing(PartialModel partial, BlockState referenceState) { @@ -25,7 +25,7 @@ public class PartialBufferer { } public static SuperByteBuffer getFacing(PartialModel partial, BlockState referenceState, Direction facing) { - return CreateClient.bufferCache.renderDirectionalPartial(partial, referenceState, facing, rotateToFace(facing)); + return CreateClient.BUFFER_CACHE.renderDirectionalPartial(partial, referenceState, facing, rotateToFace(facing)); } public static Supplier rotateToFace(Direction facing) { diff --git a/src/main/java/com/simibubi/create/foundation/render/RainbowDebugStateProvider.java b/src/main/java/com/simibubi/create/foundation/render/RainbowDebugStateProvider.java new file mode 100644 index 000000000..59aa3eb15 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/RainbowDebugStateProvider.java @@ -0,0 +1,27 @@ +package com.simibubi.create.foundation.render; + +import com.jozufozu.flywheel.core.shader.spec.IBooleanStateProvider; +import com.simibubi.create.Create; +import com.simibubi.create.content.contraptions.KineticDebugger; + +import net.minecraft.util.ResourceLocation; + +public class RainbowDebugStateProvider implements IBooleanStateProvider { + + public static final RainbowDebugStateProvider INSTANCE = new RainbowDebugStateProvider(); + public static final ResourceLocation NAME = new ResourceLocation(Create.ID, "rainbow_debug"); + + protected RainbowDebugStateProvider() { + + } + + @Override + public boolean isTrue() { + return KineticDebugger.isActive(); + } + + @Override + public ResourceLocation getID() { + return NAME; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java index f3ff7ef80..c3db4fc51 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBuffer.java @@ -1,18 +1,18 @@ package com.simibubi.create.foundation.render; -import java.nio.Buffer; -import java.nio.ByteBuffer; - +import com.jozufozu.flywheel.util.BufferBuilderReader; import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.IVertexBuilder; -import com.simibubi.create.content.contraptions.components.structureMovement.render.ContraptionRenderDispatcher; import com.simibubi.create.foundation.block.render.SpriteShiftEntry; import com.simibubi.create.foundation.utility.MatrixStacker; -import it.unimi.dsi.fastutil.longs.Long2DoubleMap; -import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; +import it.unimi.dsi.fastutil.longs.Long2IntMap; +import it.unimi.dsi.fastutil.longs.Long2IntOpenHashMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.util.Direction; import net.minecraft.util.math.BlockPos; @@ -22,34 +22,32 @@ import net.minecraft.util.math.vector.Quaternion; import net.minecraft.util.math.vector.Vector3d; import net.minecraft.util.math.vector.Vector3f; import net.minecraft.util.math.vector.Vector4f; -import net.minecraft.world.LightType; import net.minecraft.world.World; import net.minecraftforge.client.model.pipeline.LightUtil; -public class SuperByteBuffer extends TemplateBuffer { +public class SuperByteBuffer { - public interface IVertexLighter { - public int getPackedLight(float x, float y, float z); - } + private final BufferBuilderReader template; // Vertex Position private MatrixStack transforms; // Vertex Texture Coords private SpriteShiftFunc spriteShiftFunc; - - // Vertex Lighting - private boolean shouldLight; - private int packedLightCoords; - private int otherBlockLight; - private Matrix4f lightTransform; + private boolean isEntityModel; // Vertex Coloring private boolean shouldColor; private int r, g, b, a; + // Vertex Lighting + private boolean useWorldLight; + private boolean hybridLight; + private int packedLightCoords; + private Matrix4f lightTransform; + public SuperByteBuffer(BufferBuilder buf) { - super(buf); + template = new BufferBuilderReader(buf); transforms = new MatrixStack(); } @@ -63,49 +61,45 @@ public class SuperByteBuffer extends TemplateBuffer { return (v - sprite.getMinV()) / f * 16.0F; } - private static final Long2DoubleMap skyLightCache = new Long2DoubleOpenHashMap(); - private static final Long2DoubleMap blockLightCache = new Long2DoubleOpenHashMap(); + private static final Long2IntMap WORLD_LIGHT_CACHE = new Long2IntOpenHashMap(); Vector4f pos = new Vector4f(); Vector3f normal = new Vector3f(); Vector4f lightPos = new Vector4f(); public void renderInto(MatrixStack input, IVertexBuilder builder) { - ByteBuffer buffer = template; - if (((Buffer) buffer).limit() == 0) + if (isEmpty()) return; - ((Buffer) buffer).rewind(); Matrix3f normalMat = transforms.peek() .getNormal() .copy(); - // normalMat.multiply(transforms.peek().getNormal()); Matrix4f modelMat = input.peek() - .getModel() - .copy(); + .getModel() + .copy(); Matrix4f localTransforms = transforms.peek() - .getModel(); + .getModel(); modelMat.multiply(localTransforms); - if (shouldLight && lightTransform != null) { - skyLightCache.clear(); - blockLightCache.clear(); + if (useWorldLight) { + WORLD_LIGHT_CACHE.clear(); } + boolean hasDefaultLight = packedLightCoords != 0; float f = .5f; - int vertexCount = vertexCount(buffer); + int vertexCount = template.getVertexCount(); for (int i = 0; i < vertexCount; i++) { - float x = getX(buffer, i); - float y = getY(buffer, i); - float z = getZ(buffer, i); - byte r = getR(buffer, i); - 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 x = template.getX(i); + float y = template.getY(i); + float z = template.getZ(i); + byte r = template.getR(i); + byte g = template.getG(i); + byte b = template.getB(i); + byte a = template.getA(i); + float normalX = template.getNX(i) / 127f; + float normalY = template.getNY(i) / 127f; + float normalZ = template.getNZ(i) / 127f; float staticDiffuse = LightUtil.diffuseLight(normalX, normalY, normalZ); normal.set(normalX, normalY, normalZ); @@ -119,9 +113,9 @@ public class SuperByteBuffer extends TemplateBuffer { pos.transform(modelMat); builder.vertex(pos.getX(), pos.getY(), pos.getZ()); - // builder.color((byte) Math.max(0, nx * 255), (byte) Math.max(0, ny * 255), (byte) Math.max(0, nz * 255), a); - if (shouldColor) { - // float lum = (r < 0 ? 255 + r : r) / 256f; + if (isEntityModel) { + builder.color(255, 255, 255, 255); + } else if (shouldColor) { 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)); @@ -134,40 +128,65 @@ public class SuperByteBuffer extends TemplateBuffer { builder.color(colorR, colorG, colorB, a); } - float u = getU(buffer, i); - float v = getV(buffer, i); + float u = template.getU(i); + float v = template.getV(i); if (spriteShiftFunc != null) { spriteShiftFunc.shift(builder, u, v); } else builder.texture(u, v); - if (shouldLight) { - int light = packedLightCoords; + if (isEntityModel) + builder.overlay(OverlayTexture.DEFAULT_UV); + + int light; + if (useWorldLight) { + lightPos.set(((x - f) * 15 / 16f) + f, (y - f) * 15 / 16f + f, (z - f) * 15 / 16f + f, 1F); + lightPos.transform(localTransforms); if (lightTransform != null) { - 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(nx, ny, nz) - .endVertex(); + light = getLight(Minecraft.getInstance().world, lightPos); + if (hasDefaultLight) { + light = maxLight(light, packedLightCoords); + } + } else if (hasDefaultLight) { + light = packedLightCoords; + } else { + light = template.getLight(i); + } + + if (hybridLight) { + builder.light(maxLight(light, template.getLight(i))); + } else { + builder.light(light); + } + + if (isEntityModel) + builder.normal(input.peek().getNormal(), nx, ny, nz); + else + builder.normal(nx, ny, nz); + builder.endVertex(); } - transforms = new MatrixStack(); + reset(); + } + public SuperByteBuffer reset() { + transforms = new MatrixStack(); spriteShiftFunc = null; shouldColor = false; - shouldLight = false; - otherBlockLight = -1; + isEntityModel = false; + r = 0; + g = 0; + b = 0; + a = 0; + useWorldLight = false; + hybridLight = false; + packedLightCoords = 0; + lightTransform = null; + return this; } public MatrixStacker matrixStacker() { @@ -222,6 +241,15 @@ public class SuperByteBuffer extends TemplateBuffer { .translate(-.5f, -.5f, -.5f); } + public SuperByteBuffer color(int color) { + shouldColor = true; + r = ((color >> 16) & 0xFF); + g = ((color >> 8) & 0xFF); + b = (color & 0xFF); + a = 255; + return this; + } + public SuperByteBuffer shiftUV(SpriteShiftEntry entry) { this.spriteShiftFunc = (builder, u, v) -> { float targetU = entry.getTarget() @@ -258,46 +286,54 @@ public class SuperByteBuffer extends TemplateBuffer { return this; } - public SuperByteBuffer light(int packedLightCoords) { - shouldLight = true; - lightTransform = null; - this.packedLightCoords = packedLightCoords; + public SuperByteBuffer light() { + useWorldLight = true; return this; } public SuperByteBuffer light(Matrix4f lightTransform) { - shouldLight = true; + useWorldLight = true; this.lightTransform = lightTransform; return this; } - public SuperByteBuffer light(Matrix4f lightTransform, int otherBlockLight) { - shouldLight = true; - this.lightTransform = lightTransform; - this.otherBlockLight = otherBlockLight; + public SuperByteBuffer light(int packedLightCoords) { + this.packedLightCoords = packedLightCoords; return this; } - public SuperByteBuffer color(int color) { - shouldColor = true; - r = ((color >> 16) & 0xFF); - g = ((color >> 8) & 0xFF); - b = (color & 0xFF); - a = 255; + public SuperByteBuffer light(Matrix4f lightTransform, int packedLightCoords) { + useWorldLight = true; + this.lightTransform = lightTransform; + this.packedLightCoords = packedLightCoords; return this; } + public SuperByteBuffer hybridLight() { + hybridLight = true; + return this; + } + + public SuperByteBuffer asEntityModel() { + isEntityModel = true; + return this; + } + + public static int maxLight(int packedLight1, int packedLight2) { + int blockLight1 = LightTexture.getBlockLightCoordinates(packedLight1); + int skyLight1 = LightTexture.getSkyLightCoordinates(packedLight1); + int blockLight2 = LightTexture.getBlockLightCoordinates(packedLight2); + int skyLight2 = LightTexture.getSkyLightCoordinates(packedLight2); + return LightTexture.pack(Math.max(blockLight1, blockLight2), Math.max(skyLight1, skyLight2)); + } + private static int getLight(World world, Vector4f lightPos) { - BlockPos.Mutable pos = new BlockPos.Mutable(); - double sky = 0, block = 0; - 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; + BlockPos pos = new BlockPos(lightPos.getX(), lightPos.getY(), lightPos.getZ()); + return WORLD_LIGHT_CACHE.computeIfAbsent(pos.toLong(), $ -> WorldRenderer.getLightmapCoordinates(world, pos)); } public boolean isEmpty() { - return ((Buffer) template).limit() == 0; + return template.isEmpty(); } @FunctionalInterface @@ -305,4 +341,9 @@ public class SuperByteBuffer extends TemplateBuffer { void shift(IVertexBuilder builder, float u, float v); } + @FunctionalInterface + public interface IVertexLighter { + public int getPackedLight(float x, float y, float z); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java b/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java index f5f7d7559..d11742f51 100644 --- a/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java +++ b/src/main/java/com/simibubi/create/foundation/render/SuperByteBufferCache.java @@ -11,9 +11,9 @@ import org.lwjgl.opengl.GL11; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.jozufozu.flywheel.core.PartialModel; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -import com.simibubi.create.foundation.utility.VirtualEmptyModelData; import net.minecraft.block.BlockState; import net.minecraft.client.Minecraft; diff --git a/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java b/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java deleted file mode 100644 index 858fad8a8..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/TemplateBuffer.java +++ /dev/null @@ -1,97 +0,0 @@ -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/render/TileEntityRenderHelper.java b/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java index efbf65cff..cf33b7f0e 100644 --- a/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java +++ b/src/main/java/com/simibubi/create/foundation/render/TileEntityRenderHelper.java @@ -2,15 +2,17 @@ package com.simibubi.create.foundation.render; import java.util.Iterator; +import javax.annotation.Nullable; + 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.renderer.IRenderTypeBuffer; +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; @@ -23,28 +25,26 @@ import net.minecraft.world.World; public class TileEntityRenderHelper { public static void renderTileEntities(World world, Iterable customRenderTEs, MatrixStack ms, - MatrixStack localTransform, IRenderTypeBuffer buffer) { - renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer); + IRenderTypeBuffer buffer) { + renderTileEntities(world, null, customRenderTEs, ms, null, buffer); } public static void renderTileEntities(World world, Iterable customRenderTEs, MatrixStack ms, - MatrixStack localTransform, IRenderTypeBuffer buffer, float pt) { - renderTileEntities(world, null, customRenderTEs, ms, localTransform, buffer, pt); + IRenderTypeBuffer buffer, float pt) { + renderTileEntities(world, null, customRenderTEs, ms, null, buffer, pt); } - public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, - Iterable customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer) { - renderTileEntities(world, renderWorld, customRenderTEs, ms, localTransform, buffer, + public static void renderTileEntities(World world, @Nullable PlacementSimulationWorld renderWorld, + Iterable customRenderTEs, MatrixStack ms, @Nullable Matrix4f lightTransform, IRenderTypeBuffer buffer) { + renderTileEntities(world, renderWorld, customRenderTEs, ms, lightTransform, buffer, AnimationTickHolder.getPartialTicks()); } - public static void renderTileEntities(World world, PlacementSimulationWorld renderWorld, - Iterable customRenderTEs, MatrixStack ms, MatrixStack localTransform, IRenderTypeBuffer buffer, - float pt) { - Matrix4f matrix = localTransform.peek() - .getModel(); - - for (Iterator iterator = customRenderTEs.iterator(); iterator.hasNext();) { + public static void renderTileEntities(World world, @Nullable PlacementSimulationWorld renderWorld, + Iterable customRenderTEs, MatrixStack ms, @Nullable Matrix4f lightTransform, IRenderTypeBuffer buffer, + float pt) { + Iterator iterator = customRenderTEs.iterator(); + while (iterator.hasNext()) { TileEntity tileEntity = iterator.next(); // if (tileEntity instanceof IInstanceRendered) continue; // TODO: some things still need to render @@ -60,10 +60,15 @@ public class TileEntityRenderHelper { .translate(pos); try { - 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()); - int worldLight = ContraptionRenderDispatcher.getLightOnContraption(world, renderWorld, pos, lightPos); + BlockPos lightPos; + if (lightTransform != null) { + Vector4f lightVec = new Vector4f(pos.getX() + .5f, pos.getY() + .5f, pos.getZ() + .5f, 1); + lightVec.transform(lightTransform); + lightPos = new BlockPos(lightVec.getX(), lightVec.getY(), lightVec.getZ()); + } else { + lightPos = pos; + } + int worldLight = getCombinedLight(world, lightPos, renderWorld, pos); renderer.render(tileEntity, pt, ms, buffer, worldLight, OverlayTexture.DEFAULT_UV); } catch (Exception e) { @@ -73,13 +78,25 @@ public class TileEntityRenderHelper { .getRegistryName() .toString() + " didn't want to render while moved.\n"; if (AllConfigs.CLIENT.explainRenderErrors.get()) - Create.logger.error(message, e); + Create.LOGGER.error(message, e); else - Create.logger.error(message); + Create.LOGGER.error(message); } ms.pop(); } } + public static int getCombinedLight(World world, BlockPos worldPos, @Nullable PlacementSimulationWorld renderWorld, + BlockPos renderWorldPos) { + int worldLight = WorldRenderer.getLightmapCoordinates(world, worldPos); + + if (renderWorld != null) { + int renderWorldLight = WorldRenderer.getLightmapCoordinates(renderWorld, renderWorldPos); + return SuperByteBuffer.maxLight(worldLight, renderWorldLight); + } + + return worldLight; + } + } 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 deleted file mode 100644 index ece39702a..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/Backend.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.simibubi.create.foundation.render.backend; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.lwjgl.opengl.GL; -import org.lwjgl.opengl.GLCapabilities; - -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.IMultiProgram; -import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec; -import com.simibubi.create.foundation.render.backend.gl.versioned.GlCompat; -import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld; - -import net.minecraft.client.Minecraft; -import net.minecraft.resources.IReloadableResourceManager; -import net.minecraft.resources.IResourceManager; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.world.World; -import net.minecraftforge.resource.ISelectiveResourceReloadListener; - -public class Backend { - public static final Logger log = LogManager.getLogger(Backend.class); - - public static final ShaderLoader shaderLoader = new ShaderLoader(); - - public static Matrix4f projectionMatrix = new Matrix4f(); - - public static GLCapabilities capabilities; - public static GlCompat compat; - - private static boolean instancingAvailable; - private static boolean enabled; - - static final Map> registry = new HashMap<>(); - static final Map, IMultiProgram> programs = new HashMap<>(); - - public Backend() { - throw new IllegalStateException(); - } - - /** - * 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(); - } - - public static boolean isFlywheelWorld(World world) { - return world == Minecraft.getInstance().world || (world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel()); - } - - public static boolean available() { - return canUseVBOs(); - } - - public static boolean canUseInstancing() { - return enabled && instancingAvailable; - } - - public static boolean canUseVBOs() { - 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 = shaderLoader::onResourceManagerReload; - ((IReloadableResourceManager) manager).addReloadListener(listener); - } - } - - public static void refresh() { - capabilities = GL.createCapabilities(); - - compat = new GlCompat(capabilities); - - instancingAvailable = compat.vertexArrayObjectsSupported() && - compat.drawInstancedSupported() && - compat.instancedArraysSupported(); - - enabled = AllConfigs.CLIENT.experimentalRendering.get() && !OptifineHandler.usingShaders(); - } -} 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 deleted file mode 100644 index 20c7436f9..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/BufferedModel.java +++ /dev/null @@ -1,87 +0,0 @@ -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.attrib.VertexFormat; - -import net.minecraft.client.renderer.BufferBuilder; - -public abstract class BufferedModel extends TemplateBuffer { - - protected GlBuffer modelVBO; - protected boolean removed; - - protected BufferedModel(BufferBuilder buf) { - super(buf); - if (vertexCount > 0) init(); - } - - protected void init() { - - modelVBO = new GlBuffer(GL20.GL_ARRAY_BUFFER); - - modelVBO.with(vbo -> initModel()); - } - - 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 abstract void copyVertex(ByteBuffer to, int index); - - protected abstract VertexFormat getModelFormat(); - - protected int getTotalShaderAttributeCount() { - return getModelFormat().getShaderAttributeCount(); - } - - /** - * Renders this model, checking first if there is anything to render. - */ - public final void render() { - if (vertexCount == 0 || removed) return; - - doRender(); - } - - /** - * Set up any state and make the draw calls. - */ - protected abstract void doRender(); - - protected void setupAttributes() { - int numAttributes = getTotalShaderAttributeCount(); - for (int i = 0; i <= numAttributes; i++) { - GL20.glEnableVertexAttribArray(i); - } - - getModelFormat().vertexAttribPointers(0); - } - - public final 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 deleted file mode 100644 index ee9fc282f..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/FastRenderDispatcher.java +++ /dev/null @@ -1,72 +0,0 @@ -package com.simibubi.create.foundation.render.backend; - -import java.util.concurrent.ConcurrentHashMap; - -import com.simibubi.create.CreateClient; -import com.simibubi.create.content.contraptions.KineticDebugger; -import com.simibubi.create.foundation.render.KineticRenderer; -import com.simibubi.create.foundation.utility.WorldAttached; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.world.ClientWorld; -import net.minecraft.entity.Entity; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.world.World; - -public class FastRenderDispatcher { - - public static WorldAttached> queuedUpdates = new WorldAttached<>(ConcurrentHashMap::newKeySet); - - public static void enqueueUpdate(TileEntity te) { - queuedUpdates.get(te.getWorld()).add(te); - } - - public static void tick() { - Minecraft mc = Minecraft.getInstance(); - ClientWorld world = mc.world; - - KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world); - - Entity renderViewEntity = mc.renderViewEntity; - kineticRenderer.tick(renderViewEntity.getX(), renderViewEntity.getY(), renderViewEntity.getZ()); - - ConcurrentHashMap.KeySetView map = queuedUpdates.get(world); - map - .forEach(te -> { - map.remove(te); - - kineticRenderer.update(te); - }); - } - - public static boolean available() { - return Backend.canUseInstancing(); - } - - public static boolean available(World world) { - return Backend.canUseInstancing() && Backend.isFlywheelWorld(world); - } - - 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; - - ClientWorld world = Minecraft.getInstance().world; - KineticRenderer kineticRenderer = CreateClient.kineticRenderer.get(world); - - layer.startDrawing(); - - kineticRenderer.render(layer, viewProjection, cameraX, cameraY, cameraZ); - - layer.endDrawing(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/MaterialType.java b/src/main/java/com/simibubi/create/foundation/render/backend/MaterialType.java deleted file mode 100644 index f3c770051..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/MaterialType.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.simibubi.create.foundation.render.backend; - -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class MaterialType> { - - @Override - public int hashCode() { - return super.hashCode() * 31 * 493286711; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/MaterialTypes.java b/src/main/java/com/simibubi/create/foundation/render/backend/MaterialTypes.java deleted file mode 100644 index e524b295c..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/MaterialTypes.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.simibubi.create.foundation.render.backend; - -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class MaterialTypes { - public static final MaterialType> TRANSFORMED = new MaterialType<>(); - public static final MaterialType> ORIENTED = new MaterialType<>(); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/OptifineHandler.java b/src/main/java/com/simibubi/create/foundation/render/backend/OptifineHandler.java deleted file mode 100644 index 58cc82188..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/OptifineHandler.java +++ /dev/null @@ -1,86 +0,0 @@ -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/RenderUtil.java b/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java deleted file mode 100644 index 9ed534cde..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/RenderUtil.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.simibubi.create.foundation.render.backend; - -import java.util.function.Supplier; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.utility.AngleHelper; -import com.simibubi.create.foundation.utility.MatrixStacker; - -import net.minecraft.util.Direction; -import net.minecraft.util.math.vector.Matrix3f; -import net.minecraft.util.math.vector.Matrix4f; - -public class RenderUtil { - public static int nextPowerOf2(int a) { - int h = Integer.highestOneBit(a); - return (h == a) ? h : (h << 1); - } - - public static boolean isPowerOf2(int n) { - int b = n & (n - 1); - return b == 0 && n != 0; - } - - public static float[] writeMatrixStack(MatrixStack stack) { - return writeMatrixStack(stack.peek().getModel(), stack.peek().getNormal()); - } - - // GPUs want matrices in column major order. - public static float[] writeMatrixStack(Matrix4f model, Matrix3f normal) { - return new float[]{ - model.a00, - model.a10, - model.a20, - model.a30, - model.a01, - model.a11, - model.a21, - model.a31, - model.a02, - model.a12, - model.a22, - model.a32, - model.a03, - model.a13, - model.a23, - model.a33, - normal.a00, - normal.a10, - normal.a20, - normal.a01, - normal.a11, - normal.a21, - normal.a02, - normal.a12, - normal.a22, - }; - } - - public static float[] writeMatrix(Matrix4f model) { - return new float[]{ - model.a00, - model.a10, - model.a20, - model.a30, - model.a01, - model.a11, - model.a21, - model.a31, - model.a02, - model.a12, - model.a22, - model.a32, - model.a03, - model.a13, - model.a23, - model.a33, - }; - } - - public static Supplier rotateToFace(Direction facing) { - return () -> { - MatrixStack stack = new MatrixStack(); - MatrixStacker.of(stack) - .centre() - .rotateY(AngleHelper.horizontalAngle(facing)) - .rotateX(AngleHelper.verticalAngle(facing)) - .unCentre(); - return stack; - }; - } -} 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 deleted file mode 100644 index b20f1d64e..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/RenderWork.java +++ /dev/null @@ -1,21 +0,0 @@ -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/ShaderLoader.java b/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java deleted file mode 100644 index a3bf9b096..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/ShaderLoader.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.simibubi.create.foundation.render.backend; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringReader; -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; -import java.util.ArrayList; -import java.util.Collection; -import java.util.EnumMap; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.lwjgl.system.MemoryUtil; - -import com.google.common.collect.Lists; -import com.mojang.blaze3d.systems.RenderSystem; -import com.simibubi.create.foundation.render.backend.gl.GlFogMode; -import com.simibubi.create.foundation.render.backend.gl.shader.FogSensitiveProgram; -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.IMultiProgram; -import com.simibubi.create.foundation.render.backend.gl.shader.ProgramSpec; -import com.simibubi.create.foundation.render.backend.gl.shader.ShaderConstants; -import com.simibubi.create.foundation.render.backend.gl.shader.ShaderType; -import com.simibubi.create.foundation.render.backend.gl.shader.SingleProgram; - -import net.minecraft.resources.IResource; -import net.minecraft.resources.IResourceManager; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.resource.IResourceType; -import net.minecraftforge.resource.VanillaResourceType; - -public class ShaderLoader { - public static final String SHADER_DIR = "flywheel/shaders/"; - public static final ArrayList EXTENSIONS = Lists.newArrayList(".vert", ".vsh", ".frag", ".fsh", ".glsl"); - - // #flwinclude <"valid_namespace:valid/path_to_file.glsl"> - private static final Pattern includePattern = Pattern.compile("#flwinclude <\"([\\w\\d_]+:[\\w\\d_./]+)\">"); - - final Map shaderSource = new HashMap<>(); - - void onResourceManagerReload(IResourceManager manager, Predicate predicate) { - if (predicate.test(VanillaResourceType.SHADERS)) { - OptifineHandler.refresh(); - Backend.refresh(); - - if (Backend.gl20()) { - shaderSource.clear(); - loadShaderSources(manager); - - Backend.programs.values().forEach(IMultiProgram::delete); - Backend.programs.clear(); - Backend.registry.values().forEach(this::loadProgramFromSpec); - - Backend.log.info("Loaded all shader programs."); - } - } - } - - private void loadShaderSources(IResourceManager manager) { - Collection allShaders = manager.getAllResourceLocations(SHADER_DIR, s -> { - for (String ext : EXTENSIONS) { - if (s.endsWith(ext)) return true; - } - return false; - }); - - for (ResourceLocation location : allShaders) { - try { - IResource resource = manager.getResource(location); - - String file = readToString(resource.getInputStream()); - - ResourceLocation name = new ResourceLocation(location.getNamespace(), - location.getPath().substring(SHADER_DIR.length())); - - shaderSource.put(name, file); - } catch (IOException e) { - - } - } - } - - private

> void loadProgramFromSpec(S programSpec) { - - if (programSpec.fogSensitive) { - Map programGroup = new EnumMap<>(GlFogMode.class); - - for (GlFogMode fogMode : GlFogMode.values()) { - programGroup.put(fogMode, loadProgram(programSpec, fogMode)); - } - - Backend.programs.put(programSpec, new FogSensitiveProgram<>(programGroup)); - } else { - P program = loadProgram(programSpec, GlFogMode.NONE); - - Backend.programs.put(programSpec, new SingleProgram<>(program)); - } - - Backend.log.debug("Loaded program {}", programSpec.name); - } - - private

> P loadProgram(S programSpec, GlFogMode fogMode) { - GlShader vert = null; - GlShader frag = null; - try { - ShaderConstants defines = new ShaderConstants(programSpec.defines); - - defines.defineAll(fogMode.getDefines()); - - vert = loadShader(programSpec.getVert(), ShaderType.VERTEX, defines); - frag = loadShader(programSpec.getFrag(), ShaderType.FRAGMENT, defines); - - GlProgram.Builder builder = GlProgram.builder(programSpec.name, fogMode).attachShader(vert).attachShader(frag); - - programSpec.attributes.forEach(builder::addAttribute); - - return builder.build(programSpec.factory); - - } finally { - if (vert != null) vert.delete(); - if (frag != null) frag.delete(); - } - } - - private String processIncludes(ResourceLocation baseName, String source) { - HashSet seen = new HashSet<>(); - seen.add(baseName); - - return includeRecursive(source, seen).collect(Collectors.joining("\n")); - } - - private Stream includeRecursive(String source, Set seen) { - return new BufferedReader(new StringReader(source)).lines().flatMap(line -> { - - Matcher matcher = includePattern.matcher(line); - - if (matcher.find()) { - String includeName = matcher.group(1); - - ResourceLocation include = new ResourceLocation(includeName); - - if (seen.add(include)) { - String includeSource = shaderSource.get(include); - - if (includeSource != null) { - return includeRecursive(includeSource, seen); - } - } - } - - return Stream.of(line); - }); - } - - private GlShader loadShader(ResourceLocation name, ShaderType type, ShaderConstants defines) { - String source = shaderSource.get(name); - - source = processIncludes(name, source); - - if (defines != null) - source = defines.process(source); - - - return new GlShader(type, name, source); - } - - public String readToString(InputStream is) { - RenderSystem.assertThread(RenderSystem::isOnRenderThread); - ByteBuffer bytebuffer = null; - - try { - bytebuffer = readToBuffer(is); - int i = bytebuffer.position(); - ((Buffer) bytebuffer).rewind(); - return MemoryUtil.memASCII(bytebuffer, i); - } catch (IOException e) { - - } finally { - if (bytebuffer != null) { - MemoryUtil.memFree(bytebuffer); - } - - } - - return null; - } - - public ByteBuffer readToBuffer(InputStream is) throws IOException { - ByteBuffer bytebuffer; - if (is instanceof FileInputStream) { - FileInputStream fileinputstream = (FileInputStream) is; - FileChannel filechannel = fileinputstream.getChannel(); - bytebuffer = MemoryUtil.memAlloc((int) filechannel.size() + 1); - - while (filechannel.read(bytebuffer) != -1) { - } - } else { - bytebuffer = MemoryUtil.memAlloc(8192); - ReadableByteChannel readablebytechannel = Channels.newChannel(is); - - while (readablebytechannel.read(bytebuffer) != -1) { - if (bytebuffer.remaining() == 0) { - bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2); - } - } - } - - return bytebuffer; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/BasicAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/BasicAttributes.java deleted file mode 100644 index 8721aac88..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/BasicAttributes.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; -import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; - -public enum BasicAttributes implements IVertexAttrib { - LIGHT("aLight", CommonAttributes.LIGHT), - COLOR("aColor", CommonAttributes.RGBA), - ; - - private final String name; - private final IAttribSpec spec; - - BasicAttributes(String name, IAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 0; - } - - @Override - public int getBufferIndex() { - return 0; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/BasicData.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/BasicData.java deleted file mode 100644 index 531b2d929..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/BasicData.java +++ /dev/null @@ -1,78 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import java.nio.ByteBuffer; - -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class BasicData extends InstanceData implements IFlatLight { - - protected byte blockLight; - protected byte skyLight; - - protected byte r = (byte) 0xFF; - protected byte g = (byte) 0xFF; - protected byte b = (byte) 0xFF; - protected byte a = (byte) 0xFF; - - public BasicData(InstancedModel owner) { - super(owner); - } - - @Override - public BasicData setBlockLight(int blockLight) { - this.blockLight = (byte) (blockLight << 4); - markDirty(); - return this; - } - - @Override - public BasicData setSkyLight(int skyLight) { - this.skyLight = (byte) (skyLight << 4); - markDirty(); - return this; - } - - public BasicData setColor(int color) { - return setColor(color, false); - } - - public BasicData setColor(int color, boolean alpha) { - byte r = (byte) ((color >> 16) & 0xFF); - byte g = (byte) ((color >> 8) & 0xFF); - byte b = (byte) (color & 0xFF); - - if (alpha) { - byte a = (byte) ((color >> 24) & 0xFF); - return setColor(r, g, b, a); - } else { - return setColor(r, g, b); - } - } - - public BasicData setColor(int r, int g, int b) { - return setColor((byte) r, (byte) g, (byte) b); - } - - public BasicData setColor(byte r, byte g, byte b) { - this.r = r; - this.g = g; - this.b = b; - markDirty(); - return this; - } - - public BasicData setColor(byte r, byte g, byte b, byte a) { - this.r = r; - this.g = g; - this.b = b; - this.a = a; - markDirty(); - return this; - } - - @Override - public void write(ByteBuffer buf) { - buf.put(new byte[]{blockLight, skyLight, r, g, b, a}); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/IFlatLight.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/IFlatLight.java deleted file mode 100644 index fbbdd58b2..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/IFlatLight.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; - -/** - * An interface that implementors of {@link InstanceData} should also implement - * if they wish to make use of Flywheel's provided light update methods. - *

- * This only covers flat lighting, smooth lighting is still TODO. - * - * @param The name of the class that implements this interface. - */ -public interface IFlatLight> { - /** - * @param blockLight An integer in the range [0, 15] representing the - * amount of block light this instance should receive. - * @return this - */ - D setBlockLight(int blockLight); - - /** - * @param skyLight An integer in the range [0, 15] representing the - * amount of sky light this instance should receive. - * @return this - */ - D setSkyLight(int skyLight); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/ModelAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/ModelAttributes.java deleted file mode 100644 index 970fd672e..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/ModelAttributes.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; -import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.VertexAttribSpec; - -public enum ModelAttributes implements IVertexAttrib { - VERTEX_POSITION("aPos", CommonAttributes.VEC3), - NORMAL("aNormal", CommonAttributes.NORMAL), - TEXTURE("aTexCoords", CommonAttributes.UV), - ; - - private final String name; - private final VertexAttribSpec spec; - - ModelAttributes(String name, VertexAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 0; - } - - @Override - public int getBufferIndex() { - return 0; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/ModelData.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/ModelData.java deleted file mode 100644 index c2f338bf6..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/ModelData.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import java.nio.ByteBuffer; - -import com.mojang.blaze3d.matrix.MatrixStack; -import com.simibubi.create.foundation.render.backend.RenderUtil; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class ModelData extends BasicData { - private static final float[] empty = new float[25]; - - private float[] matrices = empty; - - public ModelData(InstancedModel owner) { - super(owner); - } - - public ModelData setTransform(MatrixStack stack) { - matrices = RenderUtil.writeMatrixStack(stack); - markDirty(); - return this; - } - - @Override - public void write(ByteBuffer buf) { - super.write(buf); - buf.asFloatBuffer().put(matrices); - buf.position(buf.position() + matrices.length * 4); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedAttributes.java deleted file mode 100644 index 135958501..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedAttributes.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import com.simibubi.create.foundation.render.backend.gl.attrib.CommonAttributes; -import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; - -public enum OrientedAttributes implements IVertexAttrib { - INSTANCE_POS("aInstancePos", CommonAttributes.VEC3), - PIVOT("aPivot", CommonAttributes.VEC3), - ROTATION("aRotation", CommonAttributes.QUATERNION), - ; - - private final String name; - private final IAttribSpec spec; - - OrientedAttributes(String name, IAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 0; - } - - @Override - public int getBufferIndex() { - return 0; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedData.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedData.java deleted file mode 100644 index 77becf79e..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedData.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import java.nio.ByteBuffer; - -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Quaternion; -import net.minecraft.util.math.vector.Vector3d; -import net.minecraft.util.math.vector.Vector3f; - -public class OrientedData extends BasicData { - - private float posX; - private float posY; - private float posZ; - private float pivotX = 0.5f; - private float pivotY = 0.5f; - private float pivotZ = 0.5f; - private float qX; - private float qY; - private float qZ; - private float qW; - - - public OrientedData(InstancedModel owner) { - super(owner); - } - - - public OrientedData setPosition(BlockPos pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } - - public OrientedData setPosition(Vector3f pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } - - public OrientedData setPosition(float x, float y, float z) { - this.posX = x; - this.posY = y; - this.posZ = z; - markDirty(); - return this; - } - - public OrientedData nudge(float x, float y, float z) { - this.posX += x; - this.posY += y; - this.posZ += z; - markDirty(); - return this; - } - - public OrientedData setPivot(Vector3f pos) { - return setPosition(pos.getX(), pos.getY(), pos.getZ()); - } - - public OrientedData setPivot(Vector3d pos) { - return setPosition((float) pos.getX(), (float) pos.getY(), (float) pos.getZ()); - } - - public OrientedData setPivot(float x, float y, float z) { - this.pivotX = x; - this.pivotY = y; - this.pivotZ = z; - markDirty(); - return this; - } - - public OrientedData setRotation(Quaternion q) { - return setRotation(q.getX(), q.getY(), q.getZ(), q.getW()); - } - - public OrientedData setRotation(float x, float y, float z, float w) { - this.qX = x; - this.qY = y; - this.qZ = z; - this.qW = w; - markDirty(); - return this; - } - - @Override - public void write(ByteBuffer buf) { - super.write(buf); - - buf.asFloatBuffer().put(new float[]{ - posX, - posY, - posZ, - pivotX, - pivotY, - pivotZ, - qX, - qY, - qZ, - qW - }); - - buf.position(buf.position() + 10 * 4); - } -} - diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedModel.java deleted file mode 100644 index 42ee8334b..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/OrientedModel.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -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 OrientedModel extends InstancedModel { - public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder() - .addAttributes(BasicAttributes.class) - .addAttributes(OrientedAttributes.class) - .build(); - - public OrientedModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected OrientedData newInstance() { - return new OrientedData(this); - } - - @Override - protected VertexFormat getInstanceFormat() { - return INSTANCE_FORMAT; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/PartialModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/PartialModel.java deleted file mode 100644 index 87fafb9dd..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/PartialModel.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.util.ResourceLocation; -import net.minecraftforge.client.event.ModelBakeEvent; -import net.minecraftforge.client.event.ModelRegistryEvent; -import net.minecraftforge.client.model.ModelLoader; - -/** - * A helper class for loading and accessing json models. - *

- * Creating a PartialModel will make the associated modelLocation automatically load. - * As such, PartialModels must be initialized at or before {@link ModelRegistryEvent}. - * Once {@link ModelBakeEvent} finishes, all PartialModels (with valid modelLocations) - * will have their bakedModel fields populated. - *

- * Attempting to create a PartialModel after ModelRegistryEvent will cause an error. - */ -public class PartialModel { - - private static boolean tooLate = false; - private static final List all = new ArrayList<>(); - - protected final ResourceLocation modelLocation; - protected IBakedModel bakedModel; - - public PartialModel(ResourceLocation modelLocation) { - - if (tooLate) throw new RuntimeException("PartialModel '" + modelLocation + "' loaded after ModelRegistryEvent"); - - this.modelLocation = modelLocation; - all.add(this); - } - - public static void onModelRegistry(ModelRegistryEvent event) { - for (PartialModel partial : all) - ModelLoader.addSpecialModel(partial.modelLocation); - - tooLate = true; - } - - public static void onModelBake(ModelBakeEvent event) { - Map modelRegistry = event.getModelRegistry(); - for (PartialModel partial : all) - partial.bakedModel = modelRegistry.get(partial.modelLocation); - } - - public IBakedModel get() { - return bakedModel; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/TransformAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/TransformAttributes.java deleted file mode 100644 index f35cdf988..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/TransformAttributes.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -import com.simibubi.create.foundation.render.backend.gl.attrib.IAttribSpec; -import com.simibubi.create.foundation.render.backend.gl.attrib.IVertexAttrib; -import com.simibubi.create.foundation.render.backend.gl.attrib.MatrixAttributes; - -public enum TransformAttributes implements IVertexAttrib { - TRANSFORM("aTransform", MatrixAttributes.MAT4), - NORMAL_MAT("aNormalMat", MatrixAttributes.MAT3), - ; - - private final String name; - private final IAttribSpec spec; - - TransformAttributes(String name, IAttribSpec spec) { - this.name = name; - this.spec = spec; - } - - @Override - public String attribName() { - return name; - } - - @Override - public IAttribSpec attribSpec() { - return spec; - } - - @Override - public int getDivisor() { - return 0; - } - - @Override - public int getBufferIndex() { - return 0; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/core/TransformedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/core/TransformedModel.java deleted file mode 100644 index e5fd44ed1..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/core/TransformedModel.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.simibubi.create.foundation.render.backend.core; - -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 TransformedModel extends InstancedModel { - public static final VertexFormat INSTANCE_FORMAT = VertexFormat.builder() - .addAttributes(BasicAttributes.class) - .addAttributes(TransformAttributes.class) - .build(); - - public TransformedModel(InstancedTileRenderer renderer, BufferBuilder buf) { - super(renderer, buf); - } - - @Override - protected ModelData newInstance() { - return new ModelData(this); - } - - @Override - protected VertexFormat getInstanceFormat() { - return INSTANCE_FORMAT; - } -} 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 deleted file mode 100644 index 3cd58940f..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/BasicProgram.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl; - -import org.lwjgl.opengl.GL20; - -import com.simibubi.create.foundation.render.backend.RenderUtil; -import com.simibubi.create.foundation.render.backend.gl.shader.GlProgram; -import com.simibubi.create.foundation.render.backend.gl.shader.ProgramFogMode; -import com.simibubi.create.foundation.utility.AnimationTickHolder; - -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.vector.Matrix4f; - -public class BasicProgram extends GlProgram { - protected final int uTime; - protected final int uViewProjection; - protected final int uDebug; - protected final int uCameraPos; - - protected final ProgramFogMode fogMode; - - protected int uBlockAtlas; - protected int uLightMap; - - public BasicProgram(ResourceLocation name, int handle, ProgramFogMode.Factory fogFactory) { - super(name, handle); - uTime = getUniformLocation("uTime"); - uViewProjection = getUniformLocation("uViewProjection"); - uDebug = getUniformLocation("uDebug"); - uCameraPos = getUniformLocation("uCameraPos"); - - fogMode = fogFactory.create(this); - - 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.getRenderTime()); - - uploadMatrixUniform(uViewProjection, viewProjection); - GL20.glUniform3f(uCameraPos, (float) camX, (float) camY, (float) camZ); - - fogMode.bind(); - } - - protected static void uploadMatrixUniform(int uniform, Matrix4f mat) { - GL20.glUniformMatrix4fv(uniform, false, RenderUtil.writeMatrix(mat)); - } -} 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 deleted file mode 100644 index 6d045be02..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlBuffer.java +++ /dev/null @@ -1,48 +0,0 @@ -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.compat.mapBuffer(bufferType, 0, length, upload); - } - - public void map(int offset, int length, Consumer upload) { - Backend.compat.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 deleted file mode 100644 index 6dfab5be8..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFog.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl; - -import org.lwjgl.opengl.GL11; - -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 getFogModeGlEnum() { - 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; - } - - public static GlFogMode getFogMode() { - if (!fogEnabled()) { - return GlFogMode.NONE; - } - - int mode = getFogModeGlEnum(); - - switch (mode) { - case GL11.GL_EXP2: - case GL11.GL_EXP: - return GlFogMode.EXP2; - case GL11.GL_LINEAR: - return GlFogMode.LINEAR; - default: - throw new UnsupportedOperationException("Unknown fog mode: " + mode); - } - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFogMode.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFogMode.java deleted file mode 100644 index eb333c732..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlFogMode.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl; - -import java.util.Collections; -import java.util.List; - -import com.google.common.collect.Lists; -import com.simibubi.create.foundation.render.backend.gl.shader.ProgramFogMode; - -public enum GlFogMode { - NONE(ProgramFogMode.None::new), - LINEAR(ProgramFogMode.Linear::new, "USE_FOG_LINEAR"), - EXP2(ProgramFogMode.Exp2::new, "USE_FOG_EXP2"), - ; - - public static final String USE_FOG = "USE_FOG"; - - private final ProgramFogMode.Factory fogFactory; - private final List defines; - - GlFogMode(ProgramFogMode.Factory fogFactory) { - this.fogFactory = fogFactory; - this.defines = Collections.emptyList(); - } - - GlFogMode(ProgramFogMode.Factory fogFactory, String name) { - this.fogFactory = fogFactory; - this.defines = Lists.newArrayList(USE_FOG, name); - } - - public List getDefines() { - return defines; - } - - public ProgramFogMode.Factory getFogFactory() { - return fogFactory; - } -} 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 deleted file mode 100644 index 5bc642869..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlObject.java +++ /dev/null @@ -1,43 +0,0 @@ -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 deleted file mode 100644 index da1d0efba..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlPrimitiveType.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl; - -import org.lwjgl.opengl.GL11; - -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -public enum GlPrimitiveType { - FLOAT(4, "float", GL11.GL_FLOAT), - UBYTE(1, "ubyte", GL11.GL_UNSIGNED_BYTE), - BYTE(1, "byte", GL11.GL_BYTE), - USHORT(2, "ushort", GL11.GL_UNSIGNED_SHORT), - SHORT(2, "short", GL11.GL_SHORT), - UINT(4, "uint", GL11.GL_UNSIGNED_INT), - INT(4, "int", GL11.GL_INT); - - private final int size; - private final String displayName; - private final int glConstant; - - GlPrimitiveType(int bytes, String name, int glEnum) { - this.size = bytes; - this.displayName = name; - this.glConstant = glEnum; - } - - public int getSize() { - return this.size; - } - - public String getDisplayName() { - return this.displayName; - } - - public int getGlConstant() { - return this.glConstant; - } -} 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 deleted file mode 100644 index 67fbd8dc5..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlTexture.java +++ /dev/null @@ -1,25 +0,0 @@ -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 deleted file mode 100644 index 54bb20b81..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/GlVertexArray.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl; - -import java.util.function.Consumer; - -import com.simibubi.create.foundation.render.backend.Backend; - -public class GlVertexArray extends GlObject { - public GlVertexArray() { - setHandle(Backend.compat.genVertexArrays()); - } - - public void bind() { - Backend.compat.bindVertexArray(handle()); - } - - public void unbind() { - Backend.compat.bindVertexArray(0); - } - - public void with(Consumer action) { - bind(); - action.accept(this); - unbind(); - } - - protected void deleteInternal(int handle) { - Backend.compat.deleteVertexArrays(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 deleted file mode 100644 index 5c1a3a91a..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/CommonAttributes.java +++ /dev/null @@ -1,21 +0,0 @@ -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 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 QUATERNION = new VertexAttribSpec(GlPrimitiveType.FLOAT, 4); - 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/IAttribSpec.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/IAttribSpec.java deleted file mode 100644 index 31369cd3f..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/IAttribSpec.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.attrib; - -public interface IAttribSpec { - - void vertexAttribPointer(int stride, int index, int pointer); - - int getSize(); - - int getAttributeCount(); -} 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 deleted file mode 100644 index 335ba8644..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/IVertexAttrib.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.attrib; - -public interface IVertexAttrib { - - String attribName(); - - IAttribSpec attribSpec(); - - int getDivisor(); - - int getBufferIndex(); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/MatrixAttributes.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/MatrixAttributes.java deleted file mode 100644 index 0e57cf59f..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/MatrixAttributes.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.attrib; - -import org.lwjgl.opengl.GL20; - -import com.simibubi.create.foundation.render.backend.gl.GlPrimitiveType; - -public enum MatrixAttributes implements IAttribSpec { - MAT3(3, 3), - MAT4(4, 4), - ; - - private final int rows; - private final int cols; - - MatrixAttributes(int rows, int cols) { - this.rows = rows; - this.cols = cols; - } - - @Override - public void vertexAttribPointer(int stride, int index, int pointer) { - for (int i = 0; i < rows; i++) { - long attribPointer = pointer + (long) i * cols * GlPrimitiveType.FLOAT.getSize(); - GL20.glVertexAttribPointer(index + i, cols, GlPrimitiveType.FLOAT.getGlConstant(), false, stride, attribPointer); - } - } - - @Override - public int getSize() { - return GlPrimitiveType.FLOAT.getSize() * rows * cols; - } - - @Override - public int getAttributeCount() { - return rows; - } -} 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 deleted file mode 100644 index a9b451d01..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexAttribSpec.java +++ /dev/null @@ -1,41 +0,0 @@ -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 implements IAttribSpec { - - 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; - } - - @Override - public void vertexAttribPointer(int stride, int index, int pointer) { - GL20.glVertexAttribPointer(index, count, type.getGlConstant(), normalized, stride, pointer); - } - - @Override - public int getSize() { - return size; - } - - @Override - 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 deleted file mode 100644 index 9a3fc8601..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/attrib/VertexFormat.java +++ /dev/null @@ -1,65 +0,0 @@ -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) { - IAttribSpec 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) { - IAttribSpec 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/FogSensitiveProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/FogSensitiveProgram.java deleted file mode 100644 index 9e43e520b..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/FogSensitiveProgram.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.shader; - -import java.util.Map; - -import com.simibubi.create.foundation.render.backend.gl.GlFog; -import com.simibubi.create.foundation.render.backend.gl.GlFogMode; - -public class FogSensitiveProgram

implements IMultiProgram

{ - - private final Map programs; - - public FogSensitiveProgram(Map programs) { - this.programs = programs; - } - - @Override - public P get() { - return programs.get(GlFog.getFogMode()); - } - - @Override - public void delete() { - programs.values().forEach(GlProgram::delete); - } - -} 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 deleted file mode 100644 index 30037b7c2..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GLSLType.java +++ /dev/null @@ -1,45 +0,0 @@ -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 deleted file mode 100644 index 007d94d44..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlProgram.java +++ /dev/null @@ -1,129 +0,0 @@ -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.GlFogMode; -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, GlFogMode fogMode) { - return new Builder(name, fogMode); - } - - 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.debug("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 final GlFogMode fogMode; - - private int attributeIndex; - - public Builder(ResourceLocation name, GlFogMode fogMode) { - this.name = name; - this.program = GL20.glCreateProgram(); - this.fogMode = fogMode; - } - - 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.debug("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, this.fogMode.getFogFactory()); - } - } - - @FunctionalInterface - public interface ProgramFactory

{ - P create(ResourceLocation name, int handle, ProgramFogMode.Factory fogFactory); - } -} 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 deleted file mode 100644 index 208b3843d..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/GlShader.java +++ /dev/null @@ -1,50 +0,0 @@ -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.versioned.GlCompat; - -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) { - this.type = type; - this.name = name; - int handle = GL20.glCreateShader(type.glEnum); - - GlCompat.safeShaderSource(handle, source); - GL20.glCompileShader(handle); - - String log = GL20.glGetShaderInfoLog(handle); - - if (!log.isEmpty()) { - Backend.log.error("Shader compilation log for " + name + ": " + log); - } - - if (GL20.glGetShaderi(handle, GL20.GL_COMPILE_STATUS) != GL20.GL_TRUE) { - throw new RuntimeException("Could not compile shader. See log for details."); - } - - 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/IMultiProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/IMultiProgram.java deleted file mode 100644 index 072c8ab31..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/IMultiProgram.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.shader; - -/** - * Encapsulates any number of shader programs for use in similar contexts. - * Allows the implementor to choose which shader program to use based on arbitrary state. - * - * @param

- */ -public interface IMultiProgram

{ - - /** - * Get the shader program most suited for the current game state. - * - * @return The one true program. - */ - P get(); - - /** - * Delete all shader programs encapsulated by your implementation. - */ - void delete(); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramFogMode.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramFogMode.java deleted file mode 100644 index f0cb24123..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramFogMode.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.shader; - -import org.lwjgl.opengl.GL20; - -import com.simibubi.create.foundation.render.backend.gl.GlFog; - -public abstract class ProgramFogMode { - - public abstract void bind(); - - public static class None extends ProgramFogMode { - - public None(GlProgram program) { - - } - - @Override - public void bind() { - - } - } - - public static class Linear extends ProgramFogMode { - private final int uFogColor; - private final int uFogRange; - - public Linear(GlProgram program) { - this.uFogColor = program.getUniformLocation("uFogColor"); - this.uFogRange = program.getUniformLocation("uFogRange"); - } - - @Override - public void bind() { - GL20.glUniform2f(uFogRange, GlFog.getFogStart(), GlFog.getFogEnd()); - GL20.glUniform4fv(uFogColor, GlFog.FOG_COLOR); - } - } - - public static class Exp2 extends ProgramFogMode { - private final int uFogColor; - private final int uFogDensity; - - public Exp2(GlProgram program) { - this.uFogColor = program.getUniformLocation("uFogColor"); - this.uFogDensity = program.getUniformLocation("uFogDensity"); - } - - @Override - public void bind() { - GL20.glUniform1f(uFogDensity, GlFog.getFogDensity()); - GL20.glUniform4fv(uFogColor, GlFog.FOG_COLOR); - } - } - - public interface Factory { - ProgramFogMode create(GlProgram program); - } -} 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 deleted file mode 100644 index 354649175..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ProgramSpec.java +++ /dev/null @@ -1,97 +0,0 @@ -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 final boolean fogSensitive; - - 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, boolean fogSensitive) { - this.name = name; - this.vert = vert; - this.frag = frag; - this.defines = defines; - - this.factory = factory; - this.attributes = attributes; - this.fogSensitive = fogSensitive; - } - - public ResourceLocation getVert() { - return vert; - } - - public ResourceLocation getFrag() { - return frag; - } - - public static class Builder

{ - private ResourceLocation vert; - private ResourceLocation frag; - private ShaderConstants defines = ShaderConstants.EMPTY; - private boolean fogSensitive = true; - - 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 Builder

setFogSensitive(boolean fogSensitive) { - this.fogSensitive = fogSensitive; - 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, fogSensitive); - } - } -} 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 deleted file mode 100644 index e6e17c096..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderCallback.java +++ /dev/null @@ -1,17 +0,0 @@ -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 deleted file mode 100644 index 3d1780628..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderConstants.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.shader; - -import java.io.BufferedReader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Collection; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.google.common.collect.Lists; - -public class ShaderConstants implements GlShader.PreProcessor { - public static final ShaderConstants EMPTY = new ShaderConstants(); - - private final ArrayList defines; - - public ShaderConstants() { - defines = new ArrayList<>(); - } - - public ShaderConstants(ShaderConstants other) { - this.defines = Lists.newArrayList(other.defines); - } - - public static ShaderConstants define(String def) { - return new ShaderConstants().def(def); - } - - public ShaderConstants def(String def) { - defines.add(def); - return this; - } - - public ShaderConstants defineAll(Collection defines) { - this.defines.addAll(defines); - 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 deleted file mode 100644 index 63be397f2..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/ShaderType.java +++ /dev/null @@ -1,15 +0,0 @@ -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/shader/SingleProgram.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/SingleProgram.java deleted file mode 100644 index c3ee700ab..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/shader/SingleProgram.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.shader; - -public class SingleProgram

implements IMultiProgram

{ - final P program; - - public SingleProgram(P program) { - this.program = program; - } - - @Override - public P get() { - return program; - } - - @Override - public void delete() { - program.delete(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/DrawInstanced.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/DrawInstanced.java deleted file mode 100644 index 166bd919c..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/DrawInstanced.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.versioned; - -import org.lwjgl.opengl.ARBDrawInstanced; -import org.lwjgl.opengl.EXTDrawInstanced; -import org.lwjgl.opengl.GL31; -import org.lwjgl.opengl.GLCapabilities; - -public enum DrawInstanced implements GlVersioned { - GL31_DRAW_INSTANCED { - @Override - public boolean supported(GLCapabilities caps) { - return caps.OpenGL31; - } - - @Override - public void drawArraysInstanced(int mode, int first, int count, int primcount) { - GL31.glDrawArraysInstanced(mode, first, count, primcount); - } - }, - ARB_DRAW_INSTANCED { - @Override - public boolean supported(GLCapabilities caps) { - return caps.GL_ARB_draw_instanced; - } - - @Override - public void drawArraysInstanced(int mode, int first, int count, int primcount) { - ARBDrawInstanced.glDrawArraysInstancedARB(mode, first, count, primcount); - } - }, - EXT_DRAW_INSTANCED { - @Override - public boolean supported(GLCapabilities caps) { - return caps.GL_EXT_draw_instanced; - } - - @Override - public void drawArraysInstanced(int mode, int first, int count, int primcount) { - EXTDrawInstanced.glDrawArraysInstancedEXT(mode, first, count, primcount); - } - }, - UNSUPPORTED { - @Override - public boolean supported(GLCapabilities caps) { - return true; - } - - @Override - public void drawArraysInstanced(int mode, int first, int count, int primcount) { - throw new UnsupportedOperationException(); - } - }; - - public abstract void drawArraysInstanced(int mode, int first, int count, int primcount); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlCompat.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlCompat.java deleted file mode 100644 index 59b2771ee..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlCompat.java +++ /dev/null @@ -1,121 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.versioned; - -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.function.Consumer; - -import org.lwjgl.PointerBuffer; -import org.lwjgl.opengl.GL20C; -import org.lwjgl.opengl.GLCapabilities; -import org.lwjgl.system.MemoryStack; -import org.lwjgl.system.MemoryUtil; - -/** - * An instance of this class stores information - * about what OpenGL features are available. - *

- * Each field stores an enum variant that provides access to the - * most appropriate version of a feature for the current system. - */ -public class GlCompat { - public final MapBuffer mapBuffer; - - public final VertexArrayObject vertexArrayObject; - public final InstancedArrays instancedArrays; - public final DrawInstanced drawInstanced; - - public final RGPixelFormat pixelFormat; - - public GlCompat(GLCapabilities caps) { - mapBuffer = getLatest(MapBuffer.class, caps); - - vertexArrayObject = getLatest(VertexArrayObject.class, caps); - instancedArrays = getLatest(InstancedArrays.class, caps); - drawInstanced = getLatest(DrawInstanced.class, caps); - - pixelFormat = getLatest(RGPixelFormat.class, caps); - } - - public void mapBuffer(int target, int offset, int length, Consumer upload) { - mapBuffer.mapBuffer(target, offset, length, upload); - } - - public void vertexAttribDivisor(int index, int divisor) { - instancedArrays.vertexAttribDivisor(index, divisor); - } - - public void drawArraysInstanced(int mode, int first, int count, int primcount) { - drawInstanced.drawArraysInstanced(mode, first, count, primcount); - } - - public int genVertexArrays() { - return vertexArrayObject.genVertexArrays(); - } - - public void deleteVertexArrays(int array) { - vertexArrayObject.deleteVertexArrays(array); - } - - public void bindVertexArray(int array) { - vertexArrayObject.bindVertexArray(array); - } - - public boolean vertexArrayObjectsSupported() { - return vertexArrayObject != VertexArrayObject.UNSUPPORTED; - } - - public boolean instancedArraysSupported() { - return instancedArrays != InstancedArrays.UNSUPPORTED; - } - - public boolean drawInstancedSupported() { - return drawInstanced != DrawInstanced.UNSUPPORTED; - } - - /** - * 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().get(); - } - - /** - * Copied from: - *
https://github.com/grondag/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96 - * - *

Identical in function to {@link GL20C#glShaderSource(int, CharSequence)} but - * passes a null pointer for string length to force the driver to rely on the null - * terminator for string length. This is a workaround for an apparent flaw with some - * AMD drivers that don't receive or interpret the length correctly, resulting in - * an access violation when the driver tries to read past the string memory. - * - *

Hat tip to fewizz for the find and the fix. - */ - public static void safeShaderSource(int glId, CharSequence source) { - final MemoryStack stack = MemoryStack.stackGet(); - final int stackPointer = stack.getPointer(); - - try { - final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true); - final PointerBuffer pointers = stack.mallocPointer(1); - pointers.put(sourceBuffer); - - GL20C.nglShaderSource(glId, 1, pointers.address0(), 0); - org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1); - } finally { - stack.setPointer(stackPointer); - } - } -} - 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 deleted file mode 100644 index a670cd8f9..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/GlVersioned.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.versioned; - -import org.lwjgl.opengl.GLCapabilities; - -/** - * This interface should be implemented by enums such that the - * last defined variant always returns true. - */ -public interface GlVersioned { - /** - * Queries whether this variant is supported by the current system. - * - * @param caps The {@link GLCapabilities} reported by the current system. - * @return true if this variant is supported, or if this is the last defined variant. - */ - boolean supported(GLCapabilities caps); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/InstancedArrays.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/InstancedArrays.java deleted file mode 100644 index 609242bd8..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/InstancedArrays.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.versioned; - -import org.lwjgl.opengl.ARBInstancedArrays; -import org.lwjgl.opengl.GL33; -import org.lwjgl.opengl.GLCapabilities; - -public enum InstancedArrays implements GlVersioned { - GL33_INSTANCED_ARRAYS { - @Override - public boolean supported(GLCapabilities caps) { - return caps.OpenGL33; - } - - @Override - public void vertexAttribDivisor(int index, int divisor) { - GL33.glVertexAttribDivisor(index, divisor); - } - }, - ARB_INSTANCED_ARRAYS { - @Override - public boolean supported(GLCapabilities caps) { - return caps.GL_ARB_instanced_arrays; - } - - @Override - public void vertexAttribDivisor(int index, int divisor) { - ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor); - } - }, - UNSUPPORTED { - @Override - public boolean supported(GLCapabilities caps) { - return true; - } - - @Override - public void vertexAttribDivisor(int index, int divisor) { - throw new UnsupportedOperationException(); - } - }; - - public abstract void vertexAttribDivisor(int index, int divisor); -} 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 deleted file mode 100644 index dc11699fb..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/MapBuffer.java +++ /dev/null @@ -1,75 +0,0 @@ -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); - - 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); - - 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/gl/versioned/RGPixelFormat.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/RGPixelFormat.java deleted file mode 100644 index 62233e7b4..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/RGPixelFormat.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.versioned; - -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL30; -import org.lwjgl.opengl.GLCapabilities; - -public enum RGPixelFormat implements GlVersioned { - GL30_RG { - @Override - public boolean supported(GLCapabilities caps) { - return caps.OpenGL30; - } - - @Override - public int internalFormat() { - return GL30.GL_RG8; - } - - @Override - public int format() { - return GL30.GL_RG; - } - - @Override - public int byteCount() { - return 2; - } - }, - GL11_RGB { - @Override - public boolean supported(GLCapabilities caps) { - return caps.OpenGL11; - } - - @Override - public int internalFormat() { - return GL11.GL_RGB8; - } - - @Override - public int format() { - return GL11.GL_RGB; - } - - @Override - public int byteCount() { - return 3; - } - }, - UNSUPPORTED { - @Override - public boolean supported(GLCapabilities caps) { - return true; - } - - @Override - public int internalFormat() { - throw new UnsupportedOperationException(); - } - - @Override - public int format() { - throw new UnsupportedOperationException(); - } - - @Override - public int byteCount() { - throw new UnsupportedOperationException(); - } - }; - - public abstract int internalFormat(); - - public abstract int format(); - - public abstract int byteCount(); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/VertexArrayObject.java b/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/VertexArrayObject.java deleted file mode 100644 index 16f6bfd46..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/gl/versioned/VertexArrayObject.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.simibubi.create.foundation.render.backend.gl.versioned; - -import org.lwjgl.opengl.ARBVertexArrayObject; -import org.lwjgl.opengl.GL30; -import org.lwjgl.opengl.GLCapabilities; - -public enum VertexArrayObject implements GlVersioned { - GL30_VAO { - @Override - public boolean supported(GLCapabilities caps) { - return caps.OpenGL30; - } - - @Override - public int genVertexArrays() { - return GL30.glGenVertexArrays(); - } - - @Override - public void bindVertexArray(int array) { - GL30.glBindVertexArray(array); - } - - @Override - public void deleteVertexArrays(int array) { - GL30.glDeleteVertexArrays(array); - } - }, - ARB_VAO { - @Override - public boolean supported(GLCapabilities caps) { - return caps.GL_ARB_vertex_array_object; - } - - @Override - public int genVertexArrays() { - return ARBVertexArrayObject.glGenVertexArrays(); - } - - @Override - public void bindVertexArray(int array) { - ARBVertexArrayObject.glBindVertexArray(array); - } - - @Override - public void deleteVertexArrays(int array) { - ARBVertexArrayObject.glDeleteVertexArrays(array); - } - }, - UNSUPPORTED { - @Override - public boolean supported(GLCapabilities caps) { - return true; - } - - @Override - public int genVertexArrays() { - throw new UnsupportedOperationException(); - } - - @Override - public void bindVertexArray(int array) { - throw new UnsupportedOperationException(); - } - - @Override - public void deleteVertexArrays(int array) { - throw new UnsupportedOperationException(); - } - }; - - public abstract int genVertexArrays(); - - public abstract void bindVertexArray(int array); - - public abstract void deleteVertexArrays(int array); -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java deleted file mode 100644 index a125fd11a..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IDynamicInstance.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -/** - * An interface giving {@link TileEntityInstance}s a hook to have a function called at - * the start of a frame. By implementing {@link IDynamicInstance}, a {@link TileEntityInstance} - * can animate its models in ways that could not be easily achieved by shader attribute - * parameterization. - * - *

If your goal is offloading work to shaders, but you're unsure exactly how you need - * to parameterize the instances, you're encouraged to implement this for prototyping. - */ -public interface IDynamicInstance extends IInstance { - /** - * Called every frame. - */ - void beginFrame(); - - /** - * As a further optimization, dynamic instances that are far away are ticked less often. - * This behavior can be disabled by returning false. - * - *
You might want to opt out of this if you want your animations to remain smooth - * even when far away from the camera. It is recommended to keep this as is, however. - * - * @return true if your instance should be slow ticked. - */ - default boolean decreaseFramerateWithDistance() { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IFlywheelWorld.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IFlywheelWorld.java deleted file mode 100644 index 86a00ab01..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IFlywheelWorld.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -/** - * A marker interface custom worlds can override to indicate - * that tiles inside the world should render with Flywheel. - * - * Minecraft.getInstance().world will always support Flywheel. - */ -public interface IFlywheelWorld { - default boolean supportsFlywheel() { - return true; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstance.java deleted file mode 100644 index 88ec0eb22..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstance.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -import net.minecraft.util.math.BlockPos; - -/** - * A general interface providing information about any type of thing that could use - * Flywheel's instanced rendering. Right now, that's only {@link InstancedTileRenderer}, - * but there could be an entity equivalent in the future. - */ -public interface IInstance { - - BlockPos getWorldPosition(); -} 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 deleted file mode 100644 index 386fd9b9c..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IInstanceRendered.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -public interface IInstanceRendered { - 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 deleted file mode 100644 index 206a7534e..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/IRendererFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -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/ITickableInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java deleted file mode 100644 index c9280973b..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ITickableInstance.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -/** - * An interface giving {@link TileEntityInstance}s a hook to have a function called at - * the end of every tick. By implementing {@link ITickableInstance}, a {@link TileEntityInstance} - * can update frequently, but not every frame. - *
There are a few cases in which this should be considered over {@link IDynamicInstance}: - *

- */ -public interface ITickableInstance extends IInstance { - - /** - * Called every tick. - */ - void tick(); - - /** - * As a further optimization, tickable instances that are far away are ticked less often. - * This behavior can be disabled by returning false. - * - *
You might want to opt out of this if you want your animations to remain smooth - * even when far away from the camera. It is recommended to keep this as is, however. - * - * @return true if your instance should be slow ticked. - */ - default boolean decreaseTickRateWithDistance() { - return true; - } -} 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 deleted file mode 100644 index 14d5f1fb4..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstanceData.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -import java.nio.ByteBuffer; - -public abstract class InstanceData { - - protected final InstancedModel owner; - - boolean dirty; - boolean removed; - - protected InstanceData(InstancedModel owner) { - this.owner = owner; - } - - public abstract void write(ByteBuffer buf); - - public void markDirty() { - owner.anyToUpdate = true; - dirty = true; - } - - public void delete() { - owner.anyToRemove = true; - removed = true; - } - - 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/InstancedModel.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java deleted file mode 100644 index 37db0841e..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedModel.java +++ /dev/null @@ -1,257 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.BitSet; - -import org.lwjgl.opengl.GL11; -import org.lwjgl.opengl.GL15; -import org.lwjgl.opengl.GL20; - -import com.simibubi.create.foundation.render.backend.Backend; -import com.simibubi.create.foundation.render.backend.BufferedModel; -import com.simibubi.create.foundation.render.backend.core.ModelAttributes; -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.VertexFormat; - -import net.minecraft.client.renderer.BufferBuilder; - -public abstract class InstancedModel extends BufferedModel { - public static final VertexFormat FORMAT = VertexFormat.builder().addAttributes(ModelAttributes.class).build(); - - public final InstancedTileRenderer renderer; - - protected GlVertexArray vao; - protected GlBuffer instanceVBO; - protected int glBufferSize = -1; - protected int glInstanceCount = 0; - - protected final ArrayList data = new ArrayList<>(); - - boolean anyToRemove; - boolean anyToUpdate; - - 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() { - super.deleteInternal(); - - instanceVBO.delete(); - vao.delete(); - } - - public synchronized D createInstance() { - D instanceData = newInstance(); - instanceData.dirty = true; - anyToUpdate = true; - data.add(instanceData); - - return instanceData; - } - - protected abstract D newInstance(); - - protected void doRender() { - vao.with(vao -> { - renderSetup(); - - if (glInstanceCount > 0) - Backend.compat.drawArraysInstanced(GL11.GL_QUADS, 0, vertexCount, glInstanceCount); - }); - } - - protected void renderSetup() { - if (anyToRemove) { - removeDeletedInstances(); - } - - instanceVBO.bind(); - if (!realloc()) { - - if (anyToRemove) { - clearBufferTail(); - } - - if (anyToUpdate) { - updateBuffer(); - } - - } - - glInstanceCount = data.size(); - informAttribDivisors(); - instanceVBO.unbind(); - - this.anyToRemove = false; - this.anyToUpdate = false; - } - - private void informAttribDivisors() { - int staticAttributes = getModelFormat().getShaderAttributeCount(); - getInstanceFormat().vertexAttribPointers(staticAttributes); - - for (int i = 0; i < getInstanceFormat().getShaderAttributeCount(); i++) { - Backend.compat.vertexAttribDivisor(i + staticAttributes, 1); - } - } - - private void clearBufferTail() { - int size = data.size(); - final int offset = size * getInstanceFormat().getStride(); - final int length = glBufferSize - offset; - if (length > 0) { - instanceVBO.map(offset, length, buffer -> { - buffer.put(new byte[length]); - }); - } - } - - private void updateBuffer() { - final int size = data.size(); - - if (size <= 0) return; - - final int stride = getInstanceFormat().getStride(); - final BitSet dirtySet = getDirtyBitSet(); - - if (dirtySet.isEmpty()) return; - - final int firstDirty = dirtySet.nextSetBit(0); - final int lastDirty = dirtySet.previousSetBit(size); - - final int offset = firstDirty * stride; - final int length = (1 + lastDirty - firstDirty) * stride; - - if (length > 0) { - instanceVBO.map(offset, length, buffer -> { - dirtySet.stream().forEach(i -> { - final D d = data.get(i); - - buffer.position(i * stride - offset); - d.write(buffer); - }); - }); - } - } - - private BitSet getDirtyBitSet() { - final int size = data.size(); - final BitSet dirtySet = new BitSet(size); - - for (int i = 0; i < size; i++) { - D element = data.get(i); - if (element.dirty) { - dirtySet.set(i); - - element.dirty = false; - } - } - return dirtySet; - } - - private boolean realloc() { - int size = this.data.size(); - int stride = getInstanceFormat().getStride(); - int requiredSize = size * stride; - if (requiredSize > glBufferSize) { - glBufferSize = requiredSize + stride * 16; - GL15.glBufferData(instanceVBO.getBufferType(), glBufferSize, GL15.GL_STATIC_DRAW); - - instanceVBO.map(glBufferSize, buffer -> { - for (D datum : data) { - datum.write(buffer); - } - }); - - glInstanceCount = size; - return true; - } - return false; - } - - private void removeDeletedInstances() { - // figure out which elements are to be removed - // any exception thrown from the filter predicate at this stage - // will leave the collection unmodified - final int oldSize = this.data.size(); - int removeCount = 0; - final BitSet removeSet = new BitSet(oldSize); - for (int i = 0; i < oldSize; i++) { - final D element = this.data.get(i); - if (element.removed) { - removeSet.set(i); - removeCount++; - } - } - - final int newSize = oldSize - removeCount; - - // shift surviving elements left over the spaces left by removed elements - for (int i = 0, j = 0; (i < oldSize) && (j < newSize); i++, j++) { - i = removeSet.nextClearBit(i); - - if (i != j) { - D element = data.get(i); - data.set(j, element); - element.dirty = true; - } - } - - anyToUpdate = true; - - data.subList(newSize, oldSize).clear(); - - } - - @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 deleted file mode 100644 index 19370f6a0..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderRegistry.java +++ /dev/null @@ -1,31 +0,0 @@ -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 deleted file mode 100644 index 5ae473052..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/InstancedTileRenderer.java +++ /dev/null @@ -1,283 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.render.backend.Backend; -import com.simibubi.create.foundation.render.backend.MaterialType; -import com.simibubi.create.foundation.render.backend.MaterialTypes; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.core.OrientedData; -import com.simibubi.create.foundation.render.backend.gl.BasicProgram; -import com.simibubi.create.foundation.render.backend.gl.shader.ShaderCallback; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.ActiveRenderInfo; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.vector.Matrix4f; -import net.minecraft.util.math.vector.Vector3f; -import net.minecraft.world.IBlockReader; -import net.minecraft.world.World; - -public abstract class InstancedTileRenderer

{ - protected ArrayList queuedAdditions = new ArrayList<>(64); - - protected Map> instances = new HashMap<>(); - - protected Map tickableInstances = new HashMap<>(); - protected Map dynamicInstances = new HashMap<>(); - - protected Map, RenderMaterial> materials = new HashMap<>(); - - protected int frame; - protected int tick; - - protected InstancedTileRenderer() { - registerMaterials(); - } - - public abstract BlockPos getOriginCoordinate(); - - public abstract void registerMaterials(); - - public void tick(double cameraX, double cameraY, double cameraZ) { - tick++; - - // integer camera pos - int cX = (int) cameraX; - int cY = (int) cameraY; - int cZ = (int) cameraZ; - - if (tickableInstances.size() > 0) { - for (ITickableInstance instance : tickableInstances.values()) { - if (!instance.decreaseTickRateWithDistance()) { - instance.tick(); - continue; - } - - BlockPos pos = instance.getWorldPosition(); - - int dX = pos.getX() - cX; - int dY = pos.getY() - cY; - int dZ = pos.getZ() - cZ; - - if ((tick % getUpdateDivisor(dX, dY, dZ)) == 0) - instance.tick(); - } - } - } - - public void beginFrame(ActiveRenderInfo info, double cameraX, double cameraY, double cameraZ) { - frame++; - processQueuedAdditions(); - - Vector3f look = info.getHorizontalPlane(); - float lookX = look.getX(); - float lookY = look.getY(); - float lookZ = look.getZ(); - - // integer camera pos - int cX = (int) cameraX; - int cY = (int) cameraY; - int cZ = (int) cameraZ; - - if (dynamicInstances.size() > 0) { - for (IDynamicInstance dyn : dynamicInstances.values()) { - if (!dyn.decreaseFramerateWithDistance()) { - dyn.beginFrame(); - continue; - } - - if (shouldTick(dyn.getWorldPosition(), lookX, lookY, lookZ, cX, cY, cZ)) - dyn.beginFrame(); - } - } - } - - 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); - } - } - - @SuppressWarnings("unchecked") - public > RenderMaterial getMaterial(MaterialType materialType) { - return (RenderMaterial) materials.get(materialType); - } - - public RenderMaterial> getTransformMaterial() { - return getMaterial(MaterialTypes.TRANSFORMED); - } - - public RenderMaterial> getOrientedMaterial() { - return getMaterial(MaterialTypes.ORIENTED); - } - - @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 && canCreateInstance(tile)) { - return createInternal(tile); - } 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) { - addInternal(tile); - } - } - - public void update(T tile) { - if (!Backend.canUseInstancing()) return; - - if (tile instanceof IInstanceRendered) { - TileEntityInstance instance = getInstance(tile, false); - - if (instance != null) { - - if (instance.shouldReset()) { - removeInternal(tile, instance); - - createInternal(tile); - } else { - instance.update(); - } - } - } - } - - public void remove(T tile) { - if (!Backend.canUseInstancing()) return; - - if (tile instanceof IInstanceRendered) { - removeInternal(tile); - } - } - - public synchronized void queueAdd(T tile) { - if (!Backend.canUseInstancing()) return; - - queuedAdditions.add(tile); - } - - protected synchronized void processQueuedAdditions() { - if (queuedAdditions.size() > 0) { - queuedAdditions.forEach(this::addInternal); - queuedAdditions.clear(); - } - } - - protected boolean shouldTick(BlockPos worldPos, float lookX, float lookY, float lookZ, int cX, int cY, int cZ) { - int dX = worldPos.getX() - cX; - int dY = worldPos.getY() - cY; - int dZ = worldPos.getZ() - cZ; - - float dot = (dX + lookX * 2) * lookX + (dY + lookY * 2) * lookY + (dZ + lookZ * 2) * lookZ; - - if (dot < 0) return false; // is it more than 2 blocks behind the camera? - - return (frame % getUpdateDivisor(dX, dY, dZ)) == 0; - } - - protected int getUpdateDivisor(int dX, int dY, int dZ) { - int dSq = dX * dX + dY * dY + dZ * dZ; - - return (dSq / 1024) + 1; - } - - private void addInternal(TileEntity tile) { - getInstance(tile, true); - } - - private void removeInternal(T tile) { - TileEntityInstance instance = getInstance(tile, false); - - if (instance != null) { - removeInternal(tile, instance); - } - } - - private void removeInternal(TileEntity tile, TileEntityInstance instance) { - instance.remove(); - instances.remove(tile); - dynamicInstances.remove(tile); - tickableInstances.remove(tile); - } - - private TileEntityInstance createInternal(T tile) { - TileEntityInstance renderer = InstancedTileRenderRegistry.instance.create(this, tile); - - if (renderer != null) { - renderer.updateLight(); - instances.put(tile, renderer); - - if (renderer instanceof IDynamicInstance) - dynamicInstances.put(tile, (IDynamicInstance) renderer); - - if (renderer instanceof ITickableInstance) - tickableInstances.put(tile, ((ITickableInstance) renderer)); - } - - return renderer; - } - - public void invalidate() { - for (RenderMaterial material : materials.values()) { - material.delete(); - } - instances.clear(); - dynamicInstances.clear(); - tickableInstances.clear(); - } - - public boolean canCreateInstance(TileEntity tile) { - if (tile.isRemoved()) return false; - - World world = tile.getWorld(); - - if (world == null) return false; - - if (world.isAirBlock(tile.getPos())) return false; - - if (world == Minecraft.getInstance().world) { - BlockPos pos = tile.getPos(); - - IBlockReader existingChunk = world.getExistingChunk(pos.getX() >> 4, pos.getZ() >> 4); - - return existingChunk != null; - } - - return world instanceof IFlywheelWorld && ((IFlywheelWorld) world).supportsFlywheel(); - } -} 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 deleted file mode 100644 index 2042929a8..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/ModelFactory.java +++ /dev/null @@ -1,8 +0,0 @@ -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 deleted file mode 100644 index 9458f4f6a..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/RenderMaterial.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -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.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.RenderUtil; -import com.simibubi.create.foundation.render.backend.core.PartialModel; -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.RenderType; -import net.minecraft.client.renderer.model.IBakedModel; -import net.minecraft.util.Direction; -import net.minecraft.util.math.vector.Matrix4f; - -public class RenderMaterial

> { - - protected final InstancedTileRenderer renderer; - protected final 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 = CacheBuilder.newBuilder() - .removalListener(notification -> ((InstancedModel) notification.getValue()).delete()) - .build(); - this.factory = factory; - this.programSpec = programSpec; - this.layerPredicate = layerPredicate; - } - - 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(); - } - - public void delete() { - //runOnAll(InstancedModel::delete); - models.invalidateAll(); - } - - protected void makeRenderCalls() { - runOnAll(InstancedModel::render); - } - - public void runOnAll(Consumer f) { - for (MODEL model : models.asMap().values()) { - f.accept(model); - } - } - - public MODEL getModel(PartialModel partial, BlockState referenceState) { - return get(partial, () -> buildModel(partial.get(), referenceState)); - } - - public MODEL getModel(PartialModel partial, BlockState referenceState, Direction dir) { - return getModel(partial, referenceState, dir, RenderUtil.rotateToFace(dir)); - } - - public MODEL getModel(PartialModel partial, BlockState referenceState, Direction dir, Supplier modelTransform) { - return get(Pair.of(dir, partial), - () -> buildModel(partial.get(), referenceState, modelTransform.get())); - } - - public MODEL getModel(BlockState toRender) { - return get(toRender, () -> buildModel(toRender)); - } - - public MODEL get(Object key, Supplier supplier) { - try { - return models.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 deleted file mode 100644 index f5f23f31a..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/TileEntityInstance.java +++ /dev/null @@ -1,127 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing; - -import java.util.Arrays; -import java.util.stream.Stream; - -import com.simibubi.create.foundation.render.backend.core.IFlatLight; -import com.simibubi.create.foundation.render.backend.core.ModelData; -import com.simibubi.create.foundation.render.backend.core.OrientedData; - -import net.minecraft.block.BlockState; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.LightType; -import net.minecraft.world.World; - -/** - * The layer between a {@link TileEntity} and the Flywheel backend. - * - *

{@link #updateLight()} is called after construction. - * - *

There are a few additional features that overriding classes can opt in to: - *

    - *
  • {@link IDynamicInstance}
  • - *
  • {@link ITickableInstance}
  • - *
- * See the interfaces' documentation for more information about each one. - * - *
Implementing one or more of these will give a {@link TileEntityInstance} access - * to more interesting and regular points within a tick or a frame. - * - * @param The type of {@link TileEntity} your class is an instance of. - */ -public abstract class TileEntityInstance implements IInstance { - - protected final InstancedTileRenderer renderer; - protected final T tile; - protected final World world; - protected final BlockPos pos; - protected final BlockPos instancePos; - protected final BlockState blockState; - - public TileEntityInstance(InstancedTileRenderer renderer, T tile) { - this.renderer = renderer; - this.tile = tile; - this.world = tile.getWorld(); - this.pos = tile.getPos(); - this.blockState = tile.getBlockState(); - this.instancePos = pos.subtract(renderer.getOriginCoordinate()); - } - - /** - * Update instance data here. Good for when data doesn't change very often and when animations are GPU based. - * Don't query lighting data here, that's handled separately in {@link #updateLight()}. - * - *

If your animations are complex or more CPU driven, see {@link IDynamicInstance} or {@link ITickableInstance}. - */ - protected void update() { - } - - /** - * Called after construction and when a light update occurs in the world. - * - *
If your model needs it, update light here. - */ - public void updateLight() { - } - - /** - * Free any acquired resources. - * - *
eg. call {@link InstanceKey#delete()}. - */ - public abstract void remove(); - - /** - * Just before {@link #update()} would be called, shouldReset() is checked. - * If this function returns true, then this instance will be {@link #remove}d, - * and another instance will be constructed to replace it. This allows for more sane resource - * acquisition compared to trying to update everything within the lifetime of an instance. - * - * @return true if this instance should be discarded and refreshed. - */ - public boolean shouldReset() { - return tile.getBlockState() != blockState; - } - - /** - * In order to accommodate for floating point precision errors at high coordinates, - * {@link InstancedTileRenderer}s are allowed to arbitrarily adjust the origin, and - * shift the world matrix provided as a shader uniform accordingly. - * - * @return The {@link BlockPos} at which the {@link TileEntity} this instance - * represents should be rendered at to appear in the correct location. - */ - public BlockPos getInstancePosition() { - return instancePos; - } - - @Override - public BlockPos getWorldPosition() { - return pos; - } - - protected void relight(BlockPos pos, IFlatLight... models) { - relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models); - } - - protected > void relight(BlockPos pos, Stream models) { - relight(world.getLightLevel(LightType.BLOCK, pos), world.getLightLevel(LightType.SKY, pos), models); - } - - protected void relight(int block, int sky, IFlatLight... models) { - relight(block, sky, Arrays.stream(models)); - } - - protected > void relight(int block, int sky, Stream models) { - models.forEach(model -> model.setBlockLight(block).setSkyLight(sky)); - } - - protected RenderMaterial> getTransformMaterial() { - return renderer.getTransformMaterial(); - } - - protected RenderMaterial> getOrientedMaterial() { - return renderer.getOrientedMaterial(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/ConditionalInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/ConditionalInstance.java deleted file mode 100644 index 386794900..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/ConditionalInstance.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing.util; - -import java.util.Optional; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class ConditionalInstance { - - final InstancedModel model; - Condition condition; - - @Nullable - private D instance; - - public ConditionalInstance(InstancedModel model, Condition condition) { - this.model = model; - this.condition = condition; - - update(); - } - - public ConditionalInstance setCondition(Condition condition) { - this.condition = condition; - return this; - } - - public ConditionalInstance update() { - boolean shouldShow = condition.shouldShow(); - if (shouldShow && instance == null) { - instance = model.createInstance(); - } else if (!shouldShow && instance != null) { - instance.delete(); - instance = null; - } - - return this; - } - - public Optional get() { - return Optional.ofNullable(instance); - } - - public void delete() { - if (instance != null) instance.delete(); - } - - @FunctionalInterface - public interface Condition { - boolean shouldShow(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/InstanceGroup.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/InstanceGroup.java deleted file mode 100644 index 6aa8f0cff..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/InstanceGroup.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing.util; - -import java.util.AbstractCollection; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class InstanceGroup extends AbstractCollection { - - final InstancedModel model; - final List backing; - - public InstanceGroup(InstancedModel model) { - this.model = model; - - this.backing = new ArrayList<>(); - } - - public InstanceGroup(InstancedModel model, int size) { - this.model = model; - - this.backing = new ArrayList<>(size); - - for (int i = 0; i < size; i++) { - addInstance(); - } - } - - /** - * @param count - * @return True if the number of elements changed. - */ - public boolean resize(int count) { - int size = size(); - if (count == size) return false; - - if (count <= 0) { - clear(); - return size > 0; - } - - if (count > size) { - for (int i = size; i < count; i++) { - addInstance(); - } - } else { - List unnecessary = backing.subList(count, size); - unnecessary.forEach(InstanceData::delete); - unnecessary.clear(); - } - - return true; - } - - public InstanceData addInstance() { - D instance = model.createInstance(); - backing.add(instance); - - return instance; - } - - public D get(int index) { - return backing.get(index); - } - - @Override - public Iterator iterator() { - return backing.iterator(); - } - - @Override - public int size() { - return backing.size(); - } - - @Override - public void clear() { - backing.forEach(InstanceData::delete); - backing.clear(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/SelectInstance.java b/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/SelectInstance.java deleted file mode 100644 index 25a6445d8..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/instancing/util/SelectInstance.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.simibubi.create.foundation.render.backend.instancing.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -import javax.annotation.Nullable; - -import com.simibubi.create.foundation.render.backend.instancing.InstanceData; -import com.simibubi.create.foundation.render.backend.instancing.InstancedModel; - -public class SelectInstance { - - final List> models; - - ModelSelector selector; - - private int last = -1; - @Nullable - private D current; - - public SelectInstance(ModelSelector selector) { - this.models = new ArrayList<>(); - this.selector = selector; - } - - public SelectInstance addModel(InstancedModel model) { - models.add(model); - return this; - } - - public SelectInstance update() { - int i = selector.modelIndexToShow(); - - if (i < 0 || i >= models.size()) { - if (current != null) { - current.delete(); - current = null; - } - } else if (i != last) { - if (current != null) current.delete(); - - current = models.get(i).createInstance(); - } - - last = i; - return this; - } - - public Optional get() { - return Optional.ofNullable(current); - } - - public void delete() { - if (current != null) current.delete(); - } - - public interface ModelSelector { - int modelIndexToShow(); - } -} 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 deleted file mode 100644 index 6f20a8c33..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/CoordinateConsumer.java +++ /dev/null @@ -1,6 +0,0 @@ -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/GridAlignedBB.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java deleted file mode 100644 index 3703143f5..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/GridAlignedBB.java +++ /dev/null @@ -1,323 +0,0 @@ -package com.simibubi.create.foundation.render.backend.light; - -import static com.simibubi.create.foundation.render.backend.RenderUtil.isPowerOf2; - -import com.simibubi.create.foundation.render.backend.RenderUtil; - -import net.minecraft.util.Direction; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.SectionPos; -import net.minecraft.util.math.vector.Vector3i; - -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 from(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 from(SectionPos pos) { - return new GridAlignedBB(pos.getWorldStartX(), - pos.getWorldStartY(), - pos.getWorldStartZ(), - pos.getWorldEndX() + 1, - pos.getWorldEndY() + 1, - pos.getWorldEndZ() + 1); - } - - public static GridAlignedBB from(BlockPos start, BlockPos end) { - return new GridAlignedBB(start.getX(), - start.getY(), - start.getZ(), - end.getX() + 1, - end.getY() + 1, - end.getZ() + 1); - } - - public static GridAlignedBB from(int sectionX, int sectionZ) { - int startX = sectionX << 4; - int startZ = sectionZ << 4; - return new GridAlignedBB(startX, - 0, - startZ, - startX + 16, - 256, - startZ + 16); - } - - 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 void fixMinMax() { - int minX = Math.min(this.minX, this.maxX); - int minY = Math.min(this.minY, this.maxY); - int minZ = Math.min(this.minZ, this.maxZ); - int maxX = Math.max(this.minX, this.maxX); - int maxY = Math.max(this.minY, this.maxY); - int maxZ = Math.max(this.minZ, this.maxZ); - - this.minX = minX; - this.minY = minY; - this.minZ = minZ; - this.maxX = maxX; - this.maxY = maxY; - this.maxZ = maxZ; - } - - public int sizeX() { - return maxX - minX; - } - - 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(Vector3i 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) { - Vector3i 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 = RenderUtil.nextPowerOf2(sizeX); - int newSizeY = RenderUtil.nextPowerOf2(sizeY); - int newSizeZ = RenderUtil.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 = RenderUtil.nextPowerOf2(sizeX()); - int sizeY = RenderUtil.nextPowerOf2(sizeY()); - int sizeZ = RenderUtil.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); - } - } - } - } - - public AxisAlignedBB toAABB() { - return toAABB(this); - } - - @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/LightUpdateListener.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdateListener.java deleted file mode 100644 index 09ea1a04d..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdateListener.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.simibubi.create.foundation.render.backend.light; - -import net.minecraft.world.IBlockDisplayReader; -import net.minecraft.world.LightType; - -/** - * Anything can implement this, implementors should call {@link LightUpdater#startListening} - * appropriately to make sure they get the updates they want. - */ -public interface LightUpdateListener { - - /** - * Called when a light updates in a chunk the implementor cares about. - * - * @return true if this object is no longer valid and should not receive any more updates. - */ - boolean onLightUpdate(IBlockDisplayReader world, LightType type, GridAlignedBB changed); - - /** - * Called when the server sends light data to the client. - * - * @return true if this object is no longer valid and should not receive any more updates. - */ - default boolean onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { - GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ); - - if (onLightUpdate(world, LightType.BLOCK, changedVolume)) - return true; - - return onLightUpdate(world, LightType.SKY, changedVolume); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdater.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdater.java deleted file mode 100644 index 089376a23..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightUpdater.java +++ /dev/null @@ -1,193 +0,0 @@ -package com.simibubi.create.foundation.render.backend.light; - -import java.util.WeakHashMap; -import java.util.function.LongConsumer; - -import com.simibubi.create.foundation.utility.WeakHashSet; - -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.longs.LongRBTreeSet; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.SectionPos; -import net.minecraft.world.IBlockDisplayReader; -import net.minecraft.world.LightType; - -/** - * By using WeakReferences we can automatically remove listeners when they are garbage collected. - * This allows us to easily be more clever about how we store the listeners. Each listener is associated - * with 2 sets of longs indicating what chunks and sections each listener is in. Additionally, a reverse - * mapping is created to allow for fast lookups when light updates. The reverse mapping is more interesting, - * but {@link #listenersToSections}, and {@link #listenersToChunks} are used to know what sections and - * chunks we need to remove the listeners from if they re-subscribe. Otherwise, listeners could get updates - * they no longer care about. This is done in {@link #clearSections} and {@link #clearChunks} - */ -public class LightUpdater { - - private static LightUpdater instance; - - public static LightUpdater getInstance() { - if (instance == null) - instance = new LightUpdater(); - - return instance; - } - - private final Long2ObjectMap> sections; - private final WeakHashMap listenersToSections; - - private final Long2ObjectMap> chunks; - private final WeakHashMap listenersToChunks; - - public LightUpdater() { - sections = new Long2ObjectOpenHashMap<>(); - listenersToSections = new WeakHashMap<>(); - - chunks = new Long2ObjectOpenHashMap<>(); - listenersToChunks = new WeakHashMap<>(); - } - - /** - * Add a listener associated with the given {@link BlockPos}. - *

- * When a light update occurs in the chunk the position is contained in, - * {@link LightUpdateListener#onLightUpdate} will be called. - * - * @param pos The position in the world that the listener cares about. - * @param listener The object that wants to receive light update notifications. - */ - public void startListening(BlockPos pos, LightUpdateListener listener) { - LongRBTreeSet sections = clearSections(listener); - LongRBTreeSet chunks = clearChunks(listener); - - long sectionPos = worldToSection(pos); - addToSection(sectionPos, listener); - sections.add(sectionPos); - - long chunkPos = sectionToChunk(sectionPos); - addToChunk(chunkPos, listener); - chunks.add(chunkPos); - } - - /** - * Add a listener associated with the given {@link GridAlignedBB}. - *

- * When a light update occurs in any chunk spanning the given volume, - * {@link LightUpdateListener#onLightUpdate} will be called. - * - * @param volume The volume in the world that the listener cares about. - * @param listener The object that wants to receive light update notifications. - */ - public void startListening(GridAlignedBB volume, LightUpdateListener listener) { - LongRBTreeSet sections = clearSections(listener); - LongRBTreeSet chunks = clearSections(listener); - - int minX = SectionPos.toChunk(volume.minX); - int minY = SectionPos.toChunk(volume.minY); - int minZ = SectionPos.toChunk(volume.minZ); - int maxX = SectionPos.toChunk(volume.maxX); - int maxY = SectionPos.toChunk(volume.maxY); - int maxZ = SectionPos.toChunk(volume.maxZ); - - for (int x = minX; x <= maxX; x++) { - for (int z = minZ; z <= maxZ; z++) { - for (int y = minY; y <= maxY; y++) { - long sectionPos = SectionPos.asLong(x, y, z); - addToSection(sectionPos, listener); - sections.add(sectionPos); - } - long chunkPos = SectionPos.asLong(x, 0, z); - addToChunk(chunkPos, listener); - chunks.add(chunkPos); - } - } - } - - /** - * Dispatch light updates to all registered {@link LightUpdateListener}s. - * - * @param world The world in which light was updated. - * @param type The type of light that changed. - * @param sectionPos A long representing the section position where light changed. - */ - public void onLightUpdate(IBlockDisplayReader world, LightType type, long sectionPos) { - WeakHashSet set = sections.get(sectionPos); - - if (set == null || set.isEmpty()) return; - - GridAlignedBB chunkBox = GridAlignedBB.from(SectionPos.from(sectionPos)); - - set.removeIf(listener -> listener.onLightUpdate(world, type, chunkBox.copy())); - } - - /** - * Dispatch light updates to all registered {@link LightUpdateListener}s - * when the server sends lighting data for an entire chunk. - * - * @param world The world in which light was updated. - */ - public void onLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { - - long chunkPos = SectionPos.asLong(chunkX, 0, chunkZ); - - WeakHashSet set = chunks.get(chunkPos); - - if (set == null || set.isEmpty()) return; - - set.removeIf(listener -> listener.onLightPacket(world, chunkX, chunkZ)); - } - - private LongRBTreeSet clearChunks(LightUpdateListener listener) { - return clear(listener, listenersToChunks, chunks); - } - - private LongRBTreeSet clearSections(LightUpdateListener listener) { - return clear(listener, listenersToSections, sections); - } - - private LongRBTreeSet clear(LightUpdateListener listener, WeakHashMap listeners, Long2ObjectMap> lookup) { - LongRBTreeSet set = listeners.get(listener); - - if (set == null) { - set = new LongRBTreeSet(); - listeners.put(listener, set); - } else { - set.forEach((LongConsumer) l -> { - WeakHashSet listeningSections = lookup.get(l); - - if (listeningSections != null) listeningSections.remove(listener); - }); - - set.clear(); - } - - return set; - } - - private void addToSection(long sectionPos, LightUpdateListener listener) { - getOrCreate(sections, sectionPos).add(listener); - } - - private void addToChunk(long chunkPos, LightUpdateListener listener) { - getOrCreate(chunks, chunkPos).add(listener); - } - - private WeakHashSet getOrCreate(Long2ObjectMap> sections, long chunkPos) { - WeakHashSet set = sections.get(chunkPos); - - if (set == null) { - set = new WeakHashSet<>(); - sections.put(chunkPos, set); - } - - return set; - } - - public static long worldToSection(BlockPos pos) { - return SectionPos.asLong(pos.getX(), pos.getY(), pos.getZ()); - } - - public static long sectionToChunk(long sectionPos) { - return sectionPos & 0xFFFFFFFFFFF_00000L; - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java b/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java deleted file mode 100644 index ae0bdaa23..000000000 --- a/src/main/java/com/simibubi/create/foundation/render/backend/light/LightVolume.java +++ /dev/null @@ -1,312 +0,0 @@ -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.system.MemoryUtil; - -import com.simibubi.create.foundation.render.backend.Backend; -import com.simibubi.create.foundation.render.backend.RenderWork; -import com.simibubi.create.foundation.render.backend.gl.GlTexture; -import com.simibubi.create.foundation.render.backend.gl.versioned.RGPixelFormat; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.IBlockDisplayReader; -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; - - private final RGPixelFormat pixelFormat; - - public LightVolume(GridAlignedBB sampleVolume) { - setSampleVolume(sampleVolume); - - pixelFormat = Backend.compat.pixelFormat; - - this.glTexture = new GlTexture(GL20.GL_TEXTURE_3D); - this.lightData = MemoryUtil.memAlloc(this.textureVolume.volume() * pixelFormat.byteCount()); - - // 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, pixelFormat.internalFormat(), sizeX, sizeY, sizeZ, 0, pixelFormat.format(), GL20.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(IBlockDisplayReader 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(IBlockDisplayReader world, LightType type, GridAlignedBB changedVolume) { - if (removed) - return; - - if (!changedVolume.intersects(sampleVolume)) - return; - changedVolume = changedVolume.intersect(sampleVolume); // compute the region contained by us that has dirty lighting data. - - if (type == LightType.BLOCK) copyBlock(world, changedVolume); - else if (type == LightType.SKY) copySky(world, changedVolume); - } - - public void notifyLightPacket(IBlockDisplayReader world, int chunkX, int chunkZ) { - if (removed) return; - - GridAlignedBB changedVolume = GridAlignedBB.from(chunkX, chunkZ); - if (!changedVolume.intersects(sampleVolume)) - return; - changedVolume.intersectAssign(sampleVolume); // compute the region contained by us that has dirty lighting data. - - copyLight(world, changedVolume); - } - - /** - * Completely (re)populate this volume with block and sky lighting data. - * This is expensive and should be avoided. - */ - public void initialize(IBlockDisplayReader 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(IBlockDisplayReader 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(IBlockDisplayReader 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(IBlockDisplayReader 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(GL20.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, pixelFormat.format(), GL20.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 = posToIndex(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(posToIndex(x, y, z), b); - } - - private void writeSky(int x, int y, int z, int sky) { - byte b = (byte) ((sky & 0xF) << 4); - - lightData.put(posToIndex(x, y, z) + 1, b); - } - - private int posToIndex(int x, int y, int z) { - return (x + textureVolume.sizeX() * (y + z * textureVolume.sizeY())) * pixelFormat.byteCount(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/ColorMatrices.java b/src/main/java/com/simibubi/create/foundation/render/effects/ColorMatrices.java new file mode 100644 index 000000000..07a683d16 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/effects/ColorMatrices.java @@ -0,0 +1,129 @@ +package com.simibubi.create.foundation.render.effects; + +import com.simibubi.create.foundation.utility.AngleHelper; + +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Matrix4f; + +public class ColorMatrices { + + public static final float lumaR = 0.3086f; + public static final float lumaG = 0.6094f; + public static final float lumaB = 0.0820f; + + public static Matrix4f invert() { + Matrix4f invert = new Matrix4f(); + invert.a00 = -1.0F; + invert.a11 = -1.0F; + invert.a22 = -1.0F; + invert.a33 = -1.0F; + invert.a30 = 1; + invert.a31 = 1; + invert.a32 = 1; + + return invert; + } + + public static Matrix4f grayscale() { + Matrix4f mat = new Matrix4f(); + + mat.a00 = mat.a01 = mat.a02 = lumaR; + mat.a10 = mat.a11 = mat.a12 = lumaG; + mat.a20 = mat.a21 = mat.a22 = lumaB; + mat.a33 = 1; + + return mat; + } + + public static Matrix4f saturate(float s) { + Matrix4f mat = new Matrix4f(); + + mat.a00 = (1.0f - s) * lumaR + s; + mat.a01 = (1.0f - s) * lumaR; + mat.a02 = (1.0f - s) * lumaR; + mat.a10 = (1.0f - s) * lumaG; + mat.a11 = (1.0f - s) * lumaG + s; + mat.a12 = (1.0f - s) * lumaG; + mat.a20 = (1.0f - s) * lumaB; + mat.a21 = (1.0f - s) * lumaB; + mat.a22 = (1.0f - s) * lumaB + s; + + mat.a33 = 1; + + return mat; + } + + public static Matrix4f sepia(float amount) { + Matrix4f mat = new Matrix4f(); + + mat.a00 = (float) (0.393 + 0.607 * (1 - amount)); + mat.a10 = (float) (0.769 - 0.769 * (1 - amount)); + mat.a20 = (float) (0.189 - 0.189 * (1 - amount)); + mat.a01 = (float) (0.349 - 0.349 * (1 - amount)); + mat.a11 = (float) (0.686 + 0.314 * (1 - amount)); + mat.a21 = (float) (0.168 - 0.168 * (1 - amount)); + mat.a02 = (float) (0.272 - 0.272 * (1 - amount)); + mat.a12 = (float) (0.534 - 0.534 * (1 - amount)); + mat.a22 = (float) (0.131 + 0.869 * (1 - amount)); + + mat.a33 = 1; + + return mat; + } + + // https://stackoverflow.com/a/8510751 + public static Matrix4f hueShift(float rot) { + Matrix4f mat = new Matrix4f(); + + mat.loadIdentity(); + + float cosA = MathHelper.cos(AngleHelper.rad(rot)); + float sinA = MathHelper.sin(AngleHelper.rad(rot)); + mat.a00 = (float) (cosA + (1.0 - cosA) / 3.0); + mat.a01 = (float) (1. / 3. * (1.0 - cosA) - MathHelper.sqrt(1. / 3.) * sinA); + mat.a02 = (float) (1. / 3. * (1.0 - cosA) + MathHelper.sqrt(1. / 3.) * sinA); + mat.a10 = (float) (1. / 3. * (1.0 - cosA) + MathHelper.sqrt(1. / 3.) * sinA); + mat.a11 = (float) (cosA + 1. / 3. * (1.0 - cosA)); + mat.a12 = (float) (1. / 3. * (1.0 - cosA) - MathHelper.sqrt(1. / 3.) * sinA); + mat.a20 = (float) (1. / 3. * (1.0 - cosA) - MathHelper.sqrt(1. / 3.) * sinA); + mat.a21 = (float) (1. / 3. * (1.0 - cosA) + MathHelper.sqrt(1. / 3.) * sinA); + mat.a22 = (float) (cosA + 1. / 3. * (1.0 - cosA)); + + return mat; + } + + public static Matrix4f darken(float amount) { + Matrix4f mat = new Matrix4f(); + mat.loadIdentity(); + mat.multiply(1f - amount); + return mat; + } + + public static Matrix4f brightness(float amount) { + Matrix4f mat = new Matrix4f(); + mat.loadIdentity(); + mat.a03 = amount; + mat.a13 = amount; + mat.a23 = amount; + return mat; + } + + public static Matrix4f contrast(float amount) { + Matrix4f sub = new Matrix4f(); + sub.a00 = amount; + sub.a11 = amount; + sub.a22 = amount; + sub.a33 = 1; + sub.a30 = 0.5f - amount * 0.5f; + sub.a31 = 0.5f - amount * 0.5f; + sub.a32 = 0.5f - amount * 0.5f; + + return sub; + } + + public static Matrix4f identity() { + Matrix4f mat = new Matrix4f(); + mat.loadIdentity(); + return mat; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java new file mode 100644 index 000000000..1967b49d5 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsContext.java @@ -0,0 +1,38 @@ +package com.simibubi.create.foundation.render.effects; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.backend.ShaderContext; +import com.jozufozu.flywheel.backend.gl.shader.ShaderType; +import com.jozufozu.flywheel.backend.loading.Shader; +import com.jozufozu.flywheel.core.shader.spec.ProgramSpec; +import com.simibubi.create.foundation.render.AllProgramSpecs; + +import net.minecraft.util.ResourceLocation; + +public class EffectsContext extends ShaderContext { + + public EffectsContext(Backend backend) { + super(backend); + } + + @Override + public void load() { + ProgramSpec programSpec = Backend.getInstance().getSpec(AllProgramSpecs.CHROMATIC); + + try { + programs.put(programSpec.name, new SphereFilterProgram(loadAndLink(programSpec, null))); + + Backend.log.debug("Loaded program {}", programSpec.name); + } catch (Exception e) { + Backend.log.error("Program '{}': {}", programSpec.name, e); + backend.sources.notifyError(); + } + } + + @Override + protected Shader getSource(ShaderType type, ResourceLocation name) { + Shader source = super.getSource(type, name); + source.processIncludes(); + return source; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/EffectsHandler.java b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsHandler.java new file mode 100644 index 000000000..41ce02740 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/effects/EffectsHandler.java @@ -0,0 +1,151 @@ +package com.simibubi.create.foundation.render.effects; + +import java.util.ArrayList; + +import javax.annotation.Nullable; + +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL30; + +import com.jozufozu.flywheel.backend.Backend; +import com.jozufozu.flywheel.core.FullscreenQuad; +import com.jozufozu.flywheel.util.RenderUtil; +import com.simibubi.create.foundation.render.AllProgramSpecs; +import com.simibubi.create.foundation.render.CreateContexts; +import com.simibubi.create.foundation.utility.AnimationTickHolder; + +import net.minecraft.client.MainWindow; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.FramebufferConstants; +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3d; + +public class EffectsHandler { + + private static EffectsHandler instance; + + @Nullable + public static EffectsHandler getInstance() { + if (Backend.getInstance().available() && instance == null) { + instance = new EffectsHandler(Backend.getInstance()); + } + + if (!Backend.getInstance().available() && instance != null) { + instance.delete(); + instance = null; + } + + return instance; + } + + public static float getNearPlane() { + return 0.05f; + } + + public static float getFarPlane() { + return Minecraft.getInstance().gameRenderer.getFarPlaneDistance() * 4; + } + + private final Backend backend; + private final Framebuffer framebuffer; + private final ArrayList spheres; + + public EffectsHandler(Backend backend) { + this.backend = backend; + spheres = new ArrayList<>(); + + Framebuffer render = Minecraft.getInstance().getFramebuffer(); + framebuffer = new Framebuffer(render.framebufferWidth, render.framebufferHeight, false, Minecraft.IS_RUNNING_ON_MAC); + + } + + public void addSphere(FilterSphere sphere) { + this.spheres.add(sphere); + } + + public void render(Matrix4f view) { + if (spheres.size() == 0) { + return; + } + + GL20.glEnable(GL20.GL_DEPTH_TEST); + + GL20.glDepthRange(getNearPlane(), getFarPlane()); + + prepFramebufferSize(); + + Framebuffer mainBuffer = Minecraft.getInstance().getFramebuffer(); + + backend.compat.fbo.bindFramebuffer(FramebufferConstants.FRAME_BUFFER, framebuffer.framebufferObject); + GL11.glClear(GL30.GL_COLOR_BUFFER_BIT); + + SphereFilterProgram program = CreateContexts.EFFECTS.getProgram(AllProgramSpecs.CHROMATIC); + program.bind(); + + program.bindColorTexture(mainBuffer.getColorAttachment()); + program.bindDepthTexture(mainBuffer.getDepthAttachment()); + + GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer; + ActiveRenderInfo activeRenderInfo = gameRenderer.getActiveRenderInfo(); + Matrix4f projection = gameRenderer.getBasicProjectionMatrix(activeRenderInfo, AnimationTickHolder.getPartialTicks(), true); + projection.a33 = 1; + projection.invert(); + program.bindInverseProjection(projection); + + Matrix4f inverseView = view.copy(); + inverseView.invert(); + program.bindInverseView(inverseView); + + Vector3d cameraPos = activeRenderInfo.getProjectedView(); + + program.setCameraPos(cameraPos.inverse()); + + for (FilterSphere sphere : spheres) { + sphere.x -= cameraPos.x; + sphere.y -= cameraPos.y; + sphere.z -= cameraPos.z; + } + + spheres.sort((o1, o2) -> { + double l1 = RenderUtil.length(o1.x, o1.y, o1.z); + double l2 = RenderUtil.length(o2.x, o2.y, o2.z); + return (int) Math.signum(l2 - l1); + }); + + program.uploadFilters(spheres); + + program.setFarPlane(getFarPlane()); + program.setNearPlane(getNearPlane()); + + FullscreenQuad.INSTANCE.get().draw(); + + program.bindColorTexture(0); + program.bindDepthTexture(0); + GL20.glActiveTexture(GL20.GL_TEXTURE0); + + program.unbind(); + spheres.clear(); + + backend.compat.fbo.bindFramebuffer(GL30.GL_READ_FRAMEBUFFER, framebuffer.framebufferObject); + backend.compat.fbo.bindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, mainBuffer.framebufferObject); + backend.compat.blit.blitFramebuffer(0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, 0, 0, mainBuffer.framebufferWidth, mainBuffer.framebufferHeight, GL30.GL_COLOR_BUFFER_BIT, GL20.GL_LINEAR); + backend.compat.fbo.bindFramebuffer(FramebufferConstants.FRAME_BUFFER, mainBuffer.framebufferObject); + } + + public void delete() { + framebuffer.deleteFramebuffer(); + } + + private void prepFramebufferSize() { + MainWindow window = Minecraft.getInstance().getWindow(); + if (framebuffer.framebufferWidth != window.getFramebufferWidth() + || framebuffer.framebufferHeight != window.getFramebufferHeight()) { + framebuffer.func_216491_a(window.getFramebufferWidth(), window.getFramebufferHeight(), + Minecraft.IS_RUNNING_ON_MAC); + } + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/FilterSphere.java b/src/main/java/com/simibubi/create/foundation/render/effects/FilterSphere.java new file mode 100644 index 000000000..6c9546aef --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/effects/FilterSphere.java @@ -0,0 +1,54 @@ +package com.simibubi.create.foundation.render.effects; + +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.util.RenderUtil; + +import net.minecraft.util.math.vector.Matrix4f; + +public class FilterSphere { + public float x; + public float y; + public float z; + public float radius; + + public float feather; + public float fade; + public float density = 2; + public boolean blend = false; + + public boolean surface = true; + public boolean field = true; + public float strength = 1; + + public boolean rMask; + public boolean gMask; + public boolean bMask; + + public Matrix4f filter; + + public void write(MappedBuffer buf) { + buf.putFloatArray(new float[]{ + x, + y, + z, + radius, + + feather, + fade, + density, + blend ? 1 : 0, + + surface ? 1 : 0, + field ? 1 : 0, + Math.abs(strength), + strength < 0 ? 1 : 0, + + rMask ? 1 : 0, + gMask ? 1 : 0, + bMask ? 1 : 0, + 0, // padding + }); + + buf.putFloatArray(RenderUtil.writeMatrix(filter)); + } +} diff --git a/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java b/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java new file mode 100644 index 000000000..3b69fa5db --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/render/effects/SphereFilterProgram.java @@ -0,0 +1,118 @@ +package com.simibubi.create.foundation.render.effects; + +import java.util.ArrayList; + +import org.lwjgl.opengl.GL20; +import org.lwjgl.opengl.GL31; + +import com.jozufozu.flywheel.backend.gl.buffer.GlBuffer; +import com.jozufozu.flywheel.backend.gl.buffer.GlBufferType; +import com.jozufozu.flywheel.backend.gl.buffer.MappedBuffer; +import com.jozufozu.flywheel.backend.gl.shader.GlProgram; +import com.jozufozu.flywheel.backend.loading.Program; +import com.jozufozu.flywheel.core.shader.IMultiProgram; + +import net.minecraft.util.math.vector.Matrix4f; +import net.minecraft.util.math.vector.Vector3d; + +public class SphereFilterProgram extends GlProgram implements IMultiProgram { + + protected static final int UBO_BINDING = 4; + + protected static final int SPHERE_FILTER_SIZE = 24 * 4; // + protected static final int MAX_FILTERS = 256; // arbitrary + + protected static final int EXTRA_INFO = 16; // array length: int + padding + protected static final int ALL_FILTERS_SIZE = MAX_FILTERS * SPHERE_FILTER_SIZE; + + protected static final int BUFFER_SIZE = EXTRA_INFO + ALL_FILTERS_SIZE; + + public final GlBuffer effectsUBO; + + protected final int uniformBlock; + + protected final int uDepth; + protected final int uColor; + + protected final int uInverseProjection; + protected final int uInverseView; + + protected final int uNearPlane; + protected final int uFarPlane; + + protected final int uCameraPos; + + public SphereFilterProgram(Program program) { + super(program); + + effectsUBO = new GlBuffer(GlBufferType.UNIFORM_BUFFER); + + uniformBlock = GL31.glGetUniformBlockIndex(program.program, "Filters"); + + GL31.glUniformBlockBinding(program.program, uniformBlock, UBO_BINDING); + + effectsUBO.bind(); + effectsUBO.alloc(BUFFER_SIZE); + GL31.glBindBufferBase(effectsUBO.getBufferTarget().glEnum, UBO_BINDING, effectsUBO.handle()); + effectsUBO.unbind(); + + uInverseProjection = getUniformLocation("uInverseProjection"); + uInverseView = getUniformLocation("uInverseView"); + uNearPlane = getUniformLocation("uNearPlane"); + uFarPlane = getUniformLocation("uFarPlane"); + uCameraPos = getUniformLocation("uCameraPos"); + + bind(); + uDepth = setSamplerBinding("uDepth", 8); + uColor = setSamplerBinding("uColor", 9); + unbind(); + } + + public void setNearPlane(float nearPlane) { + GL20.glUniform1f(uNearPlane, nearPlane); + } + + public void setFarPlane(float farPlane) { + GL20.glUniform1f(uFarPlane, farPlane); + } + + public void setCameraPos(Vector3d pos) { + GL20.glUniform3f(uCameraPos, (float) pos.x, (float) pos.y, (float) pos.z); + } + + public void uploadFilters(ArrayList filters) { + effectsUBO.bind(); + MappedBuffer buffer = effectsUBO.getBuffer(0, BUFFER_SIZE) + .putInt(filters.size()) + .position(16); + + filters.forEach(it -> it.write(buffer)); + + buffer.flush(); + + effectsUBO.unbind(); + } + + public void bindInverseProjection(Matrix4f mat) { + uploadMatrixUniform(uInverseProjection, mat); + } + + public void bindInverseView(Matrix4f mat) { + uploadMatrixUniform(uInverseView, mat); + } + + public void bindDepthTexture(int textureObject) { + GL20.glActiveTexture(GL20.GL_TEXTURE8); + GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject); + } + + public void bindColorTexture(int textureObject) { + GL20.glActiveTexture(GL20.GL_TEXTURE9); + GL20.glBindTexture(GL20.GL_TEXTURE_2D, textureObject); + } + + @Override + public SphereFilterProgram get() { + return this; + } +} diff --git a/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java b/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java index 31c129642..41cc284bd 100644 --- a/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java +++ b/src/main/java/com/simibubi/create/foundation/renderState/RenderTypes.java @@ -83,7 +83,7 @@ public class RenderTypes extends RenderState { .transparency(TRANSLUCENT_TRANSPARENCY) .diffuseLighting(ENABLE_DIFFUSE_LIGHTING) .alpha(ONE_TENTH_ALPHA) - .cull(DISABLE_CULLING) + .cull(ENABLE_CULLING) .lightmap(ENABLE_LIGHTMAP) .overlay(ENABLE_OVERLAY_COLOR) .build(true)); diff --git a/src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java b/src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java index 8cc83176a..286dc4423 100644 --- a/src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java +++ b/src/main/java/com/simibubi/create/foundation/renderState/SuperRenderTypeBuffer.java @@ -2,7 +2,6 @@ package com.simibubi.create.foundation.renderState; import java.util.SortedMap; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.IVertexBuilder; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; @@ -48,14 +47,12 @@ public class SuperRenderTypeBuffer implements IRenderTypeBuffer { } public void draw() { - RenderSystem.disableCull(); earlyBuffer.draw(); defaultBuffer.draw(); lateBuffer.draw(); } public void draw(RenderType type) { - RenderSystem.disableCull(); earlyBuffer.draw(type); defaultBuffer.draw(type); lateBuffer.draw(type); diff --git a/src/main/java/com/simibubi/create/foundation/sound/SoundScape.java b/src/main/java/com/simibubi/create/foundation/sound/SoundScape.java index 6fc31afe0..96ea0b8d9 100644 --- a/src/main/java/com/simibubi/create/foundation/sound/SoundScape.java +++ b/src/main/java/com/simibubi/create/foundation/sound/SoundScape.java @@ -9,6 +9,7 @@ import com.simibubi.create.foundation.utility.AnimationTickHolder; import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -80,9 +81,16 @@ class SoundScape { } public float getVolume() { + Entity renderViewEntity = Minecraft.getInstance().renderViewEntity; + float distanceMultiplier = 0; + if (renderViewEntity != null) { + double distanceTo = renderViewEntity.getPositionVec() + .distanceTo(getMeanPos()); + distanceMultiplier = (float) MathHelper.lerp(distanceTo / SoundScapes.MAX_AMBIENT_SOURCE_DISTANCE, 2, 0); + } int soundCount = SoundScapes.getSoundCount(group, pitchGroup); float argMax = (float) SoundScapes.SOUND_VOLUME_ARG_MAX; - return MathHelper.clamp(soundCount / (argMax * 10f), 0.075f, .15f); + return MathHelper.clamp(soundCount / (argMax * 10f), 0.025f, .15f) * distanceMultiplier; } } \ No newline at end of file diff --git a/src/main/java/com/simibubi/create/foundation/sound/SoundScapes.java b/src/main/java/com/simibubi/create/foundation/sound/SoundScapes.java index 163e6d2e9..ff1017416 100644 --- a/src/main/java/com/simibubi/create/foundation/sound/SoundScapes.java +++ b/src/main/java/com/simibubi/create/foundation/sound/SoundScapes.java @@ -25,9 +25,12 @@ public class SoundScapes { static final int UPDATE_INTERVAL = 5; static final int SOUND_VOLUME_ARG_MAX = 15; - enum AmbienceGroup { + public enum AmbienceGroup { - KINETIC(SoundScapes::kinetic), COG(SoundScapes::cogwheel) + KINETIC(SoundScapes::kinetic), + COG(SoundScapes::cogwheel), + + SAW((p, g) -> new SoundScape(p, g).repeating(AllSoundEvents.SAW_IDLE.getMainEvent(), 1f, .95f, 1)) ; @@ -48,7 +51,7 @@ public class SoundScapes { } private static SoundScape cogwheel(float pitch, AmbienceGroup group) { - return new SoundScape(pitch, group).continuous(AllSoundEvents.COGS.getMainEvent(), 3, 1); + return new SoundScape(pitch, group).continuous(AllSoundEvents.COGS.getMainEvent(), 1.5f, 1); } enum PitchGroup { @@ -58,14 +61,9 @@ public class SoundScapes { private static Map>> counter = new IdentityHashMap<>(); private static Map, SoundScape> activeSounds = new HashMap<>(); - public static void playGeneralKineticAmbience(BlockPos pos, float pitch) { + public static void play(AmbienceGroup group, BlockPos pos, float pitch) { if (!outOfRange(pos)) - addSound(AmbienceGroup.KINETIC, pos, pitch); - } - - public static void playCogwheelAmbience(BlockPos pos, float pitch) { - if (!outOfRange(pos)) - addSound(AmbienceGroup.COG, pos, pitch); + addSound(group, pos, pitch); } public static void tick() { @@ -93,7 +91,7 @@ public class SoundScapes { .forEach(Set::clear)); } - public static void addSound(AmbienceGroup group, BlockPos pos, float pitch) { + private static void addSound(AmbienceGroup group, BlockPos pos, float pitch) { PitchGroup groupFromPitch = getGroupFromPitch(pitch); Set set = counter.computeIfAbsent(group, ag -> new IdentityHashMap<>()) .computeIfAbsent(groupFromPitch, pg -> new HashSet<>()); @@ -107,11 +105,10 @@ public class SoundScapes { }); } - public static void clean() { - BlockPos playerLocation = getCameraPos(); - for (Map> map : counter.values()) - for (Set set : map.values()) - set.removeIf(p -> !playerLocation.withinDistance(p, MAX_AMBIENT_SOURCE_DISTANCE)); + public static void invalidateAll() { + counter.clear(); + activeSounds.forEach(($, sound) -> sound.remove()); + activeSounds.clear(); } protected static boolean outOfRange(BlockPos pos) { diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java index a589bc7ca..f3dfc18f0 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java @@ -6,7 +6,9 @@ import java.util.List; import java.util.Map; import java.util.function.Consumer; +import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; +import com.simibubi.create.foundation.utility.IPartialSafeNBT; import net.minecraft.block.BlockState; import net.minecraft.nbt.CompoundNBT; @@ -16,7 +18,7 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.items.CapabilityItemHandler; -public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity { +public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity, IPartialSafeNBT { private final Map, TileEntityBehaviour> behaviours; // Internally maintained to be identical to behaviorMap.values() in order to improve iteration performance. @@ -118,6 +120,23 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka behaviourList.forEach(tb -> tb.write(compound, clientPacket)); } + @Override + public void writeSafe(CompoundNBT compound, boolean clientPacket) { + super.write(compound); + behaviourList.forEach(tb -> { + if (tb.isSafeNBT()) + tb.write(compound, clientPacket); + }); + } + + public ItemRequirement getRequiredItems() { + return behaviourList.stream().reduce( + ItemRequirement.NONE, + (a, b) -> a.with(b.getRequiredItems()), + (a, b) -> a.with(b) + ); + } + @Override public void remove() { forEachBehaviour(TileEntityBehaviour::remove); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java index 925677123..4f0588e55 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/TileEntityBehaviour.java @@ -1,5 +1,6 @@ package com.simibubi.create.foundation.tileEntity; +import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.tileEntity.behaviour.BehaviourType; import net.minecraft.block.BlockState; @@ -42,6 +43,14 @@ public abstract class TileEntityBehaviour { } + public boolean isSafeNBT() { + return false; + } + + public ItemRequirement getRequiredItems() { + return ItemRequirement.NONE; + } + public void onBlockChanged(BlockState oldState) { } @@ -94,5 +103,4 @@ public abstract class TileEntityBehaviour { SmartTileEntity ste = (SmartTileEntity) te; return ste.getBehaviour(type); } - } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java index 87ddf3a7a..6cfcd227b 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/edgeInteraction/EdgeInteractionRenderer.java @@ -81,13 +81,13 @@ public class EdgeInteractionRenderer { } box.offsetLabel(textOffset) - .withColors(0x7A6A2C, 0xB79D64) - .passive(!hit); + .withColors(0x7A6A2C, 0xB79D64) + .passive(!hit); - CreateClient.outliner.showValueBox("edge", box) - .lineWidth(1 / 64f) - .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) - .highlightFace(face); + CreateClient.OUTLINER.showValueBox("edge", box) + .lineWidth(1 / 64f) + .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) + .highlightFace(face); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java index 803476b13..1768fd0cd 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringBehaviour.java @@ -4,6 +4,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; import com.simibubi.create.content.logistics.item.filter.FilterItem; +import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; @@ -13,6 +14,7 @@ import com.simibubi.create.foundation.utility.VecHelper; import net.minecraft.block.BlockState; import net.minecraft.entity.item.ItemEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.util.Direction; @@ -57,6 +59,9 @@ public class FilteringBehaviour extends TileEntityBehaviour { fluidFilter = false; } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.put("Filter", getFilter().serializeNBT()); @@ -165,6 +170,15 @@ public class FilteringBehaviour extends TileEntityBehaviour { super.destroy(); } + @Override + public ItemRequirement getRequiredItems() { + Item filterItem = filter.getItem(); + if (filterItem instanceof FilterItem) + return new ItemRequirement(ItemRequirement.ItemUseType.CONSUME, filterItem); + + return ItemRequirement.NONE; + } + public ItemStack getFilter(Direction side) { return getFilter(); } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringRenderer.java index 349949f76..e1d21eb6f 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/FilteringRenderer.java @@ -73,17 +73,17 @@ public class FilteringRenderer { AxisAlignedBB bb = isFilterSlotted ? emptyBB.grow(.45f, .31f, .2f) : emptyBB.grow(.25f); ValueBox box = showCount ? new ItemValueBox(label, bb, pos, filter, behaviour.scrollableValue) - : new ValueBox(label, bb, pos); + : new ValueBox(label, bb, pos); box.offsetLabel(behaviour.textShift) - .withColors(fluids ? 0x407088 : 0x7A6A2C, fluids ? 0x70adb5 : 0xB79D64) - .scrollTooltip(showCount && !isFilterSlotted ? new StringTextComponent("[").append(Lang.translate("action.scroll")).append("]") : StringTextComponent.EMPTY) - .passive(!hit); + .withColors(fluids ? 0x407088 : 0x7A6A2C, fluids ? 0x70adb5 : 0xB79D64) + .scrollTooltip(showCount && !isFilterSlotted ? new StringTextComponent("[").append(Lang.translate("action.scroll")).append("]") : StringTextComponent.EMPTY) + .passive(!hit); - CreateClient.outliner.showValueBox(Pair.of("filter", pos), box.transform(behaviour.slotPositioning)) - .lineWidth(1 / 64f) - .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) - .highlightFace(result.getFace()); + CreateClient.OUTLINER.showValueBox(Pair.of("filter", pos), box.transform(behaviour.slotPositioning)) + .lineWidth(1 / 64f) + .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) + .highlightFace(result.getFace()); } public static void renderOnTileEntity(SmartTileEntity tileEntityIn, float partialTicks, MatrixStack ms, diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java index 88097a681..28756ef0a 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/filtering/SidedFilteringBehaviour.java @@ -7,6 +7,7 @@ import java.util.Set; import java.util.function.BiFunction; import java.util.function.Predicate; +import com.simibubi.create.content.schematics.ItemRequirement; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform.Sided; @@ -109,21 +110,30 @@ public class SidedFilteringBehaviour extends FilteringBehaviour { if (!sidedFilters.containsKey(side)) return true; return sidedFilters.get(side) - .test(stack); + .test(stack); } @Override public void destroy() { sidedFilters.values() - .forEach(FilteringBehaviour::destroy); + .forEach(FilteringBehaviour::destroy); super.destroy(); } + @Override + public ItemRequirement getRequiredItems() { + return sidedFilters.values().stream().reduce( + ItemRequirement.NONE, + (a, b) -> a.with(b.getRequiredItems()), + (a, b) -> a.with(b) + ); + } + public void removeFilter(Direction side) { if (!sidedFilters.containsKey(side)) return; sidedFilters.remove(side) - .destroy(); + .destroy(); } public boolean testHit(Direction direction, Vector3d hit) { diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java index 05ddc710a..9841bbb8d 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/fluid/SmartFluidTankBehaviour.java @@ -102,7 +102,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { if (syncCooldown > 0) { syncCooldown--; - if (syncCooldown == 0 && queuedSync) + if (syncCooldown == 0 && queuedSync) updateFluids(); } @@ -203,7 +203,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { return 0; return super.fill(resource, action); } - + public int forceFill(FluidStack resource, FluidAction action) { return super.fill(resource, action); } @@ -244,6 +244,9 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { fluidLevel.chase(tank.getFluidAmount() / (float) tank.getCapacity(), .25, Chaser.EXP); if (!getWorld().isRemote) sendDataLazily(); + if (tileEntity.isVirtual() && !tank.getFluid() + .isEmpty()) + renderedFluid = tank.getFluid(); } public FluidStack getRenderedFluid() { @@ -272,7 +275,7 @@ public class SmartFluidTankBehaviour extends TileEntityBehaviour { .isEmpty()) renderedFluid = tank.getFluid(); } - + public boolean isEmpty(float partialTicks) { FluidStack renderedFluid = getRenderedFluid(); if (renderedFluid.isEmpty()) diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/InvManipulationBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/InvManipulationBehaviour.java index eac304882..80fcbf014 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/InvManipulationBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/inventory/InvManipulationBehaviour.java @@ -107,12 +107,19 @@ public class InvManipulationBehaviour extends TileEntityBehaviour { return ItemStack.EMPTY; Predicate test = getFilterTest(filter); - ItemStack extract = ItemStack.EMPTY; - if (amount != -1) - extract = ItemHelper.extract(inventory, test, amount, shouldSimulate); - else - extract = ItemHelper.extract(inventory, test, amountThreshold, shouldSimulate); - return extract; + + ItemStack simulatedItems = extractAmountOrThresh(inventory, test, amount, amountThreshold, true); + if (shouldSimulate || simulatedItems.isEmpty()) + return simulatedItems; + + return extractAmountOrThresh(inventory, test, amount, amountThreshold, false); + } + + private static ItemStack extractAmountOrThresh(IItemHandler inventory, Predicate test, int amount, + Function amountThreshold, boolean shouldSimulate) { + if (amount == -1) + return ItemHelper.extract(inventory, test, amountThreshold, shouldSimulate); + return ItemHelper.extract(inventory, test, amount, shouldSimulate); } public ItemStack insert(ItemStack stack) { @@ -156,7 +163,7 @@ public class InvManipulationBehaviour extends TileEntityBehaviour { if (!targetCapability.isPresent()) findNewCapability(); } - + @Override public void tick() { super.tick(); 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 3d708e8f1..75aa226e0 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 @@ -7,6 +7,7 @@ import java.util.function.IntSupplier; import org.apache.commons.lang3.tuple.Pair; import com.simibubi.create.Create; +import com.simibubi.create.content.logistics.IRedstoneLinkable; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler; import com.simibubi.create.content.logistics.RedstoneLinkNetworkHandler.Frequency; import com.simibubi.create.foundation.tileEntity.SmartTileEntity; @@ -17,9 +18,10 @@ import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import net.minecraft.block.BlockState; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.vector.Vector3d; -public class LinkBehaviour extends TileEntityBehaviour { +public class LinkBehaviour extends TileEntityBehaviour implements IRedstoneLinkable { public static BehaviourType TYPE = new BehaviourType<>(); @@ -76,33 +78,37 @@ public class LinkBehaviour extends TileEntityBehaviour { frequencyLast = behaviour.frequencyLast; } + @Override public boolean isListening() { return mode == Mode.RECEIVE; } + @Override public int getTransmittedStrength() { return mode == Mode.TRANSMIT ? transmission.getAsInt() : 0; } - public void updateReceiver(int networkPower) { + @Override + public void setReceivedStrength(int networkPower) { if (!newPosition) return; signalCallback.accept(networkPower); } public void notifySignalChange() { - Create.redstoneLinkNetworkHandler.updateNetworkOf(this); + Create.REDSTONE_LINK_NETWORK_HANDLER.updateNetworkOf(getWorld(), this); } @Override public void initialize() { super.initialize(); - if (tileEntity.getWorld().isRemote) + if (getWorld().isRemote) return; - getHandler().addToNetwork(this); + getHandler().addToNetwork(getWorld(), this); newPosition = true; } + @Override public Pair getNetworkKey() { return Pair.of(frequencyFirst, frequencyLast); } @@ -110,9 +116,14 @@ public class LinkBehaviour extends TileEntityBehaviour { @Override public void remove() { super.remove(); - if (tileEntity.getWorld().isRemote) + if (getWorld().isRemote) return; - getHandler().removeFromNetwork(this); + getHandler().removeFromNetwork(getWorld(), this); + } + + @Override + public boolean isSafeNBT() { + return true; } @Override @@ -146,7 +157,7 @@ public class LinkBehaviour extends TileEntityBehaviour { !ItemStack.areItemsEqual(stack, toCompare) || !ItemStack.areItemStackTagsEqual(stack, toCompare); if (changed) - getHandler().removeFromNetwork(this); + getHandler().removeFromNetwork(getWorld(), this); if (first) frequencyFirst = Frequency.of(stack); @@ -157,7 +168,7 @@ public class LinkBehaviour extends TileEntityBehaviour { return; tileEntity.sendData(); - getHandler().addToNetwork(this); + getHandler().addToNetwork(getWorld(), this); } @Override @@ -166,7 +177,7 @@ public class LinkBehaviour extends TileEntityBehaviour { } private RedstoneLinkNetworkHandler getHandler() { - return Create.redstoneLinkNetworkHandler; + return Create.REDSTONE_LINK_NETWORK_HANDLER; } public static class SlotPositioning { @@ -194,4 +205,14 @@ public class LinkBehaviour extends TileEntityBehaviour { return (first ? firstSlot : secondSlot).testHit(state, localHit); } + @Override + public boolean isAlive() { + return !tileEntity.isRemoved() && getWorld().getTileEntity(getPos()) == tileEntity; + } + + @Override + public BlockPos getLocation() { + return getPos(); + } + } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java index 30a88de18..1c5e6319f 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkHandler.java @@ -2,10 +2,12 @@ package com.simibubi.create.foundation.tileEntity.behaviour.linked; import java.util.Arrays; +import com.simibubi.create.AllItems; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.utility.RaycastHelper; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResultType; import net.minecraft.util.Hand; import net.minecraft.util.SoundCategory; @@ -35,14 +37,19 @@ public class LinkHandler { if (behaviour == null) return; + ItemStack heldItem = player.getHeldItem(hand); BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10); if (ray == null) return; + if (AllItems.LINKED_CONTROLLER.isIn(heldItem)) + return; + if (AllItems.WRENCH.isIn(heldItem)) + return; for (boolean first : Arrays.asList(false, true)) { if (behaviour.testHit(first, ray.getHitVec())) { - if (event.getSide() != LogicalSide.CLIENT) - behaviour.setFrequency(first, player.getHeldItem(hand)); + if (event.getSide() != LogicalSide.CLIENT) + behaviour.setFrequency(first, heldItem); event.setCanceled(true); event.setCancellationResult(ActionResultType.SUCCESS); world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f); diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkRenderer.java index 6ebd59da6..8e7d31245 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/linked/LinkRenderer.java @@ -49,12 +49,12 @@ public class LinkRenderer { ValueBoxTransform transform = first ? behaviour.firstSlot : behaviour.secondSlot; ValueBox box = new ValueBox(label, bb, pos).withColors(0x601F18, 0xB73C2D) - .offsetLabel(behaviour.textShift) - .passive(!hit); - CreateClient.outliner.showValueBox(Pair.of(Boolean.valueOf(first), pos), box.transform(transform)) - .lineWidth(1 / 64f) - .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) - .highlightFace(result.getFace()); + .offsetLabel(behaviour.textShift) + .passive(!hit); + CreateClient.OUTLINER.showValueBox(Pair.of(Boolean.valueOf(first), pos), box.transform(transform)) + .lineWidth(1 / 64f) + .withFaceTexture(hit ? AllSpecialTextures.THIN_CHECKERED : null) + .highlightFace(result.getFace()); } } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java index c67fc80e0..d189a689d 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueBehaviour.java @@ -54,6 +54,9 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { ticksUntilScrollPacket = -1; } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.putInt("ScrollValue", value); @@ -95,7 +98,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { clientCallback = valueCallback; return this; } - + public ScrollValueBehaviour withCallback(Consumer valueCallback) { callback = valueCallback; return this; @@ -126,7 +129,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { this.unit = unit; return this; } - + public ScrollValueBehaviour onlyActiveWhen(Supplier condition) { isActive = condition; return this; @@ -168,7 +171,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { public BehaviourType getType() { return TYPE; } - + public boolean isActive() { return isActive.get(); } @@ -182,7 +185,7 @@ public class ScrollValueBehaviour extends TileEntityBehaviour { public void setLabel(ITextComponent label) { this.label = label; } - + public static class StepContext { public int currentValue; public boolean forward; diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueRenderer.java index cae0d79e1..ab5521204 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/scrollvalue/ScrollValueRenderer.java @@ -72,12 +72,12 @@ public class ScrollValueRenderer { box.scrollTooltip(new StringTextComponent("[").append(Lang.translate("action.scroll")).append("]")); box.offsetLabel(behaviour.textShift.add(20, -10, 0)) - .withColors(0x5A5D5A, 0xB5B7B6) - .passive(!highlight); + .withColors(0x5A5D5A, 0xB5B7B6) + .passive(!highlight); - CreateClient.outliner.showValueBox(pos, box.transform(behaviour.slotPositioning)) - .lineWidth(1 / 64f) - .highlightFace(face); + CreateClient.OUTLINER.showValueBox(pos, box.transform(behaviour.slotPositioning)) + .lineWidth(1 / 64f) + .highlightFace(face); } } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java index 59db72bcf..3f1bb7fd9 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/behaviour/simple/DeferralBehaviour.java @@ -20,6 +20,9 @@ public class DeferralBehaviour extends TileEntityBehaviour { this.callback = callback; } + @Override + public boolean isSafeNBT() { return true; } + @Override public void write(CompoundNBT nbt, boolean clientPacket) { nbt.putBoolean("NeedsUpdate", needsUpdate); @@ -38,7 +41,7 @@ public class DeferralBehaviour extends TileEntityBehaviour { if (needsUpdate && callback.get()) needsUpdate = false; } - + public void scheduleUpdate() { needsUpdate = true; } diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java b/src/main/java/com/simibubi/create/foundation/tileEntity/renderer/ColoredOverlayTileEntityRenderer.java index c7b6ac979..2b47c21fb 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,8 +1,8 @@ package com.simibubi.create.foundation.tileEntity.renderer; +import com.jozufozu.flywheel.backend.Backend; import com.mojang.blaze3d.matrix.MatrixStack; import com.simibubi.create.foundation.render.SuperByteBuffer; -import com.simibubi.create.foundation.render.backend.FastRenderDispatcher; import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.RenderType; @@ -19,7 +19,7 @@ public abstract class ColoredOverlayTileEntityRenderer ext protected void renderSafe(T te, float partialTicks, MatrixStack ms, IRenderTypeBuffer buffer, int light, int overlay) { - if (FastRenderDispatcher.available(te.getWorld())) return; + if (Backend.getInstance().canUseInstancing(te.getWorld())) return; SuperByteBuffer render = render(getOverlayBuffer(te), getColor(te, partialTicks), light); render.renderInto(ms, buffer.getBuffer(RenderType.getSolid())); diff --git a/src/main/java/com/simibubi/create/foundation/utility/AngleHelper.java b/src/main/java/com/simibubi/create/foundation/utility/AngleHelper.java index 9884e71c4..3f8723672 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/AngleHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/AngleHelper.java @@ -5,6 +5,9 @@ import net.minecraft.util.Direction.Axis; public class AngleHelper { + /** + * Legacy method. See {@link #horizontalAngleNew(Direction)} for new method. + */ public static float horizontalAngle(Direction facing) { float angle = facing.getHorizontalAngle(); if (facing.getAxis() == Axis.X) @@ -12,6 +15,19 @@ public class AngleHelper { return angle; } + /** + * Same as {@link #horizontalAngle(Direction)}, but returns 0 instead of -90 for vertical directions. + */ + public static float horizontalAngleNew(Direction facing) { + if (facing.getAxis().isVertical()) { + return 0; + } + float angle = facing.getHorizontalAngle(); + if (facing.getAxis() == Axis.X) + angle = -angle; + return angle; + } + public static float verticalAngle(Direction facing) { return facing == Direction.UP ? -90 : facing == Direction.DOWN ? 90 : 0; } diff --git a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java index a70af7ca1..cc76d5dbe 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/BlockHelper.java @@ -1,9 +1,18 @@ package com.simibubi.create.foundation.utility; +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; import javax.annotation.Nullable; +import net.minecraft.block.AbstractRailBlock; +import net.minecraft.block.RailBlock; + +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.ChunkSection; +import net.minecraftforge.common.util.BlockSnapshot; + import org.apache.commons.lang3.mutable.MutableInt; import com.simibubi.create.AllBlocks; @@ -234,6 +243,24 @@ public class BlockHelper { .isEmpty(); } + private static void placeRailWithoutUpdate(World world, BlockState state, BlockPos target) { + int i = target.getX() & 15; + int j = target.getY(); + int k = target.getZ() & 15; + Chunk chunk = world.getChunkAt(target); + ChunkSection chunksection = chunk.getSections()[j >> 4]; + if (chunksection == Chunk.EMPTY_SECTION) { + chunksection = new ChunkSection(j >> 4 << 4); + chunk.getSections()[j >> 4] = chunksection; + } + BlockState old = chunksection.setBlockState(i, j & 15, k, state); + chunk.markDirty(); + world.markAndNotifyBlock(target, chunk, old, state, 82, 512); + + world.setBlockState(target, state, 82); + world.neighborChanged(target, world.getBlockState(target.down()).getBlock(), target.down()); + } + public static void placeSchematicBlock(World world, BlockState state, BlockPos target, ItemStack stack, @Nullable CompoundNBT data) { // Piston @@ -268,7 +295,13 @@ public class BlockHelper { Block.spawnDrops(state, world, target); return; } - world.setBlockState(target, state, 18); + + if (state.getBlock() instanceof AbstractRailBlock) { + placeRailWithoutUpdate(world, state, target); + } else { + world.setBlockState(target, state, 18); + } + if (data != null) { TileEntity tile = world.getTileEntity(target); if (tile != null) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/ColorHandlers.java b/src/main/java/com/simibubi/create/foundation/utility/ColorHandlers.java new file mode 100644 index 000000000..75e429dd1 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/ColorHandlers.java @@ -0,0 +1,26 @@ +package com.simibubi.create.foundation.utility; + +import net.minecraft.block.RedstoneWireBlock; +import net.minecraft.client.renderer.color.IBlockColor; +import net.minecraft.client.renderer.color.IItemColor; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.world.GrassColors; +import net.minecraft.world.biome.BiomeColors; + +public class ColorHandlers { + + public static IBlockColor getGrassyBlock() { + return (state, world, pos, layer) -> pos != null && world != null ? BiomeColors.getGrassColor(world, pos) + : GrassColors.get(0.5D, 1.0D); + } + + public static IItemColor getGrassyItem() { + return (stack, layer) -> GrassColors.get(0.5D, 1.0D); + } + + public static IBlockColor getRedstonePower() { + return (state, world, pos, layer) -> RedstoneWireBlock + .getWireColor(pos != null && world != null ? state.get(BlockStateProperties.POWER_0_15) : 0); + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/Debug.java b/src/main/java/com/simibubi/create/foundation/utility/Debug.java index b52612b30..e6445ae11 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Debug.java +++ b/src/main/java/com/simibubi/create/foundation/utility/Debug.java @@ -1,5 +1,7 @@ package com.simibubi.create.foundation.utility; +import com.simibubi.create.Create; + import net.minecraft.client.Minecraft; import net.minecraft.util.text.IFormattableTextComponent; import net.minecraft.util.text.ITextComponent; @@ -14,23 +16,27 @@ import net.minecraftforge.fml.common.thread.EffectiveSide; public class Debug { @Deprecated - public static void debugChat(ITextComponent message) { + public static void debugChat(String message) { if (Minecraft.getInstance().player != null) - Minecraft.getInstance().player.sendStatusMessage(message, false); + Minecraft.getInstance().player.sendStatusMessage(new StringTextComponent(message), false); } @Deprecated - public static void debugChatAndShowStack(ITextComponent message, int depth) { + public static void debugChatAndShowStack(String message, int depth) { if (Minecraft.getInstance().player != null) - Minecraft.getInstance().player.sendStatusMessage(message.copy() - .append("@") + Minecraft.getInstance().player.sendStatusMessage(new StringTextComponent(message).append("@") .append(debugStack(depth)), false); } @Deprecated - public static void debugMessage(ITextComponent message) { + public static void debugMessage(String message) { if (Minecraft.getInstance().player != null) - Minecraft.getInstance().player.sendStatusMessage(message, true); + Minecraft.getInstance().player.sendStatusMessage(new StringTextComponent(message), true); + } + + @Deprecated + public static void log(String message) { + Create.LOGGER.info(message); } @Deprecated diff --git a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java index 38a66f0b0..deb9d4027 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/FilesHelper.java @@ -23,7 +23,7 @@ public class FilesHelper { try { Files.createDirectories(Paths.get(name)); } catch (IOException e) { - Create.logger.warn("Could not create Folder: {}", name); + Create.LOGGER.warn("Could not create Folder: {}", name); } } diff --git a/src/main/java/com/simibubi/create/foundation/utility/Coordinate.java b/src/main/java/com/simibubi/create/foundation/utility/ICoordinate.java similarity index 81% rename from src/main/java/com/simibubi/create/foundation/utility/Coordinate.java rename to src/main/java/com/simibubi/create/foundation/utility/ICoordinate.java index 6d1a246c7..aa4bdcbb8 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/Coordinate.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ICoordinate.java @@ -3,6 +3,6 @@ package com.simibubi.create.foundation.utility; import net.minecraft.util.math.BlockPos; @FunctionalInterface -public interface Coordinate { +public interface ICoordinate { float get(BlockPos from); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/IPartialSafeNBT.java b/src/main/java/com/simibubi/create/foundation/utility/IPartialSafeNBT.java new file mode 100644 index 000000000..ae1ca8a9d --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/IPartialSafeNBT.java @@ -0,0 +1,7 @@ +package com.simibubi.create.foundation.utility; + +import net.minecraft.nbt.CompoundNBT; + +public interface IPartialSafeNBT { + public void writeSafe(CompoundNBT compound, boolean clientPacket); +} diff --git a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java index d2a119cae..cf919904a 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java +++ b/src/main/java/com/simibubi/create/foundation/utility/NBTProcessors.java @@ -11,10 +11,13 @@ import com.simibubi.create.content.logistics.item.filter.FilterItem; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.nbt.ListNBT; import net.minecraft.tileentity.MobSpawnerTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.text.ITextComponent; +import net.minecraftforge.common.util.Constants; public final class NBTProcessors { @@ -32,10 +35,26 @@ public final class NBTProcessors { static { addProcessor(TileEntityType.SIGN, data -> { for (int i = 0; i < 4; ++i) { - String s = data.getString("Text" + (i + 1)); - ITextComponent textcomponent = ITextComponent.Serializer.fromJson(s.isEmpty() ? "\"\"" : s); - if (textcomponent != null && textcomponent.getStyle() != null && textcomponent.getStyle() - .getClickEvent() != null) + if (textComponentHasClickEvent(data.getString("Text" + (i + 1)))) + return null; + } + return data; + }); + addProcessor(TileEntityType.LECTERN, data -> { + if (!data.contains("Book", Constants.NBT.TAG_COMPOUND)) + return data; + CompoundNBT book = data.getCompound("Book"); + + if (!book.contains("tag", Constants.NBT.TAG_COMPOUND)) + return data; + CompoundNBT tag = book.getCompound("tag"); + + if (!tag.contains("pages", Constants.NBT.TAG_LIST)) + return data; + ListNBT pages = tag.getList("pages", Constants.NBT.TAG_STRING); + + for (INBT inbt : pages) { + if (textComponentHasClickEvent(inbt.getString())) return null; } return data; @@ -50,7 +69,13 @@ public final class NBTProcessors { }); } - private NBTProcessors() {} + public static boolean textComponentHasClickEvent(String json) { + ITextComponent component = ITextComponent.Serializer.fromJson(json.isEmpty() ? "\"\"" : json); + return component != null && component.getStyle() != null && component.getStyle().getClickEvent() != null; + } + + private NBTProcessors() { + } @Nullable public static CompoundNBT process(TileEntity tileEntity, CompoundNBT compound, boolean survival) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/RemapHelper.java b/src/main/java/com/simibubi/create/foundation/utility/RemapHelper.java index fc362c1ca..cf9877283 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/RemapHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/RemapHelper.java @@ -200,11 +200,11 @@ public class RemapHelper { for (RegistryEvent.MissingMappings.Mapping mapping : mappings) { if (reMap.containsKey(mapping.key.getPath())) { try { - Create.logger.warn("Remapping block '{}' to '{}'", mapping.key, reMap.get(mapping.key.getPath())); + Create.LOGGER.warn("Remapping block '{}' to '{}'", mapping.key, reMap.get(mapping.key.getPath())); mapping.remap(ForgeRegistries.BLOCKS.getValue(reMap.get(mapping.key.getPath()))); } catch (Throwable t) { - Create.logger.warn("Remapping block '{}' to '{}' failed: {}", mapping.key, - reMap.get(mapping.key.getPath()), t); + Create.LOGGER.warn("Remapping block '{}' to '{}' failed: {}", mapping.key, + reMap.get(mapping.key.getPath()), t); } } } @@ -223,11 +223,11 @@ public class RemapHelper { for (RegistryEvent.MissingMappings.Mapping mapping : mappings) { if (reMap.containsKey(mapping.key.getPath())) { try { - Create.logger.warn("Remapping item '{}' to '{}'", mapping.key, reMap.get(mapping.key.getPath())); + Create.LOGGER.warn("Remapping item '{}' to '{}'", mapping.key, reMap.get(mapping.key.getPath())); mapping.remap(ForgeRegistries.ITEMS.getValue(reMap.get(mapping.key.getPath()))); } catch (Throwable t) { - Create.logger.warn("Remapping item '{}' to '{}' failed: {}", mapping.key, - reMap.get(mapping.key.getPath()), t); + Create.LOGGER.warn("Remapping item '{}' to '{}' failed: {}", mapping.key, + reMap.get(mapping.key.getPath()), t); } } } 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 665ed1796..2809bf0b6 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java +++ b/src/main/java/com/simibubi/create/foundation/utility/VecHelper.java @@ -21,6 +21,7 @@ import net.minecraft.util.math.vector.Vector3i; public class VecHelper { + public static final Vector3f ZERO_3F = new Vector3f(0, 0, 0); public static final Vector3d CENTER_OF_ORIGIN = new Vector3d(.5, .5, .5); public static Vector3d rotate(Vector3d vec, Vector3d rotationVec) { diff --git a/src/main/java/com/simibubi/create/foundation/utility/VirtualEmptyModelData.java b/src/main/java/com/simibubi/create/foundation/utility/VirtualEmptyModelData.java deleted file mode 100644 index 1c9b35287..000000000 --- a/src/main/java/com/simibubi/create/foundation/utility/VirtualEmptyModelData.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.simibubi.create.foundation.utility; - -import net.minecraftforge.client.model.data.IModelData; -import net.minecraftforge.client.model.data.ModelProperty; - -/** - * This model data instance is passed whenever a model is rendered without - * available in-world context. IBakedModel#getModelData can react accordingly - * and avoid looking for model data itself - **/ -public enum VirtualEmptyModelData implements IModelData { - - INSTANCE; - - @Override - public boolean hasProperty(ModelProperty prop) { - return false; - } - - @Override - public T getData(ModelProperty prop) { - return null; - } - - @Override - public T setData(ModelProperty prop, T data) { - return null; - } - -} diff --git a/src/main/java/com/simibubi/create/foundation/utility/WeakHashSet.java b/src/main/java/com/simibubi/create/foundation/utility/WeakHashSet.java deleted file mode 100644 index 61e4c7818..000000000 --- a/src/main/java/com/simibubi/create/foundation/utility/WeakHashSet.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.simibubi.create.foundation.utility; - -import java.util.AbstractSet; -import java.util.Collection; -import java.util.Iterator; -import java.util.WeakHashMap; - -import net.minecraft.util.Unit; - -public class WeakHashSet extends AbstractSet { - - WeakHashMap map; - - public WeakHashSet() { - map = new WeakHashMap<>(); - } - - /** - * Constructs a new set containing the elements in the specified - * collection. The HashMap is created with default load factor - * (0.75) and an initial capacity sufficient to contain the elements in - * the specified collection. - * - * @param c the collection whose elements are to be placed into this set - * @throws NullPointerException if the specified collection is null - */ - public WeakHashSet(Collection c) { - map = new WeakHashMap<>(Math.max((int) (c.size() / .75f) + 1, 16)); - addAll(c); - } - - /** - * Constructs a new, empty set; the backing HashMap instance has - * the specified initial capacity and the specified load factor. - * - * @param initialCapacity the initial capacity of the hash map - * @param loadFactor the load factor of the hash map - * @throws IllegalArgumentException if the initial capacity is less - * than zero, or if the load factor is nonpositive - */ - public WeakHashSet(int initialCapacity, float loadFactor) { - map = new WeakHashMap<>(initialCapacity, loadFactor); - } - - /** - * Constructs a new, empty set; the backing HashMap instance has - * the specified initial capacity and default load factor (0.75). - * - * @param initialCapacity the initial capacity of the hash table - * @throws IllegalArgumentException if the initial capacity is less - * than zero - */ - public WeakHashSet(int initialCapacity) { - map = new WeakHashMap<>(initialCapacity); - } - - @Override - public Iterator iterator() { - return map.keySet() - .iterator(); - } - - @Override - public int size() { - return map.size(); - } - - @Override - public boolean add(T t) { - return map.put(t, Unit.INSTANCE) == null; - } - - @Override - public boolean remove(Object o) { - return map.remove((T) o) != null; - } - - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public boolean contains(Object o) { - return map.containsKey((T) o); - } - - @Override - public Object[] toArray() { - return map.keySet() - .toArray(); - } - - @Override - public boolean containsAll(Collection c) { - return c.stream() - .allMatch(map::containsKey); - } - - @Override - public boolean addAll(Collection c) { - return false; - } - - @Override - public boolean retainAll(Collection c) { - return false; - } - - @Override - public boolean removeAll(Collection c) { - return false; - } - - @Override - public void clear() { - map.clear(); - } -} diff --git a/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java b/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java index 337ab826b..ee9022165 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java +++ b/src/main/java/com/simibubi/create/foundation/utility/WorldAttached.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.function.Consumer; import java.util.function.Supplier; import javax.annotation.Nullable; @@ -41,9 +40,4 @@ public class WorldAttached { attached.put(world, entry); } - public void forEach(Consumer consumer) { - attached.values() - .forEach(consumer); - } - } diff --git a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java index 93309a030..6878acf40 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java +++ b/src/main/java/com/simibubi/create/foundation/utility/ghost/GhostBlockRenderer.java @@ -10,10 +10,10 @@ import javax.annotation.Nullable; import org.lwjgl.system.MemoryStack; +import com.jozufozu.flywheel.util.VirtualEmptyModelData; 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 com.simibubi.create.foundation.utility.placement.PlacementHelpers; import net.minecraft.block.BlockState; diff --git a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java index 605d47dfa..e23c179fc 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java +++ b/src/main/java/com/simibubi/create/foundation/utility/outliner/Outline.java @@ -51,7 +51,7 @@ public abstract class Outline { float lineWidth = params.getLineWidth(); if (lineWidth == 0) return; - + IVertexBuilder builder = buffer.getBuffer(RenderTypes.getOutlineSolid()); Vector3d diff = end.subtract(start); 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 0dcdb3e14..2b3403f0f 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 @@ -91,20 +91,20 @@ public interface IPlacementHelper { Vector3d direction = target.subtract(center).normalize(); Vector3d facing = Vector3d.of(arrowPlane.getDirectionVec()); Vector3d start = center.add(direction); - Vector3d offset = direction.scale(distanceFromCenter-1); + Vector3d offset = direction.scale(distanceFromCenter - 1); Vector3d offsetA = direction.crossProduct(facing).normalize().scale(.25); Vector3d offsetB = facing.crossProduct(direction).normalize().scale(.25); Vector3d endA = center.add(direction.scale(.75)).add(offsetA); Vector3d endB = center.add(direction.scale(.75)).add(offsetB); - CreateClient.outliner.showLine("placementArrowA" + center + target, start.add(offset), endA.add(offset)).lineWidth(1/16f); - CreateClient.outliner.showLine("placementArrowB" + center + target, start.add(offset), endB.add(offset)).lineWidth(1/16f); + CreateClient.OUTLINER.showLine("placementArrowA" + center + target, start.add(offset), endA.add(offset)).lineWidth(1 / 16f); + 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())) + CreateClient.GHOST_BLOCKS.showGhostState(this, offset.getTransform().apply(offset.getGhostState())) .at(offset.getBlockPos()) .breathingAlpha(); } 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 ee7fa842e..17fd6505c 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 @@ -102,12 +102,15 @@ public class PlacementOffset { return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable(); } - + public ActionResultType placeInWorld(World world, BlockItem blockItem, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { if (!isReplaceable(world)) return ActionResultType.PASS; + if (world.isRemote) + return ActionResultType.SUCCESS; + ItemUseContext context = new ItemUseContext(player, hand, ray); BlockPos newPos = new BlockPos(pos); @@ -135,9 +138,6 @@ public class PlacementOffset { player.addStat(Stats.ITEM_USED.get(blockItem)); - if (world.isRemote) - return ActionResultType.SUCCESS; - if (player instanceof ServerPlayerEntity) CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItem()); 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 ac5fdae65..e0f1c9806 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 @@ -3,9 +3,11 @@ package com.simibubi.create.foundation.utility.worldWrappers; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Map; +import java.util.Set; import java.util.function.Predicate; -import com.simibubi.create.foundation.render.backend.instancing.IFlywheelWorld; +import com.jozufozu.flywheel.backend.IFlywheelWorld; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -16,10 +18,10 @@ import net.minecraft.world.World; import net.minecraft.world.lighting.WorldLightManager; public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelWorld { - public HashMap blocksAdded; - public HashMap tesAdded; + public Map blocksAdded; + public Map tesAdded; - public HashSet spannedChunks; + public Set spannedSections; public WorldLightManager lighter; public WrappedChunkProvider chunkProvider; private final BlockPos.Mutable scratch = new BlockPos.Mutable(); @@ -31,7 +33,7 @@ public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelW public PlacementSimulationWorld(World wrapped, WrappedChunkProvider chunkProvider) { super(wrapped, chunkProvider); this.chunkProvider = chunkProvider.setWorld(this); - spannedChunks = new HashSet<>(); + spannedSections = new HashSet<>(); lighter = new WorldLightManager(chunkProvider, true, false); // blockLight, skyLight blocksAdded = new HashMap<>(); tesAdded = new HashMap<>(); @@ -42,6 +44,17 @@ public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelW return lighter; } + public void updateLightSources() { + for (Map.Entry entry : blocksAdded.entrySet()) { + BlockPos pos = entry.getKey(); + BlockState state = entry.getValue(); + int light = state.getLightValue(this, pos); + if (light > 0) { + lighter.func_215573_a(pos, light); + } + } + } + public void setTileEntities(Collection tileEntities) { tesAdded.clear(); tileEntities.forEach(te -> tesAdded.put(te.getPos(), te)); @@ -53,16 +66,17 @@ public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelW @Override public boolean setBlockState(BlockPos pos, BlockState newState, int flags) { + blocksAdded.put(pos, newState); SectionPos sectionPos = SectionPos.from(pos); - - if (spannedChunks.add(sectionPos)) { + if (spannedSections.add(sectionPos)) { lighter.updateSectionStatus(sectionPos, false); } - lighter.checkBlock(pos); + if ((flags & 128) == 0) { + lighter.checkBlock(pos); + } - blocksAdded.put(pos, newState); return true; } @@ -100,8 +114,6 @@ public class PlacementSimulationWorld extends WrappedWorld implements IFlywheelW BlockState state = blocksAdded.get(pos); if (state != null) return state; - else - return Blocks.AIR.getDefaultState(); + 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 index 4bb1dfffa..dbc75fcfd 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedChunkProvider.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedChunkProvider.java @@ -6,6 +6,7 @@ import java.util.stream.Stream; import javax.annotation.Nullable; +import com.simibubi.create.foundation.utility.worldWrappers.chunk.EmptierChunk; import com.simibubi.create.foundation.utility.worldWrappers.chunk.WrappedChunk; import net.minecraft.util.math.BlockPos; @@ -52,11 +53,11 @@ public class WrappedChunkProvider extends AbstractChunkProvider { return getChunk(x, z); } - public WrappedChunk getChunk(int x, int z) { + public IChunk getChunk(int x, int z) { long pos = ChunkPos.asLong(x, z); - + if (chunks == null) - return null; + return new EmptierChunk(); return chunks.computeIfAbsent(pos, $ -> new WrappedChunk(world, x, z)); } diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedClientWorld.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedClientWorld.java index ac0a8c9b3..f72f2b771 100644 --- a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedClientWorld.java +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/WrappedClientWorld.java @@ -50,6 +50,11 @@ public class WrappedClientWorld extends ClientWorld { public boolean isBlockLoaded(BlockPos pos) { return world.isBlockLoaded(pos); } + + @Override + public boolean isBlockPresent(BlockPos pos) { + return world.isBlockPresent(pos); + } @Override public Stream getBlockCollisions(@Nullable Entity entity, AxisAlignedBB axisAlignedBB) { 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 a5984048c..634da56bd 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 @@ -35,7 +35,7 @@ import net.minecraft.world.storage.MapData; public class WrappedWorld extends World { protected World world; - private AbstractChunkProvider provider; + protected AbstractChunkProvider provider; public WrappedWorld(World world, AbstractChunkProvider provider) { super((ISpawnWorldInfo) world.getWorldInfo(), world.getRegistryKey(), world.getDimension(), world::getProfiler, @@ -51,12 +51,12 @@ public class WrappedWorld extends World { public World getWorld() { return world; } - + @Override public WorldLightManager getLightingProvider() { return world.getLightingProvider(); } - + @Override public BlockState getBlockState(@Nullable BlockPos pos) { return world.getBlockState(pos); diff --git a/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/EmptierChunk.java b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/EmptierChunk.java new file mode 100644 index 000000000..dae7595f3 --- /dev/null +++ b/src/main/java/com/simibubi/create/foundation/utility/worldWrappers/chunk/EmptierChunk.java @@ -0,0 +1,82 @@ +package com.simibubi.create.foundation.utility.worldWrappers.chunk; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.Entity; +import net.minecraft.fluid.FluidState; +import net.minecraft.fluid.Fluids; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.lighting.WorldLightManager; +import net.minecraft.world.server.ChunkHolder; + +import javax.annotation.Nullable; + +import java.util.List; +import java.util.function.Predicate; + +public class EmptierChunk extends Chunk { + + public EmptierChunk() { + super(null, null, null); + } + + public BlockState getBlockState(BlockPos p_180495_1_) { + return Blocks.VOID_AIR.getDefaultState(); + } + + @Nullable + public BlockState setBlockState(BlockPos p_177436_1_, BlockState p_177436_2_, boolean p_177436_3_) { + return null; + } + + public FluidState getFluidState(BlockPos p_204610_1_) { + return Fluids.EMPTY.getDefaultState(); + } + + @Nullable + public WorldLightManager getWorldLightManager() { + return null; + } + + public int getLightValue(BlockPos p_217298_1_) { + return 0; + } + + public void addEntity(Entity p_76612_1_) { } + + public void removeEntity(Entity p_76622_1_) { } + + public void removeEntityAtIndex(Entity p_76608_1_, int p_76608_2_) { } + + @Nullable + public TileEntity getTileEntity(BlockPos p_177424_1_, Chunk.CreateEntityType p_177424_2_) { + return null; + } + + public void addTileEntity(TileEntity p_150813_1_) { } + + public void addTileEntity(BlockPos p_177426_1_, TileEntity p_177426_2_) { } + + public void removeTileEntity(BlockPos p_177425_1_) { } + + public void markDirty() { } + + public void getEntitiesWithinAABBForEntity(@Nullable Entity p_177414_1_, AxisAlignedBB p_177414_2_, List p_177414_3_, Predicate p_177414_4_) { } + + public void getEntitiesOfTypeWithinAABB(Class p_177430_1_, AxisAlignedBB p_177430_2_, List p_177430_3_, Predicate p_177430_4_) { } + + public boolean isEmpty() { + return true; + } + + public boolean isEmptyBetween(int p_76606_1_, int p_76606_2_) { + return true; + } + + public ChunkHolder.LocationType getLocationType() { + return ChunkHolder.LocationType.BORDER; + } +} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 7f1d7e995..c47d220df 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -92,3 +92,5 @@ public net.minecraft.util.math.vector.Matrix4f field_226587_m_ #a30 public net.minecraft.util.math.vector.Matrix4f field_226588_n_ #a31 public net.minecraft.util.math.vector.Matrix4f field_226589_o_ #a32 public net.minecraft.util.math.vector.Matrix4f field_226590_p_ #a33 + +public net.minecraft.client.renderer.WorldRenderer field_228407_B_ #blockBreakingProgressions diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 3c8e798a7..55f9eab8a 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,20 +1,24 @@ -modLoader="javafml" -loaderVersion="[34,)" -#issueTrackerURL="" +modLoader="javafml" +loaderVersion="[34,)" +issueTrackerURL="https://github.com/Creators-of-Create/Create/issues" license="MIT" -[[mods]] +[[mods]] modId="create" version="${file.jarVersion}" -displayName="Create" +displayName="Create" #updateJSONURL="" -authors="simibubi" +displayURL="https://www.curseforge.com/minecraft/mc-mods/create" +logoFile="logo.png" +#credits="" +authors="simibubi" description=''' -Technology that empowers the player.''' +Technology that empowers the player. +''' -[[dependencies.create]] +[[dependencies.create]] modId="forge" - mandatory=true + mandatory=true versionRange="[35.1.16,)" ordering="NONE" side="BOTH" @@ -24,4 +28,11 @@ Technology that empowers the player.''' mandatory=true versionRange="[1.16.4,1.17)" ordering="NONE" - side="BOTH" \ No newline at end of file + side="BOTH" + +[[dependencies.create]] + modId="flywheel" + mandatory=true + versionRange="[1.16,1.17)" + ordering="AFTER" + side="CLIENT" diff --git a/src/main/resources/assets/create/flywheel/programs/belt.json b/src/main/resources/assets/create/flywheel/programs/belt.json new file mode 100644 index 000000000..e6b53432e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/belt.json @@ -0,0 +1,33 @@ +{ + "vert": "create:belt.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": "create:rainbow_debug", + "define": "DEBUG_RAINBOW" + }, + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/chromatic.json b/src/main/resources/assets/create/flywheel/programs/chromatic.json new file mode 100644 index 000000000..f521eefa6 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/chromatic.json @@ -0,0 +1,4 @@ +{ + "vert": "create:area_effect.vert", + "frag": "create:area_effect.frag" +} diff --git a/src/main/resources/assets/create/flywheel/programs/contraption_actor.json b/src/main/resources/assets/create/flywheel/programs/contraption_actor.json new file mode 100644 index 000000000..e9acf9d1e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/contraption_actor.json @@ -0,0 +1,29 @@ +{ + "vert": "create:contraption_actor.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/contraption_structure.json b/src/main/resources/assets/create/flywheel/programs/contraption_structure.json new file mode 100644 index 000000000..9440ca25a --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/contraption_structure.json @@ -0,0 +1,29 @@ +{ + "vert": "create:contraption_structure.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/flap.json b/src/main/resources/assets/create/flywheel/programs/flap.json new file mode 100644 index 000000000..f7de4c45e --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/flap.json @@ -0,0 +1,29 @@ +{ + "vert": "create:flap.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/programs/rotating.json b/src/main/resources/assets/create/flywheel/programs/rotating.json new file mode 100644 index 000000000..58d80d445 --- /dev/null +++ b/src/main/resources/assets/create/flywheel/programs/rotating.json @@ -0,0 +1,33 @@ +{ + "vert": "create:rotating.vert", + "frag": "flywheel:block.frag", + "states": [ + { + "when": "create:rainbow_debug", + "define": "DEBUG_RAINBOW" + }, + { + "when": { + "provider": "flywheel:normal_debug", + "value": "true" + }, + "define": "DEBUG_NORMAL" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "linear" + }, + "define": ["USE_FOG", "USE_FOG_LINEAR"], + "extend": "flywheel:fog_linear" + }, + { + "when": { + "provider": "flywheel:fog_mode", + "value": "exp2" + }, + "define": ["USE_FOG", "USE_FOG_EXP2"], + "extend": "flywheel:fog_exp2" + } + ] +} diff --git a/src/main/resources/assets/create/flywheel/shaders/area_effect.frag b/src/main/resources/assets/create/flywheel/shaders/area_effect.frag new file mode 100644 index 000000000..6c34704ce --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/area_effect.frag @@ -0,0 +1,167 @@ +#version 140 + +#flwinclude <"flywheel:core/color.glsl"> + +in vec2 ScreenCoord; +in vec3 WorldDir; + +out vec4 Color; + +// constants +uniform sampler2D uDepth; +uniform sampler2D uColor; +uniform float uNearPlane = 0.15; +uniform float uFarPlane = 1.; +uniform vec3 uCameraPos; + +struct SphereFilter { + vec4 sphere;// + vec4 d1;// + vec4 strength;// + vec4 channelMask;// + mat4 colorOp; +}; + + #define N 256 +layout (std140) uniform Filters { + int uCount; + SphereFilter uSpheres[N]; +}; + +float linearizeDepth(float d, float zNear, float zFar) { + float clipZ = 2.0 * d - 1.0; + return zNear * zFar / (zFar + zNear - clipZ * (zFar - zNear)); +} + +vec3 filterColor(mat4 colorOp, vec3 color) { + // preserve alpha while transforming color + vec4 i = vec4(color, 1.); + i *= colorOp; + return i.rgb; +} + +float getDepth() { + float depth = texture2D(uDepth, ScreenCoord).r; + + return linearizeDepth(depth, uNearPlane, uFarPlane); +} + +float surfaceFilterStrength(vec3 worldPos, vec4 sphere, float feather) { + float distance = distance(sphere.xyz, worldPos); + return 1 - smoothstep(sphere.w, sphere.w + feather, distance); +} + +vec2 raySphere(vec3 worldDir, vec3 position, float radius) { + float rayLengthSqr = dot(worldDir, worldDir); + float sphereDistSqr = dot(position, position); + + const vec3 M = vec3(2., 2., 4.); + vec3 f = M * vec3(dot(-position, worldDir), vec2(rayLengthSqr)); + + vec2 s = vec2(f.x, radius); + vec2 s2 = s * s; + float c = sphereDistSqr - s2.y; + float dc = f.z * c; + + float discriminant = s2.x - dc; + float hitDepth = (-f.x - sqrt(discriminant)) / f.y; + + return vec2(discriminant, hitDepth); +} + +// if i == 0 return s +// if i == 1 return 1 - s +float invert(float s, float i) { + return i - 2*i*s + s; +} + +float bubbleFilterStrength(vec3 worldDir, float depth, vec4 sphere, float feather, float density) { + vec3 position = sphere.xyz; + + vec2 hit = raySphere(worldDir, position, sphere.w + feather); + float hitDepth = hit.y; + + float strength = 0.; + + //float boo = step(0., discriminant) * step(0., hitDepth) * step(0., depth - hitDepth); + if (hit.x > 0 && hitDepth > 0 && hitDepth < depth) { + vec3 hitPos = worldDir * hitDepth; + + vec3 normal = normalize(hitPos - position); + float normalDot = dot(normal, normalize(worldDir)); + // blend into the effect based on the distance between the fragcoord and point on the sphere + // this avoinds having hard edges + strength += mix(0., normalDot * normalDot * density, clamp(depth - hitDepth, 0., feather + 1.)); + } + + return clamp(strength, 0., 1.);// * boo; +} + +float filterStrength(vec3 worldDir, float depth, inout SphereFilter f) { + vec4 sphere = f.sphere; + vec4 data = f.d1; + float feather = data.x; + + float strength; + // transition effect + float transitionRadius = sphere.w + feather; + strength = 1. - smoothstep(transitionRadius, transitionRadius + max(0.5, data.y), length(sphere.xyz)); + // bubble effect + strength = max(strength, bubbleFilterStrength(worldDir, depth, sphere, feather, data.z)); + + strength *= f.strength.y; + // surface effect + strength = max(strength, surfaceFilterStrength(worldDir * depth, sphere, feather) * f.strength.x); + + return strength * f.strength.z; +} + +vec3 applyFilters(vec3 worldDir, float depth, vec3 diffuse) { + vec3 worldPos = worldDir * depth; + + vec3 accum = vec3(diffuse); + + for (int i = 0; i < uCount; i++) { + SphereFilter s = uSpheres[i]; + + float strength = filterStrength(worldDir, depth, s); + + strength = invert(strength, s.strength.w); + + if (strength > 0) { + const float fcon = 0.; + + vec3 baseColor = mix(diffuse, accum, s.d1.w); + + vec3 filtered = filterColor(s.colorOp, baseColor); + + // vec3 baseHsv = rgb2hsv(baseColor); + // vec3 maskHsv = rgb2hsv(s.colorMask.rgb); + // float diff = dot(abs(baseHsv - maskHsv), vec3(1., 1.1, 0.1)); + // float colorMask = step(s.colorMask.w, diff); + float mixing = clamp(strength, 0., 1.); + + accum = mix(accum, filtered, mixing * s.channelMask.xyz); + //accum = vec3(colorMask); + } + } + + return accum; +} + +vec4 debugGrid(vec3 worldPos, vec4 diffuse) { + vec3 fractionalCoords = fract(worldPos - uCameraPos); + + vec3 isBonudary = step(15./16., fractionalCoords); + + return vec4(mix(diffuse.rgb, fractionalCoords, isBonudary), 1.); +} + +void main() { + float depth = getDepth(); + + vec4 diffuse = texture2D(uColor, ScreenCoord); + + Color = vec4(applyFilters(WorldDir, depth, diffuse.rgb), diffuse.a); + //Color = debugGrid(WorldDir * depth, Color); +} diff --git a/src/main/resources/assets/create/flywheel/shaders/area_effect.vert b/src/main/resources/assets/create/flywheel/shaders/area_effect.vert new file mode 100644 index 000000000..0a0d8443a --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/area_effect.vert @@ -0,0 +1,29 @@ +#version 140 + +// scaling constants +// e - 0.99, this works well, no idea why +#define SXY 1.7282818 +// 1.90 -> highp close, mediump far +// 1.91 -> mediump close, highp far +#define SZ 1.905 + +in vec4 aVertex;// + +out vec2 ScreenCoord; +out vec3 WorldDir; + +uniform mat4 uInverseProjection; +uniform mat4 uInverseView; + +void main() { + gl_Position = vec4(aVertex.xy, 0., 1.); + ScreenCoord = aVertex.zw; + + vec4 clip = vec4(aVertex.xy, 0., 1.); + + clip *= uInverseProjection; + + vec3 cameraDir = clip.xyz / clip.w; + cameraDir = cameraDir * vec3(SXY, SXY, SZ); + WorldDir = (uInverseView * vec4(cameraDir, 1.)).xyz; +} diff --git a/src/main/resources/assets/create/flywheel/shaders/belt.vert b/src/main/resources/assets/create/flywheel/shaders/belt.vert index 3a5fefcec..be5d51a43 100644 --- a/src/main/resources/assets/create/flywheel/shaders/belt.vert +++ b/src/main/resources/assets/create/flywheel/shaders/belt.vert @@ -1,87 +1,51 @@ -#version 110 #define PI 3.1415926538 -#flwinclude <"create:core/quaternion.glsl"> -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/diffuse.glsl"> +#flwbuiltins +#flwinclude <"flywheel:core/quaternion.glsl"> +#flwinclude <"flywheel:core/matutils.glsl"> +#flwinclude <"flywheel:core/diffuse.glsl"> -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; +#[InstanceData] +struct Belt { + vec2 light; + vec4 color; + vec3 pos; + float speed; + float offset; + vec4 rotation; + vec2 sourceTexture; + vec4 scrollTexture; + float scrollMult; +}; -attribute vec2 aLight; -attribute vec4 aColor; -attribute vec3 aInstancePos; -attribute float aSpeed; -attribute float aOffset; -attribute vec4 aInstanceRot; -attribute vec2 aSourceTexture; -attribute vec4 aScrollTexture; -attribute float aScrollMult; +#flwinclude <"flywheel:data/modelvertex.glsl"> +#flwinclude <"flywheel:data/blockfragment.glsl"> -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -#if defined(CONTRAPTION) -varying vec3 BoxCoord; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; -#endif - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -void main() { - vec3 rotated = rotateVertexByQuat(aPos - .5, aInstanceRot) + aInstancePos + .5; +BlockFrag FLWMain(Vertex v, Belt instance) { + vec3 rotated = rotateVertexByQuat(v.pos - .5, instance.rotation) + instance.pos + .5; vec4 worldPos = vec4(rotated, 1.); - vec3 norm = rotateVertexByQuat(aNormal, aInstanceRot); + vec3 norm = rotateVertexByQuat(v.normal, instance.rotation); -#ifdef CONTRAPTION - worldPos = uModel * worldPos; - norm = normalize(modelToNormal(uModel) * norm); + FLWFinalizeWorldPos(worldPos); + FLWFinalizeNormal(norm); - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); - #endif -#elif defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); -#endif + float scrollSize = instance.scrollTexture.w - instance.scrollTexture.y; + float scroll = fract(instance.speed * uTime / (31.5 * 16.) + instance.offset) * scrollSize * instance.scrollMult; - float scrollSize = aScrollTexture.w - aScrollTexture.y; - float scroll = fract(aSpeed * uTime / (31.5 * 16.) + aOffset) * scrollSize * aScrollMult; + BlockFrag b; + b.diffuse = diffuse(norm); + b.texCoords = v.texCoords - instance.sourceTexture + instance.scrollTexture.xy + vec2(0, scroll); + b.light = instance.light; - 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.); - } + #if defined(DEBUG_RAINBOW) + b.color = instance.color; + #elif defined(DEBUG_NORMAL) + b.color = vec4(norm, 1.); #else - if (uDebug == 1) { - Color = aColor; - } else if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } + b.color = vec4(1.); #endif + + return b; } diff --git a/src/main/resources/assets/create/flywheel/shaders/context/contraption/builtin.frag b/src/main/resources/assets/create/flywheel/shaders/context/contraption/builtin.frag new file mode 100644 index 000000000..919e64ceb --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/context/contraption/builtin.frag @@ -0,0 +1,31 @@ +#flwinclude <"flywheel:context/world/fog.glsl"> +#flwinclude <"flywheel:core/lightutil.glsl"> + +varying vec3 BoxCoord; +varying vec2 BoxLight; +uniform sampler3D uLightVolume; + +uniform sampler2D uBlockAtlas; +uniform sampler2D uLightMap; + +vec4 FLWBlockTexture(vec2 texCoords) { + return texture2D(uBlockAtlas, texCoords); +} + +void FLWFinalizeColor(vec4 color) { + #if defined(USE_FOG) + float a = color.a; + float fog = clamp(FLWFogFactor(), 0., 1.); + + color = mix(uFogColor, color, fog); + color.a = a; + #endif + + gl_FragColor = color; +} + +vec4 FLWLight(vec2 lightCoords) { + lightCoords = max(lightCoords, texture3D(uLightVolume, BoxCoord).rg); + + return texture2D(uLightMap, shiftLight(lightCoords)); +} diff --git a/src/main/resources/assets/create/flywheel/shaders/context/contraption/builtin.vert b/src/main/resources/assets/create/flywheel/shaders/context/contraption/builtin.vert new file mode 100644 index 000000000..3d82348ea --- /dev/null +++ b/src/main/resources/assets/create/flywheel/shaders/context/contraption/builtin.vert @@ -0,0 +1,34 @@ +#if defined(USE_FOG) +varying float FragDistance; +#endif + +varying vec3 BoxCoord; + +uniform vec3 uLightBoxSize; +uniform vec3 uLightBoxMin; +uniform mat4 uModel; + +uniform float uTime; +uniform mat4 uViewProjection; +uniform vec3 uCameraPos; + +void FLWFinalizeWorldPos(inout vec4 worldPos) { + worldPos = uModel * worldPos; + + BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; + + #if defined(USE_FOG) + FragDistance = length(worldPos.xyz); + #endif + + gl_Position = uViewProjection * worldPos; +} + +void FLWFinalizeNormal(inout vec3 normal) { + mat3 m; + m[0] = uModel[0].xyz; + m[1] = uModel[1].xyz; + m[2] = uModel[2].xyz; + normal = m * normal; +} + diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption.frag b/src/main/resources/assets/create/flywheel/shaders/contraption.frag deleted file mode 100644 index 9049221f1..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/contraption.frag +++ /dev/null @@ -1,54 +0,0 @@ -#version 110 - -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -varying vec3 BoxCoord; - -uniform sampler2D uBlockAtlas; -uniform sampler2D uLightMap; -uniform sampler3D uLightVolume; - -#if defined(USE_FOG) -varying float FragDistance; -uniform vec4 uFogColor; -#endif - -#if defined(USE_FOG_LINEAR) -uniform vec2 uFogRange; - -float fogFactor() { - return (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); -} -#endif - -#ifdef USE_FOG_EXP2 -uniform float uFogDensity; - -float fogFactor() { - float dist = FragDistance * uFogDensity; - return 1. / exp2(dist * dist); -} -#endif - -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); - -#if defined(USE_FOG) - float fog = clamp(fogFactor(), 0., 1.); - - gl_FragColor = mix(uFogColor, color, fog); - gl_FragColor.a = color.a; -#else - gl_FragColor = color; -#endif -} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert index b58a4df0e..25ff4980a 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_actor.vert @@ -1,71 +1,47 @@ -#version 110 #define PI 3.1415926538 -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/quaternion.glsl"> -#flwinclude <"create:core/diffuse.glsl"> +#flwbuiltins +#flwinclude <"flywheel:core/matutils.glsl"> +#flwinclude <"flywheel:core/quaternion.glsl"> +#flwinclude <"flywheel:core/diffuse.glsl"> -// model data -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; +#[InstanceData] +struct Actor { + vec3 pos; + vec2 light; + float offset; + vec3 axis; + vec4 rotation; + vec3 rotationCenter; + float speed; +}; -// instance data -attribute vec3 aInstancePos; -attribute vec2 aModelLight; -attribute float aOffset; -attribute vec3 aAxis; -attribute vec4 aInstanceRot; -attribute vec3 aRotationCenter; -attribute float aSpeed; +#flwinclude <"flywheel:data/modelvertex.glsl"> +#flwinclude <"flywheel:data/blockfragment.glsl"> - -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; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -void main() { - float degrees = aOffset + uTime * aSpeed / 20.; +BlockFrag FLWMain(Vertex v, Actor instance) { + float degrees = instance.offset + uTime * instance.speed / 20.; //float angle = fract(degrees / 360.) * PI * 2.; - vec4 kineticRot = quat(aAxis, degrees); - vec3 rotated = rotateVertexByQuat(aPos - aRotationCenter, kineticRot) + aRotationCenter; - vec3 localPos = rotateVertexByQuat(rotated - .5, aInstanceRot) + aInstancePos + .5; + vec4 kineticRot = quat(instance.axis, degrees); + vec3 rotated = rotateVertexByQuat(v.pos - instance.rotationCenter, kineticRot) + instance.rotationCenter; - vec4 worldPos = uModel * vec4(localPos, 1.); + vec4 worldPos = vec4(rotateVertexByQuat(rotated - .5, instance.rotation) + instance.pos + .5, 1.); + vec3 norm = rotateVertexByQuat(rotateVertexByQuat(v.normal, kineticRot), instance.rotation); - vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, kineticRot), aInstanceRot); - norm = modelToNormal(uModel) * norm; + FLWFinalizeWorldPos(worldPos); + FLWFinalizeNormal(norm); - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aModelLight; - gl_Position = uViewProjection * worldPos; + BlockFrag b; + b.diffuse = diffuse(norm); + b.texCoords = v.texCoords; + b.light = instance.light; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); + #if defined(DEBUG_NORMAL) + b.color = vec4(norm, 1.); + #else + b.color = vec4(1.); #endif - if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } -} \ No newline at end of file + return b; +} diff --git a/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert b/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert index dbcf4a595..a42245c1d 100644 --- a/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert +++ b/src/main/resources/assets/create/flywheel/shaders/contraption_structure.vert @@ -1,53 +1,37 @@ -#version 110 #define PI 3.1415926538 -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/diffuse.glsl"> +#flwbuiltins +#flwinclude <"flywheel:core/matutils.glsl"> +#flwinclude <"flywheel:core/diffuse.glsl"> -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; -attribute vec4 aColor; -attribute vec2 aModelLight; +#[VertexData] +struct Vertex { + vec3 pos; + vec3 normal; + vec2 texCoords; + vec4 color; + vec2 modelLight; +}; -varying float Diffuse; -varying vec2 TexCoords; -varying vec4 Color; -varying vec3 BoxCoord; -varying vec2 Light; +#flwinclude <"flywheel:data/blockfragment.glsl"> -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; +BlockFrag FLWMain(Vertex v) { + vec4 worldPos = vec4(v.pos, 1.); + vec3 norm = v.normal; -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; + FLWFinalizeWorldPos(worldPos); + FLWFinalizeNormal(norm); -uniform vec3 uCameraPos; + BlockFrag b; + b.diffuse = diffuse(norm); + b.texCoords = v.texCoords; + b.light = v.modelLight; -#if defined(USE_FOG) -varying float FragDistance; -#endif - -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; - gl_Position = uViewProjection * viewPos; - #if defined(USE_FOG) - FragDistance = length(viewPos.xyz); + #if defined(DEBUG_NORMAL) + b.color = vec4(norm, 1.); + #else + b.color = v.color / diffuse(v.normal); #endif - if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = aColor / diffuse(aNormal); - } + return b; } diff --git a/src/main/resources/assets/create/flywheel/shaders/core/diffuse.glsl b/src/main/resources/assets/create/flywheel/shaders/core/diffuse.glsl deleted file mode 100644 index bc5792231..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/core/diffuse.glsl +++ /dev/null @@ -1,5 +0,0 @@ - -float diffuse(vec3 normal) { - vec3 n2 = normal * normal * vec3(.6, .25, .8); - return min(n2.x + n2.y * (3. + normal.y) + n2.z, 1.); -} diff --git a/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl b/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl deleted file mode 100644 index f7c846e71..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/core/matutils.glsl +++ /dev/null @@ -1,42 +0,0 @@ - -//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. -// ); -//} - -mat4 rotate(vec3 axis, float angle) { - float s = sin(angle); - float c = cos(angle); - float oc = 1. - c; - - vec3 sa = axis * s; - - mat4 mr = mat4(1.); - mr[0].xyz = oc * axis.xxz * axis.xyx + vec3(c, sa.z, -sa.y); - mr[1].xyz = oc * axis.xyy * axis.yyz + vec3(-sa.z, c, sa.x); - mr[2].xyz = oc * axis.zyz * axis.xzz + vec3(sa.y, -sa.x, c); - - return mr; -} - -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); -} - -mat3 modelToNormal(mat4 mat) { - // Discard the edges. This won't be accurate for scaled or skewed matrices, - // but we don't have to work with those often. - mat3 m; - m[0] = mat[0].xyz; - m[1] = mat[1].xyz; - m[2] = mat[2].xyz; - return m; -} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/core/quaternion.glsl b/src/main/resources/assets/create/flywheel/shaders/core/quaternion.glsl deleted file mode 100644 index cbfff38ee..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/core/quaternion.glsl +++ /dev/null @@ -1,56 +0,0 @@ - -#define PIOVER2 1.5707963268 - -vec4 quat(vec3 axis, float angle) { - float halfAngle = angle * PIOVER2 / 180.0; - vec2 cs = sin(vec2(PIOVER2 - halfAngle, halfAngle)); // compute sin and cos in one instruction - return vec4(axis.xyz * cs.y, cs.x); -} - -vec4 quatMult(vec4 q1, vec4 q2) { - // disgustingly vectorized quaternion multiplication - vec4 a = q1.w * q2.xyzw; - vec4 b = q1.x * q2.wzxy * vec4(1., -1., 1., -1.); - vec4 c = q1.y * q2.zwxy * vec4(1., 1., -1., -1.); - vec4 d = q1.z * q2.yxwz * vec4(-1., 1., 1., -1.); - - return a + b + c + d; -} -// -//vec4 exp(vec4 q) { -// vec3 i = q.xyz; -// float r = sqrt(dot(i, i)); -// float et = exp(q.w); -// float s = et * sin(r) / r; -// -// vec4 qr; -// qr.w = et * cos(r); -// qr.xyz = i * s; -// -// return qr; -//} -// -//vec4 ln(vec4 q) { -// vec3 i = q.xyz; -// float r = sqrt(dot(i, i)); -// float t = atan(r, q.w) / r; -// -// vec4 qr; -// qr.w = log(dot(q, q)) * 0.5; -// qr.xyz = i * t; -// -// return qr; -//} -// -//vec4 pow(vec4 q, float n) { -// return exp(ln(q) * n); -//} - -vec3 rotateVertexByQuat(vec3 v, vec4 q) { - vec3 i = q.xyz; - return v + 2.0 * cross(i, cross(i, v) + q.w * v); -} - -vec3 rotateAbout(vec3 v, vec3 axis, float angle) { - return rotateVertexByQuat(v, quat(axis, angle)); -} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/flap.vert b/src/main/resources/assets/create/flywheel/shaders/flap.vert index 496051288..ef39637df 100644 --- a/src/main/resources/assets/create/flywheel/shaders/flap.vert +++ b/src/main/resources/assets/create/flywheel/shaders/flap.vert @@ -1,94 +1,66 @@ -#version 110 #define PI 3.1415926538 -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/quaternion.glsl"> -#flwinclude <"create:core/diffuse.glsl"> +#flwbuiltins +#flwinclude <"flywheel:core/matutils.glsl"> +#flwinclude <"flywheel:core/quaternion.glsl"> +#flwinclude <"flywheel:core/diffuse.glsl"> -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; +#[InstanceData] +struct Flap { + vec3 instancePos; + vec2 light; + vec3 segmentOffset; + vec3 pivot; + float horizontalAngle; + float intensity; + float flapScale; + float flapness; +}; -attribute vec3 aInstancePos; -attribute vec2 aLight; +#flwinclude <"flywheel:data/modelvertex.glsl"> +#flwinclude <"flywheel:data/blockfragment.glsl"> -attribute vec3 aSegmentOffset; -attribute vec3 aPivot; -attribute float aHorizontalAngle; -attribute float aIntensity; -attribute float aFlapScale; - -attribute float aFlapness; - -// outputs -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -#if defined(CONTRAPTION) -varying vec3 BoxCoord; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; -#endif - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif float toRad(float degrees) { return fract(degrees / 360.) * PI * 2.; } -float getFlapAngle() { - float absFlap = abs(aFlapness); +float getFlapAngle(float flapness, float intensity, float scale) { + float absFlap = abs(flapness); - float angle = sin((1. - absFlap) * PI * aIntensity) * 30. * aFlapness * aFlapScale; + float angle = sin((1. - absFlap) * PI * intensity) * 30. * flapness * scale; float halfAngle = angle * 0.5; - float which = step(0., aFlapness); - float degrees = which * halfAngle + (1. - which) * angle; // branchless conditional multiply + float which = step(0., flapness);// 0 if negative, 1 if positive + float degrees = which * halfAngle + (1. - which) * angle;// branchless conditional multiply return degrees; } -void main() { - float flapAngle = getFlapAngle(); +BlockFrag FLWMain(Vertex v, Flap flap) { + float flapAngle = getFlapAngle(flap.flapness, flap.intensity, flap.flapScale); - vec4 orientation = quat(vec3(0., 1., 0.), -aHorizontalAngle); + vec4 orientation = quat(vec3(0., 1., 0.), -flap.horizontalAngle); vec4 flapRotation = quat(vec3(1., 0., 0.), flapAngle); - vec3 rotated = rotateVertexByQuat(aPos - aPivot, flapRotation) + aPivot + aSegmentOffset; - rotated = rotateVertexByQuat(rotated - .5, orientation) + aInstancePos + .5; + vec3 rotated = rotateVertexByQuat(v.pos - flap.pivot, flapRotation) + flap.pivot + flap.segmentOffset; + rotated = rotateVertexByQuat(rotated - .5, orientation) + flap.instancePos + .5; vec4 worldPos = vec4(rotated, 1.); - vec3 norm = rotateVertexByQuat(rotateVertexByQuat(aNormal, flapRotation), orientation); + vec3 norm = rotateVertexByQuat(rotateVertexByQuat(v.normal, flapRotation), orientation); - #ifdef CONTRAPTION - worldPos = uModel * worldPos; - norm = modelToNormal(uModel) * norm; + FLWFinalizeWorldPos(worldPos); + FLWFinalizeNormal(norm); - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); + BlockFrag b; + b.diffuse = diffuse(norm); + b.texCoords = v.texCoords; + b.light = flap.light; + #if defined(DEBUG_NORMAL) + b.color = vec4(norm, 1.); + #else + b.color = vec4(1.); #endif - #elif defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); - #endif - - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aLight; - gl_Position = uViewProjection * worldPos; - - Color = vec4(1.); + return b; } diff --git a/src/main/resources/assets/create/flywheel/shaders/model.frag b/src/main/resources/assets/create/flywheel/shaders/model.frag deleted file mode 100644 index e8ffaa00c..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/model.frag +++ /dev/null @@ -1,51 +0,0 @@ -#version 110 - -varying vec2 TexCoords; -varying vec2 Light; -varying float Diffuse; -varying vec4 Color; - -uniform sampler2D uBlockAtlas; -uniform sampler2D uLightMap; - -#if defined(USE_FOG) -varying float FragDistance; -uniform vec4 uFogColor; -#endif - -#if defined(USE_FOG_LINEAR) -uniform vec2 uFogRange; - -float fogFactor() { - return (uFogRange.y - FragDistance) / (uFogRange.y - uFogRange.x); -} -#endif - -#ifdef USE_FOG_EXP2 -uniform float uFogDensity; - -float fogFactor() { - float dist = FragDistance * uFogDensity; - return 1. / exp2(dist * dist); -} -#endif - -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; - -#if defined(USE_FOG) - float fog = clamp(fogFactor(), 0., 1.); - - gl_FragColor = mix(uFogColor, color, fog); - gl_FragColor.a = color.a; -#else - gl_FragColor = color; -#endif -} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/model.vert b/src/main/resources/assets/create/flywheel/shaders/model.vert deleted file mode 100644 index ea4503b75..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/model.vert +++ /dev/null @@ -1,63 +0,0 @@ -#version 110 - -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/diffuse.glsl"> - -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; - -attribute vec2 aLight; -attribute vec4 aColor; -attribute mat4 aTransform; -attribute mat3 aNormalMat; - -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -#if defined(CONTRAPTION) -varying vec3 BoxCoord; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; -#endif - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -void main() { - vec4 worldPos = aTransform * vec4(aPos, 1.); - - vec3 norm = aNormalMat * aNormal; - -#ifdef CONTRAPTION - worldPos = uModel * worldPos; - norm = modelToNormal(uModel) * norm; - - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); - #endif -#elif defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); -#endif - - norm = normalize(norm); - - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aLight; - gl_Position = uViewProjection * worldPos; - - Color = aColor; -} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/oriented.vert b/src/main/resources/assets/create/flywheel/shaders/oriented.vert deleted file mode 100644 index d32feca3b..000000000 --- a/src/main/resources/assets/create/flywheel/shaders/oriented.vert +++ /dev/null @@ -1,63 +0,0 @@ -#version 110 - -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/quaternion.glsl"> -#flwinclude <"create:core/diffuse.glsl"> - -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; - -attribute vec2 aLight; -attribute vec4 aColor; -attribute vec3 aInstancePos; -attribute vec3 aPivot; -attribute vec4 aRotation; - -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -#if defined(CONTRAPTION) -varying vec3 BoxCoord; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; -#endif - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -void main() { - vec4 worldPos = vec4(rotateVertexByQuat(aPos - aPivot, aRotation) + aPivot + aInstancePos, 1.); - - vec3 norm = rotateVertexByQuat(aNormal, aRotation); - -#ifdef CONTRAPTION - worldPos = uModel * worldPos; - norm = normalize(modelToNormal(uModel) * norm); - - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); - #endif -#elif defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); -#endif - - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aLight; - gl_Position = uViewProjection * worldPos; - - Color = aColor; -} \ No newline at end of file diff --git a/src/main/resources/assets/create/flywheel/shaders/rotating.vert b/src/main/resources/assets/create/flywheel/shaders/rotating.vert index 091e16faa..5acfdbd3f 100644 --- a/src/main/resources/assets/create/flywheel/shaders/rotating.vert +++ b/src/main/resources/assets/create/flywheel/shaders/rotating.vert @@ -1,87 +1,52 @@ -#version 110 #define PI 3.1415926538 -#flwinclude <"create:core/quaternion.glsl"> -#flwinclude <"create:core/matutils.glsl"> -#flwinclude <"create:core/diffuse.glsl"> +#flwbuiltins +#flwinclude <"flywheel:core/matutils.glsl"> +#flwinclude <"flywheel:core/diffuse.glsl"> -attribute vec3 aPos; -attribute vec3 aNormal; -attribute vec2 aTexCoords; +#[InstanceData] +struct Rotating { + vec2 light; + vec4 color; + vec3 pos; + float speed; + float offset; + vec3 axis; +}; -attribute vec2 aLight; -attribute vec4 aColor; -attribute vec3 aInstancePos; -attribute float aSpeed; -attribute float aOffset; -attribute vec3 aAxis; +#flwinclude <"flywheel:data/modelvertex.glsl"> +#flwinclude <"flywheel:data/blockfragment.glsl"> -varying vec2 TexCoords; -varying vec4 Color; -varying float Diffuse; -varying vec2 Light; - -#if defined(CONTRAPTION) -varying vec3 BoxCoord; - -uniform vec3 uLightBoxSize; -uniform vec3 uLightBoxMin; -uniform mat4 uModel; -#endif - -uniform float uTime; -uniform mat4 uViewProjection; -uniform int uDebug; - -uniform vec3 uCameraPos; - -#if defined(USE_FOG) -varying float FragDistance; -#endif - -mat4 kineticRotation() { - float degrees = aOffset + uTime * aSpeed * 3./10.; +mat4 kineticRotation(float offset, float speed, vec3 axis) { + float degrees = offset + uTime * speed * 3./10.; float angle = fract(degrees / 360.) * PI * 2.; - return rotate(aAxis, angle); + return rotate(axis, angle); } -void main() { - mat4 kineticRotation = kineticRotation(); - vec4 worldPos = kineticRotation * vec4(aPos - .5, 1.) + vec4(aInstancePos + .5, 0.); +BlockFrag FLWMain(Vertex v, Rotating instance) { + mat4 spin = kineticRotation(instance.offset, instance.speed, instance.axis); - vec3 norm = modelToNormal(kineticRotation) * aNormal; + vec4 worldPos = spin * vec4(v.pos - .5, 1.); + worldPos += vec4(instance.pos + .5, 0.); - #ifdef CONTRAPTION - worldPos = uModel * worldPos; - norm = normalize(modelToNormal(uModel) * norm); + vec3 norm = modelToNormal(spin) * v.normal; - BoxCoord = (worldPos.xyz - uLightBoxMin) / uLightBoxSize; - #if defined(USE_FOG) - FragDistance = length(worldPos.xyz); - #endif - #elif defined(USE_FOG) - FragDistance = length(worldPos.xyz - uCameraPos); - #endif + FLWFinalizeWorldPos(worldPos); + FLWFinalizeNormal(norm); - Diffuse = diffuse(norm); - TexCoords = aTexCoords; - Light = aLight; - gl_Position = uViewProjection * worldPos; + BlockFrag b; + b.diffuse = diffuse(norm); + b.texCoords = v.texCoords; + b.light = instance.light; - #ifdef CONTRAPTION - if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } + #if defined(DEBUG_RAINBOW) + b.color = instance.color; + #elif defined(DEBUG_NORMAL) + b.color = vec4(norm, 1.); #else - if (uDebug == 1) { - Color = aColor; - } else if (uDebug == 2) { - Color = vec4(norm, 1.); - } else { - Color = vec4(1.); - } + b.color = vec4(1.); #endif -} \ No newline at end of file + + return b; +} diff --git a/src/main/resources/assets/create/lang/default/messages.json b/src/main/resources/assets/create/lang/default/messages.json index 22a691d46..d952edec3 100644 --- a/src/main/resources/assets/create/lang/default/messages.json +++ b/src/main/resources/assets/create/lang/default/messages.json @@ -12,6 +12,13 @@ "create.block.deployer.damage_source_name": "a rogue Deployer", "create.block.cart_assembler.invalid": "Place your Cart Assembler on a rail block", + "create.menu.return": "Return to Menu", + "create.menu.configure": "Configure...", + "create.menu.getting_started": "Getting Started", + "create.menu.project_page": "Project Page", + "create.menu.report_bugs": "Report Issues", + "create.menu.support": "Support Us", + "create.recipe.crushing": "Crushing", "create.recipe.milling": "Milling", "create.recipe.fan_washing": "Bulk Washing", @@ -37,11 +44,11 @@ "create.recipe.spout_filling": "Filling by Spout", "create.recipe.draining": "Item Draining", - "create.recipe.processing.chance": "%1$s%% Chance", + "create.recipe.processing.chance": "%1$s%% Chance", "create.recipe.heat_requirement.none": "No Heating Required", "create.recipe.heat_requirement.heated": "Heated", "create.recipe.heat_requirement.superheated": "Super-Heated", - + "create.generic.range": "Range", "create.generic.radius": "Radius", "create.generic.width": "Width", @@ -116,11 +123,11 @@ "create.gui.terrainzapper.tool.clear": "Clear", "create.gui.terrainzapper.tool.overlay": "Overlay", "create.gui.terrainzapper.tool.flatten": "Flatten", - + "create.terrainzapper.shiftRightClickToSet": "Shift-Right-Click to Select a Shape", "create.terrainzapper.usingBlock": "Using: %1$s", "create.terrainzapper.leftClickToSet": "Left-Click a Block to set Material", - + "create.minecart_coupling.two_couplings_max": "Minecarts cannot have more than two couplings each", "create.minecart_coupling.unloaded": "Parts of your train seem to be in unloaded chunks", "create.minecart_coupling.no_loops": "Couplings cannot form a loop", @@ -138,13 +145,13 @@ "create.contraptions.cart_movement_mode.rotate": "Always face toward motion", "create.contraptions.cart_movement_mode.rotate_paused": "Pause actors while rotating", "create.contraptions.cart_movement_mode.rotation_locked": "Lock rotation", - + "create.contraptions.windmill.rotation_direction": "Rotation Direction", "create.contraptions.clockwork.clock_hands": "Clock Hands", "create.contraptions.clockwork.hour_first": "Hour hand first", "create.contraptions.clockwork.minute_first": "Minute hand first", "create.contraptions.clockwork.hour_first_24": "24-Hour hand first", - + "create.logistics.filter": "Filter", "create.logistics.recipe_filter": "Recipe Filter", "create.logistics.fluid_filter": "Fluid Filter", @@ -176,7 +183,7 @@ "create.gui.stressometer.capacity": "Remaining Capacity", "create.gui.stressometer.overstressed": "Overstressed", "create.gui.stressometer.no_rotation": "No Rotation", - + "create.gui.contraptions.not_fast_enough": "It appears that this %1$s is _not_ rotating with _enough_ _speed_.", "create.gui.contraptions.network_overstressed": "It appears that this contraption is _overstressed_. Add more sources or _slow_ _down_ the components with a high _stress_ _impact_.", @@ -289,7 +296,7 @@ "create.gui.schematicannon.option.replaceWithEmpty": "Replace Solid with Empty", "create.gui.schematicannon.option.skipMissing": "Skip missing Blocks", "create.gui.schematicannon.option.skipTileEntities": "Protect Tile Entities", - + "create.gui.schematicannon.slot.gunpowder": "Add gunpowder to fuel the cannon", "create.gui.schematicannon.slot.listPrinter": "Place books here to print a Checklist for your Schematic", "create.gui.schematicannon.slot.schematic": "Add your Schematic here. Make sure it is deployed at a specific location.", @@ -330,7 +337,7 @@ "create.gui.filter.respect_data.description": "Items only match if their durability, enchantments, and other attributes match as well.", "create.gui.filter.ignore_data": "Ignore Data", "create.gui.filter.ignore_data.description": "Items match regardless of their attributes.", - + "create.item_attributes.placeable": "is placeable", "create.item_attributes.placeable.inverted": "is not placeable", "create.item_attributes.consumable": "can be eaten", @@ -392,7 +399,7 @@ "create.item_attributes.astralsorcery_perk_gem.inverted": "does not have perk attribute %1$s", "create.item_attributes.astralsorcery_amulet": "improves %1$s", "create.item_attributes.astralsorcery_amulet.inverted": "does not improve %1$s", - + "create.gui.attribute_filter.no_selected_attributes": "No attributes selected", "create.gui.attribute_filter.selected_attributes": "Selected attributes:", "create.gui.attribute_filter.add_attribute": "Add attribute to List", @@ -428,12 +435,12 @@ "create.tooltip.generationSpeed" : "Generates at %1$s %2$s", "create.tooltip.analogStrength": "Analog Strength: %1$s/15", - + "create.mechanical_arm.extract_from": "Take items from %1$s", "create.mechanical_arm.deposit_to": "Deposit items to %1$s", "create.mechanical_arm.summary": "Mechanical Arm has %1$s input(s) and %2$s output(s).", "create.mechanical_arm.points_outside_range": "%1$s selected interaction point(s) removed due to range limitations.", - + "create.weighted_ejector.target_set": "Target Selected", "create.weighted_ejector.target_not_valid": "Ejecting to Adjacent block (Target was not Valid)", "create.weighted_ejector.no_target": "Ejecting to Adjacent block (No Target was Selected)", @@ -463,7 +470,21 @@ "create.tooltip.chute.fans_pull_up": "Fans pull from Above", "create.tooltip.chute.fans_pull_down": "Fans pull from Below", "create.tooltip.chute.contains": "Contains: %1$s x%2$s", - + + "create.linked_controller.bind_mode": "Bind mode active", + "create.linked_controller.press_keybind": "Press %1$s, %2$s, %3$s, %4$s, %5$s or %6$s, to bind this frequency to the respective key", + "create.linked_controller.key_bound": "Frequency bound to %1$s", + "create.linked_controller.frequency_slot_1": "Keybind: %1$s, Freq. #1", + "create.linked_controller.frequency_slot_2": "Keybind: %1$s, Freq. #2", + + "create.crafting_blueprint.crafting_slot": "Ingredient Slot", + "create.crafting_blueprint.filter_items_viable": "Advanced filter items are viable", + "create.crafting_blueprint.display_slot": "Display Slot", + "create.crafting_blueprint.inferred": "Inferred from recipe", + "create.crafting_blueprint.manually_assigned": "Manually assigned", + "create.crafting_blueprint.secondary_display_slot": "Secondary Display Slot", + "create.crafting_blueprint.optional": "Optional", + "create.hint.hose_pulley.title": "Bottomless Supply", "create.hint.hose_pulley": "The targeted body of fluid is considered infinite.", "create.hint.mechanical_arm_no_targets.title": "No Targets", @@ -489,7 +510,8 @@ "create.command.killTPSCommand.status.usage.0": "[Create]: use /killtps stop to bring back server tick to regular speed", "create.command.killTPSCommand.status.usage.1": "[Create]: use /killtps start to artificially slow down the server tick", "create.command.killTPSCommand.argument.tickTime": "tickTime", - - "create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up" -} \ No newline at end of file + "create.contraption.minecart_contraption_too_big": "This Cart Contraption seems too big to pick up", + "create.contraption.minecart_contraption_illegal_pickup": "A mystical force is binding this Cart Contraption to the world" + +} diff --git a/src/main/resources/assets/create/lang/default/tooltips.json b/src/main/resources/assets/create/lang/default/tooltips.json index 6e54364cd..1945353f1 100644 --- a/src/main/resources/assets/create/lang/default/tooltips.json +++ b/src/main/resources/assets/create/lang/default/tooltips.json @@ -8,36 +8,36 @@ "item.create.example_item.tooltip.behaviour2": "You can add as many behaviours as you like", "item.create.example_item.tooltip.control1": "When Ctrl pressed", "item.create.example_item.tooltip.action1": "These controls are displayed.", - + "block.create.wooden_bracket.tooltip": "WOODEN BRACKET", "block.create.wooden_bracket.tooltip.summary": "_Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with a cozy and wooden bit of reinforcement.", - + "block.create.metal_bracket.tooltip": "METAL BRACKET", "block.create.metal_bracket.tooltip.summary": "_Decorate_ your _Shafts, Cogwheels_ and _Pipes_ with an industrial and sturdy bit of reinforcement.", - + "block.create.copper_casing.tooltip": "COPPER CASING", "block.create.copper_casing.tooltip.summary": "Robust machine casing with a variety of uses. Safe for decoration.", "block.create.copper_casing.tooltip.condition1": "When used on Fluid Pipe", "block.create.copper_casing.tooltip.behaviour1": "_Encases_ the _Fluid Pipe_ with the _Copper Casing_. Encased Fluid pipes will _lock their connections_ in place, no longer reacting to changes to neighbouring pipes.", - + "block.create.encased_fluid_pipe.tooltip": "ENCASED FLUID PIPE", "block.create.encased_fluid_pipe.tooltip.summary": "A _Fluid Pipe_ encased with the _Copper Casing_.", - + "block.create.seat.tooltip": "SEAT", "block.create.seat.tooltip.summary": "Sit yourself down and enjoy the ride! Will anchor a player onto a moving _contraption_. Great for static furniture too! Comes in a variety of colours.", "block.create.seat.tooltip.condition1": "Right click on Seat", "block.create.seat.tooltip.behaviour1": "Sits the player on the _Seat_. Press L-shift to leave the _Seat_.", - + "item.create.blaze_cake.tooltip": "BLAZE CAKE", "item.create.blaze_cake.tooltip.summary": "A Delicious treat for your hard-working _Blaze Burners_. Gets them all fired up!", - + "block.create.fluid_pipe.tooltip": "FLUID PIPE", "block.create.fluid_pipe.tooltip.summary": "Used for moving _fluids_ around. Needs a _Mechanical Pump_ to get the _fluid_ moving.", "block.create.fluid_pipe.tooltip.condition1": "Fluid Transfer", "block.create.fluid_pipe.tooltip.behaviour1": "Can connect to _fluid containers_ such as _Tanks_ or _Basins_. Exposed _pipe_ ends can also drain or place fluid blocks. Be careful of leaks!", "block.create.fluid_pipe.tooltip.condition2": "Right-clicked with Wrench", "block.create.fluid_pipe.tooltip.behaviour2": "Places a window on the pipe if available", - + "block.create.hose_pulley.tooltip": "HOSE PULLEY", "block.create.hose_pulley.tooltip.summary": "Used for _placing_ or _draining_ large _fluid bodies_ in the world.", "block.create.hose_pulley.tooltip.condition1": "When Powered by Kinetics", @@ -46,50 +46,50 @@ "block.create.hose_pulley.tooltip.behaviour2": "Starts _taking fluid_ blocks from the body the hose end was lowered into. Very _large bodies_ of fluids will be _considered infinite_.", "block.create.hose_pulley.tooltip.condition3": "When Fluids pushed to Pulley", "block.create.hose_pulley.tooltip.behaviour3": "Starts _filling fluid_ into the world _up to_ the _hose_ ends' _height_.", - + "block.create.fluid_tank.tooltip": "FLUID TANK", "block.create.fluid_tank.tooltip.summary": "_Stores_ all your favourite _fluids_. Scales in width and height.", "block.create.fluid_tank.tooltip.condition1": "Right-clicked with Wrench", "block.create.fluid_tank.tooltip.behaviour1": "Changes the optional window", - + "block.create.creative_fluid_tank.tooltip": "CREATIVE FLUID TANK", "block.create.creative_fluid_tank.tooltip.summary": "This _Fluid Tank_ allows infinite replication of any Fluid. Scales in width and height.", "block.create.creative_fluid_tank.tooltip.condition1": "When Fluid in Tank", "block.create.creative_fluid_tank.tooltip.behaviour1": "Anything _extracting_ from this tank will provide an _endless supply_ of the fluid specified. Fluids _inserted_ into this tank will be _voided._", "block.create.creative_fluid_tank.tooltip.condition2": "Right-clicked with Wrench", "block.create.creative_fluid_tank.tooltip.behaviour2": "Changes the optional window", - + "block.create.fluid_valve.tooltip": "FLUID VALVE", "block.create.fluid_valve.tooltip.summary": "Halts the flow of fluid down a pipe.", "block.create.fluid_valve.tooltip.condition1": "Controllable flow", "block.create.fluid_valve.tooltip.behaviour1": "Applied _rotational force_ will force the _valve_ to close, ceasing the flow of _fluids_. Reverse the direction of the _rotational force_ to re-open the valve.", - + "block.create.mechanical_pump.tooltip": "MECHANICAL PUMP", "block.create.mechanical_pump.tooltip.summary": "Takes _rotational force_ and uses it to move _fluid_ along a _pipe_. Has a maximum range of effect in both directions. (16 blocks by default)", "block.create.mechanical_pump.tooltip.condition1": "Fluid Flow", "block.create.mechanical_pump.tooltip.behaviour1": "Applied _rotational force_ creates pressure that forces _fluid_ through the _pipe_ network. Reverse the direction of the _rotational force_ to switch the direction that the _fluid_ flows.", "block.create.mechanical_pump.tooltip.control1": "Right-clicked with Wrench", - "block.create.mechanical_pump.tooltip.action1": "Reverses the direction of the _pump_, switching the default direction of the flow", - + "block.create.mechanical_pump.tooltip.action1": "Reverses the direction of the _pump_, switching the default direction of the flow", + "block.create.smart_fluid_pipe.tooltip": "SMART FLUID PIPE", "block.create.smart_fluid_pipe.tooltip.summary": "A _fluid pipe_ with a filter. Can specify which _fluids_ pass through.", "block.create.smart_fluid_pipe.tooltip.condition1": "When Fluids are pushed into it", "block.create.smart_fluid_pipe.tooltip.behaviour1": "Smart pipes receiving fluid that does not match its filter will block the flow.", "block.create.smart_fluid_pipe.tooltip.condition2": "When adjacent to fluid container", "block.create.smart_fluid_pipe.tooltip.behaviour2": "Smart pipes _starting_ a _flow_ from any container will only extract fluids that _match_ its _filter._", - + "block.create.spout.tooltip": "SPOUT", "block.create.spout.tooltip.summary": "An injector for refilling your _fluid items._", "block.create.spout.tooltip.condition1": "Fluid Transfer", "block.create.spout.tooltip.behaviour1": "When a _fluid container item_ such as a _bucket_ or _bottle_ is placed underneath, the spout will attempt to refill it with it's own stored _fluid_.", "block.create.spout.tooltip.condition2": "Fluid Automation", - "block.create.spout.tooltip.behaviour2": "The spout placed above a _belt_ or _depot_ will react automatically with a _fluid container item_ that passes beneath it.", - + "block.create.spout.tooltip.behaviour2": "The spout placed above a _belt_ or _depot_ will react automatically with a _fluid container item_ that passes beneath it.", + "block.create.item_drain.tooltip": "ITEM DRAIN", "block.create.item_drain.tooltip.summary": "A grated depot for emptying your _fluid items._", "block.create.item_drain.tooltip.condition1": "Fluid Transfer", - "block.create.item_drain.tooltip.behaviour1": "When a _fluid container item_ such as a _bucket_ or _bottle_ is inserted from the side, the drain will attempt to empty it into its own _fluid container_. The item will then be ejected on the opposite side.", - + "block.create.item_drain.tooltip.behaviour1": "When a _fluid container item_ such as a _bucket_ or _bottle_ is inserted from the side, the drain will attempt to empty it into its own _fluid container_. The item will then be ejected on the opposite side.", + "item.create.wand_of_symmetry.tooltip": "SYMMETRY WAND", "item.create.wand_of_symmetry.tooltip.summary": "Perfectly mirrors Block placement across configured planes.", "item.create.wand_of_symmetry.tooltip.condition1": "When in Hotbar", @@ -100,7 +100,7 @@ "item.create.wand_of_symmetry.tooltip.action2": "_Removes_ the active Mirror", "item.create.wand_of_symmetry.tooltip.control3": "R-Click while Sneaking", "item.create.wand_of_symmetry.tooltip.action3": "Opens the _Configuration Interface_", - + "item.create.handheld_worldshaper.tooltip": "HANDHELD WORLDSHAPER", "item.create.handheld_worldshaper.tooltip.summary": "Handy tool for creating _landscapes_ and _terrain features_.", "item.create.handheld_worldshaper.tooltip.control1": "L-Click at Block", @@ -126,7 +126,7 @@ "item.create.filter.tooltip.behaviour1": "_Controls_ item flow according to its _configuration_.", "item.create.filter.tooltip.condition2": "When R-Clicked", "item.create.filter.tooltip.behaviour2": "Opens the _configuration interface_.", - + "item.create.attribute_filter.tooltip": "ATTRIBUTE FILTER", "item.create.attribute_filter.tooltip.summary": "_Controls outputs_ and _inputs_ of logistical devices with more _precision_, matching them against a _set of_ item _attributes_ and _categories_.", "item.create.attribute_filter.tooltip.condition1": "When in filter slot", @@ -175,17 +175,17 @@ "item.create.goggles.tooltip.behaviour2": "Shows detailed information about _Speed_ or _Stress_ of the network to which the gauge is connected.", "item.create.goggles.tooltip.condition3": "When looking at fluid containers", "item.create.goggles.tooltip.behaviour3": "Shows detailed information about the _Capacity_ of the block and any _Fluids_ stored within.", - + "item.create.wrench.tooltip": "WRENCH", "item.create.wrench.tooltip.summary": "A useful tool for working on kinetic contraptions. Can be used to _Rotate_, _Dismantle_ and to _Configure_ components.", "item.create.wrench.tooltip.control1": "Right-Click a kinetic block", "item.create.wrench.tooltip.action1": "_Rotates components_ toward or away from the face with which you interacted.", "item.create.wrench.tooltip.control2": "R-Click while Sneaking", "item.create.wrench.tooltip.action2": "_Disassembles Kinetic components_ and places them back in _your inventory_.", - + "block.create.nozzle.tooltip": "NOZZLE", "block.create.nozzle.tooltip.summary": "Attach to the front of an _Encased Fan_ to distribute its effect on Entities in _all directions_.", - + "block.create.cuckoo_clock.tooltip": "CUCKOO CLOCK", "block.create.cuckoo_clock.tooltip.summary": "Fine craftsmanship for _decorating_ a space and _keeping track of time_.", "block.create.cuckoo_clock.tooltip.condition1": "When Powered by Kinetics", @@ -193,19 +193,19 @@ "block.create.turntable.tooltip": "TURNTABLE", "block.create.turntable.tooltip.summary": "Turns _Rotational Force_ into refined Motion Sickness.", - + "block.create.portable_fluid_interface.tooltip": "PORTABLE FLUID INTERFACE", "block.create.portable_fluid_interface.tooltip.summary": "A portable interchange point for _moving fluids_ to and from a _structure_ moved by a piston, bearing, minecart, or pulley. Two meeting interfaces have to _face each other_ and be spaced _1-2 blocks apart_.", "block.create.portable_fluid_interface.tooltip.condition1": "While Moving", "block.create.portable_fluid_interface.tooltip.behaviour1": "Interacts with stationary _portable storage interfaces_ to transfer fluids to or from the contraption. Pipes inserting into or extracting from the _Stationary Interface_ will interact with the tanks on the contraption _directly._ The structure will briefly stall as Fluids are exchanged.", "block.create.portable_fluid_interface.tooltip.condition2": "When Powered by Redstone", "block.create.portable_fluid_interface.tooltip.behaviour2": "_Disengages_ any active connection immediately.", - + "block.create.stockpile_switch.tooltip": "STOCKPILE SWITCH", "block.create.stockpile_switch.tooltip.summary": "Toggles a Redstone signal based on the amount of _Stored Items_ in the attached Container. Comes with a handy filter. As opposed to a _Comparator,_ the _Stockpile Switch_ allows configuration of _thresholds,_ at which signals are inverted.", "block.create.stockpile_switch.tooltip.condition1": "When R-Clicked", "block.create.stockpile_switch.tooltip.behaviour1": "Opens the _Configuration Interface_.", - + "block.create.content_observer.tooltip": "CONTENT OBSERVER", "block.create.content_observer.tooltip.summary": "_Detects Items_ inside _containers_ and _conveyors_ matching a configured _filter_. While the observed _inventory_, _belt_ or _chute contains_ a matching item, this component will emit a _Redstone Signal_. When an observed _funnel transfers_ a matching item, this component will emit a _Redstone Pulse_.", @@ -213,7 +213,7 @@ "block.create.adjustable_crate.tooltip.summary": "This _Item Container_ allows Manual control over its capacity. It can hold up to _16 Stacks_ of any Item. Supports _Redstone Comparators_.", "block.create.adjustable_crate.tooltip.condition1": "When R-Clicked", "block.create.adjustable_crate.tooltip.behaviour1": "Opens the _Interface_.", - + "block.create.creative_crate.tooltip": "THE ENDLESS CRATE", "block.create.creative_crate.tooltip.summary": "This _Storage Container_ allows infinite replication of any item. Place next to a _Schematicannon_ to remove any material requirements.", "block.create.creative_crate.tooltip.condition1": "When Item in Filter Slot", @@ -223,37 +223,92 @@ "block.create.controller_rail.tooltip.summary": "A _uni-directional powered rail_ capable of _fine control_ over a minecarts' _movement speed_.", "block.create.controller_rail.tooltip.condition1": "When Powered by Redstone", "block.create.controller_rail.tooltip.behaviour1": "_Accelerates_ or _Decelerates_ passing _minecarts_ corresponding to the _signal strength_. Propagates redstone power to adjacent controller rails. Powering two controller rails with different strengths will cause tracks between them to interpolate their signal.", - + "item.create.sand_paper.tooltip": "SAND PAPER", "item.create.sand_paper.tooltip.summary": "A rough paper that can be used to _polish materials_. Can be automatically applied using the Deployer.", "item.create.sand_paper.tooltip.condition1": "When Used", "item.create.sand_paper.tooltip.behaviour1": "Applies polish to items held in the _offhand_ or lying on the _floor_ when _looking at them_", - + "item.create.builders_tea.tooltip": "BUILDERS TEA", "item.create.builders_tea.tooltip.summary": "The perfect drink to get the day started- _Motivating_ and _Saturating._", - + "item.create.refined_radiance.tooltip": "REFINED RADIANCE", "item.create.refined_radiance.tooltip.summary": "A Chromatic material forged from _absorbed light_.", - + "item.create.refined_radiance.tooltip.condition1": "Work In Progress", + "item.create.refined_radiance.tooltip.behaviour1": "Usages for this material will be available in a future release.", + "item.create.shadow_steel.tooltip": "SHADOW STEEL", "item.create.shadow_steel.tooltip.summary": "A Chromatic material forged _in the void_.", - + "item.create.shadow_steel.tooltip.condition1": "Work In Progress", + "item.create.shadow_steel.tooltip.behaviour1": "Usages for this material will be available in a future release.", + + "item.create.linked_controller.tooltip": "LINKED CONTROLLER", + "item.create.linked_controller.tooltip.summary": "Grants _handheld_ _control_ over _Redstone Link_ frequencies assigned to its _six_ _buttons_.", + "item.create.linked_controller.tooltip.condition1": "R-Click", + "item.create.linked_controller.tooltip.behaviour1": "_Toggles_ the controller. _Movement_ _controls_ are taken over while its active.", + "item.create.linked_controller.tooltip.condition2": "R-Click while Sneaking", + "item.create.linked_controller.tooltip.behaviour2": "Opens the manual _Configuration Interface_.", + "item.create.linked_controller.tooltip.condition3": "R-Click on Redstone Link Receiver", + "item.create.linked_controller.tooltip.behaviour3": "Enables _Bind Mode_, press one of the _six controls_ to bind it to the _Links' Frequency_.", + + "item.create.diving_helmet.tooltip": "DIVING HELMET", + "item.create.diving_helmet.tooltip.summary": "Together with a _Copper_ _Backtank_, allows the weilder to _breathe_ _underwater_ for an extended amount of time.", + "item.create.diving_helmet.tooltip.condition1": "When Worn", + "item.create.diving_helmet.tooltip.behaviour1": "Provides the _Water Breathing_ effect, slowly draining _Air Pressure_ from the Backtank.", + + "item.create.copper_backtank.tooltip": "COPPER BACKTANK", + "item.create.copper_backtank.tooltip.summary": "A _Wearable_ _Tank_ for carrying Pressurized Air.", + "item.create.copper_backtank.tooltip.condition1": "When Worn", + "item.create.copper_backtank.tooltip.behaviour1": "Provides _Pressurized_ _Air_ to Equipment that requires it.", + "item.create.copper_backtank.tooltip.condition2": "When placed, Powered by Kinetics", + "item.create.copper_backtank.tooltip.behaviour2": "_Collects_ _Pressurized_ _Air_ at a rate depending on the Rotational Speed.", + + "item.create.diving_boots.tooltip": "DIVING BOOTS", + "item.create.diving_boots.tooltip.summary": "A pair of _heavy_ _boots_, allowing for better traversal of the Ocean floor.", + "item.create.diving_boots.tooltip.condition1": "When Worn", + "item.create.diving_boots.tooltip.behaviour1": "Weilder _sinks_ _faster_ and _cannot_ _swim_. Grants the ability to _walk_ and _jump_ underwater. Weilder also is no longer affected by _Mechanical_ _Belts_.", + + "item.create.crafting_blueprint.tooltip": "CRAFTING BLUEPRINT", + "item.create.crafting_blueprint.tooltip.summary": "_Placed_ on a wall, it can be used to _specify_ _ingredient_ _arrangements_ for easier manual crafting. Each slot represents a Recipe.", + "item.create.crafting_blueprint.condition1": "R-Click empty Slot", + "item.create.crafting_blueprint.behaviour1": "Opens a _Crafting_ _menu_ allowing you to _configure_ a _recipe_ and items to display.", + "item.create.crafting_blueprint.condition2": "R-Click configured Slot", + "item.create.crafting_blueprint.behaviour2": "_Applies_ the _configured_ _recipe_ with matching Ingredients found in your _Inventory_. _Sneak_ to craft up to a _Stack_ of items.", + "item.create.minecart_coupling.tooltip": "MINECART COUPLING", "item.create.minecart_coupling.tooltip.summary": "_Chains_ all your _Minecarts_ or _Carriage Contraptions_ together to form a majestic Train.", "item.create.minecart_coupling.tooltip.condition1": "When Used on Minecart", "item.create.minecart_coupling.tooltip.behaviour1": "_Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving.", - - "create.tooltip.wip": "WIP", - "create.tooltip.workInProgress": "Work in progress!", - - "create.tooltip.randomWipDescription0": "Please keep this item away from children.", - "create.tooltip.randomWipDescription1": "A baby panda dies every time you use this item. Every. Time.", - "create.tooltip.randomWipDescription2": "Use at your own risk.", - "create.tooltip.randomWipDescription3": "This is not the item you are looking for, *finger-wiggles* please disperse.", - "create.tooltip.randomWipDescription4": "This item will self-destruct in 10 seconds. 10, 9, 8...", - "create.tooltip.randomWipDescription5": "Believe me, it's useless.", - "create.tooltip.randomWipDescription6": "By using this item, you hereby consent to our disclaimer and agree to its terms.", - "create.tooltip.randomWipDescription7": "This one maybe isn't for you. What about that one?", - "create.tooltip.randomWipDescription8": "Use it and regret your decision immediately." - + + "create.tooltip.wip": "WIP", + "create.tooltip.workInProgress": "Work in progress!", + "create.tooltip.randomWipDescription0": "Please keep this item away from children.", + "create.tooltip.randomWipDescription1": "A baby panda dies every time you use this item. Every. Time.", + "create.tooltip.randomWipDescription2": "Use at your own risk.", + "create.tooltip.randomWipDescription3": "This is not the item you are looking for, *finger-wiggles* please disperse.", + "create.tooltip.randomWipDescription4": "This item will self-destruct in 10 seconds. 10, 9, 8...", + "create.tooltip.randomWipDescription5": "Believe me, it's useless.", + "create.tooltip.randomWipDescription6": "By using this item, you hereby consent to our disclaimer and agree to its terms.", + "create.tooltip.randomWipDescription7": "This one maybe isn't for you. What about that one?", + "create.tooltip.randomWipDescription8": "Use it and regret your decision immediately.", + "create.gui.chromatic_projector.title": "Chromatic Projector", + "create.gui.chromatic_projector.filter.invert": "Invert", + "create.gui.chromatic_projector.filter.sepia": "Sepia", + "create.gui.chromatic_projector.filter.grayscale": "Grayscale", + "create.gui.chromatic_projector.filter.saturate": "Saturate", + "create.gui.chromatic_projector.filter.hue_shift": "Hue shift", + "create.gui.chromatic_projector.filter.darken": "Darken", + "create.gui.chromatic_projector.filter.contrast": "Contrast", + "create.gui.chromatic_projector.filter.end": "End", + "create.gui.chromatic_projector.filter": "Filter", + "create.gui.chromatic_projector.surface": "Surface", + "create.gui.chromatic_projector.field": "Field", + "create.gui.chromatic_projector.strength": "Strength", + "create.gui.chromatic_projector.radius": "Radius", + "create.gui.chromatic_projector.feather": "Feather", + "create.gui.chromatic_projector.density": "Density", + "create.gui.chromatic_projector.fade": "Fade", + "create.gui.chromatic_projector.blend": "Blend", + "item.create.minecart_coupling.tooltip.behaviour1": "_Couples_ two Minecarts together, attempting to keep them at a _constant distance_ while moving." + } diff --git a/src/main/resources/assets/create/lang/pl_pl.json b/src/main/resources/assets/create/lang/pl_pl.json index aa77c039a..72e6c341d 100644 --- a/src/main/resources/assets/create/lang/pl_pl.json +++ b/src/main/resources/assets/create/lang/pl_pl.json @@ -57,6 +57,7 @@ "block.create.cogwheel": "Koło zębate", "block.create.content_observer": "Detektor zawartości", "block.create.controller_rail": "Tory sterujące", + "block.create.copper_backtank": "Miedziany zbiornik w plecaku", "block.create.copper_block": "Blok miedzi", "block.create.copper_casing": "Miedziana Obudowa", "block.create.copper_ore": "Ruda miedzi", @@ -437,6 +438,7 @@ "item.create.chocolate_glazed_berries": "Jagody w czekoladzie", "item.create.chromatic_compound": "Związek chromatyczny", "item.create.cinder_flour": "Rozżarzona mąka", + "item.create.copper_backtank": "Miedziany zbiornik w plecaku", "item.create.copper_ingot": "Sztabka miedzi", "item.create.copper_nugget": "Bryłka miedzi", "item.create.copper_sheet": "Arkusz miedzi", @@ -455,6 +457,8 @@ "item.create.crushed_tin_ore": "Rozkruszona ruda cyny", "item.create.crushed_uranium_ore": "Rozkruszona ruda uranu", "item.create.crushed_zinc_ore": "Rozkruszona ruda cynku", + "item.create.diving_boots": "Buty do nurkowania", + "item.create.diving_helmet": "Hełm do nurkowania", "item.create.deforester": "Wylesiacz", "item.create.dough": "Ciasto", "item.create.electron_tube": "Lampa elektronowa", @@ -685,6 +689,7 @@ "create.recipe.fan_blasting.fan": "Wiatrak za lawą", "create.recipe.pressing": "Tłoczenie", "create.recipe.mixing": "Mieszanie", + "create.recipe.deploying": "Aplikowanie", "create.recipe.automatic_shapeless": "Zautomatyzowanie nieokreślone konstruowanie", "create.recipe.automatic_brewing": "Zautomatyzowane warzenie", "create.recipe.packing": "Prasowanie", @@ -760,11 +765,20 @@ "create.gui.blockzapper.patternSection": "Wzór", "create.gui.blockzapper.pattern.solid": "Ciągły", "create.gui.blockzapper.pattern.checkered": "Szachownica", - "create.gui.blockzapper.pattern.inversecheckered": "Odwrócona Szachownica", + "create.gui.blockzapper.pattern.inversecheckered": "Odwrócona szachownica", "create.gui.blockzapper.pattern.chance25": "Obrót o 25%", "create.gui.blockzapper.pattern.chance50": "Obrót o 50%", "create.gui.blockzapper.pattern.chance75": "Obrót o 75%", "create.gui.terrainzapper.title": "Ręczny kształter", + "create.gui.terrainzapper.searchDiagonal": "Wzdłuż linii ukośnych", + "create.gui.terrainzapper.searchFuzzy": "Ignoruj krawędzie materiałów", + "create.gui.terrainzapper.patternSection": "Wzór", + "create.gui.terrainzapper.pattern.solid": "Ciągły", + "create.gui.terrainzapper.pattern.checkered": "Szachownica", + "create.gui.terrainzapper.pattern.inversecheckered": "Odrócona szachownica", + "create.gui.terrainzapper.pattern.chance25": "Obrót o 25%", + "create.gui.terrainzapper.pattern.chance50": "Obrót o 50%", + "create.gui.terrainzapper.pattern.chance75": "Obrót o 75%", "create.gui.terrainzapper.placement": "Położenie", "create.gui.terrainzapper.placement.merged": "Połączony", "create.gui.terrainzapper.placement.attached": "Przyłączony", @@ -773,6 +787,8 @@ "create.gui.terrainzapper.brush.cuboid": "Prostopadłościan", "create.gui.terrainzapper.brush.sphere": "Kula", "create.gui.terrainzapper.brush.cylinder": "Walec", + "create.gui.terrainzapper.brush.surface": "Powierzchnia", + "create.gui.terrainzapper.brush.cluster": "Grupa", "create.gui.terrainzapper.tool": "Narzędzie", "create.gui.terrainzapper.tool.fill": "Wypełnianie", "create.gui.terrainzapper.tool.place": "Stawianie", @@ -782,6 +798,8 @@ "create.gui.terrainzapper.tool.flatten": "Wypłaszczanie", "create.terrainzapper.shiftRightClickToSet": "Shift+Prawe kliknięcie, aby wybrać kształt", + "create.terrainzapper.usingBlock": "Używając: %1$s", + "create.terrainzapper.leftClickToSet": "Kliknij LPM na blok aby ustawić materiał", "create.blockzapper.usingBlock": "Używając: %1$s", "create.blockzapper.componentUpgrades": "Ulepszenia komponentów:", @@ -1147,16 +1165,35 @@ "create.command.killTPSCommand.status.usage.1": "[Create]: Użyj \"/killtps start\", aby sztucznie spowolnić serwer\n", "create.command.killTPSCommand.argument.tickTime": "tickTime", - "create.subtitle.schematicannon_launch_block": "Schematoarmata strzela", - "create.subtitle.schematicannon_finish": "Schematoarmata skończyła", - "create.subtitle.slime_added": "Szlam plaska", - "create.subtitle.mechanical_press_activation": "Mechaniczna prasa się uruchamia", - "create.subtitle.mechanical_press_item_break": "Metal brzęczy", - "create.subtitle.blockzapper_place": "Bloki lecą na miejsce", - "create.subtitle.blockzapper_confirm": "Potwierdzający sygnał", - "create.subtitle.blockzapper_deny": "Odrzucający sygnał", - "create.subtitle.block_funnel_eat": "Lejek zjada", - "create.subtitle.blaze_munch": "Płomyk szczęśliwie przeżuwa", + "create.contraption.minecart_contraption_too_big": "Ta maszyna w wagoniku jest zbyt duża, aby ją podnieść", + + + "_": "->------------------------] Napisy dla niesłyszących [------------------------<-", + + "create.subtitle.cogs": "Koła zębate terkoczą", + "create.subtitle.slime_added": "Szlam plaska", + "create.subtitle.contraption_disassemble": "Maszyna staje", + "create.subtitle.wrench_rotate": "Klucz skrzypi", + "create.subtitle.mixing": "Dźwięki mieszania", + "create.subtitle.mechanical_press_activation_belt": "Mechaniczna prasa stuka", + "create.subtitle.worldshaper_place": "Kształter strzela", + "create.subtitle.deployer_polish": "Aplikator poleruje", + "create.subtitle.depot_slide": "Przedmiot ślizga się", + "create.subtitle.deny": "Dźwięk odmowy", + "create.subtitle.blaze_munch": "Płomyk szczęśliwie przeżuwa", + "create.subtitle.schematicannon_launch_block": "Schematoarmata strzela", + "create.subtitle.funnel_flap": "Lejek trzepocze", + "create.subtitle.copper_armor_equip": "Sprzęt do nurkowania pobrzękuje", + "create.subtitle.schematicannon_finish": "Schematoarmata skończyła", + "create.subtitle.scroll_value": "Kliknięcie", + "create.subtitle.mechanical_press_activation": "Mechaniczna prasa się uruchamia", + "create.subtitle.contraption_assemble": "Maszyna przesuwa się", + "create.subtitle.crafter_craft": "Mechaniczny stół rzemieślniczy konstruuje", + "create.subtitle.cranking": "Ręczna korba obraca się", + "create.subtitle.crafter_click": "Mechaniczny stół rzemieślniczy stuka", + "create.subtitle.wrench_remove": "Komponent niszczy się", + "create.subtitle.depot_plop": "Przedmiot ląduje", + "create.subtitle.confirm": "Dźwięk potwierdzenia", "_": "->------------------------] Opisy Przedmiotów [------------------------<-", @@ -1547,11 +1584,11 @@ "create.ponder.blaze_burner.text_3": "Z użyciem płomiennego ciasta, palnik może uzyskać szczególnie wysoką temperaturę", "create.ponder.blaze_burner.text_4": "Dostarczanie płomykowi przedmiotów może zostać zautomatyzowane z użyciem aplikatorów lub mechanicznych ramion", - "create.ponder.brass_funnel.header": "Mosiężny lejek", - "create.ponder.brass_funnel.text_1": "Andezytowe lejki mogą pobierać jedynie pojedyncze przedmioty", - "create.ponder.brass_funnel.text_2": "Mosiężne lejki mogą pobierać nawet pełne stosy", + "create.ponder.brass_funnel.header": "Mosiężny lej", + "create.ponder.brass_funnel.text_1": "Andezytowe leje mogą pobierać jedynie pojedyncze przedmioty", + "create.ponder.brass_funnel.text_2": "Mosiężne leje mogą pobierać nawet pełne stosy", "create.ponder.brass_funnel.text_3": "Przewijanie na slocie filtrującym pozwala na precyzyjną kontrolę nad maksymalną wielkością stosu", - "create.ponder.brass_funnel.text_4": "Użycie przedmiotów patrząc na slot filtrujący spowoduje, że lejek będzie przesyłał tylko pasujące przedmioty", + "create.ponder.brass_funnel.text_4": "Użycie przedmiotu patrząc na slot filtrujący spowoduje, że lej będzie przesyłał tylko pasujące przedmioty", "create.ponder.brass_tunnel.header": "Używanie mosiężnych tuneli", "create.ponder.brass_tunnel.text_1": "Mosiężne tunele mogą być użyte do przykrycia Twoich taśmociągów", @@ -2114,4 +2151,4 @@ "create.ponder.windmill_structure.header": "Wiatraki", "create.ponder.windmill_structure.text_1": "Każda struktura jest uznawana za wiatrak w momencie, kiedy ma w sobie co najmniej 8 żaglo-podobnych bloków" -} \ No newline at end of file +} diff --git a/src/main/resources/assets/create/lang/zh_tw.json b/src/main/resources/assets/create/lang/zh_tw.json index 023f99011..45c124d4c 100644 --- a/src/main/resources/assets/create/lang/zh_tw.json +++ b/src/main/resources/assets/create/lang/zh_tw.json @@ -1,1792 +1,2125 @@ -{ - - "_": "->------------------------] Game Elements [------------------------<-", - - "block.create.acacia_window": "相思木窗戶", - "block.create.acacia_window_pane": "相思木窗戶片", - "block.create.adjustable_chain_gearshift": "可調式鏈式變速箱", - "block.create.adjustable_crate": "可調式板條箱", - "block.create.adjustable_pulse_repeater": "可調式脈衝中繼器", - "block.create.adjustable_repeater": "可調式中繼器", - "block.create.analog_lever": "可調式拉桿", - "block.create.andesite_belt_funnel": "安山岩輸送帶漏斗", - "block.create.andesite_bricks": "安山岩磚", - "block.create.andesite_bricks_slab": "安山岩半磚", - "block.create.andesite_bricks_stairs": "安山岩樓梯", - "block.create.andesite_bricks_wall": "安山岩牆", - "block.create.andesite_casing": "安山岩機殼", - "block.create.andesite_cobblestone": "碎安山岩", - "block.create.andesite_cobblestone_slab": "碎安山岩半磚", - "block.create.andesite_cobblestone_stairs": "碎安山岩樓梯", - "block.create.andesite_cobblestone_wall": "碎安山岩牆", - "block.create.andesite_encased_shaft": "安山傳動軸箱", - "block.create.andesite_funnel": "安山岩漏斗", - "block.create.andesite_pillar": "豎紋安山岩", - "block.create.andesite_tunnel": "安山岩物品隧道", - "block.create.basin": "作業盆", - "block.create.belt": "輸送帶", - "block.create.birch_window": "白樺木窗戶", - "block.create.birch_window_pane": "白樺木窗戶片", - "block.create.black_sail": "黑色風帆", - "block.create.black_seat": "黑色坐墊", - "block.create.black_valve_handle": "黑色閥門開關", - "block.create.blaze_burner": "烈焰使者動力爐", - "block.create.blue_sail": "藍色風帆", - "block.create.blue_seat": "藍色坐墊", - "block.create.blue_valve_handle": "藍色閥門開關", - "block.create.brass_belt_funnel": "黃銅輸送帶漏斗", - "block.create.brass_block": "黃銅磚", - "block.create.brass_casing": "黃銅機殼", - "block.create.brass_encased_shaft": "黃銅傳動軸箱", - "block.create.brass_funnel": "黃銅漏斗", - "block.create.brass_tunnel": "黃銅物品隧道", - "block.create.brown_sail": "棕色風帆", - "block.create.brown_seat": "棕色坐墊", - "block.create.brown_valve_handle": "棕色閥門開關", - "block.create.cart_assembler": "礦車裝修站", - "block.create.chiseled_dark_scoria": "鏨製黑火成岩", - "block.create.chiseled_dolomite": "鏨製白雲石", - "block.create.chiseled_gabbro": "鏨製輝長岩", - "block.create.chiseled_limestone": "鏨製石灰岩", - "block.create.chiseled_scoria": "鏨製火成岩", - "block.create.chiseled_weathered_limestone": "鏨製風化石灰岩", - "block.create.chocolate": "巧克力", - "block.create.chute": "滑道", - "block.create.clockwork_bearing": "時鐘軸承", - "block.create.clutch": "離合器", - "block.create.cogwheel": "齒輪", - "block.create.content_observer": "物品偵測器", - "block.create.controller_rail": "控制鐵軌", - "block.create.copper_block": "銅磚", - "block.create.copper_casing": "銅機殼", - "block.create.copper_ore": "銅礦石", - "block.create.copper_shingles": "塊狀銅磚", - "block.create.copper_tiles": "菱形銅磚", - "block.create.copper_valve_handle": "銅製閥門開關", - "block.create.creative_crate": "創造板條箱", - "block.create.creative_fluid_tank": "創造液體儲存罐", - "block.create.creative_motor": "創造馬達", - "block.create.crimson_window": "赤紅窗戶", - "block.create.crimson_window_pane": "赤紅窗戶片", - "block.create.crushing_wheel": "粉碎輪", - "block.create.crushing_wheel_controller": "粉碎輪控制器", - "block.create.cuckoo_clock": "布穀鳥鐘", - "block.create.cyan_sail": "藍綠色風帆", - "block.create.cyan_seat": "藍綠色坐墊", - "block.create.cyan_valve_handle": "藍綠色閥門開關", - "block.create.dark_oak_window": "黑橡木窗戶", - "block.create.dark_oak_window_pane": "黑橡木窗戶片", - "block.create.dark_scoria": "黑火成岩", - "block.create.dark_scoria_bricks": "黑火成岩磚", - "block.create.dark_scoria_bricks_slab": "黑火成岩半磚", - "block.create.dark_scoria_bricks_stairs": "黑火成岩樓梯", - "block.create.dark_scoria_bricks_wall": "黑火成岩牆", - "block.create.dark_scoria_cobblestone": "黑火成岩碎石", - "block.create.dark_scoria_cobblestone_slab": "黑火成岩碎石半磚", - "block.create.dark_scoria_cobblestone_stairs": "黑火成岩碎石樓梯", - "block.create.dark_scoria_cobblestone_wall": "黑火成岩碎石牆", - "block.create.dark_scoria_pillar": "豎紋黑火成岩", - "block.create.deployer": "機器手", - "block.create.depot": "置物臺", - "block.create.diorite_bricks": "閃長岩磚", - "block.create.diorite_bricks_slab": "閃長岩半磚", - "block.create.diorite_bricks_stairs": "閃長岩樓梯", - "block.create.diorite_bricks_wall": "閃長岩牆", - "block.create.diorite_cobblestone": "碎閃長岩", - "block.create.diorite_cobblestone_slab": "碎閃長岩半磚", - "block.create.diorite_cobblestone_stairs": "碎閃長岩樓梯", - "block.create.diorite_cobblestone_wall": "碎閃長岩牆", - "block.create.diorite_pillar": "豎紋閃長岩", - "block.create.dolomite": "白雲石", - "block.create.dolomite_bricks": "白雲石磚", - "block.create.dolomite_bricks_slab": "白雲石半磚", - "block.create.dolomite_bricks_stairs": "白雲石樓梯", - "block.create.dolomite_bricks_wall": "白雲石牆", - "block.create.dolomite_cobblestone": "碎白雲石", - "block.create.dolomite_cobblestone_slab": "碎白雲石半磚", - "block.create.dolomite_cobblestone_stairs": "碎白雲石樓梯", - "block.create.dolomite_cobblestone_wall": "碎白雲石牆", - "block.create.dolomite_pillar": "豎紋白雲石", - "block.create.encased_chain_drive": "鏈式傳動箱", - "block.create.encased_fan": "鼓風機", - "block.create.encased_fluid_pipe": "液體管道箱", - "block.create.fancy_andesite_bricks": "方紋安山岩磚", - "block.create.fancy_andesite_bricks_slab": "方紋安山岩半磚", - "block.create.fancy_andesite_bricks_stairs": "方紋安山岩樓梯", - "block.create.fancy_andesite_bricks_wall": "方紋安山岩牆", - "block.create.fancy_dark_scoria_bricks": "方紋黑火成岩", - "block.create.fancy_dark_scoria_bricks_slab": "方紋黑火成岩半磚", - "block.create.fancy_dark_scoria_bricks_stairs": "方紋黑火成岩樓梯", - "block.create.fancy_dark_scoria_bricks_wall": "方紋黑火成岩牆", - "block.create.fancy_diorite_bricks": "方紋閃長岩", - "block.create.fancy_diorite_bricks_slab": "方紋閃長岩半磚", - "block.create.fancy_diorite_bricks_stairs": "方紋閃長岩樓梯", - "block.create.fancy_diorite_bricks_wall": "方紋閃長岩牆", - "block.create.fancy_dolomite_bricks": "方紋白雲石", - "block.create.fancy_dolomite_bricks_slab": "方紋白雲石半磚", - "block.create.fancy_dolomite_bricks_stairs": "方紋白雲石樓梯", - "block.create.fancy_dolomite_bricks_wall": "方紋白雲石牆", - "block.create.fancy_gabbro_bricks": "方紋輝長岩", - "block.create.fancy_gabbro_bricks_slab": "方紋輝長岩半磚", - "block.create.fancy_gabbro_bricks_stairs": "方紋輝長岩樓梯", - "block.create.fancy_gabbro_bricks_wall": "方紋輝長岩牆", - "block.create.fancy_granite_bricks": "方紋花崗岩", - "block.create.fancy_granite_bricks_slab": "方紋花崗岩半磚", - "block.create.fancy_granite_bricks_stairs": "方紋花崗岩樓梯", - "block.create.fancy_granite_bricks_wall": "方紋花崗岩牆", - "block.create.fancy_limestone_bricks": "方紋石灰岩", - "block.create.fancy_limestone_bricks_slab": "方紋石灰岩半磚", - "block.create.fancy_limestone_bricks_stairs": "方紋石灰岩樓梯", - "block.create.fancy_limestone_bricks_wall": "方紋石灰岩牆", - "block.create.fancy_scoria_bricks": "方紋火成岩", - "block.create.fancy_scoria_bricks_slab": "方紋火成岩半磚", - "block.create.fancy_scoria_bricks_stairs": "方紋火成岩樓梯", - "block.create.fancy_scoria_bricks_wall": "方紋火成岩牆", - "block.create.fancy_weathered_limestone_bricks": "方紋風化石灰岩", - "block.create.fancy_weathered_limestone_bricks_slab": "方紋風化石灰岩半磚", - "block.create.fancy_weathered_limestone_bricks_stairs": "方紋風化石灰岩樓梯", - "block.create.fancy_weathered_limestone_bricks_wall": "方紋風化石灰岩牆", - "block.create.fluid_pipe": "液體管道", - "block.create.fluid_tank": "液體儲存罐", - "block.create.fluid_valve": "液體閥門", - "block.create.flywheel": "飛輪", - "block.create.framed_glass": "邊框玻璃", - "block.create.framed_glass_pane": "邊框玻璃片", - "block.create.furnace_engine": "熔煉引擎", - "block.create.gabbro": "輝長岩", - "block.create.gabbro_bricks": "輝長岩磚", - "block.create.gabbro_bricks_slab": "輝長岩半磚", - "block.create.gabbro_bricks_stairs": "輝長岩樓梯", - "block.create.gabbro_bricks_wall": "輝長岩牆", - "block.create.gabbro_cobblestone": "碎輝長岩", - "block.create.gabbro_cobblestone_slab": "碎輝長岩半磚", - "block.create.gabbro_cobblestone_stairs": "碎輝長岩樓梯", - "block.create.gabbro_cobblestone_wall": "碎輝長岩牆", - "block.create.gabbro_pillar": "豎紋輝長岩", - "block.create.gearbox": "齒輪箱", - "block.create.gearshift": "變速箱", - "block.create.glass_fluid_pipe": "玻璃液體管道", - "block.create.granite_bricks": "花崗岩", - "block.create.granite_bricks_slab": "花崗岩半磚", - "block.create.granite_bricks_stairs": "花崗岩樓梯", - "block.create.granite_bricks_wall": "花崗岩牆", - "block.create.granite_cobblestone": "碎花崗岩", - "block.create.granite_cobblestone_slab": "碎花崗岩半磚", - "block.create.granite_cobblestone_stairs": "碎花崗岩樓梯", - "block.create.granite_cobblestone_wall": "碎花崗岩牆", - "block.create.granite_pillar": "豎紋花崗岩", - "block.create.gray_sail": "灰色風帆", - "block.create.gray_seat": "灰色坐墊", - "block.create.gray_valve_handle": "灰色閥門開關", - "block.create.green_sail": "綠色風帆", - "block.create.green_seat": "綠色坐墊", - "block.create.green_valve_handle": "綠色閥門開關", - "block.create.hand_crank": "手搖把手", - "block.create.honey": "蜂蜜", - "block.create.horizontal_framed_glass": "豎直邊框玻璃", - "block.create.horizontal_framed_glass_pane": "豎直邊框玻璃片", - "block.create.hose_pulley": "軟管滑輪", - "block.create.item_drain": "分液池", - "block.create.jungle_window": "叢林木窗戶", - "block.create.jungle_window_pane": "叢林木窗戶片", - "block.create.large_cogwheel": "大齒輪", - "block.create.layered_andesite": "疊層安山岩", - "block.create.layered_dark_scoria": "疊層黑火成岩", - "block.create.layered_diorite": "疊層閃長岩", - "block.create.layered_dolomite": "疊層白雲石", - "block.create.layered_gabbro": "疊層輝長岩", - "block.create.layered_granite": "疊層花崗岩", - "block.create.layered_limestone": "疊層石灰岩", - "block.create.layered_scoria": "疊層火成岩", - "block.create.layered_weathered_limestone": "疊層風化石灰岩", - "block.create.light_blue_sail": "淡藍色風帆", - "block.create.light_blue_seat": "淡藍色坐墊", - "block.create.light_blue_valve_handle": "淡藍色閥門開關", - "block.create.light_gray_sail": "淡灰色風帆", - "block.create.light_gray_seat": "淡灰色坐墊", - "block.create.light_gray_valve_handle": "淡灰色閥門開關", - "block.create.lime_sail": "黃綠色風帆", - "block.create.lime_seat": "黃綠色坐墊", - "block.create.lime_valve_handle": "黃綠色閥門開關", - "block.create.limesand": "石灰沙", - "block.create.limestone": "石灰岩", - "block.create.limestone_bricks": "石灰岩", - "block.create.limestone_bricks_slab": "石灰岩半磚", - "block.create.limestone_bricks_stairs": "石灰岩樓梯", - "block.create.limestone_bricks_wall": "石灰岩牆", - "block.create.limestone_cobblestone": "碎石灰岩", - "block.create.limestone_cobblestone_slab": "碎石灰岩半磚", - "block.create.limestone_cobblestone_stairs": "碎石灰岩樓梯", - "block.create.limestone_cobblestone_wall": "碎石灰岩牆", - "block.create.limestone_pillar": "豎紋石灰岩", - "block.create.linear_chassis": "機殼底盤", - "block.create.lit_blaze_burner": "烈焰使者動力爐(已啟動)", - "block.create.magenta_sail": "洋紅色風帆", - "block.create.magenta_seat": "洋紅色坐墊", - "block.create.magenta_valve_handle": "洋紅色閥門開關", - "block.create.mechanical_arm": "機械手臂", - "block.create.mechanical_bearing": "機械軸承", - "block.create.mechanical_crafter": "機械合成器", - "block.create.mechanical_drill": "機械鑽頭", - "block.create.mechanical_harvester": "機械收割機", - "block.create.mechanical_mixer": "機械攪拌器", - "block.create.mechanical_piston": "機械活塞", - "block.create.mechanical_piston_head": "機械活塞頭", - "block.create.mechanical_plough": "機械犁", - "block.create.mechanical_press": "機械液壓機", - "block.create.mechanical_pump": "機械幫浦", - "block.create.mechanical_saw": "機械切割機", - "block.create.metal_bracket": "金屬支架", - "block.create.millstone": "石磨", - "block.create.minecart_anchor": "礦車錨", - "block.create.mossy_andesite": "青苔安山岩", - "block.create.mossy_dark_scoria": "青苔黑火成岩", - "block.create.mossy_diorite": "青苔閃長岩", - "block.create.mossy_dolomite": "青苔白雲石", - "block.create.mossy_gabbro": "青苔輝長岩", - "block.create.mossy_granite": "青苔花崗岩", - "block.create.mossy_limestone": "青苔石灰岩", - "block.create.mossy_scoria": "青苔火成岩", - "block.create.mossy_weathered_limestone": "青苔風化石灰岩", - "block.create.mysterious_cuckoo_clock": "神秘布穀鳥鐘", - "block.create.natural_scoria": "天然火成岩", - "block.create.nixie_tube": "真空管顯示器", - "block.create.nozzle": "鼓風機噴嘴", - "block.create.oak_window": "橡木窗戶", - "block.create.oak_window_pane": "橡木窗戶片", - "block.create.orange_sail": "橙色風帆", - "block.create.orange_seat": "橙色坐墊", - "block.create.orange_valve_handle": "橙色閥門開關", - "block.create.ornate_iron_window": "華麗鐵窗戶", - "block.create.ornate_iron_window_pane": "華麗鐵窗戶片", - "block.create.overgrown_andesite": "長草的安山岩", - "block.create.overgrown_dark_scoria": "長草的黑火成岩", - "block.create.overgrown_diorite": "長草的閃長岩", - "block.create.overgrown_dolomite": "長草的白雲石", - "block.create.overgrown_gabbro": "長草的輝長岩", - "block.create.overgrown_granite": "長草的花崗岩", - "block.create.overgrown_limestone": "長草的石灰岩", - "block.create.overgrown_scoria": "長草的火成岩", - "block.create.overgrown_weathered_limestone": "長草的風化石灰岩", - "block.create.paved_andesite": "安山岩鋪路石", - "block.create.paved_andesite_slab": "安山岩鋪路石半磚", - "block.create.paved_andesite_stairs": "安山岩鋪路石樓梯", - "block.create.paved_andesite_wall": "安山岩鋪路石牆", - "block.create.paved_dark_scoria": "黑火成岩鋪路石", - "block.create.paved_dark_scoria_slab": "黑火成岩鋪路石半磚", - "block.create.paved_dark_scoria_stairs": "黑火成岩鋪路石樓梯", - "block.create.paved_dark_scoria_wall": "黑火成岩鋪路石牆", - "block.create.paved_diorite": "閃長岩鋪路石", - "block.create.paved_diorite_slab": "閃長岩鋪路石半磚", - "block.create.paved_diorite_stairs": "閃長岩鋪路石樓梯", - "block.create.paved_diorite_wall": "閃長岩鋪路石牆", - "block.create.paved_dolomite": "白雲石鋪路石", - "block.create.paved_dolomite_slab": "白雲石鋪路石半磚", - "block.create.paved_dolomite_stairs": "白雲石鋪路石樓梯", - "block.create.paved_dolomite_wall": "白雲石鋪路石牆", - "block.create.paved_gabbro": "輝長岩鋪路石", - "block.create.paved_gabbro_slab": "輝長岩鋪路石半磚", - "block.create.paved_gabbro_stairs": "輝長岩鋪路石樓梯", - "block.create.paved_gabbro_wall": "輝長岩鋪路石牆", - "block.create.paved_granite": "花崗岩鋪路石", - "block.create.paved_granite_slab": "花崗岩鋪路石半磚", - "block.create.paved_granite_stairs": "花崗岩鋪路石樓梯", - "block.create.paved_granite_wall": "花崗岩鋪路石牆", - "block.create.paved_limestone": "石灰岩鋪路石", - "block.create.paved_limestone_slab": "石灰岩鋪路石半磚", - "block.create.paved_limestone_stairs": "石灰岩鋪路石樓梯", - "block.create.paved_limestone_wall": "石灰岩鋪路石牆", - "block.create.paved_scoria": "火成岩鋪路石", - "block.create.paved_scoria_slab": "火成岩鋪路石半磚", - "block.create.paved_scoria_stairs": "火成岩鋪路石樓梯", - "block.create.paved_scoria_wall": "火成岩鋪路石牆", - "block.create.paved_weathered_limestone": "風化石灰岩鋪路石", - "block.create.paved_weathered_limestone_slab": "風化石灰岩鋪路石半磚", - "block.create.paved_weathered_limestone_stairs": "風化石灰岩鋪路石樓梯", - "block.create.paved_weathered_limestone_wall": "風化石灰岩鋪路石牆", - "block.create.pink_sail": "粉紅色風帆", - "block.create.pink_seat": "粉紅色坐墊", - "block.create.pink_valve_handle": "粉紅色閥門開關", - "block.create.piston_extension_pole": "活塞桿", - "block.create.polished_dark_scoria": "磨製黑火成岩", - "block.create.polished_dark_scoria_slab": "磨製黑火成岩半磚", - "block.create.polished_dark_scoria_stairs": "磨製黑火成岩樓梯", - "block.create.polished_dark_scoria_wall": "磨製黑火成岩牆", - "block.create.polished_dolomite": "磨製白雲石", - "block.create.polished_dolomite_slab": "磨製白雲石半磚", - "block.create.polished_dolomite_stairs": "磨製白雲石樓梯", - "block.create.polished_dolomite_wall": "磨製白雲石牆", - "block.create.polished_gabbro": "磨製輝長岩", - "block.create.polished_gabbro_slab": "磨製輝長岩半磚", - "block.create.polished_gabbro_stairs": "磨製輝長岩樓梯", - "block.create.polished_gabbro_wall": "磨製輝長岩牆", - "block.create.polished_limestone": "磨製石灰岩", - "block.create.polished_limestone_slab": "磨製石灰岩半磚", - "block.create.polished_limestone_stairs": "磨製石灰岩樓梯", - "block.create.polished_limestone_wall": "磨製石灰岩牆", - "block.create.polished_scoria": "磨製火成岩", - "block.create.polished_scoria_slab": "磨製火成岩半磚", - "block.create.polished_scoria_stairs": "磨製火成岩樓梯", - "block.create.polished_scoria_wall": "磨製火成岩牆", - "block.create.polished_weathered_limestone": "磨製風化石灰岩", - "block.create.polished_weathered_limestone_slab": "磨製風化石灰岩半磚", - "block.create.polished_weathered_limestone_stairs": "磨製風化石灰岩樓梯", - "block.create.polished_weathered_limestone_wall": "磨製風化石灰岩牆", - "block.create.portable_fluid_interface": "移動式液體口", - "block.create.portable_storage_interface": "移動式物品口", - "block.create.powered_latch": "閂鎖器", - "block.create.powered_toggle_latch": "T型正反器", - "block.create.pulley_magnet": "滑輪磁鐵", - "block.create.pulse_repeater": "脈衝中繼器", - "block.create.purple_sail": "紫色風帆", - "block.create.purple_seat": "紫色坐墊", - "block.create.purple_valve_handle": "紫色閥門開關", - "block.create.radial_chassis": "旋轉底盤", - "block.create.red_sail": "紅色風帆", - "block.create.red_seat": "紅色坐墊", - "block.create.red_valve_handle": "紅色閥門開關", - "block.create.redstone_contact": "接觸式紅石訊號產生器", - "block.create.redstone_link": "無限紅石訊號機", - "block.create.refined_radiance_casing": "光輝機殼", - "block.create.reinforced_rail": "強化鐵軌", - "block.create.rope": "繩索", - "block.create.rope_pulley": "滑輪繩索", - "block.create.rotation_speed_controller": "轉速控制器", - "block.create.sail_frame": "風帆框架", - "block.create.schematic_table": "藍圖桌", - "block.create.schematicannon": "藍圖加農炮", - "block.create.scoria": "火成岩", - "block.create.scoria_bricks": "火成岩磚", - "block.create.scoria_bricks_slab": "火成岩半磚", - "block.create.scoria_bricks_stairs": "火成岩樓梯", - "block.create.scoria_bricks_wall": "火成岩牆", - "block.create.scoria_cobblestone": "碎火成岩", - "block.create.scoria_cobblestone_slab": "碎火成岩半磚", - "block.create.scoria_cobblestone_stairs": "碎火成岩樓梯", - "block.create.scoria_cobblestone_wall": "碎火成岩牆", - "block.create.scoria_pillar": "豎紋火成岩", - "block.create.secondary_linear_chassis": "機殼底盤2號", - "block.create.sequenced_gearshift": "可程式化齒輪箱", - "block.create.shadow_steel_casing": "暗影機殼", - "block.create.shaft": "傳動軸", - "block.create.smart_fluid_pipe": "智慧液體管道", - "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.tiled_glass": "十字玻璃窗", - "block.create.tiled_glass_pane": "十字玻璃窗戶片", - "block.create.turntable": "轉盤", - "block.create.vertical_framed_glass": "豎直邊框玻璃", - "block.create.vertical_framed_glass_pane": "豎直邊框玻璃片", - "block.create.warped_window": "扭曲蕈木窗戶", - "block.create.warped_window_pane": "扭曲蕈木窗戶片", - "block.create.water_wheel": "水車", - "block.create.weathered_limestone": "風化石灰岩", - "block.create.weathered_limestone_bricks": "風化石灰岩磚", - "block.create.weathered_limestone_bricks_slab": "風化石灰岩半磚", - "block.create.weathered_limestone_bricks_stairs": "風化石灰岩樓梯", - "block.create.weathered_limestone_bricks_wall": "風化石灰岩牆", - "block.create.weathered_limestone_cobblestone": "碎風化石灰岩", - "block.create.weathered_limestone_cobblestone_slab": "碎風化石灰岩半磚", - "block.create.weathered_limestone_cobblestone_stairs": "碎風化石灰岩樓梯", - "block.create.weathered_limestone_cobblestone_wall": "碎風化石灰岩牆", - "block.create.weathered_limestone_pillar": "豎紋風化石灰岩", - "block.create.white_sail": "白色風帆", - "block.create.white_seat": "白色坐墊", - "block.create.white_valve_handle": "白色閥門開關", - "block.create.windmill_bearing": "風車軸承", - "block.create.wooden_bracket": "木製支架", - "block.create.yellow_sail": "黃色風帆", - "block.create.yellow_seat": "黃色坐墊", - "block.create.yellow_valve_handle": "黃色閥門開關", - "block.create.zinc_block": "鋅磚", - "block.create.zinc_ore": "鋅礦石", - - "entity.create.contraption": "結構", - "entity.create.seat": "坐墊", - "entity.create.stationary_contraption": "固定結構", - "entity.create.super_glue": "強力膠", - - "fluid.create.chocolate": "巧克力", - "fluid.create.honey": "蜂蜜", - "fluid.create.milk": "牛奶", - "fluid.create.potion": "藥水", - "fluid.create.tea": "茶", - - "item.create.andesite_alloy": "安山合金", - "item.create.attribute_filter": "屬性過濾器", - "item.create.bar_of_chocolate": "巧克力棒", - "item.create.belt_connector": "輸送帶", - "item.create.blaze_cake": "熔岩蛋糕", - "item.create.blaze_cake_base": "熔岩蛋糕胚", - "item.create.brass_hand": "黃銅手部零件", - "item.create.brass_ingot": "黃銅錠", - "item.create.brass_nugget": "黃銅粒", - "item.create.brass_sheet": "黃銅板", - "item.create.builders_tea": "工人茶", - "item.create.chest_minecart_contraption": "裝修過的機械礦車", - "item.create.chocolate_bucket": "巧克力桶", - "item.create.chromatic_compound": "異彩化合物", - "item.create.cinder_flour": "地獄麵粉", - "item.create.copper_ingot": "銅錠", - "item.create.copper_nugget": "銅粒", - "item.create.copper_sheet": "銅板", - "item.create.crafter_slot_cover": "合成器蓋板", - "item.create.crushed_aluminum_ore": "碎狀鋁礦石", - "item.create.crushed_brass": "碎狀黃銅", - "item.create.crushed_copper_ore": "碎狀銅礦石", - "item.create.crushed_gold_ore": "碎狀金礦石", - "item.create.crushed_iron_ore": "碎狀鐵礦石", - "item.create.crushed_lead_ore": "碎狀鉛礦石", - "item.create.crushed_nickel_ore": "碎狀鎳礦石", - "item.create.crushed_osmium_ore": "碎狀鋨礦石", - "item.create.crushed_platinum_ore": "碎狀白金礦石", - "item.create.crushed_quicksilver_ore": "碎狀水銀礦石", - "item.create.crushed_silver_ore": "碎狀銀礦石", - "item.create.crushed_tin_ore": "碎狀錫礦石", - "item.create.crushed_uranium_ore": "碎狀鈾礦石", - "item.create.crushed_zinc_ore": "碎狀鋅礦石", - "item.create.deforester": "連根拔樹斧", - "item.create.dough": "麵團", - "item.create.electron_tube": "真空管", - "item.create.empty_blaze_burner": "空的烈焰使者動力爐", - "item.create.empty_schematic": "空白藍圖", - "item.create.extendo_grip": "伸縮機械手", - "item.create.filter": "過濾器", - "item.create.furnace_minecart_contraption": "裝配過的機械礦車", - "item.create.goggles": "MR護目鏡", - "item.create.golden_sheet": "金板", - "item.create.handheld_blockzapper": "方塊放置器", - "item.create.handheld_worldshaper": "地形雕塑器", - "item.create.honey_bucket": "蜂蜜桶", - "item.create.integrated_circuit": "IC板", - "item.create.iron_sheet": "鐵板", - "item.create.lapis_sheet": "青金石板", - "item.create.minecart_contraption": "裝修過的礦車", - "item.create.minecart_coupling": "礦車連結器", - "item.create.polished_rose_quartz": "磨製玫瑰石英", - "item.create.powdered_obsidian": "黑曜石粉末", - "item.create.propeller": "扇葉", - "item.create.red_sand_paper": "紅砂紙", - "item.create.refined_radiance": "光輝石", - "item.create.rose_quartz": "玫瑰石英", - "item.create.sand_paper": "砂紙", - "item.create.schematic": "藍圖", - "item.create.schematic_and_quill": "藍圖與筆", - "item.create.shadow_steel": "暗影鋼", - "item.create.super_glue": "強力膠", - "item.create.tree_fertilizer": "樹木肥料", - "item.create.vertical_gearbox": "豎直齒輪箱", - "item.create.wand_of_symmetry": "對稱杖", - "item.create.wheat_flour": "小麥粉", - "item.create.whisk": "攪拌器", - "item.create.wrench": "板手", - "item.create.zinc_ingot": "鋅錠", - "item.create.zinc_nugget": "鋅粒", - - - "_": "->------------------------] Advancements [------------------------<-", - - "advancement.create.root": "感謝你安裝機械動力模組,強烈建議您安裝JEI配合本模組遊玩", - "advancement.create.root.desc": "該來製作一些超棒的機械結構了!", - "advancement.create.andesite_alloy": "原始人類的合金替代品", - "advancement.create.andesite_alloy.desc": "機械動力有著許多的材料和合金,但受限於技術,原始的人類們暫時只能製作出安山合金", - "advancement.create.its_alive": "鮮活的機械生命", - "advancement.create.its_alive.desc": "首次使齒輪結構的旋轉。", - "advancement.create.shifting_gears": "換檔,加速,起飛!", - "advancement.create.shifting_gears.desc": "將大齒輪連接到小齒輪上,機械結構的轉速將會翻倍", - "advancement.create.overstressed": "超載", - "advancement.create.overstressed.desc": "首次使動能網路超載。", - "advancement.create.belt": "流水線作業", - "advancement.create.belt.desc": "用輸送帶連接兩個傳動軸", - "advancement.create.tunnel": "尋找掩護!", - "advancement.create.tunnel.desc": "在輸送帶上放上物品隧道。", - "advancement.create.splitter_tunnel": "分而治之", - "advancement.create.splitter_tunnel.desc": "用黃銅物品隧道設計一個分流器。", - "advancement.create.chute": "轟然倒塌", - "advancement.create.chute.desc": "放置一個滑道(垂直版本的輸送帶)。", - "advancement.create.upward_chute": "空中攔截", - "advancement.create.upward_chute.desc": "目睹拋出的物品飛入裝有風扇的滑道。", - "advancement.create.belt_funnel": "漏斗的垂簾", - "advancement.create.belt_funnel.desc": "將側向漏斗放在輸送帶或置物臺的上方。", - "advancement.create.belt_funnel_kiss": "比翼雙飛", - "advancement.create.belt_funnel_kiss.desc": "使兩個安裝在輸送帶上的漏斗相連。", - "advancement.create.fan": "機械氣槍", - "advancement.create.fan.desc": "飄浮在鼓風機吹出的氣流上", - "advancement.create.fan_lava": "空間加熱器", - "advancement.create.fan_lava.desc": "感受熔煉物品的氣流。", - "advancement.create.fan_water": "奇怪的洗滌", - "advancement.create.fan_water.desc": "被洗滌的氣流所吸引。", - "advancement.create.fan_smoke": "機械波紋管", - "advancement.create.fan_smoke.desc": "感受煙燻氣流。", - "advancement.create.wrench": "細部調整", - "advancement.create.wrench.desc": "做出一個方便調整方塊的板手", - "advancement.create.goggles": "動能,一目了然", - "advancement.create.goggles.desc": "做出一個能看到機械動能訊息的MR護目鏡", - "advancement.create.speedometer": "精密的速度控制", - "advancement.create.speedometer.desc": "放置一個速度計,並且戴上MR護目鏡來讀取數據", - "advancement.create.stressometer": "精密的動能控制", - "advancement.create.stressometer.desc": "放置一個動能計,並且戴上MR護目鏡來讀取數據", - "advancement.create.aesthetics": "繁榮與美學!", - "advancement.create.aesthetics.desc": "將支架放在傳動軸,管道和齒輪上。", - "advancement.create.reinforced": "超級加固!", - "advancement.create.reinforced.desc": "在傳動軸,管道和輸送帶上使用機殼加固。", - "advancement.create.water_wheel": "治水", - "advancement.create.water_wheel.desc": "放置一個水車並讓它開始旋轉", - "advancement.create.chocolate_wheel": "美味的動能源", - "advancement.create.chocolate_wheel.desc": "用融化的巧克力驅動水車。", - "advancement.create.lava_wheel": "風火輪", - "advancement.create.lava_wheel.desc": "它不應該有用的..。", - "advancement.create.cuckoo": "是時候了?", - "advancement.create.cuckoo.desc": "目睹布穀鳥鐘報就寢時間。", - "advancement.create.millstone": "攜帶式粉碎機", - "advancement.create.millstone.desc": "放置一個石磨並且為其供能", - "advancement.create.windmill": "微風拂過", - "advancement.create.windmill.desc": "組裝風車。", - "advancement.create.maxed_windmill": "強風襲來", - "advancement.create.maxed_windmill.desc": "組裝最大動能的風車。", - "advancement.create.andesite_casing": "安山時代", - "advancement.create.andesite_casing.desc": "使用安山合金和木頭來合成一個安山機殼", - "advancement.create.mechanical_drill": "堅若磐石", - "advancement.create.mechanical_drill.desc": "放置一個機械鑽頭並且為其供能", - "advancement.create.press": "'噹!'", - "advancement.create.press.desc": "使用液壓機來壓製一些板子", - "advancement.create.polished_rose_quartz": "粉紅鑽石", - "advancement.create.polished_rose_quartz.desc": "用砂紙將玫瑰石英磨至透明", - "advancement.create.electron_tube": "嗶~~嗶~~", - "advancement.create.electron_tube.desc": "製作一個可用來合成高級機器的真空管", - "advancement.create.mechanical_saw": "一刀兩斷", - "advancement.create.mechanical_saw.desc": "放置一個切割機並且為其供能", - "advancement.create.basin": "快到碗裡來", - "advancement.create.basin.desc": "放置一個作業盆,並且往裡面放些東西", - "advancement.create.mixer": "充分攪拌", - "advancement.create.mixer.desc": "將攪拌機放在作業盆上方,並且使其攪拌盆內的物品", - "advancement.create.blaze_burner": "活生生的壁爐", - "advancement.create.blaze_burner.desc": "獲得一個烈焰使者動力爐。", - "advancement.create.compact": "快樂壓縮", - "advancement.create.compact.desc": "使用液壓機在作業盆中壓製一些物品", - "advancement.create.brass": "真正的合金", - "advancement.create.brass.desc": "使用粉碎鋅礦石和粉碎銅礦石來製作粉碎黃銅", - "advancement.create.brass_casing": "黃銅時代", - "advancement.create.brass_casing.desc": "用黃銅和木頭製作一個黃銅機殼", - "advancement.create.copper_casing": "銅時代", - "advancement.create.copper_casing.desc": "使用銅和木頭製作一個銅製機殼", - "advancement.create.spout": "裝填!", - "advancement.create.spout.desc": "觀察注液器灌滿物品。", - "advancement.create.spout_potion": "國際級啤酒大廠", - "advancement.create.spout_potion.desc": "觀察注液器注入藥水到玻璃瓶。", - "advancement.create.chocolate": "夢裡的世界", - "advancement.create.chocolate.desc": "獲取一桶熔融巧克力。", - "advancement.create.item_drain": "滾筒洗衣機", - "advancement.create.item_drain.desc": "觀察液體物品被分液池抽空。", - "advancement.create.chained_item_drain": "讓我們一起搖滾!", - "advancement.create.chained_item_drain.desc": "看著物品穿過多個分液池。", - "advancement.create.glass_pipe": "偷窺液體", - "advancement.create.glass_pipe.desc": "透過窗戶觀察液體在管道中流動。使用板手可打開直線液體管道的窗戶。", - "advancement.create.pipe_collision": "永不交會的溪流!", - "advancement.create.pipe_collision.desc": "觀察兩種液體在您的管道中會合", - "advancement.create.pipe_spill": "漏水啦!", - "advancement.create.pipe_spill.desc": "觀察管道的末端將液體排放到到外面。", - "advancement.create.hose_pulley": "工業排放", - "advancement.create.hose_pulley.desc": "放下一個軟管滑輪,觀察它排乾或充滿液體。", - "advancement.create.infinite_water": "抽取海洋", - "advancement.create.infinite_water.desc": "從足以被認為是無限的水源中抽水。", - "advancement.create.infinite_lava": "吸取行星的核心", - "advancement.create.infinite_lava.desc": "從廣闊的岩漿湖中抽出岩漿。", - "advancement.create.infinite_chocolate": "淹沒在幻想中", - "advancement.create.infinite_chocolate.desc": "從廣闊的巧克力海中抽出巧克力。", - "advancement.create.crafter": "自動化流水作業", - "advancement.create.crafter.desc": "放置一些機械合成臺並且為其供能", - "advancement.create.clockwork_bearing": "時差", - "advancement.create.clockwork_bearing.desc": "組裝安裝在發條軸承上的結構。", - "advancement.create.nixie_tube": "風格的跡象", - "advancement.create.nixie_tube.desc": "獲得真空管顯示器並放置。", - "advancement.create.deployer": "指爽沒?", - "advancement.create.deployer.desc": "放置並且啟動一個機械手。這可是你右手完美的複製品", - "advancement.create.speed_controller": "攻城屍討厭他!", - "advancement.create.speed_controller.desc": "放置一個轉速控制器,這是換檔的終極裝置。", - "advancement.create.flywheel": "工廠之心", - "advancement.create.flywheel.desc": "將引擎成功連接到飛輪。", - "advancement.create.overstress_flywheel": "壓力過大", - "advancement.create.overstress_flywheel.desc": "超載熔爐引擎。", - "advancement.create.integrated_circuit": "複雜的運算", - "advancement.create.integrated_circuit.desc": "合成IC板。", - "advancement.create.mechanical_arm": "忙碌的手!", - "advancement.create.mechanical_arm.desc": "製作機械手臂,選擇輸入和輸出,放置並給它動能; 然後看著它完成所有你交代的工作。", - "advancement.create.musical_arm": "沒人能在我的BGM裡打敗我!", - "advancement.create.musical_arm.desc": "使用機械手臂播放唱片。", - "advancement.create.arm_many_targets": "你是要累死我?", - "advancement.create.arm_many_targets.desc": "配置一隻有十個或更多輸出位置的機械手臂。", - "advancement.create.arm_blaze_burner": "燃燒吧!烈焰使者!", - "advancement.create.arm_blaze_burner.desc": "指揮機械臂給烈焰使者動力爐投食。", - "advancement.create.fist_bump": "朋友,來碰個拳", - "advancement.create.fist_bump.desc": "使兩個機械手互相碰拳", - "advancement.create.crushing_wheel": "一對大傢伙", - "advancement.create.crushing_wheel.desc": "製作一對能更快粉碎物品的粉碎輪", - "advancement.create.blaze_cake": "糖份超標", - "advancement.create.blaze_cake.desc": "幫烈焰使者動力爐烤一份特別的蛋糕。", - "advancement.create.chromatic_compound": "兩極材料", - "advancement.create.chromatic_compound.desc": "製作一個異彩化合物", - "advancement.create.shadow_steel": "自虛空的歸來的寶石", - "advancement.create.shadow_steel.desc": "製作暗影鋼", - "advancement.create.refined_radiance": "閃耀著純白的聖光", - "advancement.create.refined_radiance.desc": "製作光輝石", - "advancement.create.chromatic_age": "繽紛時代", - "advancement.create.chromatic_age.desc": "創造出光與影的機殼。", - "advancement.create.zapper": "專業的建築師", - "advancement.create.zapper.desc": "製作一個非常方便的方塊放置器", - "advancement.create.upgraded_zapper": "來自異世界的超頻", - "advancement.create.upgraded_zapper.desc": "製作一個完全升級的方塊放置器", - "advancement.create.wand_of_symmetry": "簡單的鏡面幾何學", - "advancement.create.wand_of_symmetry.desc": "製作一個對稱杖", - "advancement.create.deforester": "超時空砍伐", - "advancement.create.deforester.desc": "製作一個連根拔樹斧,然後跟你後院的樹林道別吧", - "advancement.create.extendo_grip": "piu piu piu!", - "advancement.create.extendo_grip.desc": "拿到一個伸縮機械手", - "advancement.create.dual_extendo_grip": "piu——piu——piu——", - "advancement.create.dual_extendo_grip.desc": "雙持伸縮機械手進一步加長觸碰距離", - "advancement.create.eob": "Beta版結束", - "advancement.create.eob.desc": "期待日後的更新。", - - - "_": "->------------------------] UI & Messages [------------------------<-", - - "itemGroup.create.base": "動力機械", - "itemGroup.create.palettes": "動力機械建築與裝飾方塊", - - "death.attack.create.crush": "%1$s被壓扁了", - "death.attack.create.fan_fire": "%1$s想接受熱風的洗禮", - "death.attack.create.fan_lava": "%1$s想接受熱風的洗禮但走火入魔", - "death.attack.create.mechanical_drill": "%1$s被鑽頭鑽爆腦袋", - "death.attack.create.mechanical_saw": "%1$s被鋸切成了兩半", - "death.attack.create.cuckoo_clock_explosion": "%1$s 被布穀鳥鐘炸得粉身碎骨", - - "create.block.deployer.damage_source_name": "機械手", - "create.block.cart_assembler.invalid": "將您的礦車裝修站放在鐵軌上", - - "create.recipe.crushing": "粉碎", - "create.recipe.milling": "研磨", - "create.recipe.fan_washing": "批次洗滌", - "create.recipe.fan_washing.fan": "在水後放置鼓風機", - "create.recipe.fan_smoking": "批次煙燻", - "create.recipe.fan_smoking.fan": "在火焰後放置鼓風機", - "create.recipe.fan_blasting": "批次融煉", - "create.recipe.fan_blasting.fan": "在熔岩後放置鼓風機", - "create.recipe.pressing": "金屬壓片", - "create.recipe.mixing": "混合攪拌", - "create.recipe.automatic_shapeless": "自動攪拌", - "create.recipe.automatic_brewing": "自動釀造", - "create.recipe.packing": "壓塊塑形", - "create.recipe.automatic_packing": "自動打包", - "create.recipe.sawing": "板材切割", - "create.recipe.mechanical_crafting": "自動合成", - "create.recipe.automatic_shaped": "自動合成", - "create.recipe.block_cutting": "方塊切割", - "create.recipe.blockzapper_upgrade": "方塊放置器", - "create.recipe.sandpaper_polishing": "砂紙打磨", - "create.recipe.mystery_conversion": "神秘轉化", - "create.recipe.spout_filling": "注液", - "create.recipe.draining": "分液", - "create.recipe.processing.chance":"%1$s%%概率", - "create.recipe.heat_requirement.none": "不需加熱", - "create.recipe.heat_requirement.heated": "加熱", - "create.recipe.heat_requirement.superheated": "超級加熱", - - "create.generic.range": "範圍", - "create.generic.radius": "半徑", - "create.generic.width": "寬", - "create.generic.height": "高", - "create.generic.length": "長", - "create.generic.speed": "速度", - "create.generic.delay": "延時", - "create.generic.unit.ticks": "Ticks", - "create.generic.unit.seconds": "秒", - "create.generic.unit.minutes": "分", - "create.generic.unit.rpm": "RPM", - "create.generic.unit.stress": "SU", - "create.generic.unit.degrees": "°", - "create.generic.unit.millibuckets":"%1$smB", - "create.generic.clockwise": "順時鐘方向", - "create.generic.counter_clockwise": "逆時鐘方向", - - "create.action.scroll": "滾輪", - "create.action.confirm": "確認", - "create.action.abort": "退出", - "create.action.saveToFile": "離開", - "create.action.discard": "放棄", - - "create.keyinfo.toolmenu": "選單", - "create.keyinfo.scrollup": "(遊戲中)向上滑鼠滾輪", - "create.keyinfo.scrolldown": "(遊戲中)向下滑鼠滾輪", - - "create.gui.scrollInput.defaultTitle": "選擇一個選項:", - "create.gui.scrollInput.scrollToModify": "滾動修改", - "create.gui.scrollInput.scrollToAdjustAmount": "滾動修改數量", - "create.gui.scrollInput.scrollToSelect": "滾動選擇", - "create.gui.scrollInput.shiftScrollsFaster": "按住Shift滾動更快", - "create.gui.toolmenu.focusKey": "按住 [%1$s] 滑鼠滾輪選擇", - "create.gui.toolmenu.cycle": "[SCROLL] 循環", - "create.gui.symmetryWand.mirrorType": "鏡子類型", - "create.gui.symmetryWand.orientation": "方向", - - "create.symmetry.mirror.plane": "鏡像", - "create.symmetry.mirror.doublePlane": "矩形", - "create.symmetry.mirror.triplePlane": "八角", - - "create.orientation.orthogonal": "垂直", - "create.orientation.diagonal": "對角線", - "create.orientation.horizontal": "水平", - "create.orientation.alongZ": "以z軸對齊", - "create.orientation.alongX": "以x軸對齊", - - "create.gui.blockzapper.title": "方塊放置機", - "create.gui.blockzapper.replaceMode": "替換模式", - "create.gui.blockzapper.searchDiagonal": "對角線延伸", - "create.gui.blockzapper.searchFuzzy": "忽視種類分界", - "create.gui.blockzapper.range": "延伸範圍", - "create.gui.blockzapper.needsUpgradedAmplifier": "需要升級範圍擴大器", - "create.gui.blockzapper.patternSection": "模式", - "create.gui.blockzapper.pattern.solid": "實心", - "create.gui.blockzapper.pattern.checkered": "棋盤", - "create.gui.blockzapper.pattern.inversecheckered": "反轉棋盤", - "create.gui.blockzapper.pattern.chance25": "25% ", - "create.gui.blockzapper.pattern.chance50": "50% ", - "create.gui.blockzapper.pattern.chance75": "75% ", - "create.gui.terrainzapper.title": "地形雕塑器", - "create.gui.terrainzapper.placement": "放置模式", - "create.gui.terrainzapper.placement.merged": "結合", - "create.gui.terrainzapper.placement.attached": "依附", - "create.gui.terrainzapper.placement.inserted": "插入", - "create.gui.terrainzapper.brush": "雕塑類型", - "create.gui.terrainzapper.brush.cuboid": "矩形體", - "create.gui.terrainzapper.brush.sphere": "球體", - "create.gui.terrainzapper.brush.cylinder": "圓柱體", - "create.gui.terrainzapper.tool": "填充類型", - "create.gui.terrainzapper.tool.fill": "填充", - "create.gui.terrainzapper.tool.place": "覆寫", - "create.gui.terrainzapper.tool.replace": "替換", - "create.gui.terrainzapper.tool.clear": "清除", - "create.gui.terrainzapper.tool.overlay": "覆蓋", - "create.gui.terrainzapper.tool.flatten": "平整", - - "create.terrainzapper.shiftRightClickToSet": "Shift+滑鼠右鍵 以設定雕塑類型", - - "create.blockzapper.usingBlock": "使用:%1$s", - "create.blockzapper.componentUpgrades": "零件升級:", - "create.blockzapper.component.body": "放置器機體", - "create.blockzapper.component.amplifier": "範圍擴大器", - "create.blockzapper.component.accelerator": "射擊加速器", - "create.blockzapper.component.retriever": "物品撿回器", - "create.blockzapper.component.scope": "距離觀察鏡", - "create.blockzapper.componentTier.none": "無", - "create.blockzapper.componentTier.brass": "黃銅", - "create.blockzapper.componentTier.chromatic": "異彩化合物", - "create.blockzapper.leftClickToSet": "左鍵點擊方塊以設定方塊種類", - "create.blockzapper.empty": "方塊不足!", - - "create.minecart_coupling.two_couplings_max": "礦車無法被連接兩個以上的礦車連結器", - "create.minecart_coupling.unloaded": "有一部份礦車存在於未讀取區塊中", - "create.minecart_coupling.no_loops": "礦車連結器不能連成一個環", - "create.minecart_coupling.removed": "從礦車上移除所有礦車連結器", - "create.minecart_coupling.too_far": "礦車距離你太遠了", - - "create.contraptions.movement_mode": "運動模式", - "create.contraptions.movement_mode.move_place": "停止時實體化方塊", - "create.contraptions.movement_mode.move_place_returned": "只在初始位置實體化方塊", - "create.contraptions.movement_mode.move_never_place": "只有在機械方塊摧毀後才實體化方塊", - "create.contraptions.movement_mode.rotate_place": "停止時實體化方塊", - "create.contraptions.movement_mode.rotate_place_returned": "只在接近初始角度實體化方塊", - "create.contraptions.movement_mode.rotate_never_place": "只有在旋轉軸摧毀後才實體化方塊", - "create.contraptions.cart_movement_mode": "礦車運動模式", - "create.contraptions.cart_movement_mode.rotate": "結構與礦車保持相同方向", - "create.contraptions.cart_movement_mode.rotate_paused": "礦車轉向時機器停止工作", - "create.contraptions.cart_movement_mode.rotation_locked": "結構方向保持不變", - "create.contraptions.windmill.rotation_direction": "旋轉方向", - "create.contraptions.clockwork.clock_hands": "鐘錶指針", - "create.contraptions.clockwork.hour_first": "時針優先", - "create.contraptions.clockwork.minute_first": "分針優先", - "create.contraptions.clockwork.hour_first_24": "24小時制優先", - - "create.logistics.filter": "過濾器", - "create.logistics.recipe_filter": "配方過濾器", - "create.logistics.fluid_filter": "液體過濾器", - "create.logistics.firstFrequency": "頻道. #1", - "create.logistics.secondFrequency": "頻道. #2", - "create.logistics.filter.apply": "將過濾器應用來%1$s。", - "create.logistics.filter.apply_click_again": "將過濾器應用來%1$s,再次點擊以復制數量。", - "create.logistics.filter.apply_count": "使用提取計數過濾。", - - "create.gui.goggles.generator_stats": "產能器狀態:", - "create.gui.goggles.kinetic_stats": "機械學狀態:", - "create.gui.goggles.at_current_speed": "現在速度動能值", - "create.gui.goggles.base_value": "動能基礎值", - "create.gui.gauge.info_header": "儀表訊息:", - "create.gui.speedometer.title": "旋轉速度", - "create.gui.stressometer.title": "網路動能", - "create.gui.stressometer.capacity": "剩餘動能量", - "create.gui.stressometer.overstressed": "動能過載", - "create.gui.stressometer.no_rotation": "無旋轉", - "create.gui.contraptions.not_fast_enough": "看起來%1$s 沒有達到足夠的工作轉速。", - "create.gui.contraptions.network_overstressed": "裝置似乎過載,減少高動能消耗的裝置或者增加更多更多動能", - "create.gui.adjustable_crate.title": "板條箱", - "create.gui.adjustable_crate.storageSpace": "儲存空間", - "create.gui.stockpile_switch.title": "儲存開關", - "create.gui.stockpile_switch.invert_signal": "反轉訊號", - "create.gui.stockpile_switch.move_to_lower_at": "移至下線%1$s%%", - "create.gui.stockpile_switch.move_to_upper_at": "移至上線%1$s%%", - "create.gui.sequenced_gearshift.title": "可程式化齒輪箱", - "create.gui.sequenced_gearshift.instruction": "指令", - "create.gui.sequenced_gearshift.instruction.turn_angle": "旋轉", - "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "角度", - "create.gui.sequenced_gearshift.instruction.turn_distance": "驅動活塞", - "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "距離", - "create.gui.sequenced_gearshift.instruction.wait": "等待", - "create.gui.sequenced_gearshift.instruction.wait.duration": "間隔", - "create.gui.sequenced_gearshift.instruction.end": "停止", - "create.gui.sequenced_gearshift.speed": "速度,速度方向", - "create.gui.sequenced_gearshift.speed.forward": "一倍速,正向", - "create.gui.sequenced_gearshift.speed.forward_fast": "兩倍速,正向", - "create.gui.sequenced_gearshift.speed.back": "一倍速,反向", - "create.gui.sequenced_gearshift.speed.back_fast": "兩倍速,反向", - - "create.schematicAndQuill.dimensions": "藍圖尺寸:%1$sx%2$sx%3$s", - "create.schematicAndQuill.firstPos": "第一個位置。", - "create.schematicAndQuill.secondPos": "第二個位置。", - "create.schematicAndQuill.noTarget": "按住Ctrl選擇空氣方塊。", - "create.schematicAndQuill.abort": "刪除選擇。", - "create.schematicAndQuill.title": "藍圖名:", - "create.schematicAndQuill.convert": "立即存檔並發佈", - "create.schematicAndQuill.fallbackName": "我的藍圖", - "create.schematicAndQuill.saved": "另存為%1$s", - - "create.schematic.invalid":"[!] 無效的項目", - "create.schematic.position": "位置", - "create.schematic.rotation": "旋轉", - "create.schematic.rotation.none": "無", - "create.schematic.rotation.cw90": "順時鐘90", - "create.schematic.rotation.cw180": "順時鐘180", - "create.schematic.rotation.cw270": "順時鐘270", - "create.schematic.mirror": "鏡像", - "create.schematic.mirror.none": "無", - "create.schematic.mirror.frontBack": "前後", - "create.schematic.mirror.leftRight": "左右", - "create.schematic.tool.deploy": "發佈", - "create.schematic.tool.move": "移動 XZ", - "create.schematic.tool.movey": "移動 Y", - "create.schematic.tool.rotate": "旋轉", - "create.schematic.tool.print": "列印", - "create.schematic.tool.flip": "翻轉", - "create.schematic.tool.deploy.description.0": "將結構移到某個位置。", - "create.schematic.tool.deploy.description.1": "在地面上點擊滑鼠右鍵以放置。", - "create.schematic.tool.deploy.description.2": "按住Ctrl以固定距離選擇。", - "create.schematic.tool.deploy.description.3": "按住Ctrl滑鼠滾動更改距離。", - "create.schematic.tool.move.description.0": "水平移動藍圖", - "create.schematic.tool.move.description.1": "選定藍圖,然後按住Ctrl滑鼠滾動。", - "create.schematic.tool.move.description.2":"", - "create.schematic.tool.move.description.3":"", - "create.schematic.tool.movey.description.0": "垂直移動藍圖", - "create.schematic.tool.movey.description.1": "按住Ctrl滑鼠滾動上下移動", - "create.schematic.tool.movey.description.2":"", - "create.schematic.tool.movey.description.3":"", - "create.schematic.tool.rotate.description.0": "圍繞藍圖中心旋轉藍圖。", - "create.schematic.tool.rotate.description.1": "按住Ctrl滑鼠滾動旋轉90度", - "create.schematic.tool.rotate.description.2":"", - "create.schematic.tool.rotate.description.3":"", - "create.schematic.tool.print.description.0": "立即將結構放置在世界上", - "create.schematic.tool.print.description.1": "右鍵點擊確認目前位置。", - "create.schematic.tool.print.description.2": "該工具僅能用於創造模式。", - "create.schematic.tool.print.description.3":"", - "create.schematic.tool.flip.description.0": "沿你選擇的面翻轉藍圖。", - "create.schematic.tool.flip.description.1": "指向藍圖,然後按住Ctrl滑鼠滾動將其翻轉。", - "create.schematic.tool.flip.description.2":"", - "create.schematic.tool.flip.description.3":"", - - "create.schematics.synchronizing": "正在同步..", - "create.schematics.uploadTooLarge": "你的藍圖太大", - "create.schematics.maxAllowedSize": "允許的最大藍圖文件大小為:", - - "create.gui.schematicTable.refresh": "重新整理文件", - "create.gui.schematicTable.open_folder": "打開資料夾", - "create.gui.schematicTable.title": "藍圖桌", - "create.gui.schematicTable.availableSchematics": "可用藍圖", - "create.gui.schematicTable.noSchematics": "沒有存檔的藍圖", - "create.gui.schematicTable.uploading": "正在上傳...", - "create.gui.schematicTable.finished": "上傳完成!", - "create.gui.schematicannon.title": "藍圖加農炮", - "create.gui.schematicannon.listPrinter": "物品清單列印機", - "create.gui.schematicannon.gunpowderLevel": "火藥%1$s%%", - "create.gui.schematicannon.shotsRemaining": "發射進度:%1$s", - "create.gui.schematicannon.shotsRemainingWithBackup": "備份:%1$s", - "create.gui.schematicannon.optionEnabled": "目前啟用", - "create.gui.schematicannon.optionDisabled": "目前停用", - "create.gui.schematicannon.showOptions": "顯示藍圖加農炮設定", - "create.gui.schematicannon.option.dontReplaceSolid": "不要替換方塊", - "create.gui.schematicannon.option.replaceWithSolid": "用固體方塊替換工作區域內的方塊", - "create.gui.schematicannon.option.replaceWithAny": "用任何方塊替換工作區域內的方塊", - "create.gui.schematicannon.option.replaceWithEmpty": "用空氣替換工作區域內的方塊", - "create.gui.schematicannon.option.skipMissing": "繞過缺少的方塊", - "create.gui.schematicannon.option.skipTileEntities": "保護儲存方塊", - "create.gui.schematicannon.slot.gunpowder": "向藍圖加農炮添加火藥以提供動能", - "create.gui.schematicannon.slot.listPrinter": "在此處放置書以列印藍圖所需的材料清單", - "create.gui.schematicannon.slot.schematic": "在此處添加你的藍圖,務必確保其已被部放置在特定位置", - "create.gui.schematicannon.option.skipMissing.description": "如果材料不夠,藍圖大炮將忽略目前不夠的材料並且使用其他已有材料繼續工作", - "create.gui.schematicannon.option.skipTileEntities.description": "藍圖將避免更換儲存方塊,如箱子。", - "create.gui.schematicannon.option.dontReplaceSolid.description": "藍圖加農炮將不會替換工作範圍內的任何固體方塊。", - "create.gui.schematicannon.option.replaceWithSolid.description": "藍圖加農炮會使用所提供的固體方塊來替換工作區域內的其他固體方塊", - "create.gui.schematicannon.option.replaceWithAny.description": "藍圖加農炮會使用任何所提供的方塊來替換工作區域內的固體方塊", - "create.gui.schematicannon.option.replaceWithEmpty.description": "藍圖加農炮將清理和替換工作區域內所有原本的方塊。", - - "create.schematicannon.status.idle": "閒置", - "create.schematicannon.status.ready": "準備", - "create.schematicannon.status.running": "啟動", - "create.schematicannon.status.finished": "完成", - "create.schematicannon.status.paused": "已暫停", - "create.schematicannon.status.stopped": "停止", - "create.schematicannon.status.noGunpowder": "火藥消耗完畢", - "create.schematicannon.status.targetNotLoaded": "方塊未讀取", - "create.schematicannon.status.targetOutsideRange": "定位目標太遠", - "create.schematicannon.status.searching": "搜尋", - "create.schematicannon.status.skipping": "跳過", - "create.schematicannon.status.missingBlock": "缺少方塊:", - "create.schematicannon.status.placing": "建築中", - "create.schematicannon.status.clearing": "清除方塊中", - "create.schematicannon.status.schematicInvalid": "藍圖無效", - "create.schematicannon.status.schematicNotPlaced": "藍圖未發佈", - "create.schematicannon.status.schematicExpired": "藍圖文件已過期", - - "create.materialChecklist": "材料清單", - "create.materialChecklist.blocksNotLoaded": "*免責聲明* \n\n由於未讀取相關區塊,材料清單可能不正確。", - - "create.gui.filter.deny_list": "黑名單", - "create.gui.filter.deny_list.description": "只通過不在黑名單中的物品,如果黑名單為空,所有物品都可以通過", - "create.gui.filter.allow_list": "白名單", - "create.gui.filter.allow_list.description": "只通過在白名單中的物品,如果白名單為空,所有物品都無法通過", - "create.gui.filter.respect_data": "比對物品屬性", - "create.gui.filter.respect_data.description": "只有物品的耐久、附魔等其他屬性相同時才可以比對", - "create.gui.filter.ignore_data": "忽略物品屬性", - "create.gui.filter.ignore_data.description": "配對時忽略物品的耐久、附魔等其他屬性", - - "create.item_attributes.placeable": "可放置", - "create.item_attributes.placeable.inverted": "不可放置", - "create.item_attributes.consumable": "可食用", - "create.item_attributes.consumable.inverted": "不可食用", - "create.item_attributes.smeltable": "可被熔爐融煉", - "create.item_attributes.smeltable.inverted": "不可被熔爐融煉", - "create.item_attributes.washable": "可被篩洗", - "create.item_attributes.washable.inverted": "不可被篩洗", - "create.item_attributes.smokable": "可被煙熏", - "create.item_attributes.smokable.inverted": "不可被煙熏", - "create.item_attributes.crushable": "可被粉碎", - "create.item_attributes.crushable.inverted": "不可被粉碎", - "create.item_attributes.blastable": "可被高爐融煉", - "create.item_attributes.blastable.inverted": "不可被高爐融煉", - "create.item_attributes.enchanted": "已被附魔", - "create.item_attributes.enchanted.inverted": "未被附魔", - "create.item_attributes.damaged": "已損壞", - "create.item_attributes.damaged.inverted": "未損壞", - "create.item_attributes.badly_damaged": "嚴重受損", - "create.item_attributes.badly_damaged.inverted": "未嚴重受損", - "create.item_attributes.not_stackable": "無法堆疊", - "create.item_attributes.not_stackable.inverted": "可堆疊", - "create.item_attributes.equipable": "可裝備", - "create.item_attributes.equipable.inverted": "不可裝備", - "create.item_attributes.furnace_fuel": "是燃料", - "create.item_attributes.furnace_fuel.inverted": "不是燃料", - "create.item_attributes.in_tag": "標籤是%1$s", - "create.item_attributes.in_tag.inverted": "標籤不是%1$s", - "create.item_attributes.in_item_group": "屬於%1$s", - "create.item_attributes.in_item_group.inverted": "不屬於%1$s", - "create.item_attributes.added_by": "由%1$s添加", - "create.item_attributes.added_by.inverted": "不是由%1$s添加", - "create.item_attributes.has_enchant": "有附魔效果%1$s", - "create.item_attributes.has_enchant.inverted": "沒有附魔效果%1$s", - "create.item_attributes.has_fluid": "包含%1$s", - "create.item_attributes.has_fluid.inverted": "不包含%1$s", - "create.item_attributes.has_name": "有自定義名稱%1$s", - "create.item_attributes.has_name.inverted": "沒有自定義名稱%1$s", - "create.item_attributes.book_author": "由%1$s編寫", - "create.item_attributes.book_author.inverted": "未由%1$s編寫", - "create.item_attributes.book_copy_original": "是原創的", - "create.item_attributes.book_copy_original.inverted": "不是原創的", - "create.item_attributes.book_copy_first": "是第一份複製", - "create.item_attributes.book_copy_first.inverted": "不是第一份複製", - "create.item_attributes.book_copy_second": "是第二份複製", - "create.item_attributes.book_copy_second.inverted": "不是第二份複製", - "create.item_attributes.book_copy_tattered": "是第三份複製", - "create.item_attributes.book_copy_tattered.inverted": "不是第三份複製", - "create.item_attributes.astralsorcery_crystal": "具有晶體屬性%1$s", - "create.item_attributes.astralsorcery_crystal.inverted": "不具有晶體屬性%1$s", - "create.item_attributes.astralsorcery_constellation": "與%1$s調諧", - "create.item_attributes.astralsorcery_constellation.inverted": "未與%1$s調諧", - "create.item_attributes.astralsorcery_perk_gem": "具有特殊屬性%1$s", - "create.item_attributes.astralsorcery_perk_gem.inverted": "不具有特殊屬性%1$s", - "create.item_attributes.astralsorcery_amulet": "提升%1$s", - "create.item_attributes.astralsorcery_amulet.inverted": "不提升%1$s", - - "create.gui.attribute_filter.no_selected_attributes": "沒有標記任何屬性", - "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.description": "只要有其中一項屬性符合,就可以通過", - "create.gui.attribute_filter.allow_list_conjunctive": "全部比對白名單(全部)", - "create.gui.attribute_filter.allow_list_conjunctive.description": "只有所有屬性都相符才可以通過", - "create.gui.attribute_filter.deny_list": "黑名單", - "create.gui.attribute_filter.deny_list.description": "只要沒有上述屬性,就可以通過", - "create.gui.attribute_filter.add_reference_item": "添加參考物品", - - "create.tooltip.holdKey": "按住 [%1$s]", - "create.tooltip.holdKeyOrKey": "按住 [%1$s] 或 [%2$s]", - "create.tooltip.keyShift": "Shift", - "create.tooltip.keyCtrl": "Ctrl", - "create.tooltip.speedRequirement": "需求速度:%1$s", - "create.tooltip.speedRequirement.none": "無", - "create.tooltip.speedRequirement.medium": "適當", - "create.tooltip.speedRequirement.high": "快", - "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.low": "小", - "create.tooltip.capacityProvided.medium": "中", - "create.tooltip.capacityProvided.high": "大", - "create.tooltip.capacityProvided.asGenerator":"(作為產生器)", - "create.tooltip.generationSpeed": "產生%1$s %2$s", - "create.tooltip.analogStrength": "調節強度:%1$s/15", - - "create.mechanical_arm.extract_from": "從%1$s 拿取物品", - "create.mechanical_arm.deposit_to": "向%1$s 儲存物品", - "create.mechanical_arm.summary": "機械手臂有%1$s 輸入以及 %2$s 輸出。", - "create.mechanical_arm.points_outside_range":"%1$s 由於距離限制,選定的交互點被移除。", - - "create.logistics.when_multiple_outputs_available": "當多個輸出可用時", - - "create.mechanical_arm.selection_mode.round_robin": "輪詢調度", - "create.mechanical_arm.selection_mode.forced_round_robin": "強制輪詢調度", - "create.mechanical_arm.selection_mode.prefer_first": "第一目標優先", - - "create.tunnel.selection_mode.split": "分攤", - "create.tunnel.selection_mode.forced_split": "強制分攤", - "create.tunnel.selection_mode.round_robin": "輪詢調度", - "create.tunnel.selection_mode.forced_round_robin": "強制輪詢調度", - "create.tunnel.selection_mode.prefer_nearest": "最近優先", - "create.tunnel.selection_mode.randomize": "隨機", - "create.tunnel.selection_mode.synchronize": "同步輸入", - - "create.tooltip.chute.header": "滑道訊息", - "create.tooltip.chute.items_move_down": "物品向下移動", - "create.tooltip.chute.items_move_up": "物品向上移動", - "create.tooltip.chute.no_fans_attached": "未安裝鼓風機", - "create.tooltip.chute.fans_push_up": "鼓風機從下方進行推動", - "create.tooltip.chute.fans_push_down": "鼓風機從上方進行推動", - "create.tooltip.chute.fans_pull_up": "鼓風機從下方進行吸引", - "create.tooltip.chute.fans_pull_down": "鼓風機從上方進行吸引", - - "create.hint.mechanical_arm_no_targets.title": "沒有目標", - "create.hint.mechanical_arm_no_targets": "看起來這個_機械手臂_沒有被分配任何_目標_。在手持機械手臂的同時,右鍵選取輸送帶、置物臺、漏斗或其他設備來設定目標。", - "create.hint.horizontal_funnel.title": "水平漏斗", - "create.hint.horizontal_funnel": "無法_直接_在兩個庫存間移動物品。試著使用輸送帶或者置物臺來從庫存中提取物品。", - "create.hint.upward_funnel.title": "漏斗向上", - "create.hint.upward_funnel": "只可以傳送由_機械手臂_,鼓風機驅動的_滑道_或者被投擲的物品。試著做一些滑道來垂直輸送物品。", - "create.hint.empty_bearing.title": "更新軸承", - "create.hint.empty_bearing": "_空手右鍵_軸承來_添加_你新建造的結構。", - "create.hint.full_deployer.title": "機械手物品溢出", - "create.hint.full_deployer": "_機械手_包含_過剩的物品_需要被_提取._使用_漏斗,__漏斗_或其他方法將溢出解決。", - - "create.gui.config.overlay1": "嗨 :)", - "create.gui.config.overlay2": "這是一個實例層", - "create.gui.config.overlay3": "點擊拖拽你的滑鼠", - "create.gui.config.overlay4": "來將它移動到前方", - "create.gui.config.overlay5": "ESC退出目前界面", - "create.gui.config.overlay6": "並儲存新的位置", - "create.gui.config.overlay7": "輸入/create overlay reset", - "create.gui.config.overlay8": "重置到預設位置", - - "create.command.killTPSCommand": "killtps", - "create.command.killTPSCommand.status.slowed_by.0": "[Create]: 伺服器每秒TICK被降為 %s ms :o", - "create.command.killTPSCommand.status.slowed_by.1": "[Create]: 伺服器現在每秒TICK被降為 >:)", - "create.command.killTPSCommand.status.slowed_by.2": "[Create]: 伺服器現在不延遲了,TPS正常 :D", - "create.command.killTPSCommand.status.usage.0": "[Create]: 用 /killtps stop 來讓伺服器的TPS速度恢復正常", - "create.command.killTPSCommand.status.usage.1": "[Create]: 用 /killtps start 來手動降低伺服器TPS", - "create.command.killTPSCommand.argument.tickTime": "tickTime", - - "create.subtitle.schematicannon_launch_block": "藍圖大炮發射", - "create.subtitle.schematicannon_finish": "藍圖大炮完成任務", - "create.subtitle.slime_added": "黏液擠壓", - "create.subtitle.mechanical_press_activation": "液壓機工作", - "create.subtitle.mechanical_press_item_break": "金屬碰撞", - "create.subtitle.blockzapper_place": "放置方塊", - "create.subtitle.blockzapper_confirm": "選擇方塊", - "create.subtitle.blockzapper_deny": "放置失敗", - "create.subtitle.block_funnel_eat": "漏斗吸收", - "create.subtitle.blaze_munch": "烈焰使者開心地吃著", - - - "_": "->------------------------] Item Descriptions [------------------------<-", - - "item.create.example_item.tooltip": "EXAMPLE ITEM (just a marker that this tooltip exists)", - "item.create.example_item.tooltip.summary": "A brief description of the item._Underscores_highlight a term.", - "item.create.example_item.tooltip.condition1": "When this", - "item.create.example_item.tooltip.behaviour1": "Then this item does this。(behaviours show on shift)", - "item.create.example_item.tooltip.condition2": "And When this", - "item.create.example_item.tooltip.behaviour2": "You can add as many behaviours as you like", - "item.create.example_item.tooltip.control1": "When Ctrl pressed", - "item.create.example_item.tooltip.action1": "These controls are displayed.", - - "block.create.andesite_encased_shaft.tooltip": "安山岩傳動軸箱", - "block.create.andesite_encased_shaft.tooltip.summary": "_創造模式_物品。用安山岩機殼包覆世界中的傳動軸,將不會消耗機殼。", - - "block.create.brass_encased_shaft.tooltip": "黃銅傳動軸箱", - "block.create.brass_encased_shaft.tooltip.summary": "_創造模式_物品。用黃銅機殼包覆世界中的傳動軸,將不會消耗機殼。", - - "block.create.wooden_bracket.tooltip": "木製支架", - "block.create.wooden_bracket.tooltip.summary": "用來裝飾_傳動軸_,_齒輪_和_管道_。", - - "block.create.metal_bracket.tooltip": "金屬支架", - "block.create.metal_bracket.tooltip.summary": "用來裝飾_傳動軸_,_齒輪_和_管道_。", - - "block.create.andesite_casing.tooltip": "安山機殼", - "block.create.andesite_casing.tooltip.summary": "具多種用途簡易機殼,可用來加固並裝飾_傳動軸_,_輸送帶_", - - "block.create.andesite_funnel.tooltip": "安山漏斗", - "block.create.andesite_funnel.tooltip.summary": "一種常用的傳輸裝置,配合各種物流結構傳輸物品,可由_紅石訊號_控制。", - "block.create.andesite_funnel.tooltip.condition1": "一般形態", - "block.create.andesite_funnel.tooltip.behaviour1": "開口的面會吸收面前的_掉落物_,並_傳輸_到它所附著的_容器_裡。", - "block.create.andesite_funnel.tooltip.condition2": "安裝在輸送帶、置物臺等結構上時,會轉為附著形態", - "block.create.andesite_funnel.tooltip.behaviour2": "從容器中向輸送帶、置物臺放置物品,或從中收集物品到容器中。", - "block.create.andesite_funnel.tooltip.condition3": "垂直放置於兩個容器之間時", - "block.create.andesite_funnel.tooltip.behaviour3": "僅向下垂直傳輸物品,類似一個沒有緩衝空間的漏斗。", - - "block.create.andesite_tunnel.tooltip": "安山物品隧道", - "block.create.andesite_tunnel.tooltip.summary": "輸送帶的保護隧道,能讓你的流水線優雅的穿過牆壁。", - "block.create.andesite_tunnel.tooltip.control1": "板手右鍵側面時", - "block.create.andesite_tunnel.tooltip.action1": "如果輸送帶隧道串連的數量達到三個或以上,可在位於中間的隧道側面上開啟或關閉百葉窗。", - - "block.create.brass_funnel.tooltip": "黃銅漏斗", - "block.create.brass_funnel.tooltip.summary": "一種常用的傳輸裝置,配合各種物流結構傳輸物品,可由_紅石訊號_控制,並附有過濾插槽", - "block.create.brass_funnel.tooltip.condition1": "一般形態", - "block.create.brass_funnel.tooltip.behaviour1": "開口的面會吸收面前的_掉落物_,並_傳輸_到它所附著的_容器_里。", - "block.create.brass_funnel.tooltip.condition2": "安裝在輸送帶、置物臺等結構上時", - "block.create.brass_funnel.tooltip.behaviour2": "從容器中向輸送帶、置物臺放置物品,或從中收集物品到容器中。", - "block.create.brass_funnel.tooltip.condition3": "垂直放置於兩個容器之間時", - "block.create.brass_funnel.tooltip.behaviour3": "向下垂直傳輸物品,類似一個沒有緩衝空間的漏斗。", - - "block.create.brass_tunnel.tooltip": "黃銅物品隧道", - "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.condition3": "分流", - "block.create.brass_tunnel.tooltip.behaviour3": "_黃銅物品隧道_可以為並排的輸送帶路線提供多個物品分流的方案。", - "block.create.brass_tunnel.tooltip.control1": "扳手右鍵側面時", - "block.create.brass_tunnel.tooltip.action1": "如果輸送帶隧道串聯的數量達到三個或以上,可在位於中間的隧道側面上開啟關閉百葉窗。", - "block.create.brass_tunnel.tooltip.control2": "手持扳手在隧道頂部滾動滑鼠滾輪", - "block.create.brass_tunnel.tooltip.action2": "更改_隧道_的分流模式。", - - "block.create.copper_casing.tooltip": "銅製機殼", - "block.create.copper_casing.tooltip.summary": "具備多種用途的堅固機殼,也可用於裝飾。", - "block.create.copper_casing.tooltip.condition1": "對流體管道使用時", - "block.create.copper_casing.tooltip.behaviour1": "會把管道裝入機殼,裝進機殼的管道會與其他管道分開,以免它們自動相連。", - - "block.create.encased_fluid_pipe.tooltip": "流體管道箱", - "block.create.encased_fluid_pipe.tooltip.summary": "用銅機殼加固后的液體管道。", - - "block.create.copper_valve_handle.tooltip": "銅閥門開關", - "block.create.copper_valve_handle.tooltip.summary": "精確的機械來源,需要玩家手動操作。注意不要讓自己太累!", - "block.create.copper_valve_handle.tooltip.condition1": "右鍵使用時", - "block.create.copper_valve_handle.tooltip.behaviour1": "為連接的設備提供機械。潛行狀態下反向旋轉。", - - "block.create.seat.tooltip": "坐墊", - "block.create.seat.tooltip.summary": "坐下來享受旅程吧!坐墊將會把玩家固定在一個移動裝置上。也可以用來作為居家裝飾,畢竟他有許多顏色。", - "block.create.seat.tooltip.condition1": "對坐墊右鍵", - "block.create.seat.tooltip.behaviour1": "玩家將坐在_坐墊_上,Left-Shift可離開_坐墊_。", - - "block.create.chute.tooltip": "滑道", - "block.create.chute.tooltip.summary": "用來_收集_物品並_垂直運輸_它們。可以從_容器_中抽取也可向_容器_輸入。它的側面可以被_漏斗_、_裝配的安山岩漏斗_和_裝配的黃銅漏斗_等傳輸設備交互", - "block.create.chute.tooltip.condition1": "當被上方的鼓風機通風時", - "block.create.chute.tooltip.behaviour1": "由_鼓風機_驅動的_滑道_可由下向上傳輸_物品_,可以從_置物臺_或者_輸送帶_上吸取物品。", - - "block.create.depot.tooltip": "置物臺", - "block.create.depot.tooltip.summary": "一個方便的放置物品的地方。它為多臺機器提供了一個交互點", - "block.create.depot.tooltip.condition1": "右鍵置物臺", - "block.create.depot.tooltip.behaviour1": "可以在_置物臺_放置或取出物品。可以與_輸送帶_交互的方塊或裝置也可以與_置物臺_交互。", - - "item.create.blaze_cake.tooltip": "熔岩蛋糕", - "item.create.blaze_cake.tooltip.summary": "對辛苦的_烈焰使者_的美味款待。讓他們興奮起來吧!", - - "item.create.empty_blaze_burner.tooltip": "空的烈焰使者動力爐", - "item.create.empty_blaze_burner.tooltip.summary": "你火熱的朋友的一個小小的鐵質的家。我相信你會好好利用他們的!", - "item.create.empty_blaze_burner.tooltip.condition1": "當對著烈焰使者或烈焰使者刷怪籠使用時", - "item.create.empty_blaze_burner.tooltip.behaviour1": "即可_捕獲_烈焰使者", - - "block.create.fluid_pipe.tooltip": "液體管道", - "block.create.fluid_pipe.tooltip.summary": "用來傳輸_液體_。需要一個_機械泵_來提供壓強。", - "block.create.fluid_pipe.tooltip.condition1": "轉移液體", - "block.create.fluid_pipe.tooltip.behaviour1": "可以與_液體容器_如_儲存罐_或_作業盆_相連_。裸露的_管道_末端也可以排放或抽取液體。注意別漏水了!", - "block.create.fluid_pipe.tooltip.control1": "使用扳手右鍵", - "block.create.fluid_pipe.tooltip.action1": "如果可能的話,在管道側面開啟/關閉窗口。", - - "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.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.condition1": "使用扳手右鍵", - "block.create.fluid_tank.tooltip.behaviour1": "改變可選窗口", - - "block.create.creative_fluid_tank.tooltip": "創造液體儲存罐", - "block.create.creative_fluid_tank.tooltip.summary": "此液體儲存罐能夠_無限的復制_任何液體。", - "block.create.creative_fluid_tank.tooltip.condition1": "罐中裝有液體時", - "block.create.creative_fluid_tank.tooltip.behaviour1": "任意的_液體提取設備_能夠從中提取無窮無盡的指定液體,液體的導入功能同時也會無效。", - "block.create.creative_fluid_tank.tooltip.condition2": "扳手右擊時", - "block.create.creative_fluid_tank.tooltip.behaviour2": "打開關閉窗戶", - - "block.create.fluid_valve.tooltip": "液體閥門", - "block.create.fluid_valve.tooltip.summary": "阻止液體沿管道向前流動。", - "block.create.fluid_valve.tooltip.condition1": "控制流量", - "block.create.fluid_valve.tooltip.behaviour1": "施加的_旋轉力_將迫使閥門關閉,從而阻止液體流動。_逆轉旋轉方向_以重新打開閥門。", - - "block.create.mechanical_pump.tooltip": "機械泵", - "block.create.mechanical_pump.tooltip.summary": "_接入機械_,能迫使液體_沿管道指定方向移動_。在兩個方向上都有_最大的作用範圍_。(默認為16個方塊距離)", - "block.create.mechanical_pump.tooltip.condition1": "液體流向", - "block.create.mechanical_pump.tooltip.behaviour1": "_接入機械_后會產生壓力,迫使液體通過管道。_反轉機械_的方向以切換液體_流向_。", - "block.create.mechanical_pump.tooltip.control1": "扳手右鍵時", - "block.create.mechanical_pump.tooltip.action1": "反轉泵的方向,從而改變默認的液體流向", - - "block.create.smart_fluid_pipe.tooltip": "智慧液體管道", - "block.create.smart_fluid_pipe.tooltip.summary": "帶有過濾器的_液體管道_。可以指定通過哪個_液體_。", - "block.create.smart_fluid_pipe.tooltip.condition1": "當液體進入時", - "block.create.smart_fluid_pipe.tooltip.behaviour1": "進入的液體與_過濾器_不匹配時,智慧管道將_阻止_其通過。", - "block.create.smart_fluid_pipe.tooltip.condition2": "與_液體容器相鄰_時", - "block.create.smart_fluid_pipe.tooltip.behaviour2": "從_任何容器_開始流動的_智慧管道_只會抽取與其過濾器匹配的液體。", - - "block.create.spout.tooltip": "注液器", - "block.create.spout.tooltip.summary": "一種用來_裝罐_的機器。", - "block.create.spout.tooltip.condition1": "液體傳輸", - "block.create.spout.tooltip.behaviour1": "當下方放置類似_玻璃瓶_,_桶_這樣的液體容器物品時,注液器將試圖將自身儲存的液體注入到下方的_液體容器物品_中。", - "block.create.spout.tooltip.condition2": "液體自動化", - "block.create.spout.tooltip.behaviour2": "注液器位於_輸送帶_或者_置物臺_上方時,將自動為流水線上的_液體容器物品_進行_注入_。", - - "block.create.item_drain.tooltip": "分液池", - "block.create.item_drain.tooltip.summary": "一種用來_抽空液體容器物品_的置物臺", - "block.create.item_drain.tooltip.condition1": "液體傳輸", - "block.create.item_drain.tooltip.behaviour1": "當從側面導入諸如_桶_或_瓶子_之類的_液體容器物品_時,_分液池_將嘗試將其倒入其_自身的液體庫存_中。空的_液體容器物品_將被彈出至_另一側_。", - - "block.create.mechanical_arm.tooltip": "機械臂", - "block.create.mechanical_arm.tooltip.summary": "移動_物品_的高級裝置", - "block.create.mechanical_arm.tooltip.condition1": "轉移物品", - "block.create.mechanical_arm.tooltip.behaviour1": "可以從任意_可夠到的設備_中拿取或放置物品,比如說_輸送帶_,_置物臺_,_漏斗_以及_機械合成器_。", - "block.create.mechanical_arm.tooltip.control1": "手持時", - "block.create.mechanical_arm.tooltip.action1": "右鍵單擊一個_可獲取的容器_來將其設置為_機械臂_的_輸入端_。右鍵雙擊將其設置為_機械臂_的_輸出端_。", - "block.create.mechanical_arm.tooltip.control2": "手持扳手滾動滾輪", - "block.create.mechanical_arm.tooltip.action2": "調整_機械臂_輸出物品時的調度模式。", - - "item.create.wand_of_symmetry.tooltip": "對稱杖", - "item.create.wand_of_symmetry.tooltip.summary": "完美地鏡面復制工作區域內的方塊放置於破壞", - "item.create.wand_of_symmetry.tooltip.condition1": "當在熱鍵欄時", - "item.create.wand_of_symmetry.tooltip.behaviour1": "持續進行鏡面復制", - "item.create.wand_of_symmetry.tooltip.control1": "當右鍵地面時", - "item.create.wand_of_symmetry.tooltip.action1": "_創建_或_移動_鏡子", - "item.create.wand_of_symmetry.tooltip.control2": "當右鍵空氣時", - "item.create.wand_of_symmetry.tooltip.action2": "_刪除_鏡子", - "item.create.wand_of_symmetry.tooltip.control3": "當潛行右鍵時", - "item.create.wand_of_symmetry.tooltip.action3": "打開_gui界面_", - - "item.create.handheld_blockzapper.tooltip": "方塊放置器", - "item.create.handheld_blockzapper.tooltip.summary": "新穎的小工具,可以遠距離放置或更換方塊。", - "item.create.handheld_blockzapper.tooltip.control1": "當左鍵方塊時", - "item.create.handheld_blockzapper.tooltip.action1": "設定放置此方塊。", - "item.create.handheld_blockzapper.tooltip.control2": "當右鍵方塊時", - "item.create.handheld_blockzapper.tooltip.action2": "_放置_或_替換_目標方塊。", - "item.create.handheld_blockzapper.tooltip.control3": "當潛行右鍵時", - "item.create.handheld_blockzapper.tooltip.action3": "打開_gui界面_", - - "item.create.handheld_worldshaper.tooltip": "環境塑形器", - "item.create.handheld_worldshaper.tooltip.summary": "_大面積_更改地形的手持工具", - "item.create.handheld_worldshaper.tooltip.control1": "當左鍵方塊時", - "item.create.handheld_worldshaper.tooltip.action1": "設定放置此方塊", - "item.create.handheld_worldshaper.tooltip.control2": "當右鍵方塊時", - "item.create.handheld_worldshaper.tooltip.action2": "_放置_或_替換_目標方塊", - "item.create.handheld_worldshaper.tooltip.control3": "當潛行右鍵時", - "item.create.handheld_worldshaper.tooltip.action3": "打開工具的_gui界面_", - - "item.create.tree_fertilizer.tooltip": "樹木肥料", - "item.create.tree_fertilizer.tooltip.summary": "適用來常見樹木的快速肥料", - "item.create.tree_fertilizer.tooltip.condition1": "在樹苗上使用時", - "item.create.tree_fertilizer.tooltip.behaviour1": "無論_生長時間_多少,直接長大", - - "item.create.deforester.tooltip": "連根拔樹斧", - "item.create.deforester.tooltip.summary": "_連根拔樹斧_,從最根砍樹時,能夠瞬間連根拔起一棵樹", - - "item.create.extendo_grip.tooltip": "伸縮機械手", - "item.create.extendo_grip.tooltip.summary": "biubiubiu! 大幅度_增加了_使用者的_觸碰距離_。", - "item.create.extendo_grip.tooltip.condition1": "放置於副手欄時", - "item.create.extendo_grip.tooltip.behaviour1": "大幅增加_主手_的觸碰距離,與_主手_的伸縮機械手攜同使用,可進一步增加_觸碰距離_。", - - "item.create.filter.tooltip": "過濾器", - "item.create.filter.tooltip.summary": "將物品更精確地進行_篩選分類_,可以同時_篩選_多個物品或者將已標記的_過濾器_放在另一個_過濾器_里_嵌套_使用。", - "item.create.filter.tooltip.condition1": "放置於過濾插槽中時", - "item.create.filter.tooltip.behaviour1": "根據_過濾器_的配置,來_決定_物品是否能夠通過", - "item.create.filter.tooltip.condition2": "當右鍵時", - "item.create.filter.tooltip.behaviour2": "打開_配置面板_", - - "item.create.attribute_filter.tooltip": "屬性過濾器", - "item.create.attribute_filter.tooltip.summary": "比起普通過濾器,_屬性過濾器_可以根據不同物品的_屬性_來進行過濾", - "item.create.attribute_filter.tooltip.condition1": "放置於過濾插槽中時", - "item.create.attribute_filter.tooltip.behaviour1": "根據_過濾器_的配置,來_決定_物品是否能夠通過", - "item.create.attribute_filter.tooltip.condition2": "當右鍵時", - "item.create.attribute_filter.tooltip.behaviour2": "打開_配置面板_", - - "item.create.empty_schematic.tooltip": "空白藍圖", - "item.create.empty_schematic.tooltip.summary": "可作為合成材料或在_藍圖桌_使用", - - "item.create.schematic.tooltip": "藍圖", - "item.create.schematic.tooltip.summary": "將工程結構的_全息圖_放置於_世界中_,並使用_藍圖加農炮_進行構建。", - "item.create.schematic.tooltip.condition1": "當全息圖存在時", - "item.create.schematic.tooltip.behaviour1": "可以使用屏幕上的工具調整位置", - "item.create.schematic.tooltip.control1": "當潛行右鍵時", - "item.create.schematic.tooltip.action1": "打開一個用來輸入_精確坐標_的界面。", - - "item.create.schematic_and_quill.tooltip": "藍圖與筆", - "item.create.schematic_and_quill.tooltip.summary": "用來將世界中的結構保存到.nbt文件。", - "item.create.schematic_and_quill.tooltip.condition1": "第一步", - "item.create.schematic_and_quill.tooltip.behaviour1": "手持藍圖與右鍵旋轉兩個點", - "item.create.schematic_and_quill.tooltip.condition2": "第二步", - "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.control3": "當潛行右鍵時", - "item.create.schematic_and_quill.tooltip.action3": "_重置_並刪除選區。", - - "block.create.schematicannon.tooltip": "藍圖加農炮", - "block.create.schematicannon.tooltip.summary": "通過發射方塊以在世界中重新構建已部署的_全息圖_,使用相鄰箱子中的物品及_火藥_作為燃料。", - "block.create.schematicannon.tooltip.control1": "當右鍵時", - "block.create.schematicannon.tooltip.action1": "打開_gui界面_", - - "block.create.schematic_table.tooltip": "藍圖桌", - "block.create.schematic_table.tooltip.summary": "將保存的藍圖圖寫入_空白藍圖_", - "block.create.schematic_table.tooltip.condition1": "放入空白藍圖時", - "block.create.schematic_table.tooltip.behaviour1": "從Schematics文件夾上傳所選文件", - - "block.create.shaft.tooltip": "傳動軸", - "block.create.shaft.tooltip.summary": "將_旋轉動能_進行直線傳遞。", - - "block.create.cogwheel.tooltip": "齒輪", - "block.create.cogwheel.tooltip.summary": "將_旋轉動能_進行直線傳遞,或者傳遞到鄰近的_齒輪_上", - - "block.create.large_cogwheel.tooltip": "大齒輪", - "block.create.large_cogwheel.tooltip.summary": "大號齒輪傳動結構,連接到_小號齒輪_時改變其_轉速_。", - - "block.create.encased_shaft.tooltip": "傳動軸箱", - "block.create.encased_shaft.tooltip.summary": "將_旋轉動能_進行直線傳遞,其方塊體積使其在穿過牆體時更加_美觀_。", - - "block.create.gearbox.tooltip": "齒輪箱", - "block.create.gearbox.tooltip.summary": "十字傳動旋轉結構,同時將直線旋轉方向_反轉_。", - - "block.create.gearshift.tooltip": "換擋齒輪箱", - "block.create.gearshift.tooltip.summary": "用來反轉傳動軸_旋轉方向_的開關。", - "block.create.gearshift.tooltip.condition1": "當提供紅石訊號時", - "block.create.gearshift.tooltip.behaviour1": "_更改_旋轉方向。", - - "block.create.clutch.tooltip": "離合器", - "block.create.clutch.tooltip.summary": "傳動開關裝置。", - "block.create.clutch.tooltip.condition1": "當提供紅石訊號時", - "block.create.clutch.tooltip.behaviour1": " _停止_ 另一側的旋轉。", - - "block.create.encased_chain_drive.tooltip": "鏈式傳動箱", - "block.create.encased_chain_drive.tooltip.summary": "將動能_鏈式傳遞_給側面相貼的_鏈式傳動箱_,呈_直線_放置形成鏈式傳動箱組,它們的朝向不必一致。", - "block.create.encased_chain_drive.tooltip.condition1": "互相連接時", - "block.create.encased_chain_drive.tooltip.behaviour1": "_鏈式傳動箱組_中的_鏈式傳動箱_將以相同的速度旋轉。", - - "block.create.adjustable_chain_gearshift.tooltip": "可調節鏈式傳動箱", - "block.create.adjustable_chain_gearshift.tooltip.summary": "將動能_鏈式傳遞_給側面相貼的_鏈式傳動箱_,呈_直線_放置形成鏈式傳動箱組,可通過_紅石訊號_改變其內部主齒輪的半徑大小從而提高其耦合齒輪的_轉速_,進而提高其_連攜_的其它_鏈式傳動箱_的_轉速_。", - "block.create.adjustable_chain_gearshift.tooltip.condition1": "紅石控制", - "block.create.adjustable_chain_gearshift.tooltip.behaviour1": "沒有紅石訊號時,_鏈式傳動箱組_中的_鏈式傳動箱_將以相同的速度旋轉。紅石訊號拉滿時,_鏈式傳動箱組_中除自身以外的_鏈式傳動箱_將以兩倍的速度旋轉。介於兩者之間的任何結果都將使其速度提高1-2倍。", - - "item.create.belt_connector.tooltip": "輸送帶", - "item.create.belt_connector.tooltip.summary": "用_輸送帶_連接兩個_傳動軸_,連接的傳動軸將具有完全相同的轉速和方向。輸送帶可以_傳輸實體_和_物品_。", - "item.create.belt_connector.tooltip.control1": "當右鍵傳動軸時", - "item.create.belt_connector.tooltip.action1": "選擇傳動軸作為輸送帶的傳輸點,選定的兩個傳動軸都必須相互_垂直_,_水平_或_對角平齊_。", - "item.create.belt_connector.tooltip.control2": "當潛行右鍵時", - "item.create.belt_connector.tooltip.action2": "_重置_輸送帶的第一個選定位置", - - "item.create.goggles.tooltip": "MR護目鏡", - "item.create.goggles.tooltip.summary": "一副特殊的眼鏡,能夠讓你看見_動能_的信息。", - "item.create.goggles.tooltip.condition1": "當裝備後", - "item.create.goggles.tooltip.behaviour1": "將會展示該機械元件的_速度_、_動能_等數值", - "item.create.goggles.tooltip.condition2": "當裝備後看向儀表時", - "item.create.goggles.tooltip.behaviour2": "將會展示該儀表所連接網路的_速度_、_動能_等數值。", - - "item.create.wrench.tooltip": "板手", - "item.create.wrench.tooltip.summary": "一種常用的工具,能夠調整_動能_的_方向_、_配置_等。", - "item.create.wrench.tooltip.control1": "當右鍵點擊_動能元件_時", - "item.create.wrench.tooltip.action1": "以點擊的面為軸心_旋轉_點擊的方塊", - "item.create.wrench.tooltip.control2": "當潛行右鍵時", - "item.create.wrench.tooltip.action2": "將物品_取下_並移動到你的背包中。", - - "block.create.creative_motor.tooltip": "創造馬達", - "block.create.creative_motor.tooltip.summary": "可以獲得_無限動能_", - - "block.create.water_wheel.tooltip": "水車", - "block.create.water_wheel.tooltip.summary": "從相鄰的流水中獲得動能", - - "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.condition2": "接入機械時", - "block.create.encased_fan.tooltip.behaviour2": "根據旋轉方向_推動_或者_吸引_實體,強度和速度取決於給予的機械。", - "block.create.encased_fan.tooltip.condition3": "當氣流通過火、水、熔岩時", - "block.create.encased_fan.tooltip.behaviour3": "在_被吹出_的水,火,熔岩粒子中放置物品會獲得相應產物(_建議配合jei查看_)。", - - "block.create.nozzle.tooltip": "分散網", - "block.create.nozzle.tooltip.summary": "依附在鼓風機上,能夠將鼓風機的效果_分散_各個方向。", - - "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.cuckoo_clock.tooltip": "布穀鳥鐘", - "block.create.cuckoo_clock.tooltip.summary": "精美的布穀鳥鐘,能夠報時", - "block.create.cuckoo_clock.tooltip.condition1": "連接機械時", - "block.create.cuckoo_clock.tooltip.behaviour1": "顯示_現在時間_且一天會報時_兩次_。中午一次,黃昏可以睡覺時一次 ", - - "block.create.turntable.tooltip": "轉盤", - "block.create.turntable.tooltip.summary": "讓旋轉機械給你帶來一場刺激的旋轉風車體驗。", - - "block.create.millstone.tooltip": "石磨", - "block.create.millstone.tooltip.summary": "一個能_研磨物品_的動能裝置,可以被臨近的_齒輪_供能,或者可以在底部用傳動軸供能,成品必須被提取出石磨", - "block.create.millstone.tooltip.condition1": "當旋轉運作時", - "block.create.millstone.tooltip.behaviour1": "開始根據_研磨配方_來處理物品。", - "block.create.millstone.tooltip.condition2": "當右鍵時", - "block.create.millstone.tooltip.behaviour2": "手動取出研磨后的成品。", - - "block.create.crushing_wheel.tooltip": "粉碎輪", - "block.create.crushing_wheel.tooltip.summary": "一對能夠_粉碎一切_的粉碎輪。向這對粉碎輪提供_向內_且_相反的動能_後開始工作", - "block.create.crushing_wheel.tooltip.condition1": "當兩個粉碎輪一起工作時", - "block.create.crushing_wheel.tooltip.behaviour1": "_粉碎物品_並獲得產物(請使用JEI查看對應的產物)", - - "block.create.mechanical_press.tooltip": "機械液壓機", - "block.create.mechanical_press.tooltip.summary": "一個強力的活塞式機器,壓扁其下面的物品。", - "block.create.mechanical_press.tooltip.condition1": "當輸入_紅石訊號_時", - "block.create.mechanical_press.tooltip.behaviour1": "_壓扁_其下方的物品。", - "block.create.mechanical_press.tooltip.condition2": "在輸送帶上方時", - "block.create.mechanical_press.tooltip.behaviour2": "_自動壓扁_經過輸送帶的物品。", - "block.create.mechanical_press.tooltip.condition3": "在_作業盆_上方時", - "block.create.mechanical_press.tooltip.behaviour3": "_壓縮_配方中允許壓縮的物品。", - - "block.create.basin.tooltip": "作業盆", - "block.create.basin.tooltip.summary": "一種_物品容器_,與_液壓機_和_攪拌機_配合使用,可以被_紅石比較器_檢測", - "block.create.basin.tooltip.condition1": "自動輸出", - "block.create.basin.tooltip.behaviour1": "當其他對應容器(例如輸送帶,其他的作業盆,置物臺等)在作業盆的一側下方時,它們將自動收集在作業盆中產出的任何物品/液體。自動化的好夥伴。", - - "block.create.blaze_burner.tooltip": "烈焰使者動力爐", - "block.create.blaze_burner.tooltip.summary": "一個用來加熱_作業盆_的設備,由烈焰使者來驅動。", - "block.create.blaze_burner.tooltip.condition1": "放置於作業盆下方時", - "block.create.blaze_burner.tooltip.behaviour1": "為作業盆_提供熱量_。", - "block.create.blaze_burner.tooltip.condition2": "對本爐使用可燃物時", - "block.create.blaze_burner.tooltip.behaviour2": "_消耗_可燃物,並根據該物在_熔爐中的燃燒時間_來延長_本爐的燃燒時間_,使用_熔岩蛋糕_將提供_更高的溫度_。", - - "block.create.reinforced_rail.tooltip": "強化鐵軌", - "block.create.reinforced_rail.tooltip.summary": "堅固的鐵軌,不需要_方塊的支撐_。", - - "block.create.mechanical_mixer.tooltip": "機械攪拌器", - "block.create.mechanical_mixer.tooltip.summary": "一種能夠動態進行攪拌的機器,需要穩定且足夠快的轉速,並且下方需要放置_作業盆_(中間需要一格高)", - "block.create.mechanical_mixer.tooltip.condition1": "當位於作業盆上方", - "block.create.mechanical_mixer.tooltip.behaviour1": "只要_作業盆_中有滿足配方的物品,將自動進行攪拌", - "block.create.mechanical_mixer.tooltip.control1": "被紅石激活時", - "block.create.mechanical_mixer.tooltip.action1": "停止攪拌,試用來緊急時刻!", - - "block.create.mechanical_crafter.tooltip": "機械合成器", - "block.create.mechanical_crafter.tooltip.summary": "一種依靠_動能_的_自動_合成臺。根據想要合成的物品的_合成表尺寸_來擺放_相應數量_的機械合成器,並且用扳手調整物品在合成器里的_傳動方向_以讓他們收束在一起合成並輸出", - "block.create.mechanical_crafter.tooltip.condition1": "接入機械時", - "block.create.mechanical_crafter.tooltip.behaviour1": "當機器中_所有_的物品槽有物品時,將會啟動所有的合成器來工作。", - "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.control2": "當側方或者后方使用扳手時", - "block.create.mechanical_crafter.tooltip.action2": "連接相鄰的合成器的物品欄,這樣_相同_的物品就會自動進入所有相互連接的合成器", - - "block.create.furnace_engine.tooltip": "熔爐引擎", - "block.create.furnace_engine.tooltip.summary": "一種強力的_旋轉動能_的來源,但是需要_正在工作_的_熔爐_(三種熔爐都可以)", - "block.create.furnace_engine.tooltip.condition1": "當連接正在燃燒的熔爐", - "block.create.furnace_engine.tooltip.behaviour1": "將會帶動_相連_的_飛輪_(需要間隔一格),用高爐速度更快", - - "block.create.flywheel.tooltip": "飛輪", - "block.create.flywheel.tooltip.summary": "一種大型的金屬輪,能將_熔爐引擎_提供的動能穩定化輸出,需要與_熔爐引擎_間隔一個方塊", - "block.create.flywheel.tooltip.condition1": "當連接正在輸出的_熔爐引擎_", - "block.create.flywheel.tooltip.behaviour1": "將會提供相應的_旋轉動能_。", - - "block.create.portable_storage_interface.tooltip": "移動儲存接口", - "block.create.portable_storage_interface.tooltip.summary": "為機械活塞、裝配礦車、旋轉軸承、滑輪_等移動結構_設計的_物流接口_,_移動結構_和_固定結構_之間的物品交換站,兩個接口會面時將_自動對接_,接口必須彼此面對且彼此隔開1-2個方塊。", - "block.create.portable_storage_interface.tooltip.condition1": "裝配在移動結構上時", - "block.create.portable_storage_interface.tooltip.behaviour1": "移動到能夠滿足與_固定結構_上的_移動式儲存接口_對接的條件后,移動結構會_短暫地停下_,開始對接,並直接與_移動結構上的_儲存容器_交互,進行物品的_輸入輸出_。", - "block.create.portable_storage_interface.tooltip.condition2": "被紅石激活時", - "block.create.portable_storage_interface.tooltip.behaviour2": "立即終止任何活動連接。", - - "block.create.portable_fluid_interface.tooltip": "移動液體接口", - "block.create.portable_fluid_interface.tooltip.summary": "為機械活塞、裝配礦車、旋轉軸承、滑輪_等移動結構_設計的_液體接口_,_移動結構_和_固定結構_之間的液體交換站,兩個會面的接口必須彼此面對且彼此隔開1-2個方塊。", - "block.create.portable_fluid_interface.tooltip.condition1": "裝配在移動結構上時", - "block.create.portable_fluid_interface.tooltip.behaviour1": "移動到能夠滿足與_固定結構_上的_移動式液體接口_對接的條件后,移動結構會_短暫地停下_,開始對接,並直接與_移動結構上的_液體儲存罐_交互,進行液體的_導入導出_。", - "block.create.portable_fluid_interface.tooltip.condition2": "被紅石激活時", - "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.condition1": "接入大齒輪時", - "block.create.rotation_speed_controller.tooltip.behaviour1": "通過_滑鼠滾輪_調整接入機械的_轉速_,傳遞給連接的_大齒輪_,連接的大齒輪需要放置在其上方。", - - "block.create.mechanical_piston.tooltip": "機械活塞", - "block.create.mechanical_piston.tooltip.summary": "活塞的高級版本,使用_旋轉動能_精確地移動其連接的方塊,背面可放置活塞桿延長活塞範圍,沒有活塞桿將不會工作,使用_底盤_或者_粘液塊_可以移動多行方塊。", - "block.create.mechanical_piston.tooltip.condition1": "推拉活塞時", - "block.create.mechanical_piston.tooltip.behaviour1": "活塞的_速度_和_方向_與所接受_轉速_的_大小_以及_方向_相關。", - - "block.create.piston_extension_pole.tooltip": "活塞桿", - "block.create.piston_extension_pole.tooltip.summary": "用來增加_機械活塞_的移動範圍", - "block.create.piston_extension_pole.tooltip.condition1": "當連接到機械活塞時", - "block.create.piston_extension_pole.tooltip.behaviour1": "活塞的移動範圍將擴大", - - "block.create.mechanical_bearing.tooltip": "機械軸承", - "block.create.mechanical_bearing.tooltip.summary": "由機械驅動,根據機械的方向旋轉,用來建造大型的旋轉結構。", - "block.create.mechanical_bearing.tooltip.condition1": "接入機械時", - "block.create.mechanical_bearing.tooltip.behaviour1": "前方的旋轉盤將帶動_粘液塊_或者_底盤_來驅動更多方塊一同旋轉。", - - "block.create.windmill_bearing.tooltip": "風車軸承", - "block.create.windmill_bearing.tooltip.summary": "借助_風的力量_創造_機械_。用您獨特的設計拼接它並讓它旋轉!", - "block.create.windmill_bearing.tooltip.condition1": "右鍵時", - "block.create.windmill_bearing.tooltip.behaviour1": "啟動軸承,提供由其_附加結構_的旋轉產生的機械。結構必須包括合適的_風帆_或_羊毛_。使用_機殼地盤_,_粘液塊_或_強力膠_可以帶動更多方塊旋轉。", - - "block.create.sail_frame.tooltip": "風帆框架", - "block.create.sail_frame.tooltip.summary": "可用來_組裝風車_的結構方塊,不俗的機械來源。", - - "block.create.white_sail.tooltip": "風帆", - "block.create.white_sail.tooltip.summary": "可用來_組裝風車_的結構方塊,不俗的機械來源,有多種顏色。", - "block.create.white_sail.tooltip.condition1": "使用染料右鍵時", - "block.create.white_sail.tooltip.behaviour1": "改變顏色。", - - "block.create.clockwork_bearing.tooltip": "時鐘軸承", - "block.create.clockwork_bearing.tooltip.summary": "一種高級的機械軸承,可以根據目前遊戲內時間旋轉兩個不同的指針", - "block.create.clockwork_bearing.tooltip.condition1": "接入機械時", - "block.create.clockwork_bearing.tooltip.behaviour1": "旋轉第一個連接的結構作為時針,第二個連接的結構作為分針", - - "block.create.sequenced_gearshift.tooltip": "可編程齒輪箱", - "block.create.sequenced_gearshift.tooltip.summary": "一種可編程的組件,可以根據內部的指令設計旋轉的_方向_,_速度_,以及_距離_。此組件可以有效配合活塞和軸承等使用。最高可讓其按_順序_執行_5條指令_。條高速旋轉時可能會變得不精確。", - "block.create.sequenced_gearshift.tooltip.condition1": "當給予紅石訊號時", - "block.create.sequenced_gearshift.tooltip.behaviour1": "在接入動能的情況下,執行指令。", - "block.create.sequenced_gearshift.tooltip.condition2": "當右鍵時", - "block.create.sequenced_gearshift.tooltip.behaviour2": "將打開_配置界面_", - - "block.create.cart_assembler.tooltip": "礦車裝配站", - "block.create.cart_assembler.tooltip.summary": "將連接目前方塊的結構連接在_礦車_上", - "block.create.cart_assembler.tooltip.condition1": "當被紅石訊號激活時", - "block.create.cart_assembler.tooltip.behaviour1": "將裝配站上連接的結構組裝到礦車上,並送礦車上路", - "block.create.cart_assembler.tooltip.condition2": "沒有紅石訊號時", - "block.create.cart_assembler.tooltip.behaviour2": "將經過的礦車上的結構_實體化_,並停住礦車。", - "block.create.cart_assembler.tooltip.control1": "放置於軌道上時", - "block.create.cart_assembler.tooltip.action1": "紅石激活時_裝配_經過的礦車,未激活時_卸載_經過的礦車。", - "block.create.cart_assembler.tooltip.control2": "放置於充能鐵軌上時", - "block.create.cart_assembler.tooltip.action2": "紅石激活時_裝配_並加速礦車,未激活時_卸載_並停住經過的礦車。", - "block.create.cart_assembler.tooltip.control3": "放置在探測鐵軌上時", - "block.create.cart_assembler.tooltip.action3": "_裝配_未裝配過的礦車,_卸載_裝配過的礦車。", - "block.create.cart_assembler.tooltip.control4": "放置在激活鐵軌上時", - "block.create.cart_assembler.tooltip.action4": "紅石激活時_卸載_礦車。", - - "block.create.rope_pulley.tooltip": "繩索滑輪", - "block.create.rope_pulley.tooltip.summary": "移動繩索相連的結構。使用_底盤_或者_粘液塊_來移動多行方塊", - "block.create.rope_pulley.tooltip.condition1": "接入機械時", - "block.create.rope_pulley.tooltip.behaviour1": "根據輸入的轉速的大小以及方向,移動鏈接的結構。", - - "block.create.linear_chassis.tooltip": "機殼底盤", - "block.create.linear_chassis.tooltip.summary": "一種可配置的_底盤_。這種底盤可以將多個方塊連接起來組合成_大型結構_", - "block.create.linear_chassis.tooltip.condition1": "被移動時", - "block.create.linear_chassis.tooltip.behaviour1": "移動所有_並排_的_機殼底盤_。如果底盤上涂了_粘液球_,那麼其範圍內一條直線的方塊都會被_黏附移動_(詳情見Ctrl)。", - "block.create.linear_chassis.tooltip.condition2": "當使用扳手時", - "block.create.linear_chassis.tooltip.behaviour2": "通過_滑鼠滾輪_來配置連接的方塊的範圍。按住_Ctrl_時滾動滾輪可以同時配置相連的其他底盤。", - "block.create.linear_chassis.tooltip.control1": "當用粘液球右鍵時", - "block.create.linear_chassis.tooltip.action1": "變為_粘性機殼底盤_。所有工作範圍內與其相連的方塊會與其_一同移動_", - - "block.create.secondary_linear_chassis.tooltip": "機殼底盤2號", - "block.create.secondary_linear_chassis.tooltip.summary": "第二種_機殼底盤_,不會與第一種機殼底盤互相連接。", - - "block.create.radial_chassis.tooltip": "旋轉底盤", - "block.create.radial_chassis.tooltip.summary": "一種可配置的底盤。這種底盤可以將多個方塊連接起來組合成_大型結構_", - "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.control1": "當用粘液球右鍵時", - "block.create.radial_chassis.tooltip.action1": "變為_粘性旋轉底盤_。所有工作範圍內與其相連的方塊會與其_一同移動_。", - - "block.create.mechanical_drill.tooltip": "機械鑽頭", - "block.create.mechanical_drill.tooltip.summary": "用來_破壞方塊_的裝置,可以被_機械活塞_和_機械軸承_等移動設備帶動", - "block.create.mechanical_drill.tooltip.condition1": "被供能時", - "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.condition1": "當移動時", - "block.create.mechanical_harvester.tooltip.behaviour1": "收割機移動至成熟作物,收割作物並將作物變為初始生長狀態。", - - "block.create.mechanical_plough.tooltip": "機械犁", - "block.create.mechanical_plough.tooltip.summary": "犁是一個非常有用的多功能方塊,它可以被_機械活塞_和_機械軸承_等帶動", - "block.create.mechanical_plough.tooltip.condition1": "當移動時", - "block.create.mechanical_plough.tooltip.behaviour1": "可以打掉無碰撞體積的一些_附著方塊_,比如火把和雪等。可以在不傷害實體的情況下移動它們。能像_鋤頭_一樣翻土耕田。", - - "block.create.mechanical_saw.tooltip": "機械切割機", - "block.create.mechanical_saw.tooltip.summary": "可以用來砍樹,也可以用來切割方塊,可以被_機械活塞_和_機械軸承_等帶動", - "block.create.mechanical_saw.tooltip.condition1": "當向上放置時", - "block.create.mechanical_saw.tooltip.behaviour1": "可以切割各種物品(建議配合jei查看)", - "block.create.mechanical_saw.tooltip.condition2": "當方向在水平面時", - "block.create.mechanical_saw.tooltip.behaviour2": "可以砍倒面前的樹木", - "block.create.mechanical_saw.tooltip.condition3": "當移動時", - "block.create.mechanical_saw.tooltip.behaviour3": "將會砍倒碰撞到的樹木", - - "block.create.stockpile_switch.tooltip": "存量檢測器", - "block.create.stockpile_switch.tooltip.summary": "根據連接的容器_儲存空間_的占用情況切換紅石訊號強度。", - "block.create.stockpile_switch.tooltip.condition1": "低於_下線_或高於_上線_時", - "block.create.stockpile_switch.tooltip.behaviour1": "提供紅石訊號", - - "block.create.content_observer.tooltip": "物品偵測器", - "block.create.content_observer.tooltip.summary": "檢測_容器_和_輸送帶_中過濾器匹配的物品。當觀察到包含匹配的物品時,此組件將發出_紅石訊號_。當觀察到的漏斗_轉移匹配的物品_時,此組件將發出_紅石脈沖_。", - - "block.create.redstone_link.tooltip": "無限紅石訊號終端", - "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": "手持_任意物品_為其設置_頻道_,可以使用兩種物品組合設置_頻道_。", - "block.create.redstone_link.tooltip.control2": "當潛行右鍵時", - "block.create.redstone_link.tooltip.action2": "在_發射模式_和_接收模式_之間切換。", - - "block.create.nixie_tube.tooltip": "真空管顯示器", - "block.create.nixie_tube.tooltip.summary": "一個炫泡的_紅石強度_顯示器,範圍:0到15。", - "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.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.control1": "當右鍵時", - "block.create.adjustable_crate.tooltip.action1": "打開箱子", - - "block.create.creative_crate.tooltip": "創造板條箱", - "block.create.creative_crate.tooltip.summary": "這個容器可以給臨近的_藍圖大炮_提供無限物品以及燃料 (創造專用物品)", - "block.create.creative_crate.tooltip.condition1": "當標記了物品時", - "block.create.creative_crate.tooltip.behaviour1": "容器將會從虛空中提供_無限量_的標記物品,並且任何放置到容器中的物品都會被_送入虛空_", - - "block.create.deployer.tooltip": "機械手", - "block.create.deployer.tooltip.summary": "它是一個盡可能_模仿玩家_的行為的_機械手_,自帶一個物品_緩存區_,可以由漏斗、機械臂等輸入設備為其提供物品,並帶有過濾插槽", - "block.create.deployer.tooltip.condition1": "接入動能時", - "block.create.deployer.tooltip.behaviour1": "機械手可伸長_兩個方塊_的距離,取出_緩存區_的物品並使用。", - "block.create.deployer.tooltip.condition2": "當使用扳手右鍵時", - "block.create.deployer.tooltip.behaviour2": "啟用拳頭模式,在拳頭模式之下,機械手將會試圖使用手中的物品_破壞方塊_,或者_攻擊實體_。", - "block.create.deployer.tooltip.condition3": "配有_過濾器_時", - "block.create.deployer.tooltip.behaviour3": "當_緩存區_的物品與過濾器匹配,機械手才會取出並使用,不匹配的物品_無法從外部輸入_到機械手的_緩存區_中;_緩存區_中與過濾器匹配的物品_無法被提取_。", - - "block.create.brass_casing.tooltip": "黃銅機殼", - "block.create.brass_casing.tooltip.summary": "一種堅固的機殼,有多種用途。", - - "block.create.pulse_repeater.tooltip": "可調節脈沖中繼器", - "block.create.pulse_repeater.tooltip.summary": "一個簡單的電路元件,將通過的紅石訊號變為1tick。", - - "block.create.adjustable_repeater.tooltip": "可調節中繼器", - "block.create.adjustable_repeater.tooltip.summary": "高級中繼器,最大可設置30分鐘延遲", - - "block.create.adjustable_pulse_repeater.tooltip": "可調節脈沖中繼器", - "block.create.adjustable_pulse_repeater.tooltip.summary": "一種單次1tick的紅石脈沖器,可以調節延時至30min", - - "block.create.analog_lever.tooltip": "可調節拉桿", - "block.create.analog_lever.tooltip.summary": "一種可以調節任意訊號強度的推桿。", - - "block.create.powered_toggle_latch.tooltip": "T觸發器", - "block.create.powered_toggle_latch.tooltip.summary": "一種拉桿,在紅石電路中可以用作t觸發器。", - - "block.create.powered_latch.tooltip": "鎖存器", - "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": "根據訊號強度_加速_或_減速_經過的礦車。將紅石強度傳播到相鄰的控制鐵軌。", - - "block.create.speedometer.tooltip": "速度計", - "block.create.speedometer.tooltip.summary": "測量並展示連接網絡的旋轉速度,支持使用紅石比較器", - "block.create.speedometer.tooltip.condition1": "接入機械時", - "block.create.speedometer.tooltip.behaviour1": "將會用顏色展示速度的大小,綠-慢、藍-中、紫-快。", - - "block.create.stressometer.tooltip": "動能錶", - "block.create.stressometer.tooltip.summary": "測量並展示連接網絡的動能值,支持紅石比較器", - "block.create.stressometer.tooltip.condition1": "接入機械時", - "block.create.stressometer.tooltip.behaviour1": "將會用顏色展示承受的動能。如果網路超載則會癱瘓,必須減少機器或者增加動能", - - "item.create.sand_paper.tooltip": "紅砂紙", - "item.create.sand_paper.tooltip.summary": "用來_打磨_物品的砂紙,可以用_機械手_來實現自動化。", - "item.create.sand_paper.tooltip.condition1": "使用時", - "item.create.sand_paper.tooltip.behaviour1": "打磨_副手_上或者_準心所指_的物品。", - - "item.create.super_glue.tooltip": "強力膠", - "item.create.super_glue.tooltip.summary": "讓兩個方塊互相_粘黏_,他們會一直因此相愛到永遠", - "item.create.super_glue.tooltip.condition1": "右鍵使用時", - "item.create.super_glue.tooltip.behaviour1": "有強力膠的方塊的_那一面_會變得有粘性。和此面相鄰的方塊在被_機械活塞_或者_機械軸承_等方塊驅動的時候會被一同帶動", - "item.create.super_glue.tooltip.condition2": "在副手上時", - "item.create.super_glue.tooltip.behaviour2": "主手放置的方塊會被_直接_黏在所放置的方塊上", - - "item.create.builders_tea.tooltip": "建造工茶飲", - "item.create.builders_tea.tooltip.summary": "神清氣爽的一天,從這杯完美茶飲開始。恢復復_饑餓值_並獲得_加速_效果。", - - "item.create.refined_radiance.tooltip": "光輝石", - "item.create.refined_radiance.tooltip.summary": "一種用_光輝_鍛造的化合物材料。", - - "item.create.shadow_steel.tooltip": "暗影鋼", - "item.create.shadow_steel.tooltip.summary": "一種用_虛空_鍛造的化合物材料。", - - "item.create.minecart_coupling.tooltip": "礦車連軸器", - "item.create.minecart_coupling.tooltip.summary": "將多個_礦車_或運輸結構鏈接在一起,構成雄偉的火車。", - "item.create.minecart_coupling.tooltip.condition1": "作用與礦車時", - "item.create.minecart_coupling.tooltip.behaviour1": "將兩個礦車耦合在一起,在移動時將它們保持_恒定的距離_。", - - "item.create.crafter_slot_cover.tooltip": "合成器蓋板", - "item.create.crafter_slot_cover.tooltip.summary": "用來標記_機械合成器_以不放入物品。在制造與桶類似的斜向合成表時非常有用。", - - "create.tooltip.wip": "半成品", - "create.tooltip.workInProgress": "尚在製作中!", - "create.tooltip.randomWipDescription0": "禁止將此物品給兒童。", - "create.tooltip.randomWipDescription1": "每~一~次~你使用此物品時,就會使一隻小熊貓死亡。", - "create.tooltip.randomWipDescription2": "使用此物請自負後果。", - "create.tooltip.randomWipDescription3": "快走開,這不是你要找的東西(搖手指", - "create.tooltip.randomWipDescription4": "啟動自爆模式,10、9、8...。", - "create.tooltip.randomWipDescription5": "你已經沒有退路了。", - "create.tooltip.randomWipDescription6": "作者我將不負任何你使用此物所造成的責任。", - "create.tooltip.randomWipDescription7": "這東西不是給你用的,再找找吧!", - "create.tooltip.randomWipDescription8": "用了就死定了。", - - "_": "Thank you for translating Create!" - -} +{ + "_": "for create 0.3.1c", + + "_": "->------------------------] Game Elements [------------------------<-", + + "block.create.acacia_window": "相思木窗戶", + "block.create.acacia_window_pane": "相思木窗戶片", + "block.create.adjustable_chain_gearshift": "可調式鏈式變速箱", + "block.create.adjustable_crate": "可調式板條箱", + "block.create.adjustable_pulse_repeater": "可調式脈衝中繼器", + "block.create.adjustable_repeater": "可調式中繼器", + "block.create.analog_lever": "可調式拉桿", + "block.create.andesite_belt_funnel": "安山岩輸送帶漏斗", + "block.create.andesite_bricks": "安山岩磚", + "block.create.andesite_bricks_slab": "安山岩半磚", + "block.create.andesite_bricks_stairs": "安山岩樓梯", + "block.create.andesite_bricks_wall": "安山岩牆", + "block.create.andesite_casing": "安山岩機殼", + "block.create.andesite_cobblestone": "碎安山岩", + "block.create.andesite_cobblestone_slab": "碎安山岩半磚", + "block.create.andesite_cobblestone_stairs": "碎安山岩樓梯", + "block.create.andesite_cobblestone_wall": "碎安山岩牆", + "block.create.andesite_encased_shaft": "安山傳動軸箱", + "block.create.andesite_funnel": "安山岩漏斗", + "block.create.andesite_pillar": "豎紋安山岩", + "block.create.andesite_tunnel": "安山岩物品隧道", + "block.create.basin": "作業盆", + "block.create.belt": "輸送帶", + "block.create.birch_window": "白樺木窗戶", + "block.create.birch_window_pane": "白樺木窗戶片", + "block.create.black_sail": "黑色風帆", + "block.create.black_seat": "黑色坐墊", + "block.create.black_valve_handle": "黑色閥門開關", + "block.create.blaze_burner": "烈焰使者動力爐", + "block.create.blue_sail": "藍色風帆", + "block.create.blue_seat": "藍色坐墊", + "block.create.blue_valve_handle": "藍色閥門開關", + "block.create.brass_belt_funnel": "黃銅輸送帶漏斗", + "block.create.brass_block": "黃銅磚", + "block.create.brass_casing": "黃銅機殼", + "block.create.brass_encased_shaft": "黃銅傳動軸箱", + "block.create.brass_funnel": "黃銅漏斗", + "block.create.brass_tunnel": "黃銅物品隧道", + "block.create.brown_sail": "棕色風帆", + "block.create.brown_seat": "棕色坐墊", + "block.create.brown_valve_handle": "棕色閥門開關", + "block.create.cart_assembler": "礦車裝修站", + "block.create.chiseled_dark_scoria": "鏨製黑火成岩", + "block.create.chiseled_dolomite": "鏨製白雲石", + "block.create.chiseled_gabbro": "鏨製輝長岩", + "block.create.chiseled_limestone": "鏨製石灰岩", + "block.create.chiseled_scoria": "鏨製火成岩", + "block.create.chiseled_weathered_limestone": "鏨製風化石灰岩", + "block.create.chocolate": "巧克力", + "block.create.chute": "滑道", + "block.create.clockwork_bearing": "時鐘軸承", + "block.create.clutch": "離合器", + "block.create.cogwheel": "齒輪", + "block.create.content_observer": "物品偵測器", + "block.create.controller_rail": "控制鐵軌", + "block.create.copper_block": "銅磚", + "block.create.copper_casing": "銅機殼", + "block.create.copper_ore": "銅礦石", + "block.create.copper_shingles": "塊狀銅磚", + "block.create.copper_tiles": "菱形銅磚", + "block.create.copper_valve_handle": "銅製閥門開關", + "block.create.creative_crate": "創造板條箱", + "block.create.creative_fluid_tank": "創造液體儲存罐", + "block.create.creative_motor": "創造馬達", + "block.create.crimson_window": "赤紅窗戶", + "block.create.crimson_window_pane": "赤紅窗戶片", + "block.create.crushing_wheel": "粉碎輪", + "block.create.crushing_wheel_controller": "粉碎輪控制器", + "block.create.cuckoo_clock": "布穀鳥鐘", + "block.create.cyan_sail": "藍綠色風帆", + "block.create.cyan_seat": "藍綠色坐墊", + "block.create.cyan_valve_handle": "藍綠色閥門開關", + "block.create.dark_oak_window": "黑橡木窗戶", + "block.create.dark_oak_window_pane": "黑橡木窗戶片", + "block.create.dark_scoria": "黑火成岩", + "block.create.dark_scoria_bricks": "黑火成岩磚", + "block.create.dark_scoria_bricks_slab": "黑火成岩半磚", + "block.create.dark_scoria_bricks_stairs": "黑火成岩樓梯", + "block.create.dark_scoria_bricks_wall": "黑火成岩牆", + "block.create.dark_scoria_cobblestone": "黑火成岩碎石", + "block.create.dark_scoria_cobblestone_slab": "黑火成岩碎石半磚", + "block.create.dark_scoria_cobblestone_stairs": "黑火成岩碎石樓梯", + "block.create.dark_scoria_cobblestone_wall": "黑火成岩碎石牆", + "block.create.dark_scoria_pillar": "豎紋黑火成岩", + "block.create.deployer": "機器手", + "block.create.depot": "置物臺", + "block.create.diorite_bricks": "閃長岩磚", + "block.create.diorite_bricks_slab": "閃長岩半磚", + "block.create.diorite_bricks_stairs": "閃長岩樓梯", + "block.create.diorite_bricks_wall": "閃長岩牆", + "block.create.diorite_cobblestone": "碎閃長岩", + "block.create.diorite_cobblestone_slab": "碎閃長岩半磚", + "block.create.diorite_cobblestone_stairs": "碎閃長岩樓梯", + "block.create.diorite_cobblestone_wall": "碎閃長岩牆", + "block.create.diorite_pillar": "豎紋閃長岩", + "block.create.dolomite": "白雲石", + "block.create.dolomite_bricks": "白雲石磚", + "block.create.dolomite_bricks_slab": "白雲石半磚", + "block.create.dolomite_bricks_stairs": "白雲石樓梯", + "block.create.dolomite_bricks_wall": "白雲石牆", + "block.create.dolomite_cobblestone": "碎白雲石", + "block.create.dolomite_cobblestone_slab": "碎白雲石半磚", + "block.create.dolomite_cobblestone_stairs": "碎白雲石樓梯", + "block.create.dolomite_cobblestone_wall": "碎白雲石牆", + "block.create.dolomite_pillar": "豎紋白雲石", + "block.create.encased_chain_drive": "鏈式傳動箱", + "block.create.encased_fan": "鼓風機", + "block.create.encased_fluid_pipe": "液體管道箱", + "block.create.fancy_andesite_bricks": "方紋安山岩磚", + "block.create.fancy_andesite_bricks_slab": "方紋安山岩半磚", + "block.create.fancy_andesite_bricks_stairs": "方紋安山岩樓梯", + "block.create.fancy_andesite_bricks_wall": "方紋安山岩牆", + "block.create.fancy_dark_scoria_bricks": "方紋黑火成岩", + "block.create.fancy_dark_scoria_bricks_slab": "方紋黑火成岩半磚", + "block.create.fancy_dark_scoria_bricks_stairs": "方紋黑火成岩樓梯", + "block.create.fancy_dark_scoria_bricks_wall": "方紋黑火成岩牆", + "block.create.fancy_diorite_bricks": "方紋閃長岩", + "block.create.fancy_diorite_bricks_slab": "方紋閃長岩半磚", + "block.create.fancy_diorite_bricks_stairs": "方紋閃長岩樓梯", + "block.create.fancy_diorite_bricks_wall": "方紋閃長岩牆", + "block.create.fancy_dolomite_bricks": "方紋白雲石", + "block.create.fancy_dolomite_bricks_slab": "方紋白雲石半磚", + "block.create.fancy_dolomite_bricks_stairs": "方紋白雲石樓梯", + "block.create.fancy_dolomite_bricks_wall": "方紋白雲石牆", + "block.create.fancy_gabbro_bricks": "方紋輝長岩", + "block.create.fancy_gabbro_bricks_slab": "方紋輝長岩半磚", + "block.create.fancy_gabbro_bricks_stairs": "方紋輝長岩樓梯", + "block.create.fancy_gabbro_bricks_wall": "方紋輝長岩牆", + "block.create.fancy_granite_bricks": "方紋花崗岩", + "block.create.fancy_granite_bricks_slab": "方紋花崗岩半磚", + "block.create.fancy_granite_bricks_stairs": "方紋花崗岩樓梯", + "block.create.fancy_granite_bricks_wall": "方紋花崗岩牆", + "block.create.fancy_limestone_bricks": "方紋石灰岩", + "block.create.fancy_limestone_bricks_slab": "方紋石灰岩半磚", + "block.create.fancy_limestone_bricks_stairs": "方紋石灰岩樓梯", + "block.create.fancy_limestone_bricks_wall": "方紋石灰岩牆", + "block.create.fancy_scoria_bricks": "方紋火成岩", + "block.create.fancy_scoria_bricks_slab": "方紋火成岩半磚", + "block.create.fancy_scoria_bricks_stairs": "方紋火成岩樓梯", + "block.create.fancy_scoria_bricks_wall": "方紋火成岩牆", + "block.create.fancy_weathered_limestone_bricks": "方紋風化石灰岩", + "block.create.fancy_weathered_limestone_bricks_slab": "方紋風化石灰岩半磚", + "block.create.fancy_weathered_limestone_bricks_stairs": "方紋風化石灰岩樓梯", + "block.create.fancy_weathered_limestone_bricks_wall": "方紋風化石灰岩牆", + "block.create.fluid_pipe": "液體管道", + "block.create.fluid_tank": "液體儲存罐", + "block.create.fluid_valve": "液體閥門", + "block.create.flywheel": "飛輪", + "block.create.framed_glass": "邊框玻璃", + "block.create.framed_glass_pane": "邊框玻璃片", + "block.create.furnace_engine": "熔煉引擎", + "block.create.gabbro": "輝長岩", + "block.create.gabbro_bricks": "輝長岩磚", + "block.create.gabbro_bricks_slab": "輝長岩半磚", + "block.create.gabbro_bricks_stairs": "輝長岩樓梯", + "block.create.gabbro_bricks_wall": "輝長岩牆", + "block.create.gabbro_cobblestone": "碎輝長岩", + "block.create.gabbro_cobblestone_slab": "碎輝長岩半磚", + "block.create.gabbro_cobblestone_stairs": "碎輝長岩樓梯", + "block.create.gabbro_cobblestone_wall": "碎輝長岩牆", + "block.create.gabbro_pillar": "豎紋輝長岩", + "block.create.gantry_carriage": "門式起重機", + "block.create.gantry_shaft": "門式起重機滑道", + "block.create.gearbox": "齒輪箱", + "block.create.gearshift": "變速箱", + "block.create.glass_fluid_pipe": "玻璃液體管道", + "block.create.granite_bricks": "花崗岩", + "block.create.granite_bricks_slab": "花崗岩半磚", + "block.create.granite_bricks_stairs": "花崗岩樓梯", + "block.create.granite_bricks_wall": "花崗岩牆", + "block.create.granite_cobblestone": "碎花崗岩", + "block.create.granite_cobblestone_slab": "碎花崗岩半磚", + "block.create.granite_cobblestone_stairs": "碎花崗岩樓梯", + "block.create.granite_cobblestone_wall": "碎花崗岩牆", + "block.create.granite_pillar": "豎紋花崗岩", + "block.create.gray_sail": "灰色風帆", + "block.create.gray_seat": "灰色坐墊", + "block.create.gray_valve_handle": "灰色閥門開關", + "block.create.green_sail": "綠色風帆", + "block.create.green_seat": "綠色坐墊", + "block.create.green_valve_handle": "綠色閥門開關", + "block.create.hand_crank": "手搖把手", + "block.create.honey": "蜂蜜", + "block.create.horizontal_framed_glass": "豎直邊框玻璃", + "block.create.horizontal_framed_glass_pane": "豎直邊框玻璃片", + "block.create.hose_pulley": "軟管滑輪", + "block.create.item_drain": "分液池", + "block.create.jungle_window": "叢林木窗戶", + "block.create.jungle_window_pane": "叢林木窗戶片", + "block.create.large_cogwheel": "大齒輪", + "block.create.layered_andesite": "疊層安山岩", + "block.create.layered_dark_scoria": "疊層黑火成岩", + "block.create.layered_diorite": "疊層閃長岩", + "block.create.layered_dolomite": "疊層白雲石", + "block.create.layered_gabbro": "疊層輝長岩", + "block.create.layered_granite": "疊層花崗岩", + "block.create.layered_limestone": "疊層石灰岩", + "block.create.layered_scoria": "疊層火成岩", + "block.create.layered_weathered_limestone": "疊層風化石灰岩", + "block.create.light_blue_sail": "淡藍色風帆", + "block.create.light_blue_seat": "淡藍色坐墊", + "block.create.light_blue_valve_handle": "淡藍色閥門開關", + "block.create.light_gray_sail": "淡灰色風帆", + "block.create.light_gray_seat": "淡灰色坐墊", + "block.create.light_gray_valve_handle": "淡灰色閥門開關", + "block.create.lime_sail": "黃綠色風帆", + "block.create.lime_seat": "黃綠色坐墊", + "block.create.lime_valve_handle": "黃綠色閥門開關", + "block.create.limesand": "石灰沙", + "block.create.limestone": "石灰岩", + "block.create.limestone_bricks": "石灰岩", + "block.create.limestone_bricks_slab": "石灰岩半磚", + "block.create.limestone_bricks_stairs": "石灰岩樓梯", + "block.create.limestone_bricks_wall": "石灰岩牆", + "block.create.limestone_cobblestone": "碎石灰岩", + "block.create.limestone_cobblestone_slab": "碎石灰岩半磚", + "block.create.limestone_cobblestone_stairs": "碎石灰岩樓梯", + "block.create.limestone_cobblestone_wall": "碎石灰岩牆", + "block.create.limestone_pillar": "豎紋石灰岩", + "block.create.linear_chassis": "機殼底盤", + "block.create.lit_blaze_burner": "烈焰使者動力爐(已啟動)", + "block.create.magenta_sail": "洋紅色風帆", + "block.create.magenta_seat": "洋紅色坐墊", + "block.create.magenta_valve_handle": "洋紅色閥門開關", + "block.create.mechanical_arm": "機械手臂", + "block.create.mechanical_bearing": "機械軸承", + "block.create.mechanical_crafter": "機械合成器", + "block.create.mechanical_drill": "機械鑽頭", + "block.create.mechanical_harvester": "機械收割機", + "block.create.mechanical_mixer": "機械攪拌器", + "block.create.mechanical_piston": "機械活塞", + "block.create.mechanical_piston_head": "機械活塞頭", + "block.create.mechanical_plough": "機械犁", + "block.create.mechanical_press": "機械液壓機", + "block.create.mechanical_pump": "機械幫浦", + "block.create.mechanical_saw": "機械切割機", + "block.create.metal_bracket": "金屬支架", + "block.create.millstone": "石磨", + "block.create.minecart_anchor": "礦車錨", + "block.create.mossy_andesite": "青苔安山岩", + "block.create.mossy_dark_scoria": "青苔黑火成岩", + "block.create.mossy_diorite": "青苔閃長岩", + "block.create.mossy_dolomite": "青苔白雲石", + "block.create.mossy_gabbro": "青苔輝長岩", + "block.create.mossy_granite": "青苔花崗岩", + "block.create.mossy_limestone": "青苔石灰岩", + "block.create.mossy_scoria": "青苔火成岩", + "block.create.mossy_weathered_limestone": "青苔風化石灰岩", + "block.create.mysterious_cuckoo_clock": "神秘布穀鳥鐘", + "block.create.natural_scoria": "天然火成岩", + "block.create.nixie_tube": "真空管顯示器", + "block.create.nozzle": "鼓風機噴嘴", + "block.create.oak_window": "橡木窗戶", + "block.create.oak_window_pane": "橡木窗戶片", + "block.create.orange_sail": "橙色風帆", + "block.create.orange_seat": "橙色坐墊", + "block.create.orange_valve_handle": "橙色閥門開關", + "block.create.ornate_iron_window": "華麗鐵窗戶", + "block.create.ornate_iron_window_pane": "華麗鐵窗戶片", + "block.create.overgrown_andesite": "長草的安山岩", + "block.create.overgrown_dark_scoria": "長草的黑火成岩", + "block.create.overgrown_diorite": "長草的閃長岩", + "block.create.overgrown_dolomite": "長草的白雲石", + "block.create.overgrown_gabbro": "長草的輝長岩", + "block.create.overgrown_granite": "長草的花崗岩", + "block.create.overgrown_limestone": "長草的石灰岩", + "block.create.overgrown_scoria": "長草的火成岩", + "block.create.overgrown_weathered_limestone": "長草的風化石灰岩", + "block.create.paved_andesite": "安山岩鋪路石", + "block.create.paved_andesite_slab": "安山岩鋪路石半磚", + "block.create.paved_andesite_stairs": "安山岩鋪路石樓梯", + "block.create.paved_andesite_wall": "安山岩鋪路石牆", + "block.create.paved_dark_scoria": "黑火成岩鋪路石", + "block.create.paved_dark_scoria_slab": "黑火成岩鋪路石半磚", + "block.create.paved_dark_scoria_stairs": "黑火成岩鋪路石樓梯", + "block.create.paved_dark_scoria_wall": "黑火成岩鋪路石牆", + "block.create.paved_diorite": "閃長岩鋪路石", + "block.create.paved_diorite_slab": "閃長岩鋪路石半磚", + "block.create.paved_diorite_stairs": "閃長岩鋪路石樓梯", + "block.create.paved_diorite_wall": "閃長岩鋪路石牆", + "block.create.paved_dolomite": "白雲石鋪路石", + "block.create.paved_dolomite_slab": "白雲石鋪路石半磚", + "block.create.paved_dolomite_stairs": "白雲石鋪路石樓梯", + "block.create.paved_dolomite_wall": "白雲石鋪路石牆", + "block.create.paved_gabbro": "輝長岩鋪路石", + "block.create.paved_gabbro_slab": "輝長岩鋪路石半磚", + "block.create.paved_gabbro_stairs": "輝長岩鋪路石樓梯", + "block.create.paved_gabbro_wall": "輝長岩鋪路石牆", + "block.create.paved_granite": "花崗岩鋪路石", + "block.create.paved_granite_slab": "花崗岩鋪路石半磚", + "block.create.paved_granite_stairs": "花崗岩鋪路石樓梯", + "block.create.paved_granite_wall": "花崗岩鋪路石牆", + "block.create.paved_limestone": "石灰岩鋪路石", + "block.create.paved_limestone_slab": "石灰岩鋪路石半磚", + "block.create.paved_limestone_stairs": "石灰岩鋪路石樓梯", + "block.create.paved_limestone_wall": "石灰岩鋪路石牆", + "block.create.paved_scoria": "火成岩鋪路石", + "block.create.paved_scoria_slab": "火成岩鋪路石半磚", + "block.create.paved_scoria_stairs": "火成岩鋪路石樓梯", + "block.create.paved_scoria_wall": "火成岩鋪路石牆", + "block.create.paved_weathered_limestone": "風化石灰岩鋪路石", + "block.create.paved_weathered_limestone_slab": "風化石灰岩鋪路石半磚", + "block.create.paved_weathered_limestone_stairs": "風化石灰岩鋪路石樓梯", + "block.create.paved_weathered_limestone_wall": "風化石灰岩鋪路石牆", + "block.create.pink_sail": "粉紅色風帆", + "block.create.pink_seat": "粉紅色坐墊", + "block.create.pink_valve_handle": "粉紅色閥門開關", + "block.create.piston_extension_pole": "活塞桿", + "block.create.polished_dark_scoria": "磨製黑火成岩", + "block.create.polished_dark_scoria_slab": "磨製黑火成岩半磚", + "block.create.polished_dark_scoria_stairs": "磨製黑火成岩樓梯", + "block.create.polished_dark_scoria_wall": "磨製黑火成岩牆", + "block.create.polished_dolomite": "磨製白雲石", + "block.create.polished_dolomite_slab": "磨製白雲石半磚", + "block.create.polished_dolomite_stairs": "磨製白雲石樓梯", + "block.create.polished_dolomite_wall": "磨製白雲石牆", + "block.create.polished_gabbro": "磨製輝長岩", + "block.create.polished_gabbro_slab": "磨製輝長岩半磚", + "block.create.polished_gabbro_stairs": "磨製輝長岩樓梯", + "block.create.polished_gabbro_wall": "磨製輝長岩牆", + "block.create.polished_limestone": "磨製石灰岩", + "block.create.polished_limestone_slab": "磨製石灰岩半磚", + "block.create.polished_limestone_stairs": "磨製石灰岩樓梯", + "block.create.polished_limestone_wall": "磨製石灰岩牆", + "block.create.polished_scoria": "磨製火成岩", + "block.create.polished_scoria_slab": "磨製火成岩半磚", + "block.create.polished_scoria_stairs": "磨製火成岩樓梯", + "block.create.polished_scoria_wall": "磨製火成岩牆", + "block.create.polished_weathered_limestone": "磨製風化石灰岩", + "block.create.polished_weathered_limestone_slab": "磨製風化石灰岩半磚", + "block.create.polished_weathered_limestone_stairs": "磨製風化石灰岩樓梯", + "block.create.polished_weathered_limestone_wall": "磨製風化石灰岩牆", + "block.create.portable_fluid_interface": "移動式液體口", + "block.create.portable_storage_interface": "移動式物品口", + "block.create.powered_latch": "閂鎖器", + "block.create.powered_toggle_latch": "T型正反器", + "block.create.pulley_magnet": "滑輪磁鐵", + "block.create.pulse_repeater": "脈衝中繼器", + "block.create.purple_sail": "紫色風帆", + "block.create.purple_seat": "紫色坐墊", + "block.create.purple_valve_handle": "紫色閥門開關", + "block.create.radial_chassis": "旋轉底盤", + "block.create.red_sail": "紅色風帆", + "block.create.red_seat": "紅色坐墊", + "block.create.red_valve_handle": "紅色閥門開關", + "block.create.redstone_contact": "接觸式紅石訊號產生器", + "block.create.redstone_link": "無限紅石訊號機", + "block.create.refined_radiance_casing": "光輝機殼", + "block.create.reinforced_rail": "強化鐵軌", + "block.create.rope": "繩索", + "block.create.rope_pulley": "滑輪繩索", + "block.create.rotation_speed_controller": "轉速控制器", + "block.create.sail_frame": "風帆框架", + "block.create.schematic_table": "藍圖桌", + "block.create.schematicannon": "藍圖加農炮", + "block.create.scoria": "火成岩", + "block.create.scoria_bricks": "火成岩磚", + "block.create.scoria_bricks_slab": "火成岩半磚", + "block.create.scoria_bricks_stairs": "火成岩樓梯", + "block.create.scoria_bricks_wall": "火成岩牆", + "block.create.scoria_cobblestone": "碎火成岩", + "block.create.scoria_cobblestone_slab": "碎火成岩半磚", + "block.create.scoria_cobblestone_stairs": "碎火成岩樓梯", + "block.create.scoria_cobblestone_wall": "碎火成岩牆", + "block.create.scoria_pillar": "豎紋火成岩", + "block.create.secondary_linear_chassis": "機殼底盤2號", + "block.create.sequenced_gearshift": "可程式化齒輪箱", + "block.create.shadow_steel_casing": "暗影機殼", + "block.create.shaft": "傳動軸", + "block.create.smart_chute": "智慧滑道", + "block.create.smart_fluid_pipe": "智慧液體管道", + "block.create.speedometer": "速度計", + "block.create.spout": "液體灌注器", + "block.create.spruce_window": "雲杉木窗戶", + "block.create.spruce_window_pane": "雲杉木窗戶片", + "block.create.sticker": "方塊黏著器", + "block.create.sticky_mechanical_piston": "黏性機械活塞", + "block.create.stockpile_switch": "存量偵測器", + "block.create.stressometer": "動能錶", + "block.create.tiled_glass": "十字玻璃窗", + "block.create.tiled_glass_pane": "十字玻璃窗戶片", + "block.create.turntable": "轉盤", + "block.create.vertical_framed_glass": "豎直邊框玻璃", + "block.create.vertical_framed_glass_pane": "豎直邊框玻璃片", + "block.create.warped_window": "扭曲蕈木窗戶", + "block.create.warped_window_pane": "扭曲蕈木窗戶片", + "block.create.water_wheel": "水車", + "block.create.weathered_limestone": "風化石灰岩", + "block.create.weathered_limestone_bricks": "風化石灰岩磚", + "block.create.weathered_limestone_bricks_slab": "風化石灰岩半磚", + "block.create.weathered_limestone_bricks_stairs": "風化石灰岩樓梯", + "block.create.weathered_limestone_bricks_wall": "風化石灰岩牆", + "block.create.weathered_limestone_cobblestone": "碎風化石灰岩", + "block.create.weathered_limestone_cobblestone_slab": "碎風化石灰岩半磚", + "block.create.weathered_limestone_cobblestone_stairs": "碎風化石灰岩樓梯", + "block.create.weathered_limestone_cobblestone_wall": "碎風化石灰岩牆", + "block.create.weathered_limestone_pillar": "豎紋風化石灰岩", + "block.create.weighted_ejector": "物品彈射器", + "block.create.white_sail": "白色風帆", + "block.create.white_seat": "白色坐墊", + "block.create.white_valve_handle": "白色閥門開關", + "block.create.windmill_bearing": "風車軸承", + "block.create.wooden_bracket": "木製支架", + "block.create.yellow_sail": "黃色風帆", + "block.create.yellow_seat": "黃色坐墊", + "block.create.yellow_valve_handle": "黃色閥門開關", + "block.create.zinc_block": "鋅磚", + "block.create.zinc_ore": "鋅礦石", + + "entity.create.contraption": "結構", + "entity.create.gantry_contraption": "門式結構", + "entity.create.seat": "坐墊", + "entity.create.stationary_contraption": "固定結構", + "entity.create.super_glue": "強力膠", + + "fluid.create.milk": "牛奶", + "fluid.create.potion": "藥水", + "fluid.create.tea": "茶", + + "item.create.andesite_alloy": "安山合金", + "item.create.attribute_filter": "屬性過濾器", + "item.create.bar_of_chocolate": "巧克力棒", + "item.create.belt_connector": "輸送帶", + "item.create.blaze_cake": "熔岩蛋糕", + "item.create.blaze_cake_base": "熔岩蛋糕胚", + "item.create.brass_hand": "黃銅手部零件", + "item.create.brass_ingot": "黃銅錠", + "item.create.brass_nugget": "黃銅粒", + "item.create.brass_sheet": "黃銅板", + "item.create.builders_tea": "工人茶", + "item.create.chest_minecart_contraption": "裝修過的機械礦車", + "item.create.chocolate_bucket": "巧克力桶", + "item.create.chocolate_glazed_berries": "巧克力甜莓", + "item.create.chromatic_compound": "異彩化合物", + "item.create.cinder_flour": "地獄麵粉", + "item.create.copper_ingot": "銅錠", + "item.create.copper_nugget": "銅粒", + "item.create.copper_sheet": "銅板", + "item.create.crafter_slot_cover": "合成器蓋板", + "item.create.crushed_aluminum_ore": "碎狀鋁礦石", + "item.create.crushed_brass": "碎狀黃銅", + "item.create.crushed_copper_ore": "碎狀銅礦石", + "item.create.crushed_gold_ore": "碎狀金礦石", + "item.create.crushed_iron_ore": "碎狀鐵礦石", + "item.create.crushed_lead_ore": "碎狀鉛礦石", + "item.create.crushed_nickel_ore": "碎狀鎳礦石", + "item.create.crushed_osmium_ore": "碎狀鋨礦石", + "item.create.crushed_platinum_ore": "碎狀白金礦石", + "item.create.crushed_quicksilver_ore": "碎狀水銀礦石", + "item.create.crushed_silver_ore": "碎狀銀礦石", + "item.create.crushed_tin_ore": "碎狀錫礦石", + "item.create.crushed_uranium_ore": "碎狀鈾礦石", + "item.create.crushed_zinc_ore": "碎狀鋅礦石", + "item.create.deforester": "連根拔樹斧", + "item.create.dough": "麵團", + "item.create.electron_tube": "真空管", + "item.create.empty_blaze_burner": "空的烈焰使者動力爐", + "item.create.empty_schematic": "空白藍圖", + "item.create.extendo_grip": "伸縮機械手", + "item.create.filter": "過濾器", + "item.create.furnace_minecart_contraption": "裝配過的機械礦車", + "item.create.goggles": "MR護目鏡", + "item.create.golden_sheet": "金板", + "item.create.handheld_blockzapper": "方塊放置器", + "item.create.handheld_worldshaper": "地形雕塑器", + "item.create.honey_bucket": "蜂蜜桶", + "item.create.honeyed_apple": "蜂蜜蘋果", + "item.create.integrated_circuit": "IC板", + "item.create.iron_sheet": "鐵板", + "item.create.lapis_sheet": "青金石板", + "item.create.minecart_contraption": "裝修過的礦車", + "item.create.minecart_coupling": "礦車連結器", + "item.create.polished_rose_quartz": "磨製玫瑰石英", + "item.create.powdered_obsidian": "黑曜石粉末", + "item.create.propeller": "扇葉", + "item.create.red_sand_paper": "紅砂紙", + "item.create.refined_radiance": "光輝石", + "item.create.rose_quartz": "玫瑰石英", + "item.create.sand_paper": "砂紙", + "item.create.schematic": "藍圖", + "item.create.schematic_and_quill": "藍圖與筆", + "item.create.shadow_steel": "暗影鋼", + "item.create.super_glue": "強力膠", + "item.create.sweet_roll": "甜捲捲", + "item.create.tree_fertilizer": "樹木肥料", + "item.create.vertical_gearbox": "豎直齒輪箱", + "item.create.wand_of_symmetry": "對稱杖", + "item.create.wheat_flour": "小麥粉", + "item.create.whisk": "攪拌器", + "item.create.wrench": "扳手", + "item.create.zinc_ingot": "鋅錠", + "item.create.zinc_nugget": "鋅粒", + + + "_": "->------------------------] Advancements [------------------------<-", + + "advancement.create.root": "感謝你安裝機械動力模組,強烈建議您安裝JEI配合本模組遊玩", + "advancement.create.root.desc": "該來製作一些超棒的機械結構了!", + "advancement.create.andesite_alloy": "原始人類的合金替代品", + "advancement.create.andesite_alloy.desc": "機械動力有著許多的材料和合金,但受限於技術,原始的人類們暫時只能製作出安山合金", + "advancement.create.its_alive": "鮮活的機械生命", + "advancement.create.its_alive.desc": "首次使齒輪結構的旋轉。", + "advancement.create.shifting_gears": "換檔,加速,起飛!", + "advancement.create.shifting_gears.desc": "將大齒輪連接到小齒輪上,機械結構的轉速將會翻倍", + "advancement.create.overstressed": "過載", + "advancement.create.overstressed.desc": "首次使動能網路過載。", + "advancement.create.belt": "流水線作業", + "advancement.create.belt.desc": "用輸送帶連接兩個傳動軸", + "advancement.create.tunnel": "尋找掩護!", + "advancement.create.tunnel.desc": "在輸送帶上放上物品隧道。", + "advancement.create.splitter_tunnel": "分而治之", + "advancement.create.splitter_tunnel.desc": "用黃銅物品隧道設計一個分流器。", + "advancement.create.chute": "轟然倒塌", + "advancement.create.chute.desc": "放置一個滑道(垂直版本的輸送帶)。", + "advancement.create.upward_chute": "空中攔截", + "advancement.create.upward_chute.desc": "目睹拋出的物品飛入裝有風扇的滑道。", + "advancement.create.belt_funnel": "漏斗的垂簾", + "advancement.create.belt_funnel.desc": "將側向漏斗放在輸送帶或置物臺的上方。", + "advancement.create.belt_funnel_kiss": "比翼雙飛", + "advancement.create.belt_funnel_kiss.desc": "使兩個安裝在輸送帶上的漏斗相連。", + "advancement.create.fan": "機械氣槍", + "advancement.create.fan.desc": "飄浮在鼓風機吹出的氣流上", + "advancement.create.fan_lava": "空間加熱器", + "advancement.create.fan_lava.desc": "感受熔煉物品的氣流。", + "advancement.create.fan_water": "奇怪的洗滌", + "advancement.create.fan_water.desc": "被洗滌的氣流所吸引。", + "advancement.create.fan_smoke": "機械波紋管", + "advancement.create.fan_smoke.desc": "感受煙燻氣流。", + "advancement.create.wrench": "細部調整", + "advancement.create.wrench.desc": "做出一個方便調整方塊的板手", + "advancement.create.goggles": "動能,一目了然", + "advancement.create.goggles.desc": "做出一個能看到機械動能訊息的MR護目鏡", + "advancement.create.speedometer": "精密的速度控制", + "advancement.create.speedometer.desc": "放置一個速度計,並且戴上MR護目鏡來讀取數據", + "advancement.create.stressometer": "精密的動能控制", + "advancement.create.stressometer.desc": "放置一個動能錶,並且戴上MR護目鏡來讀取數據", + "advancement.create.aesthetics": "繁榮與美學!", + "advancement.create.aesthetics.desc": "將支架放在傳動軸,管道和齒輪上。", + "advancement.create.reinforced": "超級加固!", + "advancement.create.reinforced.desc": "在傳動軸,管道和輸送帶上使用機殼加固。", + "advancement.create.water_wheel": "治水", + "advancement.create.water_wheel.desc": "放置一個水車並讓它開始旋轉", + "advancement.create.chocolate_wheel": "美味的動能源", + "advancement.create.chocolate_wheel.desc": "用融化的巧克力驅動水車。", + "advancement.create.lava_wheel": "風火輪", + "advancement.create.lava_wheel.desc": "它不應該有用的..。", + "advancement.create.cuckoo": "是時候了?", + "advancement.create.cuckoo.desc": "目睹布穀鳥鐘報就寢時間。", + "advancement.create.millstone": "攜帶式粉碎機", + "advancement.create.millstone.desc": "放置一個石磨並且為其供能", + "advancement.create.windmill": "微風拂過", + "advancement.create.windmill.desc": "組裝風車。", + "advancement.create.maxed_windmill": "強風襲來", + "advancement.create.maxed_windmill.desc": "組裝最大動能的風車。", + "advancement.create.andesite_casing": "安山時代", + "advancement.create.andesite_casing.desc": "使用安山合金和木頭來合成一個安山機殼", + "advancement.create.mechanical_drill": "堅若磐石", + "advancement.create.mechanical_drill.desc": "放置一個機械鑽頭並且為其供能", + "advancement.create.press": "'噹!'", + "advancement.create.press.desc": "使用液壓機來壓製一些板子", + "advancement.create.polished_rose_quartz": "粉紅鑽石", + "advancement.create.polished_rose_quartz.desc": "用砂紙將玫瑰石英磨至透明", + "advancement.create.electron_tube": "嗶~~嗶~~", + "advancement.create.electron_tube.desc": "製作一個可用來合成高級機器的真空管", + "advancement.create.mechanical_saw": "一刀兩斷", + "advancement.create.mechanical_saw.desc": "放置一個切割機並且為其供能", + "advancement.create.basin": "快到碗裡來", + "advancement.create.basin.desc": "放置一個作業盆,並且往裡面放些東西", + "advancement.create.mixer": "充分攪拌", + "advancement.create.mixer.desc": "將攪拌機放在作業盆上方,並且使其攪拌盆內的物品", + "advancement.create.blaze_burner": "活生生的壁爐", + "advancement.create.blaze_burner.desc": "獲得一個烈焰使者動力爐。", + "advancement.create.compact": "快樂壓縮", + "advancement.create.compact.desc": "使用液壓機在作業盆中壓製一些物品", + "advancement.create.brass": "真正的合金", + "advancement.create.brass.desc": "使用粉碎鋅礦石和粉碎銅礦石來製作粉碎黃銅", + "advancement.create.brass_casing": "黃銅時代", + "advancement.create.brass_casing.desc": "用黃銅和木頭製作一個黃銅機殼", + "advancement.create.copper_casing": "銅時代", + "advancement.create.copper_casing.desc": "使用銅和木頭製作一個銅製機殼", + "advancement.create.spout": "裝填!", + "advancement.create.spout.desc": "觀察注液器灌滿物品。", + "advancement.create.spout_potion": "國際級啤酒大廠", + "advancement.create.spout_potion.desc": "觀察注液器注入藥水到玻璃瓶。", + "advancement.create.chocolate": "夢裡的世界", + "advancement.create.chocolate.desc": "獲取一桶熔融巧克力。", + "advancement.create.item_drain": "滾筒洗衣機", + "advancement.create.item_drain.desc": "觀察液體物品被分液池抽空。", + "advancement.create.chained_item_drain": "讓我們一起搖滾!", + "advancement.create.chained_item_drain.desc": "看著物品穿過多個分液池。", + "advancement.create.glass_pipe": "偷窺液體", + "advancement.create.glass_pipe.desc": "透過窗戶觀察液體在管道中流動。使用板手可打開直線液體管道的窗戶。", + "advancement.create.pipe_collision": "永不交會的溪流!", + "advancement.create.pipe_collision.desc": "觀察兩種液體在您的管道中會合", + "advancement.create.pipe_spill": "漏水啦!", + "advancement.create.pipe_spill.desc": "觀察管道的末端將液體排放到到外面。", + "advancement.create.hose_pulley": "工業排放", + "advancement.create.hose_pulley.desc": "放下一個軟管滑輪,觀察它排乾或充滿液體。", + "advancement.create.infinite_water": "抽取海洋", + "advancement.create.infinite_water.desc": "從足以被認為是無限的水源中抽水。", + "advancement.create.infinite_lava": "吸取行星的核心", + "advancement.create.infinite_lava.desc": "從廣闊的岩漿湖中抽出岩漿。", + "advancement.create.infinite_chocolate": "淹沒在幻想中", + "advancement.create.infinite_chocolate.desc": "從廣闊的巧克力海中抽出巧克力。", + "advancement.create.crafter": "自動化流水作業", + "advancement.create.crafter.desc": "放置一些機械合成臺並且為其供能", + "advancement.create.clockwork_bearing": "時差", + "advancement.create.clockwork_bearing.desc": "組裝安裝在發條軸承上的結構。", + "advancement.create.nixie_tube": "風格的跡象", + "advancement.create.nixie_tube.desc": "獲得真空管顯示器並放置。", + "advancement.create.deployer": "指爽沒?", + "advancement.create.deployer.desc": "放置並且啟動一個機械手。這可是你右手完美的複製品", + "advancement.create.speed_controller": "攻城屍討厭他!", + "advancement.create.speed_controller.desc": "放置一個轉速控制器,這是換檔的終極裝置。", + "advancement.create.flywheel": "工廠之心", + "advancement.create.flywheel.desc": "將引擎成功連接到飛輪。", + "advancement.create.overstress_flywheel": "壓力過大", + "advancement.create.overstress_flywheel.desc": "超載熔爐引擎。", + "advancement.create.integrated_circuit": "複雜的運算", + "advancement.create.integrated_circuit.desc": "合成IC板。", + "advancement.create.mechanical_arm": "忙碌的手!", + "advancement.create.mechanical_arm.desc": "製作機械手臂,選擇輸入和輸出,放置並給它動能; 然後看著它完成所有你交代的工作。", + "advancement.create.musical_arm": "沒人能在我的BGM裡打敗我!", + "advancement.create.musical_arm.desc": "使用機械手臂播放唱片。", + "advancement.create.arm_many_targets": "你是要累死我?", + "advancement.create.arm_many_targets.desc": "配置一隻有十個或更多輸出位置的機械手臂。", + "advancement.create.arm_blaze_burner": "燃燒吧!烈焰使者!", + "advancement.create.arm_blaze_burner.desc": "指揮機械手臂給烈焰使者動力爐投食。", + "advancement.create.fist_bump": "朋友,來擊拳", + "advancement.create.fist_bump.desc": "使兩個機械手互相碰拳", + "advancement.create.crushing_wheel": "一對大傢伙", + "advancement.create.crushing_wheel.desc": "製作一對能更快粉碎物品的粉碎輪", + "advancement.create.blaze_cake": "糖份超標", + "advancement.create.blaze_cake.desc": "幫烈焰使者動力爐烤一份特別的蛋糕。", + "advancement.create.chromatic_compound": "兩極材料", + "advancement.create.chromatic_compound.desc": "製作一個異彩化合物", + "advancement.create.shadow_steel": "自虛空的歸來的寶石", + "advancement.create.shadow_steel.desc": "製作暗影鋼", + "advancement.create.refined_radiance": "閃耀著純白的聖光", + "advancement.create.refined_radiance.desc": "製作光輝石", + "advancement.create.chromatic_age": "繽紛時代", + "advancement.create.chromatic_age.desc": "創造出光與影的機殼。", + "advancement.create.zapper": "專業的建築師", + "advancement.create.zapper.desc": "製作一個非常方便的方塊放置器", + "advancement.create.upgraded_zapper": "來自異世界的超頻", + "advancement.create.upgraded_zapper.desc": "製作一個完全升級的方塊放置器", + "advancement.create.wand_of_symmetry": "簡單的鏡面幾何學", + "advancement.create.wand_of_symmetry.desc": "製作一個對稱杖", + "advancement.create.deforester": "超時空砍伐", + "advancement.create.deforester.desc": "製作一個連根拔樹斧,然後跟你後院的樹林道別吧", + "advancement.create.extendo_grip": "piu piu piu!", + "advancement.create.extendo_grip.desc": "拿到一個伸縮機械手", + "advancement.create.dual_extendo_grip": "piu——piu——piu——", + "advancement.create.dual_extendo_grip.desc": "雙持伸縮機械手進一步加長觸碰距離", + "advancement.create.eob": "Beta版結束", + "advancement.create.eob.desc": "期待日後的更新。", + + + "_": "->------------------------] UI & Messages [------------------------<-", + + "itemGroup.create.base": "動力機械", + "itemGroup.create.palettes": "動力機械建築與裝飾方塊", + + "death.attack.create.crush": "%1$s被壓扁了", + "death.attack.create.fan_fire": "%1$s想接受熱風的洗禮", + "death.attack.create.fan_lava": "%1$s想接受熱風的洗禮但走火入魔", + "death.attack.create.mechanical_drill": "%1$s被鑽頭鑽爆腦袋", + "death.attack.create.mechanical_saw": "%1$s被鋸切成了兩半", + "death.attack.create.cuckoo_clock_explosion": "%1$s 被布穀鳥鐘炸得粉身碎骨", + + "create.block.deployer.damage_source_name": "機械手", + "create.block.cart_assembler.invalid": "將您的礦車裝修站放在鐵軌上", + + "create.recipe.crushing": "粉碎", + "create.recipe.milling": "研磨", + "create.recipe.fan_washing": "批次洗滌", + "create.recipe.fan_washing.fan": "在水後放置鼓風機", + "create.recipe.fan_smoking": "批次煙燻", + "create.recipe.fan_smoking.fan": "在火焰後放置鼓風機", + "create.recipe.fan_blasting": "批次融煉", + "create.recipe.fan_blasting.fan": "在熔岩後放置鼓風機", + "create.recipe.pressing": "金屬壓片", + "create.recipe.mixing": "混合攪拌", + "create.recipe.automatic_shapeless": "自動攪拌", + "create.recipe.automatic_brewing": "自動釀造", + "create.recipe.packing": "壓塊塑形", + "create.recipe.automatic_packing": "自動打包", + "create.recipe.sawing": "板材切割", + "create.recipe.mechanical_crafting": "自動合成", + "create.recipe.automatic_shaped": "自動合成", + "create.recipe.block_cutting": "方塊切割", + "create.recipe.wood_cutting": "木材切割", + "create.recipe.blockzapper_upgrade": "方塊放置器升級", + "create.recipe.sandpaper_polishing": "砂紙打磨", + "create.recipe.mystery_conversion": "神秘轉化", + "create.recipe.spout_filling": "注液", + "create.recipe.draining": "分液", + "create.recipe.processing.chance": "%1$s%%概率", + "create.recipe.heat_requirement.none": "不需要加熱", + "create.recipe.heat_requirement.heated": "普通加熱", + "create.recipe.heat_requirement.superheated": "超級加熱", + + "create.generic.range": "範圍", + "create.generic.radius": "半徑", + "create.generic.width": "寬", + "create.generic.height": "高", + "create.generic.length": "長", + "create.generic.speed": "速度", + "create.generic.delay": "延時", + "create.generic.unit.ticks": "Ticks", + "create.generic.unit.seconds": "秒", + "create.generic.unit.minutes": "分", + "create.generic.unit.rpm": "RPM", + "create.generic.unit.stress": "su", + "create.generic.unit.degrees": "度", + "create.generic.unit.millibuckets": "%1$smB", + "create.generic.clockwise": "順時鐘方向", + "create.generic.counter_clockwise": "逆時鐘方向", + + "create.action.scroll": "滾輪", + "create.action.confirm": "確認", + "create.action.abort": "退出", + "create.action.saveToFile": "離開", + "create.action.discard": "放棄", + + "create.keyinfo.toolmenu": "選單", + "create.keyinfo.scrollup": "(遊戲中)向上滑鼠滾輪", + "create.keyinfo.scrolldown": "(遊戲中)向下滑鼠滾輪", + + "create.gui.scrollInput.defaultTitle": "選擇一個選項:", + "create.gui.scrollInput.scrollToModify": "滾動修改", + "create.gui.scrollInput.scrollToAdjustAmount": "滾動修改數量", + "create.gui.scrollInput.scrollToSelect": "滾動選擇", + "create.gui.scrollInput.shiftScrollsFaster": "按住Shift滾動更快", + "create.gui.toolmenu.focusKey": "按住 [%1$s] 滑鼠滾輪選擇", + "create.gui.toolmenu.cycle": "[SCROLL] 循環", + "create.gui.symmetryWand.mirrorType": "鏡子類型", + "create.gui.symmetryWand.orientation": "方向", + + "create.symmetry.mirror.plane": "鏡像", + "create.symmetry.mirror.doublePlane": "矩形", + "create.symmetry.mirror.triplePlane": "八角", + + "create.orientation.orthogonal": "垂直", + "create.orientation.diagonal": "對角線", + "create.orientation.horizontal": "水平", + "create.orientation.alongZ": "以z軸對齊", + "create.orientation.alongX": "以x軸對齊", + + "create.gui.blockzapper.title": "方塊放置機", + "create.gui.blockzapper.replaceMode": "替換模式", + "create.gui.blockzapper.searchDiagonal": "對角線延伸", + "create.gui.blockzapper.searchFuzzy": "忽視種類分界", + "create.gui.blockzapper.range": "延伸範圍", + "create.gui.blockzapper.needsUpgradedAmplifier": "需要升級範圍擴大器", + "create.gui.blockzapper.patternSection": "模式", + "create.gui.blockzapper.pattern.solid": "實心", + "create.gui.blockzapper.pattern.checkered": "棋盤", + "create.gui.blockzapper.pattern.inversecheckered": "反轉棋盤", + "create.gui.blockzapper.pattern.chance25": "25% ", + "create.gui.blockzapper.pattern.chance50": "50% ", + "create.gui.blockzapper.pattern.chance75": "75% ", + "create.gui.terrainzapper.title": "地形雕塑器", + "create.gui.terrainzapper.placement": "放置模式", + "create.gui.terrainzapper.placement.merged": "結合", + "create.gui.terrainzapper.placement.attached": "依附", + "create.gui.terrainzapper.placement.inserted": "插入", + "create.gui.terrainzapper.brush": "雕塑類型", + "create.gui.terrainzapper.brush.cuboid": "矩形體", + "create.gui.terrainzapper.brush.sphere": "球體", + "create.gui.terrainzapper.brush.cylinder": "圓柱體", + "create.gui.terrainzapper.tool": "填充類型", + "create.gui.terrainzapper.tool.fill": "填充", + "create.gui.terrainzapper.tool.place": "覆寫", + "create.gui.terrainzapper.tool.replace": "替換", + "create.gui.terrainzapper.tool.clear": "清除", + "create.gui.terrainzapper.tool.overlay": "覆蓋", + "create.gui.terrainzapper.tool.flatten": "平整", + + "create.terrainzapper.shiftRightClickToSet": "Shift+滑鼠右鍵 以設定雕塑類型", + + "create.blockzapper.usingBlock": "使用:%1$s", + "create.blockzapper.componentUpgrades": "零件升級:", + "create.blockzapper.component.body": "放置器機體", + "create.blockzapper.component.amplifier": "範圍擴大器", + "create.blockzapper.component.accelerator": "射擊加速器", + "create.blockzapper.component.retriever": "物品撿回器", + "create.blockzapper.component.scope": "距離觀察鏡", + "create.blockzapper.componentTier.none": "無", + "create.blockzapper.componentTier.brass": "黃銅", + "create.blockzapper.componentTier.chromatic": "異彩化合物", + "create.blockzapper.leftClickToSet": "左鍵點擊方塊以設定方塊種類", + "create.blockzapper.empty": "方塊不足!", + + "create.minecart_coupling.two_couplings_max": "礦車無法被連接兩個以上的礦車連結器", + "create.minecart_coupling.unloaded": "有一部份礦車存在於未讀取區塊中", + "create.minecart_coupling.no_loops": "礦車連結器不能連成一個環", + "create.minecart_coupling.removed": "從礦車上移除所有礦車連結器", + "create.minecart_coupling.too_far": "礦車距離你太遠了", + + "create.contraptions.movement_mode": "運動模式", + "create.contraptions.movement_mode.move_place": "停止時實體化方塊", + "create.contraptions.movement_mode.move_place_returned": "只在初始位置實體化方塊", + "create.contraptions.movement_mode.move_never_place": "只有在機械方塊摧毀後才實體化方塊", + "create.contraptions.movement_mode.rotate_place": "停止時實體化方塊", + "create.contraptions.movement_mode.rotate_place_returned": "只在接近初始角度實體化方塊", + "create.contraptions.movement_mode.rotate_never_place": "只有在旋轉軸摧毀後才實體化方塊", + "create.contraptions.cart_movement_mode": "礦車運動模式", + "create.contraptions.cart_movement_mode.rotate": "結構與礦車保持相同方向", + "create.contraptions.cart_movement_mode.rotate_paused": "礦車轉向時機器停止工作", + "create.contraptions.cart_movement_mode.rotation_locked": "結構方向保持不變", + "create.contraptions.windmill.rotation_direction": "旋轉方向", + "create.contraptions.clockwork.clock_hands": "鐘錶指針", + "create.contraptions.clockwork.hour_first": "時針優先", + "create.contraptions.clockwork.minute_first": "分針優先", + "create.contraptions.clockwork.hour_first_24": "24小時制優先", + + "create.logistics.filter": "過濾器", + "create.logistics.recipe_filter": "配方過濾器", + "create.logistics.fluid_filter": "液體過濾器", + "create.logistics.firstFrequency": "頻道. #1", + "create.logistics.secondFrequency": "頻道. #2", + "create.logistics.filter.apply": "將過濾器應用來%1$s。", + "create.logistics.filter.apply_click_again": "將過濾器應用來%1$s,再次點擊以復制數量。", + "create.logistics.filter.apply_count": "使用提取計數過濾。", + + "create.gui.goggles.generator_stats": "產能器狀態:", + "create.gui.goggles.kinetic_stats": "機械狀態:", + "create.gui.goggles.at_current_speed": "目前動能值", + "create.gui.goggles.pole_length": "活塞桿長度:", + "create.gui.goggles.fluid_container": "液體容器資訊:", + "create.gui.goggles.fluid_container.capacity": "容量: ", + "create.gui.assembly.exception": "該結構無法組合:", + "create.gui.assembly.exception.unmovableBlock": "無法移動的方塊 (%4$s) 位於 [%1$s,%2$s,%3$s]", + "create.gui.assembly.exception.chunkNotLoaded": "位於 [%1$s,%2$s,%3$s] 方塊屬未載入區塊", + "create.gui.assembly.exception.structureTooLarge": "結構中的方塊數量過多.\nThe 可放置的數量最大為: %1$s", + "create.gui.assembly.exception.tooManyPistonPoles": "活塞的活塞桿數量過多\nThe 可放置的數量最大為: %1$s", + "create.gui.assembly.exception.noPistonPoles": "這個活塞遺失了一些活塞桿", + "create.gui.assembly.exception.not_enough_sails": "結構中所需的風帆類方塊數量不足: %1$s\n最少需要的數量為: %2$s", + "create.gui.gauge.info_header": "儀表訊息:", + "create.gui.speedometer.title": "旋轉速度", + "create.gui.stressometer.title": "網路動能", + "create.gui.stressometer.capacity": "剩餘動能量", + "create.gui.stressometer.overstressed": "動能過載", + "create.gui.stressometer.no_rotation": "無旋轉", + "create.gui.contraptions.not_fast_enough": "看起來%1$s 沒有達到足夠的工作轉速。", + "create.gui.contraptions.network_overstressed": "裝置似乎過載,減少高動能消耗的裝置或者增加更多更多動能", + "create.gui.adjustable_crate.title": "板條箱", + "create.gui.adjustable_crate.storageSpace": "儲存空間", + "create.gui.stockpile_switch.title": "儲存開關", + "create.gui.stockpile_switch.invert_signal": "反轉訊號", + "create.gui.stockpile_switch.move_to_lower_at": "移至下線%1$s%%", + "create.gui.stockpile_switch.move_to_upper_at": "移至上線%1$s%%", + "create.gui.sequenced_gearshift.title": "可程式化齒輪箱", + "create.gui.sequenced_gearshift.instruction": "指令", + "create.gui.sequenced_gearshift.instruction.turn_angle.descriptive": "以特定角度旋轉", + "create.gui.sequenced_gearshift.instruction.turn_angle": "旋轉", + "create.gui.sequenced_gearshift.instruction.turn_angle.angle": "角度", + "create.gui.sequenced_gearshift.instruction.turn_distance.descriptive": "帶動 活塞/滑輪/門式起重機", + "create.gui.sequenced_gearshift.instruction.turn_distance": "驅動活塞", + "create.gui.sequenced_gearshift.instruction.turn_distance.distance": "距離", + "create.gui.sequenced_gearshift.instruction.delay.descriptive": "延遲時間", + "create.gui.sequenced_gearshift.instruction.delay": "延遲", + "create.gui.sequenced_gearshift.instruction.delay.duration": "間隔", + "create.gui.sequenced_gearshift.instruction.end.descriptive": "結束", + "create.gui.sequenced_gearshift.instruction.end": "停止", + "create.gui.sequenced_gearshift.instruction.await.descriptive": "等待新的紅石脈衝", + "create.gui.sequenced_gearshift.instruction.await": "等待", + "create.gui.sequenced_gearshift.speed": "速度,速度方向", + "create.gui.sequenced_gearshift.speed.forward": "一倍速,正向", + "create.gui.sequenced_gearshift.speed.forward_fast": "兩倍速,正向", + "create.gui.sequenced_gearshift.speed.back": "一倍速,反向", + "create.gui.sequenced_gearshift.speed.back_fast": "兩倍速,反向", + + "create.schematicAndQuill.dimensions": "藍圖尺寸:%1$sx%2$sx%3$s", + "create.schematicAndQuill.firstPos": "第一個位置。", + "create.schematicAndQuill.secondPos": "第二個位置。", + "create.schematicAndQuill.noTarget": "按住Ctrl選擇空氣方塊。", + "create.schematicAndQuill.abort": "刪除選擇。", + "create.schematicAndQuill.title": "藍圖名:", + "create.schematicAndQuill.convert": "立即存檔並發佈", + "create.schematicAndQuill.fallbackName": "我的藍圖", + "create.schematicAndQuill.saved": "另存為%1$s", + + "create.schematic.invalid": "[!] 無效的項目", + "create.schematic.position": "位置", + "create.schematic.rotation": "旋轉", + "create.schematic.rotation.none": "無", + "create.schematic.rotation.cw90": "順時鐘90", + "create.schematic.rotation.cw180": "順時鐘180", + "create.schematic.rotation.cw270": "順時鐘270", + "create.schematic.mirror": "鏡像", + "create.schematic.mirror.none": "無", + "create.schematic.mirror.frontBack": "前後", + "create.schematic.mirror.leftRight": "左右", + "create.schematic.tool.deploy": "發佈", + "create.schematic.tool.move": "移動 XZ", + "create.schematic.tool.movey": "移動 Y", + "create.schematic.tool.rotate": "旋轉", + "create.schematic.tool.print": "列印", + "create.schematic.tool.flip": "翻轉", + "create.schematic.tool.deploy.description.0": "將結構移到某個位置。", + "create.schematic.tool.deploy.description.1": "在地面上點擊滑鼠右鍵以放置。", + "create.schematic.tool.deploy.description.2": "按住Ctrl以固定距離選擇。", + "create.schematic.tool.deploy.description.3": "按住Ctrl滑鼠滾動更改距離。", + "create.schematic.tool.move.description.0": "水平移動藍圖", + "create.schematic.tool.move.description.1": "選定藍圖,然後按住Ctrl滑鼠滾動。", + "create.schematic.tool.move.description.2": "", + "create.schematic.tool.move.description.3": "", + "create.schematic.tool.movey.description.0": "垂直移動藍圖", + "create.schematic.tool.movey.description.1": "按住Ctrl滑鼠滾動上下移動", + "create.schematic.tool.movey.description.2": "", + "create.schematic.tool.movey.description.3": "", + "create.schematic.tool.rotate.description.0": "圍繞藍圖中心旋轉藍圖。", + "create.schematic.tool.rotate.description.1": "按住Ctrl滑鼠滾動旋轉90度", + "create.schematic.tool.rotate.description.2": "", + "create.schematic.tool.rotate.description.3": "", + "create.schematic.tool.print.description.0": "立即將結構放置在世界上", + "create.schematic.tool.print.description.1": "右鍵點擊確認目前位置。", + "create.schematic.tool.print.description.2": "該工具僅能用於創造模式。", + "create.schematic.tool.print.description.3": "", + "create.schematic.tool.flip.description.0": "沿你選擇的面翻轉藍圖。", + "create.schematic.tool.flip.description.1": "指向藍圖,然後按住Ctrl滑鼠滾動將其翻轉。", + "create.schematic.tool.flip.description.2": "", + "create.schematic.tool.flip.description.3": "", + + "create.schematics.synchronizing": "正在同步..", + "create.schematics.uploadTooLarge": "你的藍圖太大", + "create.schematics.maxAllowedSize": "允許的最大藍圖文件大小為:", + + "create.gui.schematicTable.refresh": "重新整理文件", + "create.gui.schematicTable.open_folder": "打開資料夾", + "create.gui.schematicTable.title": "藍圖桌", + "create.gui.schematicTable.availableSchematics": "可用藍圖", + "create.gui.schematicTable.noSchematics": "沒有存檔的藍圖", + "create.gui.schematicTable.uploading": "正在上傳...", + "create.gui.schematicTable.finished": "上傳完成!", + "create.gui.schematicannon.title": "藍圖加農炮", + "create.gui.schematicannon.listPrinter": "物品清單列印機", + "create.gui.schematicannon.gunpowderLevel": "火藥%1$s%%", + "create.gui.schematicannon.shotsRemaining": "發射進度:%1$s", + "create.gui.schematicannon.shotsRemainingWithBackup": "備份:%1$s", + "create.gui.schematicannon.optionEnabled": "目前啟用", + "create.gui.schematicannon.optionDisabled": "目前停用", + "create.gui.schematicannon.showOptions": "顯示藍圖加農炮設定", + "create.gui.schematicannon.option.dontReplaceSolid": "不要替換方塊", + "create.gui.schematicannon.option.replaceWithSolid": "用固體方塊替換工作區域內的方塊", + "create.gui.schematicannon.option.replaceWithAny": "用任何方塊替換工作區域內的方塊", + "create.gui.schematicannon.option.replaceWithEmpty": "用空氣替換工作區域內的方塊", + "create.gui.schematicannon.option.skipMissing": "繞過缺少的方塊", + "create.gui.schematicannon.option.skipTileEntities": "保護儲存方塊", + "create.gui.schematicannon.slot.gunpowder": "向藍圖加農炮添加火藥以提供動能", + "create.gui.schematicannon.slot.listPrinter": "在此處放置書以列印藍圖所需的材料清單", + "create.gui.schematicannon.slot.schematic": "在此處添加你的藍圖,務必確保其已被部放置在特定位置", + "create.gui.schematicannon.option.skipMissing.description": "如果材料不夠,藍圖大炮將忽略目前不夠的材料並且使用其他已有材料繼續工作", + "create.gui.schematicannon.option.skipTileEntities.description": "藍圖將避免更換儲存方塊,如箱子。", + "create.gui.schematicannon.option.dontReplaceSolid.description": "藍圖加農炮將不會替換工作範圍內的任何固體方塊。", + "create.gui.schematicannon.option.replaceWithSolid.description": "藍圖加農炮會使用所提供的固體方塊來替換工作區域內的其他固體方塊", + "create.gui.schematicannon.option.replaceWithAny.description": "藍圖加農炮會使用任何所提供的方塊來替換工作區域內的固體方塊", + "create.gui.schematicannon.option.replaceWithEmpty.description": "藍圖加農炮將清理和替換工作區域內所有原本的方塊。", + + "create.schematicannon.status.idle": "閒置", + "create.schematicannon.status.ready": "準備", + "create.schematicannon.status.running": "啟動", + "create.schematicannon.status.finished": "完成", + "create.schematicannon.status.paused": "已暫停", + "create.schematicannon.status.stopped": "停止", + "create.schematicannon.status.noGunpowder": "火藥消耗完畢", + "create.schematicannon.status.targetNotLoaded": "方塊未讀取", + "create.schematicannon.status.targetOutsideRange": "定位目標太遠", + "create.schematicannon.status.searching": "搜尋", + "create.schematicannon.status.skipping": "跳過", + "create.schematicannon.status.missingBlock": "缺少方塊:", + "create.schematicannon.status.placing": "建築中", + "create.schematicannon.status.clearing": "清除方塊中", + "create.schematicannon.status.schematicInvalid": "藍圖無效", + "create.schematicannon.status.schematicNotPlaced": "藍圖未發佈", + "create.schematicannon.status.schematicExpired": "藍圖文件已過期", + + "create.materialChecklist": "材料清單", + "create.materialChecklist.blocksNotLoaded": "*免責聲明* \n\n由於未讀取相關區塊,材料清單可能不正確。", + + "create.gui.filter.deny_list": "黑名單", + "create.gui.filter.deny_list.description": "只通過不在黑名單中的物品,如果黑名單為空,所有物品都可以通過", + "create.gui.filter.allow_list": "白名單", + "create.gui.filter.allow_list.description": "只通過在白名單中的物品,如果白名單為空,所有物品都無法通過", + "create.gui.filter.respect_data": "比對物品屬性", + "create.gui.filter.respect_data.description": "只有物品的耐久、附魔等其他屬性相同時才可以比對", + "create.gui.filter.ignore_data": "忽略物品屬性", + "create.gui.filter.ignore_data.description": "配對時忽略物品的耐久、附魔等其他屬性", + + "create.item_attributes.placeable": "可放置", + "create.item_attributes.placeable.inverted": "不可放置", + "create.item_attributes.consumable": "可食用", + "create.item_attributes.consumable.inverted": "不可食用", + "create.item_attributes.smeltable": "可被熔爐融煉", + "create.item_attributes.smeltable.inverted": "不可被熔爐融煉", + "create.item_attributes.washable": "可被篩洗", + "create.item_attributes.washable.inverted": "不可被篩洗", + "create.item_attributes.smokable": "可被煙熏", + "create.item_attributes.smokable.inverted": "不可被煙熏", + "create.item_attributes.crushable": "可被粉碎", + "create.item_attributes.crushable.inverted": "不可被粉碎", + "create.item_attributes.blastable": "可被高爐融煉", + "create.item_attributes.blastable.inverted": "不可被高爐融煉", + "create.item_attributes.enchanted": "已被附魔", + "create.item_attributes.enchanted.inverted": "未被附魔", + "create.item_attributes.damaged": "已損壞", + "create.item_attributes.damaged.inverted": "未損壞", + "create.item_attributes.badly_damaged": "嚴重受損", + "create.item_attributes.badly_damaged.inverted": "未嚴重受損", + "create.item_attributes.not_stackable": "無法堆疊", + "create.item_attributes.not_stackable.inverted": "可堆疊", + "create.item_attributes.equipable": "可裝備", + "create.item_attributes.equipable.inverted": "不可裝備", + "create.item_attributes.furnace_fuel": "是燃料", + "create.item_attributes.furnace_fuel.inverted": "不是燃料", + "create.item_attributes.in_tag": "標籤是%1$s", + "create.item_attributes.in_tag.inverted": "標籤不是%1$s", + "create.item_attributes.in_item_group": "屬於%1$s", + "create.item_attributes.in_item_group.inverted": "不屬於%1$s", + "create.item_attributes.added_by": "由%1$s添加", + "create.item_attributes.added_by.inverted": "不是由%1$s添加", + "create.item_attributes.has_enchant": "有附魔效果%1$s", + "create.item_attributes.has_enchant.inverted": "沒有附魔效果%1$s", + "create.item_attributes.color": "已被染色成 %1$s", + "create.item_attributes.color.inverted": "未被染色成 %1$s", + "create.item_attributes.max_enchanted": "已達到最高附魔等級", + "create.item_attributes.max_enchanted.inverted": "未達到最高附魔等級", + "create.item_attributes.has_fluid": "包含%1$s", + "create.item_attributes.has_fluid.inverted": "不包含%1$s", + "create.item_attributes.has_name": "有自定義名稱%1$s", + "create.item_attributes.has_name.inverted": "沒有自定義名稱%1$s", + "create.item_attributes.book_author": "由%1$s編寫", + "create.item_attributes.book_author.inverted": "未由%1$s編寫", + "create.item_attributes.book_copy_original": "是原創的", + "create.item_attributes.book_copy_original.inverted": "不是原創的", + "create.item_attributes.book_copy_first": "是第一份複製", + "create.item_attributes.book_copy_first.inverted": "不是第一份複製", + "create.item_attributes.book_copy_second": "是第二份複製", + "create.item_attributes.book_copy_second.inverted": "不是第二份複製", + "create.item_attributes.book_copy_tattered": "是第三份複製", + "create.item_attributes.book_copy_tattered.inverted": "不是第三份複製", + "create.item_attributes.astralsorcery_crystal": "具有晶體屬性%1$s", + "create.item_attributes.astralsorcery_crystal.inverted": "不具有晶體屬性%1$s", + "create.item_attributes.astralsorcery_constellation": "與%1$s調諧", + "create.item_attributes.astralsorcery_constellation.inverted": "未與%1$s調諧", + "create.item_attributes.astralsorcery_perk_gem": "具有特殊屬性%1$s", + "create.item_attributes.astralsorcery_perk_gem.inverted": "不具有特殊屬性%1$s", + "create.item_attributes.astralsorcery_amulet": "提升%1$s", + "create.item_attributes.astralsorcery_amulet.inverted": "不提升%1$s", + + "create.gui.attribute_filter.no_selected_attributes": "沒有標記任何屬性", + "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.description": "只要有其中一項屬性符合,就可以通過", + "create.gui.attribute_filter.allow_list_conjunctive": "全部比對白名單(全部)", + "create.gui.attribute_filter.allow_list_conjunctive.description": "只有所有屬性都相符才可以通過", + "create.gui.attribute_filter.deny_list": "黑名單", + "create.gui.attribute_filter.deny_list.description": "只要沒有上述屬性,就可以通過", + "create.gui.attribute_filter.add_reference_item": "添加參考物品", + + "create.tooltip.holdForDescription": "按住 [%1$s] 來讀取物品概要", + "create.tooltip.holdForControls": "按住 [%1$s] 來讀取控制方法", + "create.tooltip.keyShift": "Shift", + "create.tooltip.keyCtrl": "Ctrl", + "create.tooltip.speedRequirement": "需求速度:%1$s", + "create.tooltip.speedRequirement.none": "無", + "create.tooltip.speedRequirement.medium": "適當", + "create.tooltip.speedRequirement.high": "快", + "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.low": "小", + "create.tooltip.capacityProvided.medium": "中", + "create.tooltip.capacityProvided.high": "大", + "create.tooltip.generationSpeed": "產生%1$s %2$s", + "create.tooltip.analogStrength": "調節強度:%1$s/15", + + "create.mechanical_arm.extract_from": "從%1$s 拿取物品", + "create.mechanical_arm.deposit_to": "向%1$s 儲存物品", + "create.mechanical_arm.summary": "機械手臂有%1$s 輸入以及 %2$s 輸出。", + "create.mechanical_arm.points_outside_range": "%1$s 由於距離限制,選定的交互點被移除。", + + "create.weighted_ejector.target_set": "已選取目的地", + "create.weighted_ejector.target_not_valid": "彈射到鄰近的方塊 (目的地無效)", + "create.weighted_ejector.no_target": "彈射到鄰近的方塊 (未選取目的地)", + "create.weighted_ejector.targeting": "彈射到 [%1$s,%2$s,%3$s]", + "create.weighted_ejector.stack_size": "彈射物品數量", + + "create.logistics.when_multiple_outputs_available": "當多個輸出可用時", + + "create.mechanical_arm.selection_mode.round_robin": "輪詢調度", + "create.mechanical_arm.selection_mode.forced_round_robin": "強制輪詢調度", + "create.mechanical_arm.selection_mode.prefer_first": "第一目標優先", + + "create.tunnel.selection_mode.split": "分攤", + "create.tunnel.selection_mode.forced_split": "強制分攤", + "create.tunnel.selection_mode.round_robin": "輪詢調度", + "create.tunnel.selection_mode.forced_round_robin": "強制輪詢調度", + "create.tunnel.selection_mode.prefer_nearest": "最近優先", + "create.tunnel.selection_mode.randomize": "隨機", + "create.tunnel.selection_mode.synchronize": "同步輸入", + + "create.tooltip.chute.header": "滑道訊息", + "create.tooltip.chute.items_move_down": "物品向下移動", + "create.tooltip.chute.items_move_up": "物品向上移動", + "create.tooltip.chute.no_fans_attached": "未安裝鼓風機", + "create.tooltip.chute.fans_push_up": "鼓風機從下方進行推動", + "create.tooltip.chute.fans_push_down": "鼓風機從上方進行推動", + "create.tooltip.chute.fans_pull_up": "鼓風機從下方進行吸引", + "create.tooltip.chute.fans_pull_down": "鼓風機從上方進行吸引", + "create.tooltip.chute.contains": "物品: %1$s x%2$s", + + "create.hint.hose_pulley.title": "無限供應", + "create.hint.hose_pulley": "目標液體為無限供應", + "create.hint.mechanical_arm_no_targets.title": "沒有目標", + "create.hint.mechanical_arm_no_targets": "看起來這個_機械手臂_沒有被分配任何_目標_。在手持機械手臂的同時,右鍵選取輸送帶、置物臺、漏斗或其他設備來設定目標。", + "create.hint.empty_bearing.title": "更新軸承", + "create.hint.empty_bearing": "_空手右鍵_軸承來_添加_你新建造的結構。", + "create.hint.full_deployer.title": "機械手物品溢出", + "create.hint.full_deployer": "_機械手_包含_過剩的物品_需要被_取出._使用漏斗_或其他方法將溢出解決。", + + "create.gui.config.overlay1": "嗨 :)", + "create.gui.config.overlay2": "這是一個實例層", + "create.gui.config.overlay3": "點擊拖拽你的滑鼠", + "create.gui.config.overlay4": "來將它移動到前方", + "create.gui.config.overlay5": "ESC退出目前介面", + "create.gui.config.overlay6": "並儲存新的位置", + "create.gui.config.overlay7": "輸入/create overlay reset", + "create.gui.config.overlay8": "重置到預設位置", + + "create.command.killTPSCommand": "killtps", + "create.command.killTPSCommand.status.slowed_by.0": "[Create]: 伺服器每秒TICK被降為 %s ms :o", + "create.command.killTPSCommand.status.slowed_by.1": "[Create]: 伺服器現在每秒TICK被降為 >:)", + "create.command.killTPSCommand.status.slowed_by.2": "[Create]: 伺服器現在不延遲了,TPS正常 :D", + "create.command.killTPSCommand.status.usage.0": "[Create]: 用 /killtps stop 來讓伺服器的TPS速度恢復正常", + "create.command.killTPSCommand.status.usage.1": "[Create]: 用 /killtps start 來手動降低伺服器TPS", + "create.command.killTPSCommand.argument.tickTime": "tickTime", + + "create.contraption.minecart_contraption_too_big": "這個礦車結構太大了而無法撿取", + + + "_": "->------------------------] Subtitles [------------------------<-", + + "create.subtitle.schematicannon_launch_block": "藍圖大炮發射", + "create.subtitle.schematicannon_finish": "藍圖大炮完成任務", + "create.subtitle.slime_added": "黏液擠壓", + "create.subtitle.mechanical_press_activation_belt": "液壓機工作", + "create.subtitle.mechanical_press_activation": "液壓機工作", + "create.subtitle.blockzapper_deny": "放置失敗", + "create.subtitle.blockzapper_confirm": "選擇方塊", + "create.subtitle.blockzapper_place": "放置方塊", + "create.subtitle.blaze_munch": "烈焰使者開心地吃著", + + + "_": "->------------------------] Item Descriptions [------------------------<-", + + "item.create.example_item.tooltip": "EXAMPLE ITEM (just a marker that this tooltip exists)", + "item.create.example_item.tooltip.summary": "A brief description of the item._Underscores_highlight a term.", + "item.create.example_item.tooltip.condition1": "When this", + "item.create.example_item.tooltip.behaviour1": "Then this item does this。(behaviours show on shift)", + "item.create.example_item.tooltip.condition2": "And When this", + "item.create.example_item.tooltip.behaviour2": "You can add as many behaviours as you like", + "item.create.example_item.tooltip.control1": "When Ctrl pressed", + "item.create.example_item.tooltip.action1": "These controls are displayed.", + + "block.create.wooden_bracket.tooltip": "木製支架", + "block.create.wooden_bracket.tooltip.summary": "用來裝飾_傳動軸_,_齒輪_和_管道_。", + + "block.create.metal_bracket.tooltip": "金屬支架", + "block.create.metal_bracket.tooltip.summary": "用來裝飾_傳動軸_,_齒輪_和_管道_。", + + "block.create.copper_casing.tooltip": "銅製機殼", + "block.create.copper_casing.tooltip.summary": "具備多種用途的堅固機殼,也可用於裝飾。", + "block.create.copper_casing.tooltip.condition1": "對液體管道使用時", + "block.create.copper_casing.tooltip.behaviour1": "會把管道裝入機殼,裝進機殼的管道會與其他管道分開,以免它們自動相連。", + + "block.create.encased_fluid_pipe.tooltip": "液體管道箱", + "block.create.encased_fluid_pipe.tooltip.summary": "用銅機殼加固后的液體管道。", + + "block.create.seat.tooltip": "坐墊", + "block.create.seat.tooltip.summary": "坐下來享受旅程吧!坐墊將會把玩家固定在一個移動裝置上。也可以用來作為居家裝飾,畢竟他有許多顏色。", + "block.create.seat.tooltip.condition1": "對坐墊右鍵", + "block.create.seat.tooltip.behaviour1": "玩家將坐在_坐墊_上,Left-Shift可離開_坐墊_。", + + "item.create.blaze_cake.tooltip": "熔岩蛋糕", + "item.create.blaze_cake.tooltip.summary": "對辛苦的_烈焰使者_的美味款待。讓他們興奮起來吧!", + + "block.create.fluid_pipe.tooltip": "液體管道", + "block.create.fluid_pipe.tooltip.summary": "用來傳輸_液體_。需要一個_機械泵_來提供壓強。", + "block.create.fluid_pipe.tooltip.condition1": "轉移液體", + "block.create.fluid_pipe.tooltip.behaviour1": "可以與_液體容器_如_儲存罐_或_作業盆_相連_。裸露的_管道_末端也可以排放或抽取液體。注意別漏水了!", + "block.create.fluid_pipe.tooltip.condition2": "使用扳手對其右鍵時", + "block.create.fluid_pipe.tooltip.behaviour2": "在狀況許可的情況下在管道上安裝透明窗", + + "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.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.condition1": "使用扳手右鍵", + "block.create.fluid_tank.tooltip.behaviour1": "改變可選窗口", + + "block.create.creative_fluid_tank.tooltip": "創造液體儲存罐", + "block.create.creative_fluid_tank.tooltip.summary": "此液體儲存罐能夠_無限的復制_任何液體。", + "block.create.creative_fluid_tank.tooltip.condition1": "罐中裝有液體時", + "block.create.creative_fluid_tank.tooltip.behaviour1": "任意的_液體提取設備_能夠從中提取無窮無盡的指定液體,液體的導入功能同時也會無效。", + "block.create.creative_fluid_tank.tooltip.condition2": "扳手右擊時", + "block.create.creative_fluid_tank.tooltip.behaviour2": "打開關閉窗戶", + + "block.create.fluid_valve.tooltip": "液體閥門", + "block.create.fluid_valve.tooltip.summary": "阻止液體沿管道向前流動。", + "block.create.fluid_valve.tooltip.condition1": "控制流量", + "block.create.fluid_valve.tooltip.behaviour1": "施加的_動能_將迫使閥門關閉,從而阻止液體流動。_逆轉旋轉方向_以重新打開閥門。", + + "block.create.mechanical_pump.tooltip": "機械泵", + "block.create.mechanical_pump.tooltip.summary": "_接入機械_,能迫使液體_沿管道指定方向移動_。在兩個方向上都有_最大的作用範圍_。(默認為16個方塊距離)", + "block.create.mechanical_pump.tooltip.condition1": "液體流向", + "block.create.mechanical_pump.tooltip.behaviour1": "_接入機械_后會產生壓力,迫使液體通過管道。_反轉機械_的方向以切換液體_流向_。", + "block.create.mechanical_pump.tooltip.control1": "扳手右鍵時", + "block.create.mechanical_pump.tooltip.action1": "反轉泵的方向,從而改變默認的液體流向", + + "block.create.smart_fluid_pipe.tooltip": "智慧液體管道", + "block.create.smart_fluid_pipe.tooltip.summary": "帶有過濾器的_液體管道_。可以指定通過哪個_液體_。", + "block.create.smart_fluid_pipe.tooltip.condition1": "當液體進入時", + "block.create.smart_fluid_pipe.tooltip.behaviour1": "進入的液體與_過濾器_不匹配時,智慧管道將_阻止_其通過。", + "block.create.smart_fluid_pipe.tooltip.condition2": "與_液體容器相鄰_時", + "block.create.smart_fluid_pipe.tooltip.behaviour2": "從_任何容器_開始流動的_智慧管道_只會抽取與其過濾器匹配的液體。", + + "block.create.spout.tooltip": "注液器", + "block.create.spout.tooltip.summary": "一種用來_裝罐_的機器。", + "block.create.spout.tooltip.condition1": "液體傳輸", + "block.create.spout.tooltip.behaviour1": "當下方放置類似_玻璃瓶_,_桶_這樣的液體容器物品時,注液器將試圖將自身儲存的液體注入到下方的_液體容器物品_中。", + "block.create.spout.tooltip.condition2": "液體自動化", + "block.create.spout.tooltip.behaviour2": "注液器位於_輸送帶_或者_置物臺_上方時,將自動為流水線上的_液體容器物品_進行_注入_。", + + "block.create.item_drain.tooltip": "分液池", + "block.create.item_drain.tooltip.summary": "一種用來_抽空液體容器物品_的置物臺", + "block.create.item_drain.tooltip.condition1": "液體傳輸", + "block.create.item_drain.tooltip.behaviour1": "當從側面導入諸如_桶_或_瓶子_之類的_液體容器物品_時,_分液池_將嘗試將其倒入其_自身的液體庫存_中。空的_液體容器物品_將被彈出至_另一側_。", + + "item.create.wand_of_symmetry.tooltip": "對稱杖", + "item.create.wand_of_symmetry.tooltip.summary": "完美地鏡面復制工作區域內的方塊放置於破壞", + "item.create.wand_of_symmetry.tooltip.condition1": "當在熱鍵欄時", + "item.create.wand_of_symmetry.tooltip.behaviour1": "持續進行鏡面復制", + "item.create.wand_of_symmetry.tooltip.control1": "當右鍵地面時", + "item.create.wand_of_symmetry.tooltip.action1": "_創建_或_移動_鏡子", + "item.create.wand_of_symmetry.tooltip.control2": "當右鍵空氣時", + "item.create.wand_of_symmetry.tooltip.action2": "_刪除_鏡子", + "item.create.wand_of_symmetry.tooltip.control3": "當潛行右鍵時", + "item.create.wand_of_symmetry.tooltip.action3": "打開_gui介面_", + + "item.create.handheld_blockzapper.tooltip": "方塊放置器", + "item.create.handheld_blockzapper.tooltip.summary": "新穎的小工具,可以遠距離放置或更換方塊。", + "item.create.handheld_blockzapper.tooltip.control1": "當左鍵方塊時", + "item.create.handheld_blockzapper.tooltip.action1": "設定放置此方塊。", + "item.create.handheld_blockzapper.tooltip.control2": "當右鍵方塊時", + "item.create.handheld_blockzapper.tooltip.action2": "_放置_或_替換_目標方塊。", + "item.create.handheld_blockzapper.tooltip.control3": "當潛行右鍵時", + "item.create.handheld_blockzapper.tooltip.action3": "打開_gui介面_", + + "item.create.handheld_worldshaper.tooltip": "環境塑形器", + "item.create.handheld_worldshaper.tooltip.summary": "_大面積_更改地形的手持工具", + "item.create.handheld_worldshaper.tooltip.control1": "當左鍵方塊時", + "item.create.handheld_worldshaper.tooltip.action1": "設定放置此方塊", + "item.create.handheld_worldshaper.tooltip.control2": "當右鍵方塊時", + "item.create.handheld_worldshaper.tooltip.action2": "_放置_或_替換_目標方塊", + "item.create.handheld_worldshaper.tooltip.control3": "當潛行右鍵時", + "item.create.handheld_worldshaper.tooltip.action3": "打開工具的_gui介面_", + + "item.create.tree_fertilizer.tooltip": "樹木肥料", + "item.create.tree_fertilizer.tooltip.summary": "適用來常見樹木的快速肥料", + "item.create.tree_fertilizer.tooltip.condition1": "在樹苗上使用時", + "item.create.tree_fertilizer.tooltip.behaviour1": "無論_生長時間_多少,直接長大", + + "item.create.deforester.tooltip": "連根拔樹斧", + "item.create.deforester.tooltip.summary": "_連根拔樹斧_,從最根砍樹時,能夠瞬間連根拔起一棵樹", + + "item.create.extendo_grip.tooltip": "伸縮機械手", + "item.create.extendo_grip.tooltip.summary": "biubiubiu! 大幅度_增加了_使用者的_觸碰距離_。", + "item.create.extendo_grip.tooltip.condition1": "放置於副手欄時", + "item.create.extendo_grip.tooltip.behaviour1": "大幅增加_主手_的觸碰距離,與_主手_的伸縮機械手攜同使用,可進一步增加_觸碰距離_。", + + "item.create.filter.tooltip": "過濾器", + "item.create.filter.tooltip.summary": "將物品更精確地進行_篩選分類_,可以同時_篩選_多個物品或者將已標記的_過濾器_放在另一個_過濾器_里_嵌套_使用。", + "item.create.filter.tooltip.condition1": "放置於過濾插槽中時", + "item.create.filter.tooltip.behaviour1": "根據_過濾器_的設定,來_決定_物品是否能夠通過", + "item.create.filter.tooltip.condition2": "當右鍵時", + "item.create.filter.tooltip.behaviour2": "打開_設定面板_", + + "item.create.attribute_filter.tooltip": "屬性過濾器", + "item.create.attribute_filter.tooltip.summary": "比起普通過濾器,_屬性過濾器_可以根據不同物品的_屬性_來進行過濾", + "item.create.attribute_filter.tooltip.condition1": "放置於過濾插槽中時", + "item.create.attribute_filter.tooltip.behaviour1": "根據_過濾器_的配置,來_決定_物品是否能夠通過", + "item.create.attribute_filter.tooltip.condition2": "當右鍵時", + "item.create.attribute_filter.tooltip.behaviour2": "打開_配置面板_", + + "item.create.empty_schematic.tooltip": "空白藍圖", + "item.create.empty_schematic.tooltip.summary": "可作為合成材料或在_藍圖桌_使用", + + "item.create.schematic.tooltip": "藍圖", + "item.create.schematic.tooltip.summary": "將工程結構的_設計圖_放置於_世界中_,並使用_藍圖加農炮_進行構建。", + "item.create.schematic.tooltip.condition1": "當設計圖存在時", + "item.create.schematic.tooltip.behaviour1": "可以使用屏幕上的工具調整位置", + "item.create.schematic.tooltip.control1": "當潛行右鍵時", + "item.create.schematic.tooltip.action1": "打開一個用來輸入_精確坐標_的介面。", + + "item.create.schematic_and_quill.tooltip": "藍圖與筆", + "item.create.schematic_and_quill.tooltip.summary": "用來將世界中的結構存到.nbt文件。", + "item.create.schematic_and_quill.tooltip.condition1": "第一步", + "item.create.schematic_and_quill.tooltip.behaviour1": "手持藍圖與右鍵旋轉兩個點", + "item.create.schematic_and_quill.tooltip.condition2": "第二步", + "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.control3": "當潛行右鍵時", + "item.create.schematic_and_quill.tooltip.action3": "_重置_並刪除選區。", + + "block.create.schematicannon.tooltip": "藍圖加農炮", + "block.create.schematicannon.tooltip.summary": "通過發射方塊以在世界中重新構建已部署的_全息圖_,使用相鄰箱子中的物品及_火藥_作為燃料。", + "block.create.schematicannon.tooltip.condition1": "當你對加農砲右鍵時", + "block.create.schematicannon.tooltip.behaviour1": "打開加農砲的設定介面", + + "block.create.schematic_table.tooltip": "藍圖桌", + "block.create.schematic_table.tooltip.summary": "將保存的藍圖圖寫入_空白藍圖_", + "block.create.schematic_table.tooltip.condition1": "放入空白藍圖時", + "block.create.schematic_table.tooltip.behaviour1": "從Schematics文件夾上傳所選文件", + + "item.create.goggles.tooltip": "MR護目鏡", + "item.create.goggles.tooltip.summary": "一副特殊的眼鏡,能夠讓你看見_動能_的信息。", + "item.create.goggles.tooltip.condition1": "當裝備後", + "item.create.goggles.tooltip.behaviour1": "將會顯示該機械元件的_速度_、_動能_等數值。", + "item.create.goggles.tooltip.condition2": "當裝備後看向儀表時", + "item.create.goggles.tooltip.behaviour2": "將會顯示該儀表所連接網路的_速度_、_動能_等數值。", + "item.create.goggles.tooltip.condition3": "當裝備後看向液體容器時", + "item.create.goggles.tooltip.behaviour3": "將會顯示儲存在該容器內的 _液體_ 以及其 _容量_ 等資訊。", + + "item.create.wrench.tooltip": "板手", + "item.create.wrench.tooltip.summary": "一種常用的工具,能夠調整_動能_的_方向_、_配置_等。", + "item.create.wrench.tooltip.control1": "當右鍵點擊_動能元件_時", + "item.create.wrench.tooltip.action1": "以點擊的面為軸心_旋轉_點擊的方塊", + "item.create.wrench.tooltip.control2": "當潛行右鍵時", + "item.create.wrench.tooltip.action2": "將物品_取下_並移動到你的背包中。", + + "block.create.nozzle.tooltip": "分散網", + "block.create.nozzle.tooltip.summary": "依附在鼓風機上,能夠將鼓風機的效果_分散_各個方向。", + + "block.create.cuckoo_clock.tooltip": "布穀鳥鐘", + "block.create.cuckoo_clock.tooltip.summary": "精美的布穀鳥鐘,能夠報時", + "block.create.cuckoo_clock.tooltip.condition1": "連接機械時", + "block.create.cuckoo_clock.tooltip.behaviour1": "顯示_現在時間_且一天會報時_兩次_。中午一次,黃昏可以睡覺時一次 ", + + "block.create.turntable.tooltip": "轉盤", + "block.create.turntable.tooltip.summary": "讓旋轉機械給你帶來一場刺激的旋轉風車體驗。", + + "block.create.portable_fluid_interface.tooltip": "移動液體接口", + "block.create.portable_fluid_interface.tooltip.summary": "為機械活塞、裝配礦車、旋轉軸承、滑輪_等移動結構_設計的_液體接口_,_移動結構_和_固定結構_之間的液體交換站,兩個會面的接口必須彼此面對且彼此隔開1-2個方塊。", + "block.create.portable_fluid_interface.tooltip.condition1": "裝配在移動結構上時", + "block.create.portable_fluid_interface.tooltip.behaviour1": "移動到能夠滿足與_固定結構_上的_移動式液體接口_對接的條件后,移動結構會_短暫地停下_,開始對接,並直接與_移動結構上的_液體儲存罐_交互,進行液體的_導入導出_。", + "block.create.portable_fluid_interface.tooltip.condition2": "被紅石激活時", + "block.create.portable_fluid_interface.tooltip.behaviour2": "立即終止任何活動的連接。", + + "block.create.stockpile_switch.tooltip": "存量偵測器", + "block.create.stockpile_switch.tooltip.summary": "根據連接的容器_儲存空間_的占用情況切換紅石訊號強度。", + "block.create.stockpile_switch.tooltip.condition1": "低於_下線_或高於_上線_時", + "block.create.stockpile_switch.tooltip.behaviour1": "提供紅石訊號", + + "block.create.content_observer.tooltip": "物品偵測器", + "block.create.content_observer.tooltip.summary": "偵測_容器_和_輸送帶_中過濾器匹配的物品。當觀察到包含匹配的物品時,此組件將發出_紅石訊號_。當觀察到的漏斗_轉移匹配的物品_時,此組件將發出_紅石脈沖_。", + + "block.create.adjustable_crate.tooltip": "可調節板條箱", + "block.create.adjustable_crate.tooltip.summary": "這個箱子可以調整容量,最大可以收納_16組_物品。", + "block.create.adjustable_crate.tooltip.condition1": "當你對箱子按右鍵時", + "block.create.adjustable_crate.tooltip.behaviour1": "打開箱子的設定介面", + + "block.create.creative_crate.tooltip": "創造板條箱", + "block.create.creative_crate.tooltip.summary": "這個容器可以給臨近的_藍圖大炮_提供無限物品以及燃料 (創造專用物品)", + "block.create.creative_crate.tooltip.condition1": "當標記了物品時", + "block.create.creative_crate.tooltip.behaviour1": "容器將會從虛空中提供_無限量_的標記物品,並且任何放置到容器中的物品都會被_送入虛空_", + + "block.create.controller_rail.tooltip": "控制鐵軌", + "block.create.controller_rail.tooltip.summary": "單向電動導軌,能夠精細控制礦車的移動速度。", + "block.create.controller_rail.tooltip.condition1": "被紅石激活時", + "block.create.controller_rail.tooltip.behaviour1": "根據訊號強度_加速_或_減速_經過的礦車。將紅石強度傳播到相鄰的控制鐵軌。", + + "item.create.sand_paper.tooltip": "紅砂紙", + "item.create.sand_paper.tooltip.summary": "用來_打磨_物品的砂紙,可以用_機械手_來實現自動化。", + "item.create.sand_paper.tooltip.condition1": "使用時", + "item.create.sand_paper.tooltip.behaviour1": "打磨_副手_上或者_準心所指_的物品。", + + "item.create.builders_tea.tooltip": "工人茶", + "item.create.builders_tea.tooltip.summary": "神清氣爽的一天,從這杯完美茶飲開始。恢復復_饑餓值_並獲得_加速_效果。", + + "item.create.refined_radiance.tooltip": "光輝石", + "item.create.refined_radiance.tooltip.summary": "一種用_光輝_鍛造的化合物材料。", + + "item.create.shadow_steel.tooltip": "暗影鋼", + "item.create.shadow_steel.tooltip.summary": "一種用_虛空_鍛造的化合物材料。", + + "item.create.minecart_coupling.tooltip": "礦車連軸器", + "item.create.minecart_coupling.tooltip.summary": "將多個_礦車_或運輸結構鏈接在一起,構成雄偉的火車。", + "item.create.minecart_coupling.tooltip.condition1": "作用與礦車時", + "item.create.minecart_coupling.tooltip.behaviour1": "將兩個礦車耦合在一起,在移動時將它們保持_恒定的距離_。", + + "create.tooltip.wip": "半成品", + "create.tooltip.workInProgress": "尚在製作中!", + "create.tooltip.randomWipDescription0": "禁止將此物品給屁孩。", + "create.tooltip.randomWipDescription1": "每~一~次~你使用此物品時,就會使一隻小熊貓死亡。", + "create.tooltip.randomWipDescription2": "使用此物品請自負後果。", + "create.tooltip.randomWipDescription3": "快走開,這不是你要找的東西(搖手指", + "create.tooltip.randomWipDescription4": "啟動自爆模式,10、9、8...。", + "create.tooltip.randomWipDescription5": "你已經沒有退路了。", + "create.tooltip.randomWipDescription6": "作者我將不負任何你使用此物所造成的責任。", + "create.tooltip.randomWipDescription7": "這東西不是給你用的,再找找吧!", + "create.tooltip.randomWipDescription8": "用了就死定了。", + + + "_": "->------------------------] Ponder Content [------------------------<-", + + "create.ponder.hold_to_ponder": "按住 [%1$s] 來思考此物品", + "create.ponder.subject": "本場景的主題", + "create.ponder.pondering": "思考有關於...", + "create.ponder.identify_mode": "暫停模式已啟動\n按 [%1$s] 來取消暫停模式", + "create.ponder.associated": "相關物品", + "create.ponder.close": "關閉", + "create.ponder.identify": "暫停", + "create.ponder.next": "下個場景", + "create.ponder.previous": "上個場景", + "create.ponder.replay": "重放", + "create.ponder.think_back": "返回", + "create.ponder.slow_text": "降低文字顯示速度", + "create.ponder.shared.movement_anchors": "有了機殼底盤和強力膠就可以移動大型結構", + "create.ponder.shared.rpm32": "32 RPM", + "create.ponder.shared.sneak_and": "潛行 +", + "create.ponder.shared.storage_on_contraption": "與結構相連的儲物空間會自動撿取物品", + "create.ponder.shared.behaviour_modify_wrench": "使用扳手來調整這個動作", + "create.ponder.shared.rpm8": "8 RPM", + "create.ponder.shared.ctrl_and": "Ctrl +", + "create.ponder.shared.rpm16_source": "轉速: 16 RPM", + "create.ponder.shared.rpm16": "16 RPM", + "create.ponder.tag.kinetic_sources": "動能產生裝置", + "create.ponder.tag.kinetic_sources.description": "該裝置能夠產生動能", + "create.ponder.tag.contraption_actor": "Contraption Actors", + "create.ponder.tag.contraption_actor.description": "Components which expose special behaviour when attached to a moving contraption", + "create.ponder.tag.arm_targets": "機械手臂的目標物", + "create.ponder.tag.arm_targets.description": "該裝置可作為機械手臂的工作目標", + "create.ponder.tag.logistics": "傳輸物品", + "create.ponder.tag.logistics.description": "該裝置用於物品的傳輸", + "create.ponder.tag.movement_anchor": "Movement Anchors", + "create.ponder.tag.movement_anchor.description": "Components which allow the creation of moving contraptions, animating an attached structure in a variety of ways", + "create.ponder.tag.creative": "創造模式", + "create.ponder.tag.creative.description": "該裝置無法在生存模式中獲得", + "create.ponder.tag.kinetic_relays": "動能傳遞方塊", + "create.ponder.tag.kinetic_relays.description": "該裝置用於傳遞動能", + "create.ponder.tag.windmill_sails": "風車軸承的帆", + "create.ponder.tag.windmill_sails.description": "建造風車時用於產生動能的帆,每個帆對風車產生的效果都是同等的", + "create.ponder.tag.contraption_assembly": "方塊連接物件", + "create.ponder.tag.contraption_assembly.description": "此物件用於連接各個零件以便組成一個成品", + "create.ponder.tag.decoration": "裝飾", + "create.ponder.tag.decoration.description": "這些零件通常用於裝飾", + "create.ponder.tag.kinetic_appliances": "動能利用裝置", + "create.ponder.tag.kinetic_appliances.description": "這些裝置利用動能運作", + "create.ponder.tag.redstone": "邏輯控制裝置", + "create.ponder.tag.redstone.description": "這些裝置會在紅石電路中發揮用處", + "create.ponder.tag.fluids": "液體控制裝置", + "create.ponder.tag.fluids.description": "這些裝置可傳輸並利用液體", + + "create.ponder.adjustable_pulse_repeater.header": "使用可調式脈衝中繼器來控制訊號", + "create.ponder.adjustable_pulse_repeater.text_1": "可調式脈衝中繼器每次運作時會產生一個短脈衝", + "create.ponder.adjustable_pulse_repeater.text_2": "使用滑鼠滾輪來設定啟動後到產生脈衝的延遲", + "create.ponder.adjustable_pulse_repeater.text_3": "延遲可設定到最大30分鐘", + + "create.ponder.adjustable_repeater.header": "使用可調式中繼器來控制訊號", + "create.ponder.adjustable_repeater.text_1": "可調式中繼器就像一般的中繼器", + "create.ponder.adjustable_repeater.text_2": "收到訊號後在設定好的時間過後才啟動...", + "create.ponder.adjustable_repeater.text_3": "...訊號停止後也需要相隔同樣的時間過後才會停止", + "create.ponder.adjustable_repeater.text_4": "使用滑鼠滾輪來設定延遲", + "create.ponder.adjustable_repeater.text_5": "延遲可設定到最大30分鐘", + + "create.ponder.analog_lever.header": "使用可調式拉桿來控制訊號", + "create.ponder.analog_lever.text_1": "可調式拉桿是一種小巧而輕準的紅石能源", + "create.ponder.analog_lever.text_2": "右鍵來增加其紅石訊號輸出", + "create.ponder.analog_lever.text_3": "潛行並右鍵來減少其紅石訊號輸出", + + "create.ponder.andesite_tunnel.header": "使用安山岩物品隧道", + "create.ponder.andesite_tunnel.text_1": "安山岩物品隧道可以覆蓋在輸送帶上", + "create.ponder.andesite_tunnel.text_2": "當安山岩物品隧道側邊連接到另一條輸送帶時...", + "create.ponder.andesite_tunnel.text_3": "...隧道將會從經過的整組物品中拿出一個丟到另一條輸送帶上", + "create.ponder.andesite_tunnel.text_4": "剩餘物品則按照原路輸出", + + "create.ponder.basin.header": "在作業盆中處理物品", + "create.ponder.basin.text_1": "作業盆可以放入物品或液體來進行處理", + "create.ponder.basin.text_2": "在每次的處理完成後, 作業盆會試著輸出成品到他的側面下方", + "create.ponder.basin.text_3": "當側面下方有一個有效的容器或設備, 作業盆側面會出現一個輸出嘴", + "create.ponder.basin.text_4": "有很多的容器或設備可以觸發上述現象", + "create.ponder.basin.text_5": "作業盆輸出的成品會被儲存到該容器或設備內", + "create.ponder.basin.text_6": "如果側面沒有出現輸出嘴, 則作業盆內的成品則不會輸出", + "create.ponder.basin.text_7": "這個原理用在產生的成品為下一輪處理的原料時相當有用", + "create.ponder.basin.text_8": "期望的成品將會從作業盆中輸出", + "create.ponder.basin.text_9": "加裝過濾器可防止未被處理的物品輸出", + + "create.ponder.bearing_modes.header": "機械軸承的工作模式", + "create.ponder.bearing_modes.text_1": "當機械軸承停止時,它會控制整個結構停在最近的垂直線上並實體化", + "create.ponder.bearing_modes.text_2": "你可以控制它不要實體化,或是在結構起始位置才實體化", + + "create.ponder.belt_casing.header": "包裹住輸送帶", + "create.ponder.belt_casing.text_1": "安山岩機殼或黃銅機殼可以用來裝飾輸送帶", + "create.ponder.belt_casing.text_2": "使用扳手可以移除機殼", + + "create.ponder.belt_connector.header": "使用輸送帶", + "create.ponder.belt_connector.text_1": "手持輸送帶對兩根傳動軸右鍵以安裝輸送帶", + "create.ponder.belt_connector.text_2": "不小心點到傳動軸的話可以用潛行+右鍵來取消選取", + "create.ponder.belt_connector.text_3": "輸送帶間只要有空間就能安裝額外的傳動軸", + "create.ponder.belt_connector.text_4": "相同輸送帶接出來的傳動軸轉速及轉向會相同", + "create.ponder.belt_connector.text_5": "使用扳手可以移除已安裝的傳動軸", + "create.ponder.belt_connector.text_6": "輸送帶可以被各種染料染色", + + "create.ponder.belt_directions.header": "輸送帶正確的安裝方向", + "create.ponder.belt_directions.text_1": "輸送帶不可以隨意聯結", + "create.ponder.belt_directions.text_2": "1. 輸送帶可以水平連結", + "create.ponder.belt_directions.text_3": "2. 輸送帶可以對角連結", + "create.ponder.belt_directions.text_4": "3. 輸送帶可以垂直連結", + "create.ponder.belt_directions.text_5": "4. 也可以連結在垂直的傳動軸上", + "create.ponder.belt_directions.text_6": "這些都是可以使用的連接方式,輸送帶可以放置的長度為2~20格", + + "create.ponder.belt_transport.header": "將輸送帶用於後勤", + "create.ponder.belt_transport.text_1": "被啟動的輸送帶能運送物品及實體", + "create.ponder.belt_transport.text_2": "空手對輸送帶上的物品右鍵即可從輸送帶上取下物品", + + "create.ponder.blaze_burner.header": "餵食烈焰使者動力爐", + "create.ponder.blaze_burner.text_1": "烈焰使者動力爐可以用來加熱作業盆", + "create.ponder.blaze_burner.text_2": "你需要餵食可以燃燒的物品來加熱作業盆", + "create.ponder.blaze_burner.text_3": "餵食熔岩蛋糕可以讓烈焰使者動力爐加熱到另一個更高的境界", + "create.ponder.blaze_burner.text_4": "使用機械手或機械手臂來將餵食自動化", + + "create.ponder.brass_funnel.header": "黃銅漏斗", + "create.ponder.brass_funnel.text_1": "安山岩漏斗每次只能傳輸一個物品", + "create.ponder.brass_funnel.text_2": "但黃銅漏斗每次可以傳輸整組物品", + "create.ponder.brass_funnel.text_3": "對漏斗上的過濾格使用滾輪可以調整每次輸出物品的數量", + "create.ponder.brass_funnel.text_4": "手持物品對漏斗上的過濾格右鍵可以限制漏斗只輸出該物品", + + "create.ponder.brass_tunnel.header": "使用黃銅隧道", + "create.ponder.brass_tunnel.text_1": "黃銅隧道必須裝設在輸送帶上", + "create.ponder.brass_tunnel.text_2": "黃銅隧道輸出入口上都有過濾格", + "create.ponder.brass_tunnel.text_3": "在輸入口上的過濾器會阻擋不相符的物品", + "create.ponder.brass_tunnel.text_4": "在輸出口上的過濾器可依種類整理排列物品", + "create.ponder.brass_tunnel.text_5": "如果數種與過濾相符的物品通過隧道, 隧道的分配模式將決定如何處理這些物品", + "create.ponder.brass_tunnel.text_6": "在平行相鄰的輸送帶上,相鄰的黃銅隧道將會成為一組", + "create.ponder.brass_tunnel.text_7": "輸入該組內的物品將會採用該組隧道的分配模式輸送", + "create.ponder.brass_tunnel.text_8": "在這個情況下, 物品也能被直接輸入到隧道方塊", + + "create.ponder.brass_tunnel_modes.header": "黃銅隧道的分配模式", + "create.ponder.brass_tunnel_modes.text_1": "使用扳手來調整隧道的分配模式", + "create.ponder.brass_tunnel_modes.text_10": "'同步輸入' 是一種黃銅隧道的特殊設定", + "create.ponder.brass_tunnel_modes.text_11": "當同組內的所有隧道都有一個可通過的物品時,所有隧道才可輸出物品", + "create.ponder.brass_tunnel_modes.text_12": "這確保了同組隧道所在的輸送帶都能以同一速率輸出物品", + "create.ponder.brass_tunnel_modes.text_2": "'分流輸出' 此模式會將物品輸出到該組隧道可用的輸出口", + "create.ponder.brass_tunnel_modes.text_3": "如果該組隧道內某個輸出口無法再輸出物品,則該輸出口會被跳過", + "create.ponder.brass_tunnel_modes.text_4": "'強制分流輸出' 模式不會跳過某個無法輸出物品的輸出口, 直到該輸出口可以輸出物品", + "create.ponder.brass_tunnel_modes.text_5": "'輪詢輸入' 模式將會保持整組物品完整性, 然後在有輸出口可以輸出時才輸入物品", + "create.ponder.brass_tunnel_modes.text_6": "如果該組隧道內某個輸出口無法再輸出物品,則該輸出口會被跳過", + "create.ponder.brass_tunnel_modes.text_7": "'強制輪詢輸入' 模式不會跳過某個無法輸出物品的輸出口, 直到該輸出口可以輸出物品", + "create.ponder.brass_tunnel_modes.text_8": "'鄰近優先' 模式會將物品輸出到該組隧道離物品輸入口最近的出口", + "create.ponder.brass_tunnel_modes.text_9": "'隨機輸出' 模式會隨機選擇同組隧道的一個輸出口輸出", + + "create.ponder.cart_assembler.header": "使用礦車裝修站裝修礦車來移動結構", + "create.ponder.cart_assembler.text_1": "礦車裝修站會將所有連接到礦車的結構裝在礦車上", + "create.ponder.cart_assembler.text_2": "如果沒有紅時訊號,它會將礦車結構分解成方塊", + "create.ponder.cart_assembler.text_3": "對礦車結構使用扳手可以將礦車變成物品", + + "create.ponder.cart_assembler_dual.header": "雙礦車結構", + "create.ponder.cart_assembler_dual.text_1": "當兩台礦車在同一礦車結構上", + "create.ponder.cart_assembler_dual.text_2": "任一礦車裝修站收到紅石訊號時,會形成完整的一個礦車結構", + "create.ponder.cart_assembler_dual.text_3": "整個礦車結構會類似於用礦車連結器連接兩個礦車結構", + + "create.ponder.cart_assembler_modes.header": "礦車結構的方向設定", + "create.ponder.cart_assembler_modes.text_1": "礦車結構會隨著礦車方向改變", + "create.ponder.cart_assembler_modes.text_2": "如果在裝修站鎖定其方向,則結構方向不會隨礦車方向改變", + + "create.ponder.cart_assembler_rails.header": "其他種類的礦車和鐵軌", + "create.ponder.cart_assembler_rails.text_1": "放在普通鐵軌上的礦車裝修站不會影響礦車的動作", + "create.ponder.cart_assembler_rails.text_2": "如果裝修站在沒有紅石訊號的動力鐵軌或控制鐵軌上,則礦車會停下直到鐵軌收到紅石訊號", + "create.ponder.cart_assembler_rails.text_3": "有幾種礦車可以當作錨來使用", + "create.ponder.cart_assembler_rails.text_4": "熔爐礦車會盡可能維持熔煉狀態,並會拿取鄰近儲存結構上的燃料", + + "create.ponder.chain_drive.header": "使用鏈式傳動箱傳遞動能", + "create.ponder.chain_drive.text_1": "同一排上的鏈式傳動箱會互相傳遞動能", + "create.ponder.chain_drive.text_2": "所有傳動軸此時會朝相同方向旋轉", + "create.ponder.chain_drive.text_3": "任一個鏈式傳動箱被旋轉90度時所有鏈式傳動箱仍可正常運作", + + "create.ponder.chain_gearshift.header": "使用可調式鏈式變速箱來調整轉速", + "create.ponder.chain_gearshift.text_1": "未被控制的可調式鏈式變速箱與鏈式傳動箱無異", + "create.ponder.chain_gearshift.text_2": "當可調式鏈式變速箱被啟動後,它會把轉速提升兩倍傳至其他鏈式傳動箱", + "create.ponder.chain_gearshift.text_3": "當被啟動的可調式鏈式變速箱並不是動能輸入端,則它會把轉速減半", + "create.ponder.chain_gearshift.text_4": "上述兩種狀況中,其他鏈式傳動箱都會被可調式鏈式變速箱提升兩倍的轉速", + "create.ponder.chain_gearshift.text_5": "利用紅石訊號的強弱可以調整轉速倍率為x1或x2", + "create.ponder.chain_gearshift.text_6": "12 RPM", + + "create.ponder.chute.header": "使用滑道向下輸送物品", + "create.ponder.chute.text_1": "滑道可以在兩個垂直的儲物空間中輸送物品", + "create.ponder.chute.text_2": "使用扳手可以讓它產生一個觀景窗", + "create.ponder.chute.text_3": "在滑道的側面放置另一個滑道,會產生一個斜狀的滑道", + + "create.ponder.chute_upward.header": "使用滑道向上輸送物品", + "create.ponder.chute_upward.text_1": "在滑道上方或下方使用鼓風機時,物品會根據被向上或向下吹", + "create.ponder.chute_upward.text_2": "裝備MR護目鏡以觀測物品的傳輸方向", + "create.ponder.chute_upward.text_3": "如滑道底端被擋住,則物品只能由側邊進行輸出入", + + "create.ponder.clockwork_bearing.header": "使用時鐘軸承來建造時鐘結構", + "create.ponder.clockwork_bearing.text_1": "時鐘軸承會黏住其前方方塊產生一個時針結構", + "create.ponder.clockwork_bearing.text_2": "在輸入動能後,該結構會依照遊戲時間來旋轉", + "create.ponder.clockwork_bearing.text_3": "3:00", + "create.ponder.clockwork_bearing.text_4": "4:00", + "create.ponder.clockwork_bearing.text_5": "對軸承右鍵會使結構啟動或停止", + "create.ponder.clockwork_bearing.text_6": "在時針結構的前方可再增加一組分針結構", + "create.ponder.clockwork_bearing.text_7": "你必須確保時針分針結構間未被使用強力膠之類的相連零件", + "create.ponder.clockwork_bearing.text_8": "分針結構此時將正常運作", + + "create.ponder.clutch.header": "使用離合器控制動能", + "create.ponder.clutch.text_1": "離合器能將動能直線傳遞", + "create.ponder.clutch.text_2": "當離合器被啟動,離合器會中斷動能傳遞", + + "create.ponder.cog_speedup.header": "使用大小齒輪來變速", + "create.ponder.cog_speedup.text_1": "大齒輪與小齒輪可以斜向傳遞動能", + "create.ponder.cog_speedup.text_2": "從大齒輪傳遞動能至小齒輪時,轉速加倍", + "create.ponder.cog_speedup.text_3": "從小齒輪傳遞動能至大齒輪時,轉速減半", + + "create.ponder.cogwheel.header": "使用齒輪來傳遞動能", + "create.ponder.cogwheel.text_1": "齒輪會將動力傳遞至臨近的齒輪", + "create.ponder.cogwheel.text_2": "以此方式連接的齒輪,旋轉方向相反", + + "create.ponder.creative_motor.header": "使用創造馬達產生動能", + "create.ponder.creative_motor.text_1": "創造馬達不僅能夠手動設定輸出動能,而且體積相當小巧", + "create.ponder.creative_motor.text_2": "對其背後面板滾動滾輪,可以改變馬達的轉速", + + "create.ponder.crushing_wheels.header": "使用粉碎輪處理物品", + "create.ponder.crushing_wheels.text_1": "一對粉碎輪,磨物快又準", + "create.ponder.crushing_wheels.text_2": "接入的動能必須使這兩個輪子契合轉動", + "create.ponder.crushing_wheels.text_3": "扔入或者放入的物品都會被粉碎處理", + "create.ponder.crushing_wheels.text_4": "你也可以使用自動化進行物品的輸入以及撿取", + + "create.ponder.deployer.header": "使用機械手", + "create.ponder.deployer.text_1": "在機械手獲得動能後能夠模仿玩家的各種行為", + "create.ponder.deployer.text_10": "對機械手手部右鍵,即可將手上的物品給它使用", + "create.ponder.deployer.text_11": "物品也可以自動化輸入到機械手內", + "create.ponder.deployer.text_12": "機械手附帶一個過濾格", + "create.ponder.deployer.text_13": "當設定了過濾後,只有當它的手中物品與過濾格相符時,它才會工作", + "create.ponder.deployer.text_14": "只有與過濾格相符的物品才可輸入...", + "create.ponder.deployer.text_15": "...不符的物品可被取出來", + "create.ponder.deployer.text_2": "它只會與它正前方兩格處的位置進行互動", + "create.ponder.deployer.text_3": "放在在它面前的方塊不會阻攔它的工作", + "create.ponder.deployer.text_4": "機械手可以:", + "create.ponder.deployer.text_5": "放置方塊", + "create.ponder.deployer.text_6": "使用物品", + "create.ponder.deployer.text_7": "啟動方塊", + "create.ponder.deployer.text_8": "採收方塊", + "create.ponder.deployer.text_9": "以及攻擊生物", + + "create.ponder.deployer_contraption.header": "在裝置上使用機械手", + "create.ponder.deployer_contraption.text_1": "當機械手在移動的結構上時...", + "create.ponder.deployer_contraption.text_2": "機械手會對每一個經過的方塊使用裝置中任意容器內的物品", + "create.ponder.deployer_contraption.text_3": "可以透過過濾格來指定其從存儲空間中抽取的物品", + + "create.ponder.deployer_modes.header": "機械手的工作模式", + "create.ponder.deployer_modes.text_1": "在設設情況下,機械手模仿玩家的右鍵", + "create.ponder.deployer_modes.text_2": "使用扳手可以將模式調整為模仿玩家的左鍵", + + "create.ponder.deployer_redstone.header": "使用紅石控制機械手", + "create.ponder.deployer_redstone.text_1": "當機械手收到紅時訊號時會停止工作", + "create.ponder.deployer_redstone.text_2": "在停止工作前,機械手會完成目前手頭上的工作", + "create.ponder.deployer_redstone.text_3": "因此,輸入脈衝訊號可以使其每次只進行一個週期的工作", + + "_": "m", + + "create.ponder.depot.header": "使用置物台", + "create.ponder.depot.text_1": "置物台可以被當成一個“靜止的”傳送帶原件使用", + "create.ponder.depot.text_2": "右擊可以手動放置或取下物品", + "create.ponder.depot.text_3": "與傳送帶一樣,它也可以將其內的物品轉送到其他設備中進行加工...", + "create.ponder.depot.text_4": "...同時物品也可以被機械手存取", + + "create.ponder.empty_blaze_burner.header": "使用空的烈焰人燃燒室", + "create.ponder.empty_blaze_burner.text_1": "手持空的烈焰人燃燒室右擊烈焰人來抓取烈焰人", + "create.ponder.empty_blaze_burner.text_2": "或者,也可以透過右擊烈焰人刷怪籠來填充啟動烈焰人燃燒室", + "create.ponder.empty_blaze_burner.text_3": "這樣,你便有了一個可供部分機器加工的熱源", + "create.ponder.empty_blaze_burner.text_4": "如果是為了美觀,空的烈焰人燃燒室也可以被打火石點燃", + "create.ponder.empty_blaze_burner.text_5": "但是,這樣的熱源不足以給機器提加工供足夠的熱量", + + "create.ponder.fan_direction.header": "鼓風機的氣流", + "create.ponder.fan_direction.text_1": "鼓風機使用動能來製造氣流", + "create.ponder.fan_direction.text_2": "流速以及方向由所接收動能的強弱以及方向而定", + + "create.ponder.fan_processing.header": "使用鼓風機加工物品", + "create.ponder.fan_processing.text_1": "當氣流吹過熔岩時,氣流會被加熱", + "create.ponder.fan_processing.text_2": "熱氣流中的物品會被冶煉", + "create.ponder.fan_processing.text_3": "但在氣流中的食物會被直接燒成灰", + "create.ponder.fan_processing.text_4": "而想要烹飪食物,必須要透過吹過火焰的氣流來煙燻食物", + "create.ponder.fan_processing.text_5": "當氣流吹過水後,便可用於洗滌物品", + "create.ponder.fan_processing.text_6": "這種加工方法可以做到不少有趣的事情", + "create.ponder.fan_processing.text_7": "鼓風機的轉速對加工的速度沒有影響,只影響氣流的吹拂距離", + "create.ponder.fan_processing.text_8": "而那些放置在置物台或者傳送帶上的物品,鼓風機也是可以處理的", + + "create.ponder.fan_source.header": "使用鼓風機來產生動能", + "create.ponder.fan_source.text_1": "如鼓風機的扇葉向下朝著熱源放置,鼓風機可以藉此產生動能", + "create.ponder.fan_source.text_2": "當鼓風機接受紅石訊號後,它便會向外供給動能", + + "create.ponder.flywheel.header": "使用飛輪來產生動能", + "create.ponder.flywheel.text_1": "飛輪和熔爐引擎必須配套使用,方可產生動能", + "create.ponder.flywheel.text_2": "如此產生的動能具有非常大的應力值", + "create.ponder.flywheel.text_3": "使用高爐會使得引擎的效率翻倍", + + "create.ponder.funnel_compat.header": "漏斗的相容性", + "create.ponder.funnel_compat.text_1": "漏斗可以與一些其他組件互動", + "create.ponder.funnel_compat.text_2": "動力鋸", + "create.ponder.funnel_compat.text_3": "置物台", + "create.ponder.funnel_compat.text_4": "分液池", + + "create.ponder.funnel_direction.header": "物流方向", + "create.ponder.funnel_direction.text_1": "直接放置時,漏斗會將物品從容器中取出", + "create.ponder.funnel_direction.text_2": "潛行時放置時,漏斗會將物品置入容器中", + "create.ponder.funnel_direction.text_3": "使用扳手可以改變漏斗的存/取模式", + "create.ponder.funnel_direction.text_4": "對大多數朝向放置的漏斗都具有此特性", + "create.ponder.funnel_direction.text_5": "在傳送帶末端放置的漏斗會根據傳送帶的傳動方向存/取物品", + + "create.ponder.funnel_intro.header": "使用漏斗", + "create.ponder.funnel_intro.text_1": "用漏斗來存取物品欄內的物品,可謂又快又好", + + "create.ponder.funnel_redstone.header": "紅石訊號控制", + "create.ponder.funnel_redstone.text_1": "紅石訊號會使漏斗停止工作", + + "create.ponder.funnel_transfer.header": "直接運輸", + "create.ponder.funnel_transfer.text_1": "漏斗無法將物品傳輸到非開放式的物品欄中", + "create.ponder.funnel_transfer.text_2": "溜槽和智慧溜槽更適用於這樣的場景", + "create.ponder.funnel_transfer.text_3": "水平傳輸也是如此,也許傳送帶更方便快捷", + + "create.ponder.furnace_engine.header": "使用熔爐引擎生產動能", + "create.ponder.furnace_engine.text_1": "熔爐引擎會在與其相連熔爐工作時生產動能", + "create.ponder.furnace_engine.text_2": "如此產生的動能具有非常大的應力值", + "create.ponder.furnace_engine.text_3": "使用高爐會使得引擎的效率翻倍", + + "create.ponder.gantry_carriage.header": "使用起重機取物器", + "create.ponder.gantry_carriage.text_1": "起重機取物器可以被放置在起重機杆上,並且可以沿著起重機杆運動", + "create.ponder.gantry_carriage.text_2": "起重機可以移動其黏附的方塊", + + "create.ponder.gantry_cascaded.header": "串聯起重機", + "create.ponder.gantry_cascaded.text_1": "無需強力膠,取物器便可與起重機杆相連", + "create.ponder.gantry_cascaded.text_2": "即使是在移動的起重機杆上也是如此", + "create.ponder.gantry_cascaded.text_3": "因此,起重機系統可以串聯起來,如此可以影響到多軸向的運動", + + "create.ponder.gantry_direction.header": "起重機移動方向", + "create.ponder.gantry_direction.text_1": "起重機杆可以有相反的方向", + "create.ponder.gantry_direction.text_2": "取物器的移動方向取決於起重機杆的方向", + "create.ponder.gantry_direction.text_3": "......以及起重機杆的旋轉方向", + "create.ponder.gantry_direction.text_4": "在旋轉傳遞中,此規則同樣適用", + + "create.ponder.gantry_redstone.header": "起重機的力傳遞", + "create.ponder.gantry_redstone.text_1": "被紅石訊號啟動的起重機,將不會移動其上的取物器", + "create.ponder.gantry_redstone.text_2": "作為替代,杆上的動能會傳遞到取物器的輸出杆上", + + "create.ponder.gantry_shaft.header": "使用起重機杆", + "create.ponder.gantry_shaft.text_1": "起重機杆組成了起重機結構的基礎。與其相接的載物器可以沿著杆進行移動。", + "create.ponder.gantry_shaft.text_2": "起重機結構可以移動與其相接的方塊。", + + "create.ponder.gearbox.header": "使用十字齒輪箱傳遞動能", + "create.ponder.gearbox.text_1": "更改旋轉軸,很容易使得整個旋轉體系變得臃腫不堪", + "create.ponder.gearbox.text_2": "十字齒輪箱則是替代方案,它的體積更為小巧緊", + "create.ponder.gearbox.text_3": "側邊連接的傳動桿,旋轉方向與輸入端一致", + "create.ponder.gearbox.text_4": "直線連接的傳動桿,旋轉方向會被反轉", + + "create.ponder.gearshift.header": "使用反轉齒輪箱控制動能", + "create.ponder.gearshift.text_1": "反轉齒輪箱可以直線傳輸旋轉", + "create.ponder.gearshift.text_2": "通入紅石訊號後,輸出端的旋轉方向會被反轉", + + "create.ponder.hand_crank.header": "使用手搖把手產生動能", + "create.ponder.hand_crank.text_1": "玩家可以使用手搖把手來手動產生動能", + "create.ponder.hand_crank.text_2": "按住右鍵可以逆時針旋轉它", + "create.ponder.hand_crank.text_3": "它產生的轉速相對較高", + "create.ponder.hand_crank.text_4": "潛行長按右鍵可以順時針旋轉它", + + "create.ponder.large_cogwheel.header": "使用大齒輪傳遞動能", + "create.ponder.large_cogwheel.text_1": "大齒輪可以以特定的角度相互連接", + "create.ponder.large_cogwheel.text_2": "可以利用大齒輪變更旋轉軸向", + + "create.ponder.linear_chassis_attachment.header": "使用機殼底盤黏合方塊", + "create.ponder.linear_chassis_attachment.text_1": "它的開放面可以變為黏性面", + "create.ponder.linear_chassis_attachment.text_2": "再次點擊黏性面,可以將它的相反面也變得具有黏性", + "create.ponder.linear_chassis_attachment.text_3": "空手潛行右擊可以移除此面的黏性物", + "create.ponder.linear_chassis_attachment.text_4": "黏性面可以將此面前方的一長條方塊黏住", + "create.ponder.linear_chassis_attachment.text_5": "使用扳手可以精確控制底盤的影響範圍", + "create.ponder.linear_chassis_attachment.text_6": "按住 Ctrl 滑動滾輪,你可以一次性調節所有底盤的影響範圍", + "create.ponder.linear_chassis_attachment.text_7": "若想讓底盤的其他面也能黏方塊,你需要用到強力膠", + "create.ponder.linear_chassis_attachment.text_8": "利用這些機制,任何形狀的機制都可以像裝置那樣移動", + + "create.ponder.linear_chassis_group.header": "成組移動機殼底盤", + "create.ponder.linear_chassis_group.text_1": "相鄰的機殼底盤可以相互連接在一起", + "create.ponder.linear_chassis_group.text_2": "其中的一個底盤若被移動,其餘的底盤也會跟著移動", + "create.ponder.linear_chassis_group.text_3": "不同種類的底盤,或者是朝向不一致的底盤,將不會相連", + + "create.ponder.mechanical_arm.header": "設定動力臂", + "create.ponder.mechanical_arm.text_1": "你得在放置動力臂之前就設定好它的輸入以及輸出端", + "create.ponder.mechanical_arm.text_2": "手持動力臂右擊某個存儲空間,可以將其指定為目標", + "create.ponder.mechanical_arm.text_3": "再次右擊可以將其在輸入端(藍色)以及輸出端(橙色)之間切換", + "create.ponder.mechanical_arm.text_4": "左擊此組件可以移除選擇", + "create.ponder.mechanical_arm.text_5": "將動力臂放下來後,它會將此前選擇的方塊作為目標", + "create.ponder.mechanical_arm.text_6": "在有效範圍內,機械手臂可以有任意數量的輸出以及輸入端", + "create.ponder.mechanical_arm.text_7": "然而,並不是所有的存儲空間可以被直接互動", + "create.ponder.mechanical_arm.text_8": "在此情況下,漏斗和置物台可以解決此問題", + + "create.ponder.mechanical_arm_filtering.header": "過濾動力臂的輸出端", + "create.ponder.mechanical_arm_filtering.text_1": "輸入", + "create.ponder.mechanical_arm_filtering.text_2": "輸出", + "create.ponder.mechanical_arm_filtering.text_3": "有時,你會想著利用某種過濾限煞車力臂的目標", + "create.ponder.mechanical_arm_filtering.text_4": "動力臂自身並不提供任何過濾選項", + "create.ponder.mechanical_arm_filtering.text_5": "然而,若將黃銅漏斗作為目標,則漏斗的過濾槽則可以應用至動力臂上", + "create.ponder.mechanical_arm_filtering.text_6": "動力臂足夠智慧,它不會去拿取那些它無法分配的物品", + + "create.ponder.mechanical_arm_modes.header": "動力臂的分配模式", + "create.ponder.mechanical_arm_modes.text_1": "輸入", + "create.ponder.mechanical_arm_modes.text_2": "輸出", + "create.ponder.mechanical_arm_modes.text_3": "若動力臂必須在數個有效的輸出端之間作出選擇...", + "create.ponder.mechanical_arm_modes.text_4": "...它會依照自己的設定選擇特定的行為", + "create.ponder.mechanical_arm_modes.text_5": "手持扳手對其滑動滾輪,可以改變其設定", + "create.ponder.mechanical_arm_modes.text_6": "輪詢調度模式很好理解,即循環輸出至所有有效的輸出端", + "create.ponder.mechanical_arm_modes.text_7": "如果某個輸出端無法容納更多物品,則它會被跳過", + "create.ponder.mechanical_arm_modes.text_8": "強制輪詢調度不會跳過任何輸出端,動力臂會一直等待,直到輸出端有空位容納物品輸入", + "create.ponder.mechanical_arm_modes.text_9": "最近優先模式會使得動力臂先將物品輸出至更早被選擇的輸出端", + + "create.ponder.mechanical_arm_redstone.header": "利用紅石訊號控制動力臂", + "create.ponder.mechanical_arm_redstone.text_1": "通入紅石訊號後,動力臂會停止工作", + "create.ponder.mechanical_arm_redstone.text_2": "在停止工作前,它會完成目前正在進行的工作週期", + "create.ponder.mechanical_arm_redstone.text_3": "因此,通入單次負紅石脈衝可以精確控制動力臂,使其每次只進行單個週期的工作", + + "create.ponder.mechanical_bearing.header": "使用動力軸承移動結構", + "create.ponder.mechanical_bearing.text_1": "動力軸承會與其前方的方塊黏合在一起", + "create.ponder.mechanical_bearing.text_2": "接收到動能後,它會將這一黏合結構組裝為旋轉裝置", + + "create.ponder.mechanical_crafter.header": "設置動力合成器", + "create.ponder.mechanical_crafter.text_1": "動力合成器陣列可用於自動化任何合成配方的製作", + "create.ponder.mechanical_crafter.text_2": "使用扳手可以調控合成器的合成通路", + "create.ponder.mechanical_crafter.text_3": "所有的合成通路必須匯集到任意一側的一個出口,整套合成器方可算是設置正確", + "create.ponder.mechanical_crafter.text_4": "輸出產物會被放入位於出口的存儲空間中", + "create.ponder.mechanical_crafter.text_5": "動力合成器的運轉需要動能的供應", + "create.ponder.mechanical_crafter.text_6": "右擊合成器正面,可以手動放入物品", + "create.ponder.mechanical_crafter.text_7": "一旦合成通路上的所有合成槽位都有了物品,合成就會開始", + "create.ponder.mechanical_crafter.text_8": "而對於那些沒有完全占滿所有合成器槽位的配方,你可以通入紅石訊號強制開啟合成", + + "create.ponder.mechanical_crafter_connect.header": "為合成器連接物品欄", + "create.ponder.mechanical_crafter_connect.text_1": "合成器可以自動接受向其輸入的物品", + "create.ponder.mechanical_crafter_connect.text_2": "對其背面使用扳手,可以連接合成器", + "create.ponder.mechanical_crafter_connect.text_3": "所有相連的合成器可以訪問同一個位置的輸入", + + "create.ponder.mechanical_crafter_covers.header": "蓋住動力合成器的合成槽", + "create.ponder.mechanical_crafter_covers.text_1": "有些配方需要額外的合成器,來補足合成通路上的間隙", + "create.ponder.mechanical_crafter_covers.text_2": "使用合成槽蓋板,合成器會在合成進行時的行為就如同一個空的合成槽位", + "create.ponder.mechanical_crafter_covers.text_3": "被蓋住的合成器並不會阻斷共享輸入端的影響", + + "create.ponder.mechanical_drill.header": "使用機械鑽頭破壞方塊", + "create.ponder.mechanical_drill.text_1": "當向其通入動能後,機械鑽頭會破壞它面前的方塊", + "create.ponder.mechanical_drill.text_2": "它的挖掘速度取決於通入的動能轉速", + + "create.ponder.mechanical_drill_contraption.header": "在裝置中使用機械鑽頭", + "create.ponder.mechanical_drill_contraption.text_1": "在運動裝置中使用機械鑽頭時...", + "create.ponder.mechanical_drill_contraption.text_2": "...它會破壞掉它撞上的方塊", + + "create.ponder.mechanical_harvester.header": "在裝置中使用動力收割機", + "create.ponder.mechanical_harvester.text_1": "在運動裝置中使用動力收割機時...", + "create.ponder.mechanical_harvester.text_2": "它會採收其路徑上的作物,並重設這些作物的生長進度", + + "create.ponder.mechanical_mixer.header": "使用動力攪拌器處理物品", + "create.ponder.mechanical_mixer.text_1": "使用攪拌器和工作盆,你可以自動化某些合成配方", + "create.ponder.mechanical_mixer.text_2": "有效配方包括各種無序合成配方,以及一些額外的配方", + "create.ponder.mechanical_mixer.text_3": "一些配方可能需要使用烈焰人燃燒室提供熱量", + "create.ponder.mechanical_mixer.text_4": "過濾槽可用於解決兩個配方相互衝突的情況", + + "create.ponder.mechanical_piston.header": "使用動力活塞移動結構", + "create.ponder.mechanical_piston.text_1": "動力活塞可以移動它前方的方塊", + "create.ponder.mechanical_piston.text_2": "移動速度和方向取決於通入活塞的動能", + "create.ponder.mechanical_piston.text_3": "黏性動力活塞可以將相接的方塊拉回來", + + "create.ponder.mechanical_piston_modes.header": "動力活塞的移動模式", + "create.ponder.mechanical_piston_modes.text_1": "一旦活塞停下,被移動的結構就會回退到方塊狀態", + "create.ponder.mechanical_piston_modes.text_2": "你也可以將其設定為從不方塊化,或者只在起始位置方塊化", + + "create.ponder.mechanical_plough.header": "在裝置中使用動力犁", + "create.ponder.mechanical_plough.text_1": "在運動裝置中使用動力犁時...", + "create.ponder.mechanical_plough.text_2": "...它會破壞掉那些不具有固體碰撞箱的方塊", + "create.ponder.mechanical_plough.text_3": "此外,動力犁可以耕地", + "create.ponder.mechanical_plough.text_4": "...它也可以在不傷害實體的情況下推動它們", + + "create.ponder.mechanical_press.header": "使用機械液壓機處理物品", + "create.ponder.mechanical_press.text_1": "機械液壓機可以處理位於其下方的物品", + "create.ponder.mechanical_press.text_2": "在其下方丟入物品,或者將物品放在置物台上,都算作有效的物品輸入", + "create.ponder.mechanical_press.text_3": "若物品被輸入時正位於傳送帶上...", + "create.ponder.mechanical_press.text_4": "輥軋機會使物品停下,然後自動處理這一物品", + + "create.ponder.mechanical_press_compacting.header": "使用機械液壓機壓縮物品", + "create.ponder.mechanical_press_compacting.text_1": "對放置於工作盆內的物品進行輥軋,可以將這些物品壓縮在一起", + "create.ponder.mechanical_press_compacting.text_2": "壓縮意指任何同種物品填滿了 2x2 或者 3x3 網格的配方,以及一些額外的配方", + "create.ponder.mechanical_press_compacting.text_3": "一些配方可能需要烈焰人燃燒室提供熱量", + "create.ponder.mechanical_press_compacting.text_4": "過濾槽可用於解決兩個配方相互衝突的情況", + + "create.ponder.mechanical_saw_breaker.header": "使用動力鋸伐木", + "create.ponder.mechanical_saw_breaker.text_1": "向其通入動能後,動力鋸可以直接砍伐掉它面前的樹木", + "create.ponder.mechanical_saw_breaker.text_2": "想要一次性砍掉整棵樹,鋸子必須破壞掉樹與地面連接的最後一個方塊", + + "create.ponder.mechanical_saw_contraption.header": "在裝置中使用動力鋸", + "create.ponder.mechanical_saw_contraption.text_1": "若在運動裝置中使用動力鋸...", + "create.ponder.mechanical_saw_contraption.text_2": "...它會將撞到它的樹木破壞掉", + + "create.ponder.mechanical_saw_processing.header": "使用動力鋸處理物品", + "create.ponder.mechanical_saw_processing.text_1": "面向朝上的動力鋸可以將物品處理為其變種", + "create.ponder.mechanical_saw_processing.text_2": "處理過後的物品的彈出方向始終與通入鋸中的旋轉轉向相反", + "create.ponder.mechanical_saw_processing.text_3": "鋸子可以", + "create.ponder.mechanical_saw_processing.text_4": "若輸入原料有多種可能產物,你可以用動力鋸上的過濾槽指定只產出某種產物", + "create.ponder.mechanical_saw_processing.text_5": "若沒有使用過濾槽,動力鋸會在各產物中按順序循環輸出", + + "create.ponder.millstone.header": "使用石磨處理物品", + "create.ponder.millstone.text_1": "石磨會對輸入的物品進行磨製", + "create.ponder.millstone.text_2": "在其側邊使用齒輪與其相耦合,方可為其通入動力", + "create.ponder.millstone.text_3": "頂部可以丟入或者塞入物品", + "create.ponder.millstone.text_4": "一段時間過後,右擊石磨可以拿出其中的產物", + "create.ponder.millstone.text_5": "產物的提取也是可以自動化的", + + "create.ponder.nixie_tube.header": "使用真空管顯示器", + "create.ponder.nixie_tube.text_1": "通入紅石訊號後,真空管顯示器會顯示出紅石訊號的強度", + "create.ponder.nixie_tube.text_2": "使用命名牌在鐵砧上為其命名,可以自訂它的顯示文本", + + "create.ponder.piston_pole.header": "活塞延長杆", + "create.ponder.piston_pole.text_1": "若無相接的延長杆,動力活塞無法移動其他方塊", + "create.ponder.piston_pole.text_2": "在其背面安裝的延長杆長度,決定了活塞的推動範圍", + + "create.ponder.portable_storage_interface.header": "裝置存儲交換", + "create.ponder.portable_storage_interface.text_1": "玩家無法與運動裝置內的存儲空間進行互動", + "create.ponder.portable_storage_interface.text_2": "這一組件可以在不停止裝置的情況下與裝置內的存儲空間進行互動", + "create.ponder.portable_storage_interface.text_3": "放置第二個介面時,記得要與裝置介面相隔 1 格或者 2 格的距離", + "create.ponder.portable_storage_interface.text_4": "當它們彼此經過時,它們會連接在一起", + "create.ponder.portable_storage_interface.text_5": "連接狀態下,固定側介面便會作為整個裝置的存儲空間代理", + "create.ponder.portable_storage_interface.text_6": "物品會被輸入到裝置內...", + "create.ponder.portable_storage_interface.text_7": "...或是從裝置中提取出來", + "create.ponder.portable_storage_interface.text_8": "物品交換完畢後,裝置仍然會停留在原地一小會,然後才會繼續前行", + + "create.ponder.portable_storage_interface_redstone.header": "紅石控制", + "create.ponder.portable_storage_interface_redstone.text_1": "通入紅石訊號可以阻止固定側介面的連接行為", + + "create.ponder.powered_latch.header": "使用閂鎖器控制訊號", + "create.ponder.powered_latch.text_1": "閂鎖器是一種可以用紅石訊號控制的拉杆", + "create.ponder.powered_latch.text_2": "後方輸入的訊號會將其設為開啟狀態", + "create.ponder.powered_latch.text_3": "側邊輸入的訊號會將其設為關閉狀態", + "create.ponder.powered_latch.text_4": "你也可以手動切換其狀態", + + "create.ponder.powered_toggle_latch.header": "使用T型正反器控制訊號", + "create.ponder.powered_toggle_latch.text_1": "T型正反器是一種可以用紅石訊號控制的拉杆", + "create.ponder.powered_toggle_latch.text_2": "後方訊號輸入可以改變它的狀態", + "create.ponder.powered_toggle_latch.text_3": "...開啟或者是關閉", + "create.ponder.powered_toggle_latch.text_4": "你也可以手動切換其狀態", + + "create.ponder.pulse_repeater.header": "使用脈衝中繼器控制訊號", + "create.ponder.pulse_repeater.text_1": "脈衝中繼器會將所有通入的紅石訊號縮減為一次脈衝", + + "create.ponder.radial_chassis.header": "使用旋轉底盤黏著方塊", + "create.ponder.radial_chassis.text_1": "同一行上的旋轉底盤會相互連接在一起", + "create.ponder.radial_chassis.text_2": "當其中的一個底盤被裝置帶動時,其餘的底盤也會被帶動", + "create.ponder.radial_chassis.text_3": "底盤的側邊可以變為黏性面", + "create.ponder.radial_chassis.text_4": "再次點擊黏性面,可以讓其所有面都變得帶黏性", + "create.ponder.radial_chassis.text_5": "空手潛行右擊可以移除其上的黏性物", + "create.ponder.radial_chassis.text_6": "若有物品與底盤的黏性面相接觸...", + "create.ponder.radial_chassis.text_7": "...底盤便會與同層且位於半徑內的所有可及方塊黏著在一起", + "create.ponder.radial_chassis.text_8": "使用扳手可以精確指定底盤的影響範圍", + "create.ponder.radial_chassis.text_9": "黏性面一側的不可及方塊不會被黏著", + + "create.ponder.redstone_contact.header": "接觸式紅石訊號發生器", + "create.ponder.redstone_contact.text_1": "當兩個接觸式紅石訊號發生器面對面時,它們會發出紅石訊號", + "create.ponder.redstone_contact.text_2": "並且,若有一方位於運動裝置上,此特性也能正常生效", + + "create.ponder.redstone_link.header": "使用無線紅石訊號機", + "create.ponder.redstone_link.text_1": "無線紅石訊號機可以無線傳輸紅石訊號", + "create.ponder.redstone_link.text_2": "潛行右擊可以改變其接收模式", + "create.ponder.redstone_link.text_3": "手持扳手右擊也可以", + "create.ponder.redstone_link.text_4": "接收端會發出由傳輸端發來的訊號,有效距離為 128 格", + "create.ponder.redstone_link.text_5": "在它們所帶的槽位中放上物品,可以為它們指定頻道", + "create.ponder.redstone_link.text_6": "只有頻道相互匹配的機方可互通", + + "create.ponder.rope_pulley.header": "使用繩索滑輪移動結構", + "create.ponder.rope_pulley.text_1": "繩索滑輪在接受動能時可以垂直移動方塊結構", + "create.ponder.rope_pulley.text_2": "移動的方向及速度取決於提供的轉速", + + "create.ponder.rope_pulley_attachment.header": "繩索滑輪與裝置一同運動", + "create.ponder.rope_pulley_attachment.text_1": "當繩索滑輪本身在裝置中被帶動時...", + "create.ponder.rope_pulley_attachment.text_2": "...它附著在滑輪上的結構會被滑輪拉著一同移動", + "create.ponder.rope_pulley_attachment.text_3": "注意,只有繩索滑輪停止工作時才能被移動", + + "create.ponder.rope_pulley_modes.header": "繩索滑輪的運動模式", + "create.ponder.rope_pulley_modes.text_1": "當繩索滑輪停止運動時,它所附屬的移動結構便會方塊化", + "create.ponder.rope_pulley_modes.text_2": "你可以調整整個結構永不方塊化,或者僅在結構的初始位置方塊化", + + "create.ponder.rotation_speed_controller.header": "使用轉速控制器", + "create.ponder.rotation_speed_controller.text_1": "轉速控制器將動能從其轉軸傳遞至它上方的大齒輪", + "create.ponder.rotation_speed_controller.text_2": "在其側面滾動滑鼠滾輪,可以調節輸出轉速", + + "create.ponder.sail.header": "使用風帆來組裝風車", + "create.ponder.sail.text_1": "風帆是製作風車的趁手材料", + "create.ponder.sail.text_2": "無需強力膠等黏附手段,它們便可自行互相連結", + "create.ponder.sail.text_3": "手持染料右擊可對其染色", + "create.ponder.sail.text_4": "手持剪刀右擊可剪除帆布,使其變迴風帆框架", + + "create.ponder.sail_frame.header": "使用風帆框架來組裝風車", + "create.ponder.sail_frame.text_1": "風帆框架是製作風車的趁手材料", + "create.ponder.sail_frame.text_2": "無需強力膠等黏附手段,它們便可自行互相連結", + + "create.ponder.sequenced_gearshift.header": "使用可編程齒輪箱來控制轉速", + "create.ponder.sequenced_gearshift.text_1": "可編程齒輪箱能夠根據玩家設置的預設時序表來傳遞旋轉", + "create.ponder.sequenced_gearshift.text_2": "對其右擊可以打開設置面板", + "create.ponder.sequenced_gearshift.text_3": "接受紅石訊號時,它會開始執行其內部已設定好的時序指令表", + "create.ponder.sequenced_gearshift.text_4": "當完成時序指令表後,它會進入待機狀態,再次接受紅石訊號後,它才會再次執行時序指令表內容", + "create.ponder.sequenced_gearshift.text_5": "紅石比較器可以讀取目前時序指令表完成進度", + + "create.ponder.shaft.header": "使用傳動軸來傳送動能", + "create.ponder.shaft.text_1": "傳動軸可以直線傳送動能", + + "create.ponder.shaft_casing.header": "包裹傳動軸", + "create.ponder.shaft_casing.text_1": "黃銅及安山岩機殼可以用來裝飾傳動軸", + + "create.ponder.smart_chute.header": "使用智慧滑道來過濾物品", + "create.ponder.smart_chute.text_1": "智慧滑道是一種可以被控制的滑道", + "create.ponder.smart_chute.text_2": "當在其過濾槽內指定了物品後,溜槽只會傳輸這一指定標記的物品", + "create.ponder.smart_chute.text_3": "使用滑鼠滾輪可以指定被過濾的物品數量", + "create.ponder.smart_chute.text_4": "通入紅石訊號,智慧溜槽將會完全暫停工作", + + "create.ponder.speedometer.header": "使用速度計來監測轉速", + "create.ponder.speedometer.text_1": "速度計能顯示相接組件的轉速", + "create.ponder.speedometer.text_2": "當佩戴MR護目鏡時,可以看到儀表所顯示的更詳細的數據", + "create.ponder.speedometer.text_3": "紅石比較器可以根據速度計的數值輸出不同強弱的紅石訊號", + + "create.ponder.stabilized_bearings.header": "裝置固定朝向", + "create.ponder.stabilized_bearings.text_1": "當動力軸承在結構被帶動時...", + "create.ponder.stabilized_bearings.text_2": "...它會確保它轉盤的垂直朝向不變", + "create.ponder.stabilized_bearings.text_3": "跟預設的一樣,動力軸承會黏著它前方的方塊", + "create.ponder.stabilized_bearings.text_4": "這種情況下,它所黏著的子結構的垂直朝向也不會改變", + + "create.ponder.sticker.header": "使用方塊黏著器來黏取方塊", + "create.ponder.sticker.text_1": "方塊黏著器是一個很棒的裝置,他受控於紅石訊號", + "create.ponder.sticker.text_2": "當接收到訊號時,他會黏起面前的一個方塊", + "create.ponder.sticker.text_3": "如果此時方塊黏著器被移動,被黏到的方塊會跟著移動", + "create.ponder.sticker.text_4": "再次接收到訊號後,黏著器會放下它面前的方塊", + + "create.ponder.stressometer.header": "使用動能錶來監測應力", + "create.ponder.stressometer.text_1": "動能錶能顯示目前動能網路內的應力訊息", + "create.ponder.stressometer.text_2": "當佩戴MR護目鏡時,可以看到儀表所顯示的更詳細的數據", + "create.ponder.stressometer.text_3": "紅石比較器可以根據動能錶的數值輸出不同強弱的紅石訊號", + + "create.ponder.super_glue.header": "使用強力膠來黏附方塊", + "create.ponder.super_glue.text_1": "強力膠可以在任意兩個方塊間使用", + "create.ponder.super_glue.text_2": "當被黏合的方塊被組裝為裝置時,他們會一起運動", + "create.ponder.super_glue.text_3": "當強力膠在副手時...", + "create.ponder.super_glue.text_4": "...新放置的方塊會自動被黏附在所放置方塊的面上", + "create.ponder.super_glue.text_5": "左擊可以清除強力膠", + + "create.ponder.valve_handle.header": "使用閥門手輪產生動能", + "create.ponder.valve_handle.text_1": "玩家可以手動使用閥門手輪來產生動能", + "create.ponder.valve_handle.text_2": "右擊可使它逆時針旋轉", + "create.ponder.valve_handle.text_3": "它的轉速慢而精確", + "create.ponder.valve_handle.text_4": "潛行右擊可使它順時針旋轉", + "create.ponder.valve_handle.text_5": "可以透過染色來美化閥門手輪", + + "create.ponder.water_wheel.header": "使用水車產生動能", + "create.ponder.water_wheel.text_1": "水車利用臨近的水流來進行應力發生", + "create.ponder.water_wheel.text_2": "水車接觸水流的麵越多,它的轉速越高", + "create.ponder.water_wheel.text_3": "水車葉片應逆著水流方向擺放", + "create.ponder.water_wheel.text_4": "如果順著水流擺放,它的效率則會降低", + + "create.ponder.weighted_ejector.header": "使用彈射置物台", + "create.ponder.weighted_ejector.text_1": "手持彈射置物台時,潛行時右擊可以設置彈射目標位置", + "create.ponder.weighted_ejector.text_10": "現在,只有等被放置的物品數量等於所設定數量時,彈射置物台才會彈射物品", + "create.ponder.weighted_ejector.text_11": "當其他實體站在彈射置物台上時會被直接彈射", + "create.ponder.weighted_ejector.text_2": "現在,放置下的彈射置物台會將物品彈射至目標位置", + "create.ponder.weighted_ejector.text_3": "限制範圍內的任意距離和高度均可作為有效目標地點", + "create.ponder.weighted_ejector.text_4": "但是,目標位置與置物台的連線,必須垂直於置物台的側面", + "create.ponder.weighted_ejector.text_5": "如果沒有設置有效目標位置,彈射置物台會直接將其前方一格設為默認目標位置", + "create.ponder.weighted_ejector.text_6": "提供動能可為其蓄力", + "create.ponder.weighted_ejector.text_7": "蓄力完畢後,放置在它上方的物品會被立刻彈射出去", + "create.ponder.weighted_ejector.text_8": "如果目標為容器,則彈射置物台會等待容器有位置後再彈射物品", + "create.ponder.weighted_ejector.text_9": "使用扳手可以調整彈射所要求的物品數量", + + "create.ponder.weighted_ejector_redstone.header": "使用紅石控制彈射置物台", + "create.ponder.weighted_ejector_redstone.text_1": "當被紅石充能時,彈射置物台停止工作", + "create.ponder.weighted_ejector_redstone.text_2": "此外,置物台彈射的瞬間可以被偵測器偵測", + "create.ponder.weighted_ejector_tunnel.header": "使用彈射置物台來分流物品", + "create.ponder.weighted_ejector_tunnel.text_1": "與黃銅隧道搭配使用時,彈射置物台可以將物品以特定數量進行分流", + "create.ponder.weighted_ejector_tunnel.text_2": "首先,將黃銅隧道調整為“最近優先”模式,從而讓它優先側面輸出", + "create.ponder.weighted_ejector_tunnel.text_3": "置物台上所設置的物品數量則為被分流出去的物品數量", + "create.ponder.weighted_ejector_tunnel.text_4": "當所設置的物品數量被分流出去後...", + "create.ponder.weighted_ejector_tunnel.text_5": "...剩餘的物品則會繼續前進", + + "create.ponder.windmill_source.header": "使用風車軸承產生動能", + "create.ponder.windmill_source.text_1": "風車軸承會黏著它面前的方塊結構", + "create.ponder.windmill_source.text_2": "如果黏著的方塊結構包含足夠的風帆方塊即為風車", + "create.ponder.windmill_source.text_3": "右鍵啟動風車後,風車開始提供動能", + "create.ponder.windmill_source.text_4": "產生的動能將取決於所黏風帆方塊之數量", + "create.ponder.windmill_source.text_5": "使用扳手來調整其旋轉方向", + "create.ponder.windmill_source.text_6": "對風車軸承右鍵可使其停止方便你維修風車", + + "create.ponder.windmill_structure.header": "風車結構", + "create.ponder.windmill_structure.text_1": "任一包含至少8個風帆方塊的結構即為有效的風車", + + "_": "Thank you for translating Create!" + +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/entity/crafting_blueprint_large.json b/src/main/resources/assets/create/models/entity/crafting_blueprint_large.json new file mode 100644 index 000000000..2fdd1143c --- /dev/null +++ b/src/main/resources/assets/create/models/entity/crafting_blueprint_large.json @@ -0,0 +1,81 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "create:entity/blueprint_large", + "particle": "create:entity/blueprint_large" + }, + "elements": [ + { + "from": [ + -16, + 0, + -16 + ], + "to": [ + 32, + 1, + 32 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 12, + 0.25 + ], + "rotation": 180, + "texture": "#0" + }, + "east": { + "uv": [ + 11.75, + 0, + 12, + 12 + ], + "rotation": 90, + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 11.75, + 12, + 12 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 0.25, + 12 + ], + "rotation": 270, + "texture": "#0" + }, + "up": { + "uv": [ + 0, + 0, + 12, + 12 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 0, + 0, + 12, + 12 + ], + "rotation": 270, + "texture": "#0" + } + } + } + ] +} diff --git a/src/main/resources/assets/create/models/entity/crafting_blueprint_medium.json b/src/main/resources/assets/create/models/entity/crafting_blueprint_medium.json new file mode 100644 index 000000000..6dcdf49dc --- /dev/null +++ b/src/main/resources/assets/create/models/entity/crafting_blueprint_medium.json @@ -0,0 +1,81 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "create:entity/blueprint_medium", + "particle": "create:entity/blueprint_medium" + }, + "elements": [ + { + "from": [ + -8, + 0, + -8 + ], + "to": [ + 24, + 1, + 24 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 0.5 + ], + "rotation": 180, + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 15.5, + 16, + 16 + ], + "rotation": 180, + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 15.5, + 16, + 16 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 0.5, + 16 + ], + "rotation": 270, + "texture": "#0" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "rotation": 270, + "texture": "#0" + } + } + } + ] +} diff --git a/src/main/resources/assets/create/models/entity/crafting_blueprint_small.json b/src/main/resources/assets/create/models/entity/crafting_blueprint_small.json new file mode 100644 index 000000000..e70b7bbf5 --- /dev/null +++ b/src/main/resources/assets/create/models/entity/crafting_blueprint_small.json @@ -0,0 +1,81 @@ +{ + "credit": "Made with Blockbench", + "textures": { + "0": "create:entity/blueprint_small", + "particle": "create:entity/blueprint_small" + }, + "elements": [ + { + "from": [ + 0, + 0, + 0 + ], + "to": [ + 16, + 1, + 16 + ], + "faces": { + "north": { + "uv": [ + 0, + 0, + 16, + 1 + ], + "rotation": 180, + "texture": "#0" + }, + "east": { + "uv": [ + 0, + 15, + 16, + 16 + ], + "rotation": 180, + "texture": "#0" + }, + "south": { + "uv": [ + 0, + 15, + 16, + 16 + ], + "texture": "#0" + }, + "west": { + "uv": [ + 0, + 0, + 1, + 16 + ], + "rotation": 270, + "texture": "#0" + }, + "up": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "texture": "#0" + }, + "down": { + "uv": [ + 0, + 0, + 16, + 16 + ], + "rotation": 270, + "texture": "#0" + } + } + } + ] +} diff --git a/src/main/resources/assets/create/models/item/linked_controller/button.json b/src/main/resources/assets/create/models/item/linked_controller/button.json new file mode 100644 index 000000000..9859c72ab --- /dev/null +++ b/src/main/resources/assets/create/models/item/linked_controller/button.json @@ -0,0 +1,22 @@ +{ + "credit": "Made with Blockbench", + "parent": "create:item/linked_controller/powered", + "textures": { + "particle": "create:item/linked_controller", + "redstone_bridge": "create:item/linked_controller" + }, + "elements": [ + { + "from": [3, 1, 0.5], + "to": [5, 3, 2.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/linked_controller/item.json b/src/main/resources/assets/create/models/item/linked_controller/item.json new file mode 100644 index 000000000..88c8e9cdc --- /dev/null +++ b/src/main/resources/assets/create/models/item/linked_controller/item.json @@ -0,0 +1,166 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "redstone_antenna": "create:block/redstone_antenna", + "particle": "create:item/linked_controller", + "redstone_bridge": "create:item/linked_controller" + }, + "elements": [ + { + "name": "Controller", + "from": [4, 0, 1.5], + "to": [12, 2, 14.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "east": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "south": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "west": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "up": {"uv": [0, 0, 13, 8], "rotation": 270, "texture": "#redstone_bridge"}, + "down": {"uv": [0, 0, 13, 8], "rotation": 90, "texture": "#redstone_bridge"} + } + }, + { + "name": "AntennaTop", + "from": [3, 6, 4.5], + "to": [4, 7, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaZ", + "from": [3, 0, 3.5], + "to": [4, 8, 6.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "east": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "west": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaX", + "from": [2, 0, 4.5], + "to": [5, 8, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "south": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"} + } + }, + { + "from": [9, 1, 8.5], + "to": [11, 3, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [5, 1, 8.5], + "to": [7, 3, 10.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [7, 1, 10.5], + "to": [9, 3, 12.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [7, 1, 6.5], + "to": [9, 3, 8.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [8, 1, 3.5], + "to": [10, 3, 5.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + }, + { + "from": [6, 1, 3.5], + "to": [8, 3, 5.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "east": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "south": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "west": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"}, + "up": {"uv": [2, 11, 4, 13], "texture": "#redstone_bridge"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [0, -90, -74], + "translation": [-3, 3.25, 4.5], + "scale": [0.7, 0.7, 0.7] + }, + "thirdperson_lefthand": { + "rotation": [0, 90, 74], + "translation": [-3, 3.5, 5], + "scale": [0.7, 0.7, 0.7] + }, + "firstperson_righthand": { + "rotation": [0, -90, -13], + "translation": [1.13, 3, 1.13], + "scale": [0.68, 0.68, 0.68] + }, + "firstperson_lefthand": { + "rotation": [0, 71, 17], + "translation": [1.13, 3, 1.13], + "scale": [0.68, 0.68, 0.68] + }, + "ground": { + "translation": [0, 3, 0], + "scale": [0.65, 0.65, 0.65] + }, + "gui": { + "rotation": [30, -44, 0], + "translation": [0, 3.5, 0], + "scale": [0.76, 0.76, 0.76] + }, + "head": { + "rotation": [0, 180, 0], + "translation": [0, 13, 0] + }, + "fixed": { + "rotation": [0, 90, -90], + "translation": [0, 0, -8] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/linked_controller/powered.json b/src/main/resources/assets/create/models/item/linked_controller/powered.json new file mode 100644 index 000000000..1a747b4fa --- /dev/null +++ b/src/main/resources/assets/create/models/item/linked_controller/powered.json @@ -0,0 +1,94 @@ +{ + "credit": "Made with Blockbench", + "parent": "block/block", + "textures": { + "redstone_antenna": "create:block/redstone_antenna_powered", + "particle": "create:item/linked_controller_powered", + "redstone_bridge": "create:item/linked_controller_powered" + }, + "elements": [ + { + "name": "Controller", + "from": [4, 0, 1.5], + "to": [12, 2, 14.5], + "rotation": {"angle": 0, "axis": "y", "origin": [0, 0, 0.5]}, + "faces": { + "north": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "east": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "south": {"uv": [13, 0, 15, 8], "rotation": 90, "texture": "#redstone_bridge"}, + "west": {"uv": [0, 8, 13, 10], "texture": "#redstone_bridge"}, + "up": {"uv": [0, 0, 13, 8], "rotation": 270, "texture": "#redstone_bridge"}, + "down": {"uv": [0, 0, 13, 8], "rotation": 90, "texture": "#redstone_bridge"} + } + }, + { + "name": "AntennaTop", + "from": [3, 6, 4.5], + "to": [4, 7, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "up": {"uv": [1, 1, 2, 2], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaZ", + "from": [3, 0, 3.5], + "to": [4, 8, 6.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "east": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "west": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"} + } + }, + { + "name": "AntennaX", + "from": [2, 0, 4.5], + "to": [5, 8, 5.5], + "rotation": {"angle": 0, "axis": "z", "origin": [4, 2, 14.5]}, + "faces": { + "north": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "south": {"uv": [0, 0, 3, 8], "texture": "#redstone_antenna"}, + "down": {"uv": [0, 9, 3, 10], "texture": "#redstone_antenna"} + } + } + ], + "display": { + "thirdperson_righthand": { + "rotation": [0, -90, -74], + "translation": [-3, 3.25, 4.5], + "scale": [0.7, 0.7, 0.7] + }, + "thirdperson_lefthand": { + "rotation": [0, 90, 74], + "translation": [-3, 3.5, 5], + "scale": [0.7, 0.7, 0.7] + }, + "firstperson_righthand": { + "rotation": [0, -113, -27], + "translation": [-2, 9, 1.13], + "scale": [0.97, 0.97, 0.97] + }, + "firstperson_lefthand": { + "rotation": [0, 47, 27], + "translation": [-2, 9, 1.13], + "scale": [0.97, 0.97, 0.97] + }, + "ground": { + "translation": [0, 2, 0], + "scale": [0.75, 0.75, 0.75] + }, + "gui": { + "rotation": [30, -44, 0], + "translation": [0, 1.75, 0], + "scale": [0.76, 0.76, 0.76] + }, + "head": { + "rotation": [0, 180, 0], + "translation": [0, 13, 0] + }, + "fixed": { + "rotation": [0, 90, -90], + "translation": [0, 0, -8] + } + } +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/wrench/item.json b/src/main/resources/assets/create/models/item/wrench/item.json index 656143148..55cbe7e35 100644 --- a/src/main/resources/assets/create/models/item/wrench/item.json +++ b/src/main/resources/assets/create/models/item/wrench/item.json @@ -81,13 +81,65 @@ "to": [10.4, 9, 9], "rotation": {"angle": 0, "axis": "y", "origin": [9, 11, 8]}, "faces": { - "north": {"uv": [4, 10, 12, 12], "texture": "#5"}, - "east": {"uv": [4, 10, 6, 14], "rotation": 90, "texture": "#5"}, - "south": {"uv": [12, 10, 4, 12], "texture": "#5"}, - "west": {"uv": [4, 10, 6, 14], "rotation": 90, "texture": "#5"}, - "up": {"uv": [4, 10, 12, 14], "rotation": 180, "texture": "#5"}, - "down": {"uv": [6, 0, 9, 2], "texture": "#5"} - } + "north": { + "uv": [ + 4, + 10, + 12, + 12 + ], + "texture": "#5" + }, + "east": { + "uv": [ + 4, + 10, + 6, + 14 + ], + "rotation": 90, + "texture": "#5" + }, + "south": { + "uv": [ + 12, + 10, + 4, + 12 + ], + "texture": "#5" + }, + "west": { + "uv": [ + 4, + 10, + 6, + 14 + ], + "rotation": 90, + "texture": "#5" + }, + "up": { + "uv": [ + 4, + 10, + 12, + 14 + ], + "rotation": 180, + "texture": "#5" + }, + "down": { + "uv": [ + 4, + 10, + 12, + 13 + ], + "rotation": 180, + "texture": "#5" + } + } }, { "name": "gear case", @@ -142,4 +194,4 @@ "children": [0, 1, 2, 3, 4, 5, 6] } ] -} \ No newline at end of file +} diff --git a/src/main/resources/assets/create/textures/entity/blueprint_large.png b/src/main/resources/assets/create/textures/entity/blueprint_large.png new file mode 100644 index 000000000..5d56ae44e Binary files /dev/null and b/src/main/resources/assets/create/textures/entity/blueprint_large.png differ diff --git a/src/main/resources/assets/create/textures/entity/blueprint_medium.png b/src/main/resources/assets/create/textures/entity/blueprint_medium.png new file mode 100644 index 000000000..ced7b7045 Binary files /dev/null and b/src/main/resources/assets/create/textures/entity/blueprint_medium.png differ diff --git a/src/main/resources/assets/create/textures/entity/blueprint_small.png b/src/main/resources/assets/create/textures/entity/blueprint_small.png new file mode 100644 index 000000000..a386ea078 Binary files /dev/null and b/src/main/resources/assets/create/textures/entity/blueprint_small.png differ diff --git a/src/main/resources/assets/create/textures/gui/curiosities2.png b/src/main/resources/assets/create/textures/gui/curiosities2.png new file mode 100644 index 000000000..10b4a353c Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/curiosities2.png differ diff --git a/src/main/resources/assets/create/textures/gui/icons.png b/src/main/resources/assets/create/textures/gui/icons.png index f0b91e13c..9c862ea80 100644 Binary files a/src/main/resources/assets/create/textures/gui/icons.png and b/src/main/resources/assets/create/textures/gui/icons.png differ diff --git a/src/main/resources/assets/create/textures/gui/logo.png b/src/main/resources/assets/create/textures/gui/logo.png new file mode 100644 index 000000000..beac8a31b Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/logo.png differ diff --git a/src/main/resources/assets/create/textures/gui/projector.png b/src/main/resources/assets/create/textures/gui/projector.png new file mode 100644 index 000000000..6638b2b2f Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/projector.png differ diff --git a/src/main/resources/assets/create/textures/gui/title/background/panorama_0.png b/src/main/resources/assets/create/textures/gui/title/background/panorama_0.png new file mode 100644 index 000000000..2a955e5f8 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/title/background/panorama_0.png differ diff --git a/src/main/resources/assets/create/textures/gui/title/background/panorama_1.png b/src/main/resources/assets/create/textures/gui/title/background/panorama_1.png new file mode 100644 index 000000000..dc8632fa2 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/title/background/panorama_1.png differ diff --git a/src/main/resources/assets/create/textures/gui/title/background/panorama_2.png b/src/main/resources/assets/create/textures/gui/title/background/panorama_2.png new file mode 100644 index 000000000..b8ea73f25 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/title/background/panorama_2.png differ diff --git a/src/main/resources/assets/create/textures/gui/title/background/panorama_3.png b/src/main/resources/assets/create/textures/gui/title/background/panorama_3.png new file mode 100644 index 000000000..64542f2a3 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/title/background/panorama_3.png differ diff --git a/src/main/resources/assets/create/textures/gui/title/background/panorama_4.png b/src/main/resources/assets/create/textures/gui/title/background/panorama_4.png new file mode 100644 index 000000000..c094a82e9 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/title/background/panorama_4.png differ diff --git a/src/main/resources/assets/create/textures/gui/title/background/panorama_5.png b/src/main/resources/assets/create/textures/gui/title/background/panorama_5.png new file mode 100644 index 000000000..bbac982a8 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/title/background/panorama_5.png differ diff --git a/src/main/resources/assets/create/textures/gui/widgets.png b/src/main/resources/assets/create/textures/gui/widgets.png index 33cfed66c..3588a5cfc 100644 Binary files a/src/main/resources/assets/create/textures/gui/widgets.png and b/src/main/resources/assets/create/textures/gui/widgets.png differ diff --git a/src/main/resources/assets/create/textures/item/crafting_blueprint.png b/src/main/resources/assets/create/textures/item/crafting_blueprint.png new file mode 100644 index 000000000..4481759f1 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/crafting_blueprint.png differ diff --git a/src/main/resources/assets/create/textures/item/linked_controller.png b/src/main/resources/assets/create/textures/item/linked_controller.png new file mode 100644 index 000000000..474b3bf2c Binary files /dev/null and b/src/main/resources/assets/create/textures/item/linked_controller.png differ diff --git a/src/main/resources/assets/create/textures/item/linked_controller_powered.png b/src/main/resources/assets/create/textures/item/linked_controller_powered.png new file mode 100644 index 000000000..bf0dcb3d3 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/linked_controller_powered.png differ diff --git a/src/main/resources/assets/create/textures/item/refined_radiance.png b/src/main/resources/assets/create/textures/item/refined_radiance.png index 8781918cb..54aae40dc 100644 Binary files a/src/main/resources/assets/create/textures/item/refined_radiance.png and b/src/main/resources/assets/create/textures/item/refined_radiance.png differ diff --git a/src/main/resources/create.mixins.json b/src/main/resources/create.mixins.json index 0938f8534..dc2d36193 100644 --- a/src/main/resources/create.mixins.json +++ b/src/main/resources/create.mixins.json @@ -7,17 +7,11 @@ "mixins": [ ], "client": [ - "CancelTileEntityRenderMixin", + "BreakProgressMixin", "EntityContraptionInteractionMixin", - "FogColorTrackerMixin", + "FixNormalScalingMixin", "HeavyBootsOnPlayerMixin", - "LightUpdateMixin", - "NetworkLightUpdateMixin", - "RenderHooksMixin", - "ShaderCloseMixin", - "StoreProjectionMatrixMixin", - "TileRemoveMixin", - "TileWorldHookMixin", + "ModelDataRefreshMixin", "WindowResizeMixin" ], "injectors": { diff --git a/src/main/resources/data/create/recipes/compat/alexsmobs/emptying/lava_bottle.json b/src/main/resources/data/create/recipes/compat/alexsmobs/emptying/lava_bottle.json new file mode 100644 index 000000000..bf3ed681e --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/alexsmobs/emptying/lava_bottle.json @@ -0,0 +1,23 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "alexsmobs" + } + ], + "type": "create:emptying", + "ingredients": [ + { + "item": "alexsmobs:lava_bottle" + } + ], + "results": [ + { + "item": "minecraft:glass_bottle" + }, + { + "fluid": "minecraft:lava", + "amount": 250 + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/alexsmobs/filling/lava_bottle.json b/src/main/resources/data/create/recipes/compat/alexsmobs/filling/lava_bottle.json new file mode 100644 index 000000000..a32b4262b --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/alexsmobs/filling/lava_bottle.json @@ -0,0 +1,23 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "alexsmobs" + } + ], + "type": "create:filling", + "ingredients": [ + { + "item": "minecraft:glass_bottle" + }, + { + "fluid": "minecraft:lava", + "amount": 250 + } + ], + "results": [ + { + "item": "alexsmobs:lava_bottle" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/atmospheric/pressing/crustose_path.json b/src/main/resources/data/create/recipes/compat/atmospheric/pressing/crustose_path.json new file mode 100644 index 000000000..d46e53cd2 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/atmospheric/pressing/crustose_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "atmospheric" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "atmospheric:crustose" + } + ] + ], + "results": [ + { + "item": "atmospheric:crustose_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/amber_moss_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/amber_moss_path.json new file mode 100644 index 000000000..4a580ce1d --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/amber_moss_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:amber_moss" + } + ] + ], + "results": [ + { + "item": "betterendforge:amber_moss_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/cave_moss_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/cave_moss_path.json new file mode 100644 index 000000000..ee93ce6f5 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/cave_moss_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:cave_moss" + } + ] + ], + "results": [ + { + "item": "betterendforge:cave_moss_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/chorus_nylium_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/chorus_nylium_path.json new file mode 100644 index 000000000..96c02b035 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/chorus_nylium_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:chorus_nylium" + } + ] + ], + "results": [ + { + "item": "betterendforge:chorus_nylium_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/crystal_moss_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/crystal_moss_path.json new file mode 100644 index 000000000..40e7bb3f5 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/crystal_moss_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:crystal_moss" + } + ] + ], + "results": [ + { + "item": "betterendforge:crystal_moss_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/end_moss_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/end_moss_path.json new file mode 100644 index 000000000..48d9d7991 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/end_moss_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:end_moss" + } + ] + ], + "results": [ + { + "item": "betterendforge:end_moss_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/end_myclium_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/end_myclium_path.json new file mode 100644 index 000000000..d117d9df6 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/end_myclium_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:end_mycelium" + } + ] + ], + "results": [ + { + "item": "betterendforge:end_mycelium_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/jungle_moss_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/jungle_moss_path.json new file mode 100644 index 000000000..36fc2aa30 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/jungle_moss_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:jungle_moss" + } + ] + ], + "results": [ + { + "item": "betterendforge:jungle_moss_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/pink_moss_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/pink_moss_path.json new file mode 100644 index 000000000..f41bcf66c --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/pink_moss_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:pink_moss" + } + ] + ], + "results": [ + { + "item": "betterendforge:pink_moss_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/betterendforge/pressing/shadow_grass_path.json b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/shadow_grass_path.json new file mode 100644 index 000000000..2194ae013 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/betterendforge/pressing/shadow_grass_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "betterendforge" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "betterendforge:shadow_grass" + } + ] + ], + "results": [ + { + "item": "betterendforge:shadow_grass_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/buttercup.json b/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/buttercup.json new file mode 100644 index 000000000..daf89729b --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/buttercup.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "buzzier_bees" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "buzzier_bees:buttercup" + } + ], + "results": [ + { + "item": "minecraft:yellow_dye", + "count": 2 + }, + { + "item": "minecraft:lime_dye", + "count": 1, + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_clover.json b/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_clover.json index c8753a417..f52886520 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_clover.json +++ b/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_clover.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "buzzier_bees" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:pink_clover" + "item": "buzzier_bees:pink_clover" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/white_clover.json b/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/white_clover.json index 7c9a228b2..1542d6ddb 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/white_clover.json +++ b/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/white_clover.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "buzzier_bees" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:white_clover" + "item": "buzzier_bees:white_clover" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock.json new file mode 100644 index 000000000..922cd9445 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:end_corrock" + } + ], + "results": [ + { + "item": "endergetic:petrified_end_corrock" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock_block.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock_block.json new file mode 100644 index 000000000..33f3e4598 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock_block.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:end_corrock_block" + } + ], + "results": [ + { + "item": "endergetic:petrified_end_corrock_block" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock_crown.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock_crown.json new file mode 100644 index 000000000..f0bdfc6e1 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_end_corrock_crown.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:end_corrock_crown" + } + ], + "results": [ + { + "item": "endergetic:petrified_end_corrock_crown" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock.json new file mode 100644 index 000000000..5f0e48f9f --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:nether_corrock" + } + ], + "results": [ + { + "item": "endergetic:petrified_nether_corrock" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock_block.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock_block.json new file mode 100644 index 000000000..5a28a9723 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock_block.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:nether_corrock_block" + } + ], + "results": [ + { + "item": "endergetic:petrified_nether_corrock_block" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock_crown.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock_crown.json new file mode 100644 index 000000000..6613d9bb4 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_nether_corrock_crown.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:nether_corrock_crown" + } + ], + "results": [ + { + "item": "endergetic:petrified_nether_corrock_crown" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock.json new file mode 100644 index 000000000..82cd86c81 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:overworld_corrock" + } + ], + "results": [ + { + "item": "endergetic:petrified_overworld_corrock" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock_block.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock_block.json new file mode 100644 index 000000000..8f451fa5f --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock_block.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:overworld_corrock_block" + } + ], + "results": [ + { + "item": "endergetic:petrified_overworld_corrock_block" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock_crown.json b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock_crown.json new file mode 100644 index 000000000..840b884a0 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/endergetic/splashing/petrified_overworld_corrock_crown.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "endergetic" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "endergetic:overworld_corrock_crown" + } + ], + "results": [ + { + "item": "endergetic:petrified_overworld_corrock_crown" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/bird_of_paradise.json b/src/main/resources/data/create/recipes/compat/environmental/milling/bird_of_paradise.json similarity index 84% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/bird_of_paradise.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/bird_of_paradise.json index 5edf6abea..0128172cc 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/bird_of_paradise.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/bird_of_paradise.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:bird_of_paradise" + "item": "environmental:bird_of_paradise" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/environmental/milling/blue_delphinium.json b/src/main/resources/data/create/recipes/compat/environmental/milling/blue_delphinium.json new file mode 100644 index 000000000..c37ac70bb --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/blue_delphinium.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "environmental:blue_delphinium" + } + ], + "results": [ + { + "item": "minecraft:blue_dye", + "count": 3 + }, + { + "item": "minecraft:blue_dye", + "count": 1, + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/bluebell.json b/src/main/resources/data/create/recipes/compat/environmental/milling/bluebell.json similarity index 77% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/bluebell.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/bluebell.json index b049cbc96..b56eb9e8c 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/bluebell.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/bluebell.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:bluebell" + "item": "environmental:bluebell" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/cartwheel.json b/src/main/resources/data/create/recipes/compat/environmental/milling/cartwheel.json similarity index 82% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/cartwheel.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/cartwheel.json index 169193092..2659d0528 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/cartwheel.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/cartwheel.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:cartwheel" + "item": "environmental:cartwheel" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/dianthus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/dianthus.json similarity index 82% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/dianthus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/dianthus.json index 48c05d143..646c2c6ee 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/dianthus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/dianthus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:jolyce" + "item": "environmental:dianthus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/magenta_hibiscus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/magenta_hibiscus.json similarity index 81% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/magenta_hibiscus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/magenta_hibiscus.json index 9e00cf80c..f33e7bda3 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/magenta_hibiscus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/magenta_hibiscus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:magenta_hibiscus" + "item": "environmental:magenta_hibiscus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/orange_hibiscus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/orange_hibiscus.json similarity index 81% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/orange_hibiscus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/orange_hibiscus.json index 6cc0c4ac3..ab7f0b6e9 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/orange_hibiscus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/orange_hibiscus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:orange_hibiscus" + "item": "environmental:orange_hibiscus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/environmental/milling/pink_delphinium.json b/src/main/resources/data/create/recipes/compat/environmental/milling/pink_delphinium.json new file mode 100644 index 000000000..9c2e2591c --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/pink_delphinium.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "environmental:pink_delphinium" + } + ], + "results": [ + { + "item": "minecraft:pink_dye", + "count": 3 + }, + { + "item": "minecraft:pink_dye", + "count": 1, + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_hibiscus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/pink_hibiscus.json similarity index 81% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_hibiscus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/pink_hibiscus.json index fa8c4c473..a85f2e64b 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/pink_hibiscus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/pink_hibiscus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:pink_hibiscus" + "item": "environmental:pink_hibiscus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/environmental/milling/purple_delphinium.json b/src/main/resources/data/create/recipes/compat/environmental/milling/purple_delphinium.json new file mode 100644 index 000000000..b99812be8 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/purple_delphinium.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "environmental:purple_delphinium" + } + ], + "results": [ + { + "item": "minecraft:purple_dye", + "count": 3 + }, + { + "item": "minecraft:purple_dye", + "count": 1, + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/purple_hibiscus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/purple_hibiscus.json similarity index 81% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/purple_hibiscus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/purple_hibiscus.json index 91ac754a7..2615523eb 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/purple_hibiscus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/purple_hibiscus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:purple_hibiscus" + "item": "environmental:purple_hibiscus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/red_hibiscus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/red_hibiscus.json similarity index 81% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/red_hibiscus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/red_hibiscus.json index 5b50d8189..6424ad955 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/red_hibiscus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/red_hibiscus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:red_hibiscus" + "item": "environmental:red_hibiscus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/environmental/milling/red_lotus_flower.json b/src/main/resources/data/create/recipes/compat/environmental/milling/red_lotus_flower.json new file mode 100644 index 000000000..7e3f96013 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/red_lotus_flower.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "environmental:red_lotus_flower" + } + ], + "results": [ + { + "item": "minecraft:red_dye", + "count": 2 + }, + { + "item": "minecraft:red_dye", + "count": 1, + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/violet.json b/src/main/resources/data/create/recipes/compat/environmental/milling/violet.json similarity index 83% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/violet.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/violet.json index fea46a464..b9be9005f 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/violet.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/violet.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:violet" + "item": "environmental:violet" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/environmental/milling/white_delphinium.json b/src/main/resources/data/create/recipes/compat/environmental/milling/white_delphinium.json new file mode 100644 index 000000000..9f49ca4d4 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/white_delphinium.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "environmental:white_delphinium" + } + ], + "results": [ + { + "item": "minecraft:white_dye", + "count": 3 + }, + { + "item": "minecraft:white_dye", + "count": 1, + "chance": 0.1 + } + ], + "processingTime": 50 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/columbine.json b/src/main/resources/data/create/recipes/compat/environmental/milling/white_lotus_flower.json similarity index 71% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/columbine.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/white_lotus_flower.json index f5988729e..e024f73c5 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/columbine.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/white_lotus_flower.json @@ -2,22 +2,22 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:columbine" + "item": "environmental:white_lotus_flower" } ], "results": [ { - "item": "minecraft:purple_dye", + "item": "minecraft:white_dye", "count": 2 }, { - "item": "minecraft:white_dye", + "item": "minecraft:lime_dye", "count": 1, "chance": 0.1 } diff --git a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/yellow_hibiscus.json b/src/main/resources/data/create/recipes/compat/environmental/milling/yellow_hibiscus.json similarity index 81% rename from src/main/resources/data/create/recipes/compat/buzzier_bees/milling/yellow_hibiscus.json rename to src/main/resources/data/create/recipes/compat/environmental/milling/yellow_hibiscus.json index f2ce4cead..bd9b8453c 100644 --- a/src/main/resources/data/create/recipes/compat/buzzier_bees/milling/yellow_hibiscus.json +++ b/src/main/resources/data/create/recipes/compat/environmental/milling/yellow_hibiscus.json @@ -2,13 +2,13 @@ "conditions": [ { "type": "forge:mod_loaded", - "modid": "buzzierbees" + "modid": "environmental" } ], "type": "create:milling", "ingredients": [ { - "item": "buzzierbees:daybloom" + "item": "environmental:yellow_hibiscus" } ], "results": [ diff --git a/src/main/resources/data/create/recipes/compat/environmental/pressing/mycelium_path.json b/src/main/resources/data/create/recipes/compat/environmental/pressing/mycelium_path.json new file mode 100644 index 000000000..452fcc3ab --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/pressing/mycelium_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "minecraft:mycelium" + } + ] + ], + "results": [ + { + "item": "environmental:mycelium_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/environmental/pressing/podzol_path.json b/src/main/resources/data/create/recipes/compat/environmental/pressing/podzol_path.json new file mode 100644 index 000000000..a75ed6119 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/environmental/pressing/podzol_path.json @@ -0,0 +1,21 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "environmental" + } + ], + "type": "create:pressing", + "ingredients": [ + [ + { + "item": "minecraft:podzol" + } + ] + ], + "results": [ + { + "item": "environmental:podzol_path" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/neapolitan/crushing/ice.json b/src/main/resources/data/create/recipes/compat/neapolitan/crushing/ice.json new file mode 100644 index 000000000..cc093968a --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/neapolitan/crushing/ice.json @@ -0,0 +1,26 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "neapolitan" + } + ], + "type": "create:crushing", + "ingredients": [ + { + "item": "minecraft:ice" + } + ], + "results": [ + { + "item": "neapolitan:ice_cubes", + "count": 3 + }, + { + "item": "neapolitan:ice_cubes", + "count": 3, + "chance": 0.25 + } + ], + "processingTime": 100 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/neapolitan/emptying/milk_bottle.json b/src/main/resources/data/create/recipes/compat/neapolitan/emptying/milk_bottle.json new file mode 100644 index 000000000..f4785b681 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/neapolitan/emptying/milk_bottle.json @@ -0,0 +1,23 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "neapolitan" + } + ], + "type": "create:emptying", + "ingredients": [ + { + "item": "neapolitan:milk_bottle" + } + ], + "results": [ + { + "item": "minecraft:glass_bottle" + }, + { + "fluid": "create:milk", + "amount": 250 + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/neapolitan/filling/milk_bottle.json b/src/main/resources/data/create/recipes/compat/neapolitan/filling/milk_bottle.json new file mode 100644 index 000000000..42ed87174 --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/neapolitan/filling/milk_bottle.json @@ -0,0 +1,23 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "neapolitan" + } + ], + "type": "create:filling", + "ingredients": [ + { + "item": "minecraft:glass_bottle" + }, + { + "fluidTag": "forge:milk", + "amount": 250 + } + ], + "results": [ + { + "item": "neapolitan:milk_bottle" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/supplementaries/milling/flax.json b/src/main/resources/data/create/recipes/compat/supplementaries/milling/flax.json new file mode 100644 index 000000000..178dfd21d --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/supplementaries/milling/flax.json @@ -0,0 +1,29 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "supplementaries" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "supplementaries:flax" + } + ], + "results": [ + { + "item": "minecraft:string" + }, + { + "item": "minecraft:string", + "count": 2, + "chance": 0.25 + }, + { + "item": "supplementaries:flax_seeds", + "chance": 0.25 + } + ], + "processingTime": 150 +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/supplementaries/splashing/blackboard.json b/src/main/resources/data/create/recipes/compat/supplementaries/splashing/blackboard.json new file mode 100644 index 000000000..badf6115d --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/supplementaries/splashing/blackboard.json @@ -0,0 +1,19 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "supplementaries" + } + ], + "type": "create:splashing", + "ingredients": [ + { + "item": "supplementaries:blackboard" + } + ], + "results": [ + { + "item": "supplementaries:blackboard" + } + ] +} \ No newline at end of file diff --git a/src/main/resources/data/create/recipes/compat/tconstruct/milling/necrotic_bone.json b/src/main/resources/data/create/recipes/compat/tconstruct/milling/necrotic_bone.json new file mode 100644 index 000000000..bf66d163f --- /dev/null +++ b/src/main/resources/data/create/recipes/compat/tconstruct/milling/necrotic_bone.json @@ -0,0 +1,30 @@ +{ + "conditions": [ + { + "type": "forge:mod_loaded", + "modid": "tconstruct" + } + ], + "type": "create:milling", + "ingredients": [ + { + "item": "tconstruct:necrotic_bone" + } + ], + "results": [ + { + "item": "minecraft:bone_meal", + "count": 3 + }, + { + "item": "minecraft:black_dye", + "chance": 0.25 + }, + { + "item": "minecraft:bone_meal", + "count": 3, + "chance": 0.25 + } + ], + "processingTime": 100 +} \ No newline at end of file diff --git a/src/main/resources/logo.png b/src/main/resources/logo.png new file mode 100644 index 000000000..beac8a31b Binary files /dev/null and b/src/main/resources/logo.png differ diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 8c6c34537..8feb30fb0 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,6 +1,6 @@ { "pack": { - "description": "create resources", + "description": "Create resources", "pack_format": 6 } } diff --git a/src/main/resources/ponder/debug/scene_10.nbt b/src/main/resources/ponder/debug/scene_10.nbt new file mode 100644 index 000000000..41e45e42d Binary files /dev/null and b/src/main/resources/ponder/debug/scene_10.nbt differ diff --git a/src/main/resources/ponder/deployer/processing.nbt b/src/main/resources/ponder/deployer/processing.nbt new file mode 100644 index 000000000..daa9f2845 Binary files /dev/null and b/src/main/resources/ponder/deployer/processing.nbt differ diff --git a/src/main/resources/ponder/fluid_pipe/encasing.nbt b/src/main/resources/ponder/fluid_pipe/encasing.nbt new file mode 100644 index 000000000..c6e1d76e6 Binary files /dev/null and b/src/main/resources/ponder/fluid_pipe/encasing.nbt differ diff --git a/src/main/resources/ponder/fluid_pipe/flow.nbt b/src/main/resources/ponder/fluid_pipe/flow.nbt new file mode 100644 index 000000000..f3dd374bc Binary files /dev/null and b/src/main/resources/ponder/fluid_pipe/flow.nbt differ diff --git a/src/main/resources/ponder/fluid_pipe/interaction.nbt b/src/main/resources/ponder/fluid_pipe/interaction.nbt new file mode 100644 index 000000000..1779c5bf8 Binary files /dev/null and b/src/main/resources/ponder/fluid_pipe/interaction.nbt differ